HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/public/builder/builder.js
/*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
var BuilderBundle;
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ "./node_modules/ejs-browser/lib/ejs.js":
/*!*********************************************!*\
  !*** ./node_modules/ejs-browser/lib/ejs.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

eval("/*\n * EJS Embedded JavaScript templates\n * Copyright 2112 Matthew Eernisse ([email protected])\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *         http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n*/\n\n\n\n/**\n * @file Embedded JavaScript templating engine. {@link http://ejs.co}\n * @author Matthew Eernisse <[email protected]>\n * @author Tiancheng \"Timothy\" Gu <[email protected]>\n * @project EJS\n * @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}\n */\n\n/**\n * EJS internal functions.\n *\n * Technically this \"module\" lies in the same file as {@link module:ejs}, for\n * the sake of organization all the private functions re grouped into this\n * module.\n *\n * @module ejs-internal\n * @private\n */\n\n/**\n * Embedded JavaScript templating engine.\n *\n * @module ejs\n * @public\n */\n\n\nvar fs = {};\nvar path = {};\nvar utils = __webpack_require__(/*! ./utils */ \"./node_modules/ejs-browser/lib/utils.js\");\n\nvar scopeOptionWarned = false;\n/** @type {string} */\nvar _VERSION_STRING = (__webpack_require__(/*! ../package.json */ \"./node_modules/ejs-browser/package.json\").version);\nvar _DEFAULT_OPEN_DELIMITER = '<';\nvar _DEFAULT_CLOSE_DELIMITER = '>';\nvar _DEFAULT_DELIMITER = '%';\nvar _DEFAULT_LOCALS_NAME = 'locals';\nvar _NAME = 'ejs';\nvar _REGEX_STRING = '(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)';\nvar _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compileDebug',\n  'client', '_with', 'rmWhitespace', 'strict', 'filename', 'async'];\n// We don't allow 'cache' option to be passed in the data obj for\n// the normal `render` call, but this is where Express 2 & 3 put it\n// so we make an exception for `renderFile`\nvar _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');\nvar _BOM = /^\\uFEFF/;\nvar _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;\n\n/**\n * EJS template function cache. This can be a LRU object from lru-cache NPM\n * module. By default, it is {@link module:utils.cache}, a simple in-process\n * cache that grows continuously.\n *\n * @type {Cache}\n */\n\nexports.cache = utils.cache;\n\n/**\n * Custom file loader. Useful for template preprocessing or restricting access\n * to a certain part of the filesystem.\n *\n * @type {fileLoader}\n */\n\nexports.fileLoader = fs.readFileSync;\n\n/**\n * Name of the object containing the locals.\n *\n * This variable is overridden by {@link Options}`.localsName` if it is not\n * `undefined`.\n *\n * @type {String}\n * @public\n */\n\nexports.localsName = _DEFAULT_LOCALS_NAME;\n\n/**\n * Promise implementation -- defaults to the native implementation if available\n * This is mostly just for testability\n *\n * @type {PromiseConstructorLike}\n * @public\n */\n\nexports.promiseImpl = (new Function('return this;'))().Promise;\n\n/**\n * Get the path to the included file from the parent file path and the\n * specified path.\n *\n * @param {String}  name     specified path\n * @param {String}  filename parent file path\n * @param {Boolean} [isDir=false] whether the parent file path is a directory\n * @return {String}\n */\nexports.resolveInclude = function(name, filename, isDir) {\n  var dirname = path.dirname;\n  var extname = path.extname;\n  var resolve = path.resolve;\n  var includePath = resolve(isDir ? filename : dirname(filename), name);\n  var ext = extname(name);\n  if (!ext) {\n    includePath += '.ejs';\n  }\n  return includePath;\n};\n\n/**\n * Try to resolve file path on multiple directories\n *\n * @param  {String}        name  specified path\n * @param  {Array<String>} paths list of possible parent directory paths\n * @return {String}\n */\nfunction resolvePaths(name, paths) {\n  var filePath;\n  if (paths.some(function (v) {\n    filePath = exports.resolveInclude(name, v, true);\n    return fs.existsSync(filePath);\n  })) {\n    return filePath;\n  }\n}\n\n/**\n * Get the path to the included file by Options\n *\n * @param  {String}  path    specified path\n * @param  {Options} options compilation options\n * @return {String}\n */\nfunction getIncludePath(path, options) {\n  var includePath;\n  var filePath;\n  var views = options.views;\n  var match = /^[A-Za-z]+:\\\\|^\\//.exec(path);\n\n  // Abs path\n  if (match && match.length) {\n    path = path.replace(/^\\/*/, '');\n    if (Array.isArray(options.root)) {\n      includePath = resolvePaths(path, options.root);\n    } else {\n      includePath = exports.resolveInclude(path, options.root || '/', true);\n    }\n  }\n  // Relative paths\n  else {\n    // Look relative to a passed filename first\n    if (options.filename) {\n      filePath = exports.resolveInclude(path, options.filename);\n      if (fs.existsSync(filePath)) {\n        includePath = filePath;\n      }\n    }\n    // Then look in any views directories\n    if (!includePath && Array.isArray(views)) {\n      includePath = resolvePaths(path, views);\n    }\n    if (!includePath && typeof options.includer !== 'function') {\n      throw new Error('Could not find the include file \"' +\n          options.escapeFunction(path) + '\"');\n    }\n  }\n  return includePath;\n}\n\n/**\n * Get the template from a string or a file, either compiled on-the-fly or\n * read from cache (if enabled), and cache the template if needed.\n *\n * If `template` is not set, the file specified in `options.filename` will be\n * read.\n *\n * If `options.cache` is true, this function reads the file from\n * `options.filename` so it must be set prior to calling this function.\n *\n * @memberof module:ejs-internal\n * @param {Options} options   compilation options\n * @param {String} [template] template source\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `options.client`, either type might be returned.\n * @static\n */\n\nfunction handleCache(options, template) {\n  var func;\n  var filename = options.filename;\n  var hasTemplate = arguments.length > 1;\n\n  if (options.cache) {\n    if (!filename) {\n      throw new Error('cache option requires a filename');\n    }\n    func = exports.cache.get(filename);\n    if (func) {\n      return func;\n    }\n    if (!hasTemplate) {\n      template = fileLoader(filename).toString().replace(_BOM, '');\n    }\n  }\n  else if (!hasTemplate) {\n    // istanbul ignore if: should not happen at all\n    if (!filename) {\n      throw new Error('Internal EJS error: no file name or template '\n                    + 'provided');\n    }\n    template = fileLoader(filename).toString().replace(_BOM, '');\n  }\n  func = exports.compile(template, options);\n  if (options.cache) {\n    exports.cache.set(filename, func);\n  }\n  return func;\n}\n\n/**\n * Try calling handleCache with the given options and data and call the\n * callback with the result. If an error occurs, call the callback with\n * the error. Used by renderFile().\n *\n * @memberof module:ejs-internal\n * @param {Options} options    compilation options\n * @param {Object} data        template data\n * @param {RenderFileCallback} cb callback\n * @static\n */\n\nfunction tryHandleCache(options, data, cb) {\n  var result;\n  if (!cb) {\n    if (typeof exports.promiseImpl == 'function') {\n      return new exports.promiseImpl(function (resolve, reject) {\n        try {\n          result = handleCache(options)(data);\n          resolve(result);\n        }\n        catch (err) {\n          reject(err);\n        }\n      });\n    }\n    else {\n      throw new Error('Please provide a callback function');\n    }\n  }\n  else {\n    try {\n      result = handleCache(options)(data);\n    }\n    catch (err) {\n      return cb(err);\n    }\n\n    cb(null, result);\n  }\n}\n\n/**\n * fileLoader is independent\n *\n * @param {String} filePath ejs file path.\n * @return {String} The contents of the specified file.\n * @static\n */\n\nfunction fileLoader(filePath){\n  return exports.fileLoader(filePath);\n}\n\n/**\n * Get the template function.\n *\n * If `options.cache` is `true`, then the template is cached.\n *\n * @memberof module:ejs-internal\n * @param {String}  path    path for the specified file\n * @param {Options} options compilation options\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `options.client`, either type might be returned\n * @static\n */\n\nfunction includeFile(path, options) {\n  var opts = utils.shallowCopy(utils.createNullProtoObjWherePossible(), options);\n  opts.filename = getIncludePath(path, opts);\n  if (typeof options.includer === 'function') {\n    var includerResult = options.includer(path, opts.filename);\n    if (includerResult) {\n      if (includerResult.filename) {\n        opts.filename = includerResult.filename;\n      }\n      if (includerResult.template) {\n        return handleCache(opts, includerResult.template);\n      }\n    }\n  }\n  return handleCache(opts);\n}\n\n/**\n * Re-throw the given `err` in context to the `str` of ejs, `filename`, and\n * `lineno`.\n *\n * @implements {RethrowCallback}\n * @memberof module:ejs-internal\n * @param {Error}  err      Error object\n * @param {String} str      EJS source\n * @param {String} flnm     file name of the EJS file\n * @param {Number} lineno   line number of the error\n * @param {EscapeCallback} esc\n * @static\n */\n\nfunction rethrow(err, str, flnm, lineno, esc) {\n  var lines = str.split('\\n');\n  var start = Math.max(lineno - 3, 0);\n  var end = Math.min(lines.length, lineno + 3);\n  var filename = esc(flnm);\n  // Error context\n  var context = lines.slice(start, end).map(function (line, i){\n    var curr = i + start + 1;\n    return (curr == lineno ? ' >> ' : '    ')\n      + curr\n      + '| '\n      + line;\n  }).join('\\n');\n\n  // Alter exception message\n  err.path = filename;\n  err.message = (filename || 'ejs') + ':'\n    + lineno + '\\n'\n    + context + '\\n\\n'\n    + err.message;\n\n  throw err;\n}\n\nfunction stripSemi(str){\n  return str.replace(/;(\\s*$)/, '$1');\n}\n\n/**\n * Compile the given `str` of ejs into a template function.\n *\n * @param {String}  template EJS template\n *\n * @param {Options} [opts] compilation options\n *\n * @return {(TemplateFunction|ClientFunction)}\n * Depending on the value of `opts.client`, either type might be returned.\n * Note that the return type of the function also depends on the value of `opts.async`.\n * @public\n */\n\nexports.compile = function compile(template, opts) {\n  var templ;\n\n  // v1 compat\n  // 'scope' is 'context'\n  // FIXME: Remove this in a future version\n  if (opts && opts.scope) {\n    if (!scopeOptionWarned){\n      console.warn('`scope` option is deprecated and will be removed in EJS 3');\n      scopeOptionWarned = true;\n    }\n    if (!opts.context) {\n      opts.context = opts.scope;\n    }\n    delete opts.scope;\n  }\n  templ = new Template(template, opts);\n  return templ.compile();\n};\n\n/**\n * Render the given `template` of ejs.\n *\n * If you would like to include options but not data, you need to explicitly\n * call this function with `data` being an empty object or `null`.\n *\n * @param {String}   template EJS template\n * @param {Object}  [data={}] template data\n * @param {Options} [opts={}] compilation and rendering options\n * @return {(String|Promise<String>)}\n * Return value type depends on `opts.async`.\n * @public\n */\n\nexports.render = function (template, d, o) {\n  var data = d || utils.createNullProtoObjWherePossible();\n  var opts = o || utils.createNullProtoObjWherePossible();\n\n  // No options object -- if there are optiony names\n  // in the data, copy them to options\n  if (arguments.length == 2) {\n    utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA);\n  }\n\n  return handleCache(opts, template)(data);\n};\n\n/**\n * Render an EJS file at the given `path` and callback `cb(err, str)`.\n *\n * If you would like to include options but not data, you need to explicitly\n * call this function with `data` being an empty object or `null`.\n *\n * @param {String}             path     path to the EJS file\n * @param {Object}            [data={}] template data\n * @param {Options}           [opts={}] compilation and rendering options\n * @param {RenderFileCallback} cb callback\n * @public\n */\n\nexports.renderFile = function () {\n  var args = Array.prototype.slice.call(arguments);\n  var filename = args.shift();\n  var cb;\n  var opts = {filename: filename};\n  var data;\n  var viewOpts;\n\n  // Do we have a callback?\n  if (typeof arguments[arguments.length - 1] == 'function') {\n    cb = args.pop();\n  }\n  // Do we have data/opts?\n  if (args.length) {\n    // Should always have data obj\n    data = args.shift();\n    // Normal passed opts (data obj + opts obj)\n    if (args.length) {\n      // Use shallowCopy so we don't pollute passed in opts obj with new vals\n      utils.shallowCopy(opts, args.pop());\n    }\n    // Special casing for Express (settings + opts-in-data)\n    else {\n      // Express 3 and 4\n      if (data.settings) {\n        // Pull a few things from known locations\n        if (data.settings.views) {\n          opts.views = data.settings.views;\n        }\n        if (data.settings['view cache']) {\n          opts.cache = true;\n        }\n        // Undocumented after Express 2, but still usable, esp. for\n        // items that are unsafe to be passed along with data, like `root`\n        viewOpts = data.settings['view options'];\n        if (viewOpts) {\n          utils.shallowCopy(opts, viewOpts);\n        }\n      }\n      // Express 2 and lower, values set in app.locals, or people who just\n      // want to pass options in their data. NOTE: These values will override\n      // anything previously set in settings  or settings['view options']\n      utils.shallowCopyFromList(opts, data, _OPTS_PASSABLE_WITH_DATA_EXPRESS);\n    }\n    opts.filename = filename;\n  }\n  else {\n    data = utils.createNullProtoObjWherePossible();\n  }\n\n  return tryHandleCache(opts, data, cb);\n};\n\n/**\n * Clear intermediate JavaScript cache. Calls {@link Cache#reset}.\n * @public\n */\n\n/**\n * EJS template class\n * @public\n */\nexports.Template = Template;\n\nexports.clearCache = function () {\n  exports.cache.reset();\n};\n\nfunction Template(text, opts) {\n  opts = opts || utils.createNullProtoObjWherePossible();\n  var options = utils.createNullProtoObjWherePossible();\n  this.templateText = text;\n  /** @type {string | null} */\n  this.mode = null;\n  this.truncate = false;\n  this.currentLine = 1;\n  this.source = '';\n  options.client = opts.client || false;\n  options.escapeFunction = opts.escape || opts.escapeFunction || utils.escapeXML;\n  options.compileDebug = opts.compileDebug !== false;\n  options.debug = !!opts.debug;\n  options.filename = opts.filename;\n  options.openDelimiter = opts.openDelimiter || exports.openDelimiter || _DEFAULT_OPEN_DELIMITER;\n  options.closeDelimiter = opts.closeDelimiter || exports.closeDelimiter || _DEFAULT_CLOSE_DELIMITER;\n  options.delimiter = opts.delimiter || exports.delimiter || _DEFAULT_DELIMITER;\n  options.strict = opts.strict || false;\n  options.context = opts.context;\n  options.cache = opts.cache || false;\n  options.rmWhitespace = opts.rmWhitespace;\n  options.root = opts.root;\n  options.includer = opts.includer;\n  options.outputFunctionName = opts.outputFunctionName;\n  options.localsName = opts.localsName || exports.localsName || _DEFAULT_LOCALS_NAME;\n  options.views = opts.views;\n  options.async = opts.async;\n  options.destructuredLocals = opts.destructuredLocals;\n  options.legacyInclude = typeof opts.legacyInclude != 'undefined' ? !!opts.legacyInclude : true;\n\n  if (options.strict) {\n    options._with = false;\n  }\n  else {\n    options._with = typeof opts._with != 'undefined' ? opts._with : true;\n  }\n\n  this.opts = options;\n\n  this.regex = this.createRegex();\n}\n\nTemplate.modes = {\n  EVAL: 'eval',\n  ESCAPED: 'escaped',\n  RAW: 'raw',\n  COMMENT: 'comment',\n  LITERAL: 'literal'\n};\n\nTemplate.prototype = {\n  createRegex: function () {\n    var str = _REGEX_STRING;\n    var delim = utils.escapeRegExpChars(this.opts.delimiter);\n    var open = utils.escapeRegExpChars(this.opts.openDelimiter);\n    var close = utils.escapeRegExpChars(this.opts.closeDelimiter);\n    str = str.replace(/%/g, delim)\n      .replace(/</g, open)\n      .replace(/>/g, close);\n    return new RegExp(str);\n  },\n\n  compile: function () {\n    /** @type {string} */\n    var src;\n    /** @type {ClientFunction} */\n    var fn;\n    var opts = this.opts;\n    var prepended = '';\n    var appended = '';\n    /** @type {EscapeCallback} */\n    var escapeFn = opts.escapeFunction;\n    /** @type {FunctionConstructor} */\n    var ctor;\n    /** @type {string} */\n    var sanitizedFilename = opts.filename ? JSON.stringify(opts.filename) : 'undefined';\n\n    if (!this.source) {\n      this.generateSource();\n      prepended +=\n        '  var __output = \"\";\\n' +\n        '  function __append(s) { if (s !== undefined && s !== null) __output += s }\\n';\n      if (opts.outputFunctionName) {\n        if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {\n          throw new Error('outputFunctionName is not a valid JS identifier.');\n        }\n        prepended += '  var ' + opts.outputFunctionName + ' = __append;' + '\\n';\n      }\n      if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {\n        throw new Error('localsName is not a valid JS identifier.');\n      }\n      if (opts.destructuredLocals && opts.destructuredLocals.length) {\n        var destructuring = '  var __locals = (' + opts.localsName + ' || {}),\\n';\n        for (var i = 0; i < opts.destructuredLocals.length; i++) {\n          var name = opts.destructuredLocals[i];\n          if (!_JS_IDENTIFIER.test(name)) {\n            throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');\n          }\n          if (i > 0) {\n            destructuring += ',\\n  ';\n          }\n          destructuring += name + ' = __locals.' + name;\n        }\n        prepended += destructuring + ';\\n';\n      }\n      if (opts._with !== false) {\n        prepended +=  '  with (' + opts.localsName + ' || {}) {' + '\\n';\n        appended += '  }' + '\\n';\n      }\n      appended += '  return __output;' + '\\n';\n      this.source = prepended + this.source + appended;\n    }\n\n    if (opts.compileDebug) {\n      src = 'var __line = 1' + '\\n'\n        + '  , __lines = ' + JSON.stringify(this.templateText) + '\\n'\n        + '  , __filename = ' + sanitizedFilename + ';' + '\\n'\n        + 'try {' + '\\n'\n        + this.source\n        + '} catch (e) {' + '\\n'\n        + '  rethrow(e, __lines, __filename, __line, escapeFn);' + '\\n'\n        + '}' + '\\n';\n    }\n    else {\n      src = this.source;\n    }\n\n    if (opts.client) {\n      src = 'escapeFn = escapeFn || ' + escapeFn.toString() + ';' + '\\n' + src;\n      if (opts.compileDebug) {\n        src = 'rethrow = rethrow || ' + rethrow.toString() + ';' + '\\n' + src;\n      }\n    }\n\n    if (opts.strict) {\n      src = '\"use strict\";\\n' + src;\n    }\n    if (opts.debug) {\n      console.log(src);\n    }\n    if (opts.compileDebug && opts.filename) {\n      src = src + '\\n'\n        + '//# sourceURL=' + sanitizedFilename + '\\n';\n    }\n\n    try {\n      if (opts.async) {\n        // Have to use generated function for this, since in envs without support,\n        // it breaks in parsing\n        try {\n          ctor = (new Function('return (async function(){}).constructor;'))();\n        }\n        catch(e) {\n          if (e instanceof SyntaxError) {\n            throw new Error('This environment does not support async/await');\n          }\n          else {\n            throw e;\n          }\n        }\n      }\n      else {\n        ctor = Function;\n      }\n      fn = new ctor(opts.localsName + ', escapeFn, include, rethrow', src);\n    }\n    catch(e) {\n      // istanbul ignore else\n      if (e instanceof SyntaxError) {\n        if (opts.filename) {\n          e.message += ' in ' + opts.filename;\n        }\n        e.message += ' while compiling ejs\\n\\n';\n        e.message += 'If the above error is not helpful, you may want to try EJS-Lint:\\n';\n        e.message += 'https://github.com/RyanZim/EJS-Lint';\n        if (!opts.async) {\n          e.message += '\\n';\n          e.message += 'Or, if you meant to create an async function, pass `async: true` as an option.';\n        }\n      }\n      throw e;\n    }\n\n    // Return a callable function which will execute the function\n    // created by the source-code, with the passed data as locals\n    // Adds a local `include` function which allows full recursive include\n    var returnedFn = opts.client ? fn : function anonymous(data) {\n      var include = function (path, includeData) {\n        var d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);\n        if (includeData) {\n          d = utils.shallowCopy(d, includeData);\n        }\n        return includeFile(path, opts)(d);\n      };\n      return fn.apply(opts.context,\n        [data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);\n    };\n    if (opts.filename && typeof Object.defineProperty === 'function') {\n      var filename = opts.filename;\n      var basename = path.basename(filename, path.extname(filename));\n      try {\n        Object.defineProperty(returnedFn, 'name', {\n          value: basename,\n          writable: false,\n          enumerable: false,\n          configurable: true\n        });\n      } catch (e) {/* ignore */}\n    }\n    return returnedFn;\n  },\n\n  generateSource: function () {\n    var opts = this.opts;\n\n    if (opts.rmWhitespace) {\n      // Have to use two separate replace here as `^` and `$` operators don't\n      // work well with `\\r` and empty lines don't work well with the `m` flag.\n      this.templateText =\n        this.templateText.replace(/[\\r\\n]+/g, '\\n').replace(/^\\s+|\\s+$/gm, '');\n    }\n\n    // Slurp spaces and tabs before <%_ and after _%>\n    this.templateText =\n      this.templateText.replace(/[ \\t]*<%_/gm, '<%_').replace(/_%>[ \\t]*/gm, '_%>');\n\n    var self = this;\n    var matches = this.parseTemplateText();\n    var d = this.opts.delimiter;\n    var o = this.opts.openDelimiter;\n    var c = this.opts.closeDelimiter;\n\n    if (matches && matches.length) {\n      matches.forEach(function (line, index) {\n        var closing;\n        // If this is an opening tag, check for closing tags\n        // FIXME: May end up with some false positives here\n        // Better to store modes as k/v with openDelimiter + delimiter as key\n        // Then this can simply check against the map\n        if ( line.indexOf(o + d) === 0        // If it is a tag\n          && line.indexOf(o + d + d) !== 0) { // and is not escaped\n          closing = matches[index + 2];\n          if (!(closing == d + c || closing == '-' + d + c || closing == '_' + d + c)) {\n            throw new Error('Could not find matching close tag for \"' + line + '\".');\n          }\n        }\n        self.scanLine(line);\n      });\n    }\n\n  },\n\n  parseTemplateText: function () {\n    var str = this.templateText;\n    var pat = this.regex;\n    var result = pat.exec(str);\n    var arr = [];\n    var firstPos;\n\n    while (result) {\n      firstPos = result.index;\n\n      if (firstPos !== 0) {\n        arr.push(str.substring(0, firstPos));\n        str = str.slice(firstPos);\n      }\n\n      arr.push(result[0]);\n      str = str.slice(result[0].length);\n      result = pat.exec(str);\n    }\n\n    if (str) {\n      arr.push(str);\n    }\n\n    return arr;\n  },\n\n  _addOutput: function (line) {\n    if (this.truncate) {\n      // Only replace single leading linebreak in the line after\n      // -%> tag -- this is the single, trailing linebreak\n      // after the tag that the truncation mode replaces\n      // Handle Win / Unix / old Mac linebreaks -- do the \\r\\n\n      // combo first in the regex-or\n      line = line.replace(/^(?:\\r\\n|\\r|\\n)/, '');\n      this.truncate = false;\n    }\n    if (!line) {\n      return line;\n    }\n\n    // Preserve literal slashes\n    line = line.replace(/\\\\/g, '\\\\\\\\');\n\n    // Convert linebreaks\n    line = line.replace(/\\n/g, '\\\\n');\n    line = line.replace(/\\r/g, '\\\\r');\n\n    // Escape double-quotes\n    // - this will be the delimiter during execution\n    line = line.replace(/\"/g, '\\\\\"');\n    this.source += '    ; __append(\"' + line + '\")' + '\\n';\n  },\n\n  scanLine: function (line) {\n    var self = this;\n    var d = this.opts.delimiter;\n    var o = this.opts.openDelimiter;\n    var c = this.opts.closeDelimiter;\n    var newLineCount = 0;\n\n    newLineCount = (line.split('\\n').length - 1);\n\n    switch (line) {\n    case o + d:\n    case o + d + '_':\n      this.mode = Template.modes.EVAL;\n      break;\n    case o + d + '=':\n      this.mode = Template.modes.ESCAPED;\n      break;\n    case o + d + '-':\n      this.mode = Template.modes.RAW;\n      break;\n    case o + d + '#':\n      this.mode = Template.modes.COMMENT;\n      break;\n    case o + d + d:\n      this.mode = Template.modes.LITERAL;\n      this.source += '    ; __append(\"' + line.replace(o + d + d, o + d) + '\")' + '\\n';\n      break;\n    case d + d + c:\n      this.mode = Template.modes.LITERAL;\n      this.source += '    ; __append(\"' + line.replace(d + d + c, d + c) + '\")' + '\\n';\n      break;\n    case d + c:\n    case '-' + d + c:\n    case '_' + d + c:\n      if (this.mode == Template.modes.LITERAL) {\n        this._addOutput(line);\n      }\n\n      this.mode = null;\n      this.truncate = line.indexOf('-') === 0 || line.indexOf('_') === 0;\n      break;\n    default:\n      // In script mode, depends on type of tag\n      if (this.mode) {\n        // If '//' is found without a line break, add a line break.\n        switch (this.mode) {\n        case Template.modes.EVAL:\n        case Template.modes.ESCAPED:\n        case Template.modes.RAW:\n          if (line.lastIndexOf('//') > line.lastIndexOf('\\n')) {\n            line += '\\n';\n          }\n        }\n        switch (this.mode) {\n        // Just executing code\n        case Template.modes.EVAL:\n          this.source += '    ; ' + line + '\\n';\n          break;\n          // Exec, esc, and output\n        case Template.modes.ESCAPED:\n          this.source += '    ; __append(escapeFn(' + stripSemi(line) + '))' + '\\n';\n          break;\n          // Exec and output\n        case Template.modes.RAW:\n          this.source += '    ; __append(' + stripSemi(line) + ')' + '\\n';\n          break;\n        case Template.modes.COMMENT:\n          // Do nothing\n          break;\n          // Literal <%% mode, append as raw output\n        case Template.modes.LITERAL:\n          this._addOutput(line);\n          break;\n        }\n      }\n      // In string mode, just add the output\n      else {\n        this._addOutput(line);\n      }\n    }\n\n    if (self.opts.compileDebug && newLineCount) {\n      this.currentLine += newLineCount;\n      this.source += '    ; __line = ' + this.currentLine + '\\n';\n    }\n  }\n};\n\n/**\n * Escape characters reserved in XML.\n *\n * This is simply an export of {@link module:utils.escapeXML}.\n *\n * If `markup` is `undefined` or `null`, the empty string is returned.\n *\n * @param {String} markup Input string\n * @return {String} Escaped string\n * @public\n * @func\n * */\nexports.escapeXML = utils.escapeXML;\n\n/**\n * Express.js support.\n *\n * This is an alias for {@link module:ejs.renderFile}, in order to support\n * Express.js out-of-the-box.\n *\n * @func\n */\n\nexports.__express = exports.renderFile;\n\n/**\n * Version of EJS.\n *\n * @readonly\n * @type {String}\n * @public\n */\n\nexports.VERSION = _VERSION_STRING;\n\n/**\n * Name for detection of EJS.\n *\n * @readonly\n * @type {String}\n * @public\n */\n\nexports.name = _NAME;\n\n/* istanbul ignore if */\nif (typeof window != 'undefined') {\n  window.ejs = exports;\n}\n\n\n//# sourceURL=webpack://BuilderBundle/./node_modules/ejs-browser/lib/ejs.js?");

/***/ }),

/***/ "./node_modules/ejs-browser/lib/utils.js":
/*!***********************************************!*\
  !*** ./node_modules/ejs-browser/lib/utils.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, exports) => {

eval("/*\n * EJS Embedded JavaScript templates\n * Copyright 2112 Matthew Eernisse ([email protected])\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *         http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n*/\n\n/**\n * Private utility functions\n * @module utils\n * @private\n */\n\n\n\nvar regExpChars = /[|\\\\{}()[\\]^$+*?.]/g;\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nvar hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };\n\n/**\n * Escape characters reserved in regular expressions.\n *\n * If `string` is `undefined` or `null`, the empty string is returned.\n *\n * @param {String} string Input string\n * @return {String} Escaped string\n * @static\n * @private\n */\nexports.escapeRegExpChars = function (string) {\n  // istanbul ignore if\n  if (!string) {\n    return '';\n  }\n  return String(string).replace(regExpChars, '\\\\$&');\n};\n\nvar _ENCODE_HTML_RULES = {\n  '&': '&amp;',\n  '<': '&lt;',\n  '>': '&gt;',\n  '\"': '&#34;',\n  \"'\": '&#39;'\n};\nvar _MATCH_HTML = /[&<>'\"]/g;\n\nfunction encode_char(c) {\n  return _ENCODE_HTML_RULES[c] || c;\n}\n\n/**\n * Stringified version of constants used by {@link module:utils.escapeXML}.\n *\n * It is used in the process of generating {@link ClientFunction}s.\n *\n * @readonly\n * @type {String}\n */\n\nvar escapeFuncStr =\n  'var _ENCODE_HTML_RULES = {\\n'\n+ '      \"&\": \"&amp;\"\\n'\n+ '    , \"<\": \"&lt;\"\\n'\n+ '    , \">\": \"&gt;\"\\n'\n+ '    , \\'\"\\': \"&#34;\"\\n'\n+ '    , \"\\'\": \"&#39;\"\\n'\n+ '    }\\n'\n+ '  , _MATCH_HTML = /[&<>\\'\"]/g;\\n'\n+ 'function encode_char(c) {\\n'\n+ '  return _ENCODE_HTML_RULES[c] || c;\\n'\n+ '};\\n';\n\n/**\n * Escape characters reserved in XML.\n *\n * If `markup` is `undefined` or `null`, the empty string is returned.\n *\n * @implements {EscapeCallback}\n * @param {String} markup Input string\n * @return {String} Escaped string\n * @static\n * @private\n */\n\nexports.escapeXML = function (markup) {\n  return markup == undefined\n    ? ''\n    : String(markup)\n      .replace(_MATCH_HTML, encode_char);\n};\n\nfunction escapeXMLToString() {\n  return Function.prototype.toString.call(this) + ';\\n' + escapeFuncStr;\n}\n\ntry {\n  if (typeof Object.defineProperty === 'function') {\n  // If the Function prototype is frozen, the \"toString\" property is non-writable. This means that any objects which inherit this property\n  // cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict\n  // mode, attempting that will be silently ignored.\n  // However, we can still explicitly shadow the prototype's \"toString\" property by defining a new \"toString\" property on this object.\n    Object.defineProperty(exports.escapeXML, 'toString', { value: escapeXMLToString });\n  } else {\n    // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.\n    exports.escapeXML.toString = escapeXMLToString;\n  }\n} catch (err) {\n  console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');\n}\n\n/**\n * Naive copy of properties from one object to another.\n * Does not recurse into non-scalar properties\n * Does not check to see if the property has a value before copying\n *\n * @param  {Object} to   Destination object\n * @param  {Object} from Source object\n * @return {Object}      Destination object\n * @static\n * @private\n */\nexports.shallowCopy = function (to, from) {\n  from = from || {};\n  if ((to !== null) && (to !== undefined)) {\n    for (var p in from) {\n      if (!hasOwn(from, p)) {\n        continue;\n      }\n      if (p === '__proto__' || p === 'constructor') {\n        continue;\n      }\n      to[p] = from[p];\n    }\n  }\n  return to;\n};\n\n/**\n * Naive copy of a list of key names, from one object to another.\n * Only copies property if it is actually defined\n * Does not recurse into non-scalar properties\n *\n * @param  {Object} to   Destination object\n * @param  {Object} from Source object\n * @param  {Array} list List of properties to copy\n * @return {Object}      Destination object\n * @static\n * @private\n */\nexports.shallowCopyFromList = function (to, from, list) {\n  list = list || [];\n  from = from || {};\n  if ((to !== null) && (to !== undefined)) {\n    for (var i = 0; i < list.length; i++) {\n      var p = list[i];\n      if (typeof from[p] != 'undefined') {\n        if (!hasOwn(from, p)) {\n          continue;\n        }\n        if (p === '__proto__' || p === 'constructor') {\n          continue;\n        }\n        to[p] = from[p];\n      }\n    }\n  }\n  return to;\n};\n\n/**\n * Simple in-process cache implementation. Does not implement limits of any\n * sort.\n *\n * @implements {Cache}\n * @static\n * @private\n */\nexports.cache = {\n  _data: {},\n  set: function (key, val) {\n    this._data[key] = val;\n  },\n  get: function (key) {\n    return this._data[key];\n  },\n  remove: function (key) {\n    delete this._data[key];\n  },\n  reset: function () {\n    this._data = {};\n  }\n};\n\n/**\n * Transforms hyphen case variable into camel case.\n *\n * @param {String} string Hyphen case string\n * @return {String} Camel case string\n * @static\n * @private\n */\nexports.hyphenToCamel = function (str) {\n  return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });\n};\n\n/**\n * Returns a null-prototype object in runtimes that support it\n *\n * @return {Object} Object, prototype will be set to null where possible\n * @static\n * @private\n */\nexports.createNullProtoObjWherePossible = (function () {\n  if (typeof Object.create == 'function') {\n    return function () {\n      return Object.create(null);\n    };\n  }\n  if (!({__proto__: null} instanceof Object)) {\n    return function () {\n      return {__proto__: null};\n    };\n  }\n  // Not possible, just pass through\n  return function () {\n    return {};\n  };\n})();\n\n\n\n\n//# sourceURL=webpack://BuilderBundle/./node_modules/ejs-browser/lib/utils.js?");

/***/ }),

/***/ "./node_modules/ejs-browser/package.json":
/*!***********************************************!*\
  !*** ./node_modules/ejs-browser/package.json ***!
  \***********************************************/
/***/ ((module) => {

eval("module.exports = /*#__PURE__*/JSON.parse('{\"name\":\"ejs-browser\",\"description\":\"Embedded JavaScript templates\",\"keywords\":[\"template\",\"engine\",\"ejs\"],\"version\":\"3.2.2\",\"author\":\"Matthew Eernisse <[email protected]> (http://fleegix.org)\",\"license\":\"Apache-2.0\",\"bin\":{\"ejs\":\"./bin/cli.js\"},\"main\":\"./lib/ejs.js\",\"jsdelivr\":\"ejs.min.js\",\"unpkg\":\"ejs.min.js\",\"repository\":{\"type\":\"git\",\"url\":\"git://github.com/mde/ejs.git\"},\"bugs\":\"https://github.com/mde/ejs/issues\",\"homepage\":\"https://github.com/mde/ejs\",\"dependencies\":{\"jake\":\"^10.8.5\"},\"devDependencies\":{\"browserify\":\"^16.5.1\",\"eslint\":\"^6.8.0\",\"git-directory-deploy\":\"^1.5.1\",\"jsdoc\":\"^4.0.2\",\"lru-cache\":\"^4.0.1\",\"mocha\":\"^10.2.0\",\"uglify-js\":\"^3.3.16\"},\"engines\":{\"node\":\">=0.10.0\"},\"scripts\":{\"test\":\"mocha -u tdd\",\"publish\":\"npm publish\"}}');\n\n//# sourceURL=webpack://BuilderBundle/./node_modules/ejs-browser/package.json?");

/***/ }),

/***/ "./src/builder.js":
/*!************************!*\
  !*** ./src/builder.js ***!
  \************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _includes_Builder_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./includes/Builder.js */ \"./src/includes/Builder.js\");\n/* harmony import */ var _includes_I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./includes/I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _includes_BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./includes/BuilderjsPopup.js */ \"./src/includes/BuilderjsPopup.js\");\n/* harmony import */ var _includes_ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./includes/ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _includes_InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./includes/InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _includes_overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./includes/overlays/TextInlineToolbarOverlay.js */ \"./src/includes/overlays/TextInlineToolbarOverlay.js\");\n/* harmony import */ var _includes_overlays_RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./includes/overlays/RichDropdownMenuOverlay.js */ \"./src/includes/overlays/RichDropdownMenuOverlay.js\");\n/* harmony import */ var _includes_TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./includes/TextSelectionTracker.js */ \"./src/includes/TextSelectionTracker.js\");\n/* harmony import */ var _includes_WidgetsBox_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./includes/WidgetsBox.js */ \"./src/includes/WidgetsBox.js\");\n/* harmony import */ var _includes_HeadingWidget_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./includes/HeadingWidget.js */ \"./src/includes/HeadingWidget.js\");\n/* harmony import */ var _includes_ParagraphWidget_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./includes/ParagraphWidget.js */ \"./src/includes/ParagraphWidget.js\");\n/* harmony import */ var _includes_WelcomeWidget_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./includes/WelcomeWidget.js */ \"./src/includes/WelcomeWidget.js\");\n/* harmony import */ var _includes_MenuWidget_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./includes/MenuWidget.js */ \"./src/includes/MenuWidget.js\");\n/* harmony import */ var _includes_ListWidget_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./includes/ListWidget.js */ \"./src/includes/ListWidget.js\");\n/* harmony import */ var _includes_ListElement_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./includes/ListElement.js */ \"./src/includes/ListElement.js\");\n/* harmony import */ var _includes_ImageWidget_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./includes/ImageWidget.js */ \"./src/includes/ImageWidget.js\");\n/* harmony import */ var _includes_GridWidget_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./includes/GridWidget.js */ \"./src/includes/GridWidget.js\");\n/* harmony import */ var _includes_SelectWidget_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./includes/SelectWidget.js */ \"./src/includes/SelectWidget.js\");\n/* harmony import */ var _includes_RadioWidget_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./includes/RadioWidget.js */ \"./src/includes/RadioWidget.js\");\n/* harmony import */ var _includes_CheckboxWidget_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./includes/CheckboxWidget.js */ \"./src/includes/CheckboxWidget.js\");\n/* harmony import */ var _includes_PricingCardsWidget_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./includes/PricingCardsWidget.js */ \"./src/includes/PricingCardsWidget.js\");\n/* harmony import */ var _includes_H1Element_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./includes/H1Element.js */ \"./src/includes/H1Element.js\");\n/* harmony import */ var _includes_PElement_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./includes/PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _includes_MenuElement_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./includes/MenuElement.js */ \"./src/includes/MenuElement.js\");\n/* harmony import */ var _includes_GridElement_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./includes/GridElement.js */ \"./src/includes/GridElement.js\");\n/* harmony import */ var _includes_CellElement_js__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./includes/CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _includes_ButtonElement_js__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./includes/ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _includes_ButtonWidget_js__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./includes/ButtonWidget.js */ \"./src/includes/ButtonWidget.js\");\n/* harmony import */ var _includes_VideoElement_js__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(/*! ./includes/VideoElement.js */ \"./src/includes/VideoElement.js\");\n/* harmony import */ var _includes_VideoWidget_js__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(/*! ./includes/VideoWidget.js */ \"./src/includes/VideoWidget.js\");\n/* harmony import */ var _includes_AlertElement_js__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(/*! ./includes/AlertElement.js */ \"./src/includes/AlertElement.js\");\n/* harmony import */ var _includes_AlertWidget_js__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(/*! ./includes/AlertWidget.js */ \"./src/includes/AlertWidget.js\");\n/* harmony import */ var _includes_TabsManager_js__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(/*! ./includes/TabsManager.js */ \"./src/includes/TabsManager.js\");\n/* harmony import */ var _includes_UIManager_js__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(/*! ./includes/UIManager.js */ \"./src/includes/UIManager.js\");\n/* harmony import */ var _includes_BaseElement_js__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(/*! ./includes/BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _includes_TextControl_js__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(/*! ./includes/TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _includes_ImageElement_js__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(/*! ./includes/ImageElement.js */ \"./src/includes/ImageElement.js\");\n/* harmony import */ var _includes_BaseWidget_js__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(/*! ./includes/BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _includes_ElementFactory_js__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(/*! ./includes/ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _includes_LinkElement_js__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(/*! ./includes/LinkElement.js */ \"./src/includes/LinkElement.js\");\n/* harmony import */ var _includes_H2Element_js__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(/*! ./includes/H2Element.js */ \"./src/includes/H2Element.js\");\n/* harmony import */ var _includes_H3Element_js__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(/*! ./includes/H3Element.js */ \"./src/includes/H3Element.js\");\n/* harmony import */ var _includes_H4Element_js__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(/*! ./includes/H4Element.js */ \"./src/includes/H4Element.js\");\n/* harmony import */ var _includes_H5Element_js__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(/*! ./includes/H5Element.js */ \"./src/includes/H5Element.js\");\n/* harmony import */ var _includes_TextInputElement_js__WEBPACK_IMPORTED_MODULE_45__ = __webpack_require__(/*! ./includes/TextInputElement.js */ \"./src/includes/TextInputElement.js\");\n/* harmony import */ var _includes_ListControl_js__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(/*! ./includes/ListControl.js */ \"./src/includes/ListControl.js\");\n/* harmony import */ var _includes_PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(/*! ./includes/PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _includes_InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(/*! ./includes/InnerPaddingControl.js */ \"./src/includes/InnerPaddingControl.js\");\n/* harmony import */ var _includes_RSSElement_js__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(/*! ./includes/RSSElement.js */ \"./src/includes/RSSElement.js\");\n/* harmony import */ var _includes_RSSWidget_js__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(/*! ./includes/RSSWidget.js */ \"./src/includes/RSSWidget.js\");\n/* harmony import */ var _includes_RSSControl_js__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(/*! ./includes/RSSControl.js */ \"./src/includes/RSSControl.js\");\n/* harmony import */ var _includes_FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(/*! ./includes/FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _includes_FontWeightControl_js__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(/*! ./includes/FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _includes_ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(/*! ./includes/ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _includes_RichTextControl_js__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(/*! ./includes/RichTextControl.js */ \"./src/includes/RichTextControl.js\");\n/* harmony import */ var _includes_BlockElement_js__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(/*! ./includes/BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _includes_GridControl_js__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(/*! ./includes/GridControl.js */ \"./src/includes/GridControl.js\");\n/* harmony import */ var _includes_SettingsTabManager_js__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(/*! ./includes/SettingsTabManager.js */ \"./src/includes/SettingsTabManager.js\");\n/* harmony import */ var _includes_CheckboxControl_js__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(/*! ./includes/CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _includes_RadiosControl_js__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(/*! ./includes/RadiosControl.js */ \"./src/includes/RadiosControl.js\");\n/* harmony import */ var _includes_DropdownControl_js__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(/*! ./includes/DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _includes_SocialIconsElement_js__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(/*! ./includes/SocialIconsElement.js */ \"./src/includes/SocialIconsElement.js\");\n/* harmony import */ var _includes_SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(/*! ./includes/SocialIconsControl.js */ \"./src/includes/SocialIconsControl.js\");\n/* harmony import */ var _includes_RangeControl_js__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(/*! ./includes/RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _includes_SAlert_js__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(/*! ./includes/SAlert.js */ \"./src/includes/SAlert.js\");\n/* harmony import */ var _includes_BackgroundControl_js__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(/*! ./includes/BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _includes_ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(/*! ./includes/ImageEffectControl.js */ \"./src/includes/ImageEffectControl.js\");\n/* harmony import */ var _includes_LabelElement_js__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(/*! ./includes/LabelElement.js */ \"./src/includes/LabelElement.js\");\n/* harmony import */ var _includes_FontSizeControl_js__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(/*! ./includes/FontSizeControl.js */ \"./src/includes/FontSizeControl.js\");\n/* harmony import */ var _includes_NumberControl_js__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(/*! ./includes/NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _includes_TextColorControl_js__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(/*! ./includes/TextColorControl.js */ \"./src/includes/TextColorControl.js\");\n/* harmony import */ var _includes_LinkColorControl_js__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(/*! ./includes/LinkColorControl.js */ \"./src/includes/LinkColorControl.js\");\n/* harmony import */ var _includes_LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./includes/LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\n/* harmony import */ var _includes_ParagraphSpacingControl_js__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(/*! ./includes/ParagraphSpacingControl.js */ \"./src/includes/ParagraphSpacingControl.js\");\n/* harmony import */ var _includes_LineHeightControl_js__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(/*! ./includes/LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _includes_LetterSpacingControl_js__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(/*! ./includes/LetterSpacingControl.js */ \"./src/includes/LetterSpacingControl.js\");\n/* harmony import */ var _includes_TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(/*! ./includes/TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _includes_HTMLElement_js__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(/*! ./includes/HTMLElement.js */ \"./src/includes/HTMLElement.js\");\n/* harmony import */ var _includes_Formatter_js__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(/*! ./includes/Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _includes_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(/*! ./includes/BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _includes_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(/*! ./includes/PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\n/* harmony import */ var _includes_BJS_js__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(/*! ./includes/BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _includes_overlays_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(/*! ./includes/overlays/DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\n/* harmony import */ var _includes_overlays_NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(/*! ./includes/overlays/NativeDragHandleOverlay.js */ \"./src/includes/overlays/NativeDragHandleOverlay.js\");\n/* harmony import */ var _includes_overlays_EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(/*! ./includes/overlays/EdgeResizerOverlay.js */ \"./src/includes/overlays/EdgeResizerOverlay.js\");\n/* harmony import */ var _includes_overlays_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(/*! ./includes/overlays/FloatingActionBarOverlay.js */ \"./src/includes/overlays/FloatingActionBarOverlay.js\");\n/* harmony import */ var _includes_overlays_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(/*! ./includes/overlays/StructureVisualizerOverlay.js */ \"./src/includes/overlays/StructureVisualizerOverlay.js\");\n/* harmony import */ var _includes_overlays_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(/*! ./includes/overlays/InlineEditorOverlay.js */ \"./src/includes/overlays/InlineEditorOverlay.js\");\n/* harmony import */ var _includes_overlays_ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(/*! ./includes/overlays/ResizeCornerOverlay.js */ \"./src/includes/overlays/ResizeCornerOverlay.js\");\n/* harmony import */ var _includes_overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(/*! ./includes/overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\n/* harmony import */ var _includes_SelectElement_js__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(/*! ./includes/SelectElement.js */ \"./src/includes/SelectElement.js\");\n/* harmony import */ var _includes_SelectControl_js__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(/*! ./includes/SelectControl.js */ \"./src/includes/SelectControl.js\");\n/* harmony import */ var _includes_RadioElement_js__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(/*! ./includes/RadioElement.js */ \"./src/includes/RadioElement.js\");\n/* harmony import */ var _includes_CheckboxElement_js__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(/*! ./includes/CheckboxElement.js */ \"./src/includes/CheckboxElement.js\");\n/* harmony import */ var _includes_PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(/*! ./includes/PricingCardsElement.js */ \"./src/includes/PricingCardsElement.js\");\n/* harmony import */ var _includes_PricingCardElement_js__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(/*! ./includes/PricingCardElement.js */ \"./src/includes/PricingCardElement.js\");\n/* harmony import */ var _includes_StyleControl_js__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(/*! ./includes/StyleControl.js */ \"./src/includes/StyleControl.js\");\n/* harmony import */ var _includes_IconPickerControl_js__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(/*! ./includes/IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _includes_YoutubeElement_js__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(/*! ./includes/YoutubeElement.js */ \"./src/includes/YoutubeElement.js\");\n/* harmony import */ var _includes_YoutubeWidget_js__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(/*! ./includes/YoutubeWidget.js */ \"./src/includes/YoutubeWidget.js\");\n/* harmony import */ var _includes_HorizonAlignmentControl_js__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(/*! ./includes/HorizonAlignmentControl.js */ \"./src/includes/HorizonAlignmentControl.js\");\n/* harmony import */ var _includes_CustomRangeControl_js__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(/*! ./includes/CustomRangeControl.js */ \"./src/includes/CustomRangeControl.js\");\n/* harmony import */ var _includes_BorderControl_js__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(/*! ./includes/BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _includes_BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_103__ = __webpack_require__(/*! ./includes/BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _includes_HeadingElement_js__WEBPACK_IMPORTED_MODULE_104__ = __webpack_require__(/*! ./includes/HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _includes_HeadingControl_js__WEBPACK_IMPORTED_MODULE_105__ = __webpack_require__(/*! ./includes/HeadingControl.js */ \"./src/includes/HeadingControl.js\");\n/* harmony import */ var _includes_SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_106__ = __webpack_require__(/*! ./includes/SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _includes_FormContainerCell_js__WEBPACK_IMPORTED_MODULE_107__ = __webpack_require__(/*! ./includes/FormContainerCell.js */ \"./src/includes/FormContainerCell.js\");\n/* harmony import */ var _includes_FieldElement_js__WEBPACK_IMPORTED_MODULE_108__ = __webpack_require__(/*! ./includes/FieldElement.js */ \"./src/includes/FieldElement.js\");\n/* harmony import */ var _includes_FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_109__ = __webpack_require__(/*! ./includes/FieldConfigControl.js */ \"./src/includes/FieldConfigControl.js\");\n/* harmony import */ var _includes_SubmitButtonElement_js__WEBPACK_IMPORTED_MODULE_110__ = __webpack_require__(/*! ./includes/SubmitButtonElement.js */ \"./src/includes/SubmitButtonElement.js\");\n/* harmony import */ var _includes_TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_111__ = __webpack_require__(/*! ./includes/TermsConfigControl.js */ \"./src/includes/TermsConfigControl.js\");\n/* harmony import */ var _includes_TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_112__ = __webpack_require__(/*! ./includes/TermsOfServiceElement.js */ \"./src/includes/TermsOfServiceElement.js\");\n/* harmony import */ var _includes_TermsOfServiceWidget_js__WEBPACK_IMPORTED_MODULE_113__ = __webpack_require__(/*! ./includes/TermsOfServiceWidget.js */ \"./src/includes/TermsOfServiceWidget.js\");\n/* harmony import */ var _includes_CheckoutElement_js__WEBPACK_IMPORTED_MODULE_114__ = __webpack_require__(/*! ./includes/CheckoutElement.js */ \"./src/includes/CheckoutElement.js\");\n/* harmony import */ var _includes_CheckoutControl_js__WEBPACK_IMPORTED_MODULE_115__ = __webpack_require__(/*! ./includes/CheckoutControl.js */ \"./src/includes/CheckoutControl.js\");\n/* harmony import */ var _includes_CheckoutWidget_js__WEBPACK_IMPORTED_MODULE_116__ = __webpack_require__(/*! ./includes/CheckoutWidget.js */ \"./src/includes/CheckoutWidget.js\");\n/* harmony import */ var _includes_CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_117__ = __webpack_require__(/*! ./includes/CheckoutSimpleElement.js */ \"./src/includes/CheckoutSimpleElement.js\");\n/* harmony import */ var _includes_CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_118__ = __webpack_require__(/*! ./includes/CheckoutSimpleControl.js */ \"./src/includes/CheckoutSimpleControl.js\");\n/* harmony import */ var _includes_CheckoutSimpleWidget_js__WEBPACK_IMPORTED_MODULE_119__ = __webpack_require__(/*! ./includes/CheckoutSimpleWidget.js */ \"./src/includes/CheckoutSimpleWidget.js\");\n/* harmony import */ var _includes_DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_120__ = __webpack_require__(/*! ./includes/DividerStyleControl.js */ \"./src/includes/DividerStyleControl.js\");\n/* harmony import */ var _includes_DividerElement_js__WEBPACK_IMPORTED_MODULE_121__ = __webpack_require__(/*! ./includes/DividerElement.js */ \"./src/includes/DividerElement.js\");\n/* harmony import */ var _includes_DividerWidget_js__WEBPACK_IMPORTED_MODULE_122__ = __webpack_require__(/*! ./includes/DividerWidget.js */ \"./src/includes/DividerWidget.js\");\n/* harmony import */ var _includes_AlignControl_js__WEBPACK_IMPORTED_MODULE_123__ = __webpack_require__(/*! ./includes/AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _includes_ImageTextLeftWidget_js__WEBPACK_IMPORTED_MODULE_124__ = __webpack_require__(/*! ./includes/ImageTextLeftWidget.js */ \"./src/includes/ImageTextLeftWidget.js\");\n/* harmony import */ var _includes_ImageTextRightWidget_js__WEBPACK_IMPORTED_MODULE_125__ = __webpack_require__(/*! ./includes/ImageTextRightWidget.js */ \"./src/includes/ImageTextRightWidget.js\");\n/* harmony import */ var _includes_ImageTextTopWidget_js__WEBPACK_IMPORTED_MODULE_126__ = __webpack_require__(/*! ./includes/ImageTextTopWidget.js */ \"./src/includes/ImageTextTopWidget.js\");\n/* harmony import */ var _includes_ImageTextBottomWidget_js__WEBPACK_IMPORTED_MODULE_127__ = __webpack_require__(/*! ./includes/ImageTextBottomWidget.js */ \"./src/includes/ImageTextBottomWidget.js\");\n/* harmony import */ var _includes_ImageTextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_128__ = __webpack_require__(/*! ./includes/ImageTextDoubleWidget.js */ \"./src/includes/ImageTextDoubleWidget.js\");\n/* harmony import */ var _includes_TextCenterWidget_js__WEBPACK_IMPORTED_MODULE_129__ = __webpack_require__(/*! ./includes/TextCenterWidget.js */ \"./src/includes/TextCenterWidget.js\");\n/* harmony import */ var _includes_TextLeftWidget_js__WEBPACK_IMPORTED_MODULE_130__ = __webpack_require__(/*! ./includes/TextLeftWidget.js */ \"./src/includes/TextLeftWidget.js\");\n/* harmony import */ var _includes_TextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_131__ = __webpack_require__(/*! ./includes/TextDoubleWidget.js */ \"./src/includes/TextDoubleWidget.js\");\n/* harmony import */ var _includes_ads_AdHeadlineWidget_js__WEBPACK_IMPORTED_MODULE_132__ = __webpack_require__(/*! ./includes/ads/AdHeadlineWidget.js */ \"./src/includes/ads/AdHeadlineWidget.js\");\n/* harmony import */ var _includes_ads_AdPrimaryTextWidget_js__WEBPACK_IMPORTED_MODULE_133__ = __webpack_require__(/*! ./includes/ads/AdPrimaryTextWidget.js */ \"./src/includes/ads/AdPrimaryTextWidget.js\");\n/* harmony import */ var _includes_ads_AdDescriptionWidget_js__WEBPACK_IMPORTED_MODULE_134__ = __webpack_require__(/*! ./includes/ads/AdDescriptionWidget.js */ \"./src/includes/ads/AdDescriptionWidget.js\");\n/* harmony import */ var _includes_ads_AdCTAWidget_js__WEBPACK_IMPORTED_MODULE_135__ = __webpack_require__(/*! ./includes/ads/AdCTAWidget.js */ \"./src/includes/ads/AdCTAWidget.js\");\n/* harmony import */ var _includes_ads_AdImageSlotWidget_js__WEBPACK_IMPORTED_MODULE_136__ = __webpack_require__(/*! ./includes/ads/AdImageSlotWidget.js */ \"./src/includes/ads/AdImageSlotWidget.js\");\n/* harmony import */ var _includes_ads_AdLogoSlotWidget_js__WEBPACK_IMPORTED_MODULE_137__ = __webpack_require__(/*! ./includes/ads/AdLogoSlotWidget.js */ \"./src/includes/ads/AdLogoSlotWidget.js\");\n/* harmony import */ var _includes_ads_AdCarouselCardWidget_js__WEBPACK_IMPORTED_MODULE_138__ = __webpack_require__(/*! ./includes/ads/AdCarouselCardWidget.js */ \"./src/includes/ads/AdCarouselCardWidget.js\");\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_139__ = __webpack_require__(/*! ejs-browser */ \"./node_modules/ejs-browser/lib/ejs.js\");\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_139___default = /*#__PURE__*/__webpack_require__.n(ejs_browser__WEBPACK_IMPORTED_MODULE_139__);\n\n\n\n\n\n\n\n\nwindow.BuilderjsPopup = _includes_BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"];\n// Pure static utility; exposed globally so the demo page showcase can\n// visualise its decisions without spinning up a full Builder instance.\n// PLAN_EFFECT W0.3.\nwindow.ToolbarPositioner = _includes_ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"];\n// TEXT_INLINE_PLAN W0.5 — inline whitelist primitive. Stateless class\n// with three entry points (sanitize / normalize / emit). Exposed\n// globally so the showcase paste-playground + future W1-W6 toolbar\n// consumers can reach it without a Builder instance.\nwindow.InlineSanitizer = _includes_InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"];\n// TEXT_INLINE_PLAN W1.1 — floating inline text formatting toolbar. Class\n// exposed globally so host apps can invoke `builder._textInlineToolbar.*`\n// for test introspection; the instance itself is lifecycle-managed by\n// Builder._textInlineToolbarInit() and never user-instantiated.\nwindow.TextInlineToolbarOverlay = _includes_overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"];\n// TEXT_INLINE_PLAN W2.1 — sectioned dropdown menu primitive with full\n// keyboard nav + ARIA + submenu. Standalone — the showcase demo pages\n// and future kebab menus instantiate it directly. Backs W2.2 (clipboard)\n// + W2.3 (paragraph / case / insert / semantic submenus).\nwindow.RichDropdownMenuOverlay = _includes_overlays_RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"];\n// TEXT_INLINE_PLAN W5.2 — selection save/restore helper. Exposed globally\n// so future popover consumers outside the core bundle can wrap their\n// apply handlers + so test harnesses can probe save/restore/run\n// behaviour without a mount-point dependency.\nwindow.SelectionGuard = _includes_TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__.SelectionGuard;\n// TEXT_INLINE_PLAN W4.3 — link config composite (type-first URL +\n// target + rel chips + title + aria-label + download + UTM builder).\n// Shared by LinkElement + ButtonElement + W1.3 inline link popover;\n// exposed on window so test harnesses + future consumers can mount\n// standalone without reaching into the Builder graph.\nwindow.LinkConfigControl = _includes_LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"];\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nwindow.Formatter = _includes_Formatter_js__WEBPACK_IMPORTED_MODULE_78__[\"default\"];\nwindow.I18n = _includes_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"];\n\n// ─────────────────────────────────────────────────────────────────\n// Canvas Overlay system\n// See docs/core/OVERLAY.md for design spec.\n// See docs/archived/OVERLAY_PLAN.md for phased rollout.\n// CSS lives in src/builder.css (appended — webpack has no JS→CSS\n// module loader; builder.css is copied whole via CopyWebpackPlugin).\n// ─────────────────────────────────────────────────────────────────\n// Phase 1.1 — foundation\n\n\nwindow.BaseOverlay = _includes_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_79__[\"default\"];\nwindow.PointerCaptureRegistry = _includes_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_80__[\"default\"];\n\n// Phase 1.9 — framework debug namespace. Eager import so\n// `window.__bjsDebug = true` in DevTools immediately enables BJS.log tracing.\n\nwindow.BJS = _includes_BJS_js__WEBPACK_IMPORTED_MODULE_81__[\"default\"];\n\n// Phase 1.2 — 7 primitive base classes. No element consumes them yet;\n// Phase 1.3+ subclasses them for Grid / Image / Cell / Block affordances.\n\n\n\n\n\n\n\n\nwindow.DraggableHandleOverlay = _includes_overlays_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_82__[\"default\"];\nwindow.NativeDragHandleOverlay = _includes_overlays_NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_83__[\"default\"];\nwindow.EdgeResizerOverlay = _includes_overlays_EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_84__[\"default\"];\nwindow.FloatingActionBarOverlay = _includes_overlays_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_85__[\"default\"];\nwindow.StructureVisualizerOverlay = _includes_overlays_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_86__[\"default\"];\nwindow.InlineEditorOverlay = _includes_overlays_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_87__[\"default\"];\nwindow.ResizeCornerOverlay = _includes_overlays_ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_88__[\"default\"];\nwindow.PaddingVisualizerOverlay = _includes_overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_89__[\"default\"];\n\n// Phase 1.3 — Grid element overlays (GridStructureOverlay + GridColumnResizeOverlay)\n// are imported INSIDE GridElement.js itself; no separate window exposure needed\n// since they're element-specific and instantiated via GridElement.getOverlays().\n\n//*temporal elements\n\n\n\n\n\n\n\n\n\n\n\n\n// temporal elements*\n\n\n\n\n\n\n\nwindow.SectionLabelControl = _includes_SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_106__[\"default\"];\n\n//\n\nwindow.FormContainerCell = _includes_FormContainerCell_js__WEBPACK_IMPORTED_MODULE_107__[\"default\"];\n\nwindow.FieldElement = _includes_FieldElement_js__WEBPACK_IMPORTED_MODULE_108__[\"default\"];\n\nwindow.FieldConfigControl = _includes_FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_109__[\"default\"];\n\nwindow.SubmitButtonElement = _includes_SubmitButtonElement_js__WEBPACK_IMPORTED_MODULE_110__[\"default\"];\n\nwindow.TermsConfigControl = _includes_TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_111__[\"default\"];\n\nwindow.TermsOfServiceElement = _includes_TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_112__[\"default\"];\n\nwindow.TermsOfServiceWidget = _includes_TermsOfServiceWidget_js__WEBPACK_IMPORTED_MODULE_113__[\"default\"];\n\nwindow.CheckoutElement = _includes_CheckoutElement_js__WEBPACK_IMPORTED_MODULE_114__[\"default\"];\n\nwindow.CheckoutControl = _includes_CheckoutControl_js__WEBPACK_IMPORTED_MODULE_115__[\"default\"];\n\nwindow.CheckoutWidget = _includes_CheckoutWidget_js__WEBPACK_IMPORTED_MODULE_116__[\"default\"];\n\nwindow.CheckoutSimpleElement = _includes_CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_117__[\"default\"];\n\nwindow.CheckoutSimpleControl = _includes_CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_118__[\"default\"];\n\nwindow.CheckoutSimpleWidget = _includes_CheckoutSimpleWidget_js__WEBPACK_IMPORTED_MODULE_119__[\"default\"];\n\n//\n\nwindow.DividerStyleControl = _includes_DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_120__[\"default\"];\n\nwindow.DividerElement = _includes_DividerElement_js__WEBPACK_IMPORTED_MODULE_121__[\"default\"];\n\nwindow.DividerWidget = _includes_DividerWidget_js__WEBPACK_IMPORTED_MODULE_122__[\"default\"];\n\nwindow.AlignControl = _includes_AlignControl_js__WEBPACK_IMPORTED_MODULE_123__[\"default\"];\n\n//\n\nwindow.ImageTextLeftWidget = _includes_ImageTextLeftWidget_js__WEBPACK_IMPORTED_MODULE_124__[\"default\"];\n\nwindow.ImageTextRightWidget = _includes_ImageTextRightWidget_js__WEBPACK_IMPORTED_MODULE_125__[\"default\"];\n\nwindow.ImageTextTopWidget = _includes_ImageTextTopWidget_js__WEBPACK_IMPORTED_MODULE_126__[\"default\"];\n\nwindow.ImageTextBottomWidget = _includes_ImageTextBottomWidget_js__WEBPACK_IMPORTED_MODULE_127__[\"default\"];\n\nwindow.ImageTextDoubleWidget = _includes_ImageTextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_128__[\"default\"];\n\nwindow.TextCenterWidget = _includes_TextCenterWidget_js__WEBPACK_IMPORTED_MODULE_129__[\"default\"];\n\nwindow.TextLeftWidget = _includes_TextLeftWidget_js__WEBPACK_IMPORTED_MODULE_130__[\"default\"];\n\nwindow.TextDoubleWidget = _includes_TextDoubleWidget_js__WEBPACK_IMPORTED_MODULE_131__[\"default\"];\n\n// ─────────────────────────────────────────────────────────────────\n// Ads widgets — drag-drop building blocks for paid ad creative\n// (Meta / Google / TikTok / LinkedIn). All use existing core\n// elements under the hood; no new Element classes, no registry\n// changes. Consumer (host app) registers these in the ads-mode\n// builder via `builder.widgetsBox.addWidget(new AdXxxWidget(), ...)`.\n// See docs/BUILDER.md → \"Ads mode\" section for the full design.\n// ─────────────────────────────────────────────────────────────────\n\nwindow.AdHeadlineWidget = _includes_ads_AdHeadlineWidget_js__WEBPACK_IMPORTED_MODULE_132__[\"default\"];\n\nwindow.AdPrimaryTextWidget = _includes_ads_AdPrimaryTextWidget_js__WEBPACK_IMPORTED_MODULE_133__[\"default\"];\n\nwindow.AdDescriptionWidget = _includes_ads_AdDescriptionWidget_js__WEBPACK_IMPORTED_MODULE_134__[\"default\"];\n\nwindow.AdCTAWidget = _includes_ads_AdCTAWidget_js__WEBPACK_IMPORTED_MODULE_135__[\"default\"];\n\nwindow.AdImageSlotWidget = _includes_ads_AdImageSlotWidget_js__WEBPACK_IMPORTED_MODULE_136__[\"default\"];\n\nwindow.AdLogoSlotWidget = _includes_ads_AdLogoSlotWidget_js__WEBPACK_IMPORTED_MODULE_137__[\"default\"];\n\nwindow.AdCarouselCardWidget = _includes_ads_AdCarouselCardWidget_js__WEBPACK_IMPORTED_MODULE_138__[\"default\"];\n\n// Attach all classes to the global `window` object\nwindow.Builder = _includes_Builder_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\nwindow.WidgetsBox = _includes_WidgetsBox_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"];\nwindow.HeadingWidget = _includes_HeadingWidget_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"];\nwindow.ParagraphWidget = _includes_ParagraphWidget_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"];\nwindow.WelcomeWidget = _includes_WelcomeWidget_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"];\nwindow.MenuWidget = _includes_MenuWidget_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"];\nwindow.ListWidget = _includes_ListWidget_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"];\nwindow.ListElement = _includes_ListElement_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"];\nwindow.ImageWidget = _includes_ImageWidget_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"];\nwindow.GridWidget = _includes_GridWidget_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"];\nwindow.SelectWidget = _includes_SelectWidget_js__WEBPACK_IMPORTED_MODULE_18__[\"default\"];\nwindow.RadioWidget = _includes_RadioWidget_js__WEBPACK_IMPORTED_MODULE_19__[\"default\"];\nwindow.CheckboxWidget = _includes_CheckboxWidget_js__WEBPACK_IMPORTED_MODULE_20__[\"default\"];\nwindow.PricingCardsWidget = _includes_PricingCardsWidget_js__WEBPACK_IMPORTED_MODULE_21__[\"default\"];\nwindow.H1Element = _includes_H1Element_js__WEBPACK_IMPORTED_MODULE_22__[\"default\"];\nwindow.PElement = _includes_PElement_js__WEBPACK_IMPORTED_MODULE_23__[\"default\"];\nwindow.MenuElement = _includes_MenuElement_js__WEBPACK_IMPORTED_MODULE_24__[\"default\"];\nwindow.GridElement = _includes_GridElement_js__WEBPACK_IMPORTED_MODULE_25__[\"default\"];\nwindow.CellElement = _includes_CellElement_js__WEBPACK_IMPORTED_MODULE_26__[\"default\"];\nwindow.ButtonElement = _includes_ButtonElement_js__WEBPACK_IMPORTED_MODULE_27__[\"default\"];\nwindow.ButtonWidget = _includes_ButtonWidget_js__WEBPACK_IMPORTED_MODULE_28__[\"default\"];\nwindow.VideoElement = _includes_VideoElement_js__WEBPACK_IMPORTED_MODULE_29__[\"default\"];\nwindow.VideoWidget = _includes_VideoWidget_js__WEBPACK_IMPORTED_MODULE_30__[\"default\"];\nwindow.AlertElement = _includes_AlertElement_js__WEBPACK_IMPORTED_MODULE_31__[\"default\"];\nwindow.AlertWidget = _includes_AlertWidget_js__WEBPACK_IMPORTED_MODULE_32__[\"default\"];\nwindow.TabsManager = _includes_TabsManager_js__WEBPACK_IMPORTED_MODULE_33__[\"default\"];\nwindow.UIManager = _includes_UIManager_js__WEBPACK_IMPORTED_MODULE_34__[\"default\"];\nwindow.BaseElement = _includes_BaseElement_js__WEBPACK_IMPORTED_MODULE_35__[\"default\"];\nwindow.TextControl = _includes_TextControl_js__WEBPACK_IMPORTED_MODULE_36__[\"default\"];\nwindow.ImageElement = _includes_ImageElement_js__WEBPACK_IMPORTED_MODULE_37__[\"default\"];\nwindow.BaseWidget = _includes_BaseWidget_js__WEBPACK_IMPORTED_MODULE_38__[\"default\"];\nwindow.ElementFactory = _includes_ElementFactory_js__WEBPACK_IMPORTED_MODULE_39__[\"default\"];\nwindow.LinkElement = _includes_LinkElement_js__WEBPACK_IMPORTED_MODULE_40__[\"default\"];\nwindow.H2Element = _includes_H2Element_js__WEBPACK_IMPORTED_MODULE_41__[\"default\"];\nwindow.H3Element = _includes_H3Element_js__WEBPACK_IMPORTED_MODULE_42__[\"default\"];\nwindow.H4Element = _includes_H4Element_js__WEBPACK_IMPORTED_MODULE_43__[\"default\"];\nwindow.H5Element = _includes_H5Element_js__WEBPACK_IMPORTED_MODULE_44__[\"default\"];\nwindow.TextInputElement = _includes_TextInputElement_js__WEBPACK_IMPORTED_MODULE_45__[\"default\"];\nwindow.ListControl = _includes_ListControl_js__WEBPACK_IMPORTED_MODULE_46__[\"default\"];\nwindow.PaddingMarginControl = _includes_PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_47__[\"default\"];\nwindow.InnerPaddingControl = _includes_InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_48__[\"default\"];\nwindow.RSSElement = _includes_RSSElement_js__WEBPACK_IMPORTED_MODULE_49__[\"default\"];\nwindow.RSSWidget = _includes_RSSWidget_js__WEBPACK_IMPORTED_MODULE_50__[\"default\"];\nwindow.RSSControl = _includes_RSSControl_js__WEBPACK_IMPORTED_MODULE_51__[\"default\"];\nwindow.FontFamilyControl = _includes_FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_52__[\"default\"];\nwindow.FontWeightControl = _includes_FontWeightControl_js__WEBPACK_IMPORTED_MODULE_53__[\"default\"];\nwindow.ColorPickerControl = _includes_ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_54__[\"default\"];\nwindow.RichTextControl = _includes_RichTextControl_js__WEBPACK_IMPORTED_MODULE_55__[\"default\"];\nwindow.BlockElement = _includes_BlockElement_js__WEBPACK_IMPORTED_MODULE_56__[\"default\"];\nwindow.GridControl = _includes_GridControl_js__WEBPACK_IMPORTED_MODULE_57__[\"default\"];\nwindow.SettingsTabManager = _includes_SettingsTabManager_js__WEBPACK_IMPORTED_MODULE_58__[\"default\"];\nwindow.CheckboxControl = _includes_CheckboxControl_js__WEBPACK_IMPORTED_MODULE_59__[\"default\"];\nwindow.RadiosControl = _includes_RadiosControl_js__WEBPACK_IMPORTED_MODULE_60__[\"default\"];\nwindow.DropdownControl = _includes_DropdownControl_js__WEBPACK_IMPORTED_MODULE_61__[\"default\"];\nwindow.SocialIconsElement = _includes_SocialIconsElement_js__WEBPACK_IMPORTED_MODULE_62__[\"default\"];\nwindow.SocialIconsControl = _includes_SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_63__[\"default\"];\nwindow.RangeControl = _includes_RangeControl_js__WEBPACK_IMPORTED_MODULE_64__[\"default\"];\nwindow.SAlert = _includes_SAlert_js__WEBPACK_IMPORTED_MODULE_65__[\"default\"];\nwindow.BackgroundControl = _includes_BackgroundControl_js__WEBPACK_IMPORTED_MODULE_66__[\"default\"];\nwindow.ImageEffectControl = _includes_ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_67__[\"default\"];\nwindow.LabelElement = _includes_LabelElement_js__WEBPACK_IMPORTED_MODULE_68__[\"default\"];\nwindow.YoutubeElement = _includes_YoutubeElement_js__WEBPACK_IMPORTED_MODULE_98__[\"default\"];\nwindow.YoutubeWidget = _includes_YoutubeWidget_js__WEBPACK_IMPORTED_MODULE_99__[\"default\"];\nwindow.FontSizeControl = _includes_FontSizeControl_js__WEBPACK_IMPORTED_MODULE_69__[\"default\"];\nwindow.NumberControl = _includes_NumberControl_js__WEBPACK_IMPORTED_MODULE_70__[\"default\"];\nwindow.TextColorControl = _includes_TextColorControl_js__WEBPACK_IMPORTED_MODULE_71__[\"default\"];\nwindow.LinkColorControl = _includes_LinkColorControl_js__WEBPACK_IMPORTED_MODULE_72__[\"default\"];\nwindow.LinkConfigControl = _includes_LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"];\nwindow.ParagraphSpacingControl = _includes_ParagraphSpacingControl_js__WEBPACK_IMPORTED_MODULE_73__[\"default\"];\nwindow.LineHeightControl = _includes_LineHeightControl_js__WEBPACK_IMPORTED_MODULE_74__[\"default\"];\nwindow.LetterSpacingControl = _includes_LetterSpacingControl_js__WEBPACK_IMPORTED_MODULE_75__[\"default\"];\nwindow.TextDirectionControl = _includes_TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_76__[\"default\"];\nwindow.HTMLElement = _includes_HTMLElement_js__WEBPACK_IMPORTED_MODULE_77__[\"default\"];\nwindow.HorizonAlignmentControl = _includes_HorizonAlignmentControl_js__WEBPACK_IMPORTED_MODULE_100__[\"default\"];\n\n//*temporal elements\nwindow.SelectElement = _includes_SelectElement_js__WEBPACK_IMPORTED_MODULE_90__[\"default\"];\nwindow.SelectControl = _includes_SelectControl_js__WEBPACK_IMPORTED_MODULE_91__[\"default\"];\nwindow.RadioElement = _includes_RadioElement_js__WEBPACK_IMPORTED_MODULE_92__[\"default\"];\nwindow.CheckboxElement = _includes_CheckboxElement_js__WEBPACK_IMPORTED_MODULE_93__[\"default\"];\nwindow.PricingCardsElement = _includes_PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_94__[\"default\"];\nwindow.PricingCardElement = _includes_PricingCardElement_js__WEBPACK_IMPORTED_MODULE_95__[\"default\"];\nwindow.StyleControl = _includes_StyleControl_js__WEBPACK_IMPORTED_MODULE_96__[\"default\"];\nwindow.IconPickerControl = _includes_IconPickerControl_js__WEBPACK_IMPORTED_MODULE_97__[\"default\"];\n// temporal elements*\n\nwindow.CustomRangeControl = _includes_CustomRangeControl_js__WEBPACK_IMPORTED_MODULE_101__[\"default\"];\nwindow.BorderControl = _includes_BorderControl_js__WEBPACK_IMPORTED_MODULE_102__[\"default\"];\nwindow.BorderRadiusControl = _includes_BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_103__[\"default\"];\nwindow.HeadingControl = _includes_HeadingControl_js__WEBPACK_IMPORTED_MODULE_105__[\"default\"];\nwindow.HeadingElement = _includes_HeadingElement_js__WEBPACK_IMPORTED_MODULE_104__[\"default\"];\n\nwindow.ejs = (ejs_browser__WEBPACK_IMPORTED_MODULE_139___default());\n\n//# sourceURL=webpack://BuilderBundle/./src/builder.js?");

/***/ }),

/***/ "./src/includes/ActionButtonControl.js":
/*!*********************************************!*\
  !*** ./src/includes/ActionButtonControl.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\n/**\n * ActionButtonControl — single-click action row for settings panels.\n *\n * Renders a labelled button + optional one-line hint. Used for \"reset to\n * defaults\", \"clean up\", \"duplicate\" style actions — anything that's not a\n * value edit but a discrete user action.\n *\n * Styling piggybacks on `.bjs-info-banner` (tinted surface) + a native\n * button inside. Keeps the panel visually consistent with InfoBannerControl.\n *\n * Usage:\n *   new ActionButtonControl({\n *     label: 'Reset this card',\n *     hint: 'Re-applies the current style defaults to every element.',\n *     buttonText: 'Reset',\n *     variant: 'danger' | 'default',   // default = subtle\n *     onClick: () => cell.applyStylePreset(),\n *   })\n */\nvar ActionButtonControl = /*#__PURE__*/_createClass(function ActionButtonControl() {\n  var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n    _ref$label = _ref.label,\n    label = _ref$label === void 0 ? '' : _ref$label,\n    _ref$hint = _ref.hint,\n    hint = _ref$hint === void 0 ? '' : _ref$hint,\n    _ref$buttonText = _ref.buttonText,\n    buttonText = _ref$buttonText === void 0 ? 'Run' : _ref$buttonText,\n    _ref$variant = _ref.variant,\n    variant = _ref$variant === void 0 ? 'default' : _ref$variant,\n    _ref$onClick = _ref.onClick,\n    onClick = _ref$onClick === void 0 ? function () {} : _ref$onClick;\n  _classCallCheck(this, ActionButtonControl);\n  this.domNode = document.createElement('div');\n  this.domNode.classList.add('bjs-action-row');\n  this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-action-row-body\\\">\\n                <div class=\\\"bjs-action-row-label\\\">\".concat(label, \"</div>\\n                \").concat(hint ? \"<div class=\\\"bjs-action-row-hint\\\">\".concat(hint, \"</div>\") : '', \"\\n            </div>\\n            <button type=\\\"button\\\"\\n                    class=\\\"bjs-action-row-btn \").concat(variant === 'danger' ? 'is-danger' : '', \"\\\">\\n                \").concat(buttonText, \"\\n            </button>\\n        \");\n  var btn = this.domNode.querySelector('.bjs-action-row-btn');\n  btn.addEventListener('click', function (e) {\n    e.preventDefault();\n    e.stopPropagation();\n    try {\n      onClick();\n    } catch (err) {\n      console.error('[ActionButtonControl]', err);\n    }\n  });\n});\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ActionButtonControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ActionButtonControl.js?");

/***/ }),

/***/ "./src/includes/AlertElement.js":
/*!**************************************!*\
  !*** ./src/includes/AlertElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar AlertElement = /*#__PURE__*/function (_BaseElement) {\n  function AlertElement(template) {\n    var _this;\n    var text = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'This is an alert!';\n    _classCallCheck(this, AlertElement);\n    _this = _callSuper(this, AlertElement); // Call the parent class constructor\n    _this.template = template;\n    _this.text = text;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['text'];\n\n    // Formatter - Bootstrap alert component default styles\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"]({\n      // text styles\n      font_family: \"inherit\",\n      font_weight: \"400\",\n      font_size: \"16px\",\n      text_color: \"#084298\",\n      link_color: \"#06357a\",\n      paragraph_spacing: \"0\",\n      text_align: 'left',\n      // left, center, right,\n      line_height: \"1.5\",\n      letter_spacing: null,\n      text_direction: \"ltr\",\n      // ltr, rtl\n\n      // background - Bootstrap alert-primary background\n      background_color: \"#cff4fc\",\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      // spacing - Bootstrap alert padding\n      padding_top: \"0.75rem\",\n      padding_right: \"1.25rem\",\n      padding_bottom: \"0.75rem\",\n      padding_left: \"1.25rem\",\n      // border - Bootstrap alert border (subtle)\n      border_top_style: \"solid\",\n      border_top_width: \"1px\",\n      border_top_color: \"#b6effb\",\n      border_right_style: \"solid\",\n      border_right_width: \"1px\",\n      border_right_color: \"#b6effb\",\n      border_bottom_style: \"solid\",\n      border_bottom_width: \"1px\",\n      border_bottom_color: \"#b6effb\",\n      border_left_width: \"1px\",\n      border_left_style: \"solid\",\n      border_left_color: \"#b6effb\",\n      // border radius - Bootstrap alert radius\n      border_radius: \"0.375rem\"\n    });\n\n    // Inline edit\n    // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n    _this.registerInlineEdit('text');\n    return _this;\n  }\n  _inherits(AlertElement, _BaseElement);\n  return _createClass(AlertElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.alert');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged (W0.2c); inline-edit auto-wires (W0.2b)\n      this.domNode.innerHTML = this.renderTemplate({});\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(AlertElement, \"getData\", this, 3)([])), {}, {\n        text: this.text\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [\n      // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n      // Canvas inline-edit = text surface; sidebar = config panel only.\n      new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_family', value);\n          _this2.render();\n        }\n      }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_weight', value);\n          _this2.render();\n        }\n      }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_size', value);\n          _this2.render();\n        }\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_color', value);\n          _this2.render();\n        }\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('link_color', value);\n          _this2.render();\n        }\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_align', value);\n          _this2.render();\n        }\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('paragraph_spacing', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('line_height', value);\n          _this2.render();\n        }\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('letter_spacing', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_direction', value);\n          _this2.render();\n        }\n      }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this2.formatter.setFormat('background_color', values.color);\n          _this2.formatter.setFormat('background_image', values.image);\n          _this2.formatter.setFormat('background_position', values.position);\n          _this2.formatter.setFormat('background_size', values.size);\n          _this2.formatter.setFormat('background_repeat', values.repeat);\n          _this2.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this2.formatter.setFormat('border_top_style', border_top_style);\n          _this2.formatter.setFormat('border_top_width', border_top_width);\n          _this2.formatter.setFormat('border_top_color', border_top_color);\n          _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this2.formatter.setFormat('border_left_style', border_left_style);\n          _this2.formatter.setFormat('border_left_width', border_left_width);\n          _this2.formatter.setFormat('border_left_color', border_left_color);\n          _this2.formatter.setFormat('border_right_style', border_right_style);\n          _this2.formatter.setFormat('border_right_width', border_right_width);\n          _this2.formatter.setFormat('border_right_color', border_right_color);\n\n          // re-render\n          _this2.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this2.formatter.setFormat('border_radius', v);\n          _this2.render();\n        }\n      }),\n      // W3.8b — InnerPaddingControl (intrinsic shape).\n      new InnerPaddingControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alert_padding'),\n      // value\n      {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      },\n      // callback\n      {\n        setValues: function setValues(values) {\n          _this2.formatter.setFormat('padding_top', values.top);\n          _this2.formatter.setFormat('padding_right', values.right);\n          _this2.formatter.setFormat('padding_bottom', values.bottom);\n          _this2.formatter.setFormat('padding_left', values.left);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.text), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AlertElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/AlertElement.js?");

/***/ }),

/***/ "./src/includes/AlertWidget.js":
/*!*************************************!*\
  !*** ./src/includes/AlertWidget.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _AlertElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AlertElement.js */ \"./src/includes/AlertElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar AlertWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AlertWidget() {\n    var _this;\n    _classCallCheck(this, AlertWidget);\n    _this = _callSuper(this, AlertWidget); // Call the parent class constructor\n\n    // Add an AlertElement to the widget\n    var alert = new _AlertElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Alert', 'This is an alert!');\n\n    // Append the new element to the block\n    _this.block.appendElements([alert]);\n    return _this;\n  }\n  _inherits(AlertWidget, _BaseWidget);\n  return _createClass(AlertWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.alert');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'notification_important';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AlertWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/AlertWidget.js?");

/***/ }),

/***/ "./src/includes/AlignControl.js":
/*!**************************************!*\
  !*** ./src/includes/AlignControl.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * AlignControl — segmented radio picker for 2-N mutually-exclusive values.\n *\n * Primary use: text alignment (left/center/right/justify) on text-bearing\n * elements (PElement, HeadingElement, LinkElement, ButtonElement,\n * AlertElement, LabelElement, SubmitButtonElement). Also re-used with\n * custom icons for orientation (MenuElement), block alignment (ImageElement,\n * GridElement cell-alignment), and other 2-3-option pickers.\n *\n * ── Bus subscription (TEXT_INLINE_PLAN W1.1b — D13 v5 dual-view sync) ──\n * When constructed with `options = { bus, elementUid, formatterKey }` the\n * control subscribes to `formatter:change` on the bus and mirrors its UI\n * state whenever another surface (inline toolbar / future W4.1 advanced\n * popover / any surface writing via `element.formatter.*`) writes the same\n * `{ elementUid, formatterKey }` pair. Echoes are skipped via a unique\n * `source` tag stamped on every emit. The control also emits on user click\n * so the inverse direction is already wired for later subscribers (e.g.\n * the inline toolbar itself when it wants to mirror sidebar clicks).\n *\n * Without `options` the control behaves exactly as pre-W1.1b — zero\n * behaviour change for non-text-align callsites (MenuElement orientation,\n * GridElement align-items, etc.). Opt-in only.\n *\n * ── Lifecycle ──\n * `destroy()` tears down the bus subscription. `Builder.renderElementControls`\n * (Builder.js:1117) calls it on every outgoing control before the sidebar\n * rebuilds (BaseControl invariant I14), so subscriptions never outlive the\n * control instance.\n */\nvar AlignControl = /*#__PURE__*/function () {\n  /**\n   * @param {string}   label\n   * @param {string}   value\n   * @param {object}   callback\n   * @param {Array<string|{value: string, icon: string}>} possibleValues\n   *   Each entry is either a raw value string (icon auto-derived as\n   *   `format_align_<value>` — the text-alignment default) or an object\n   *   with an explicit Material Symbol icon name. Use the explicit form\n   *   when the value isn't a text alignment (e.g. MenuElement orientation:\n   *   `[{value: 'horizontal', icon: 'view_column'}, {value: 'vertical', icon: 'view_agenda'}]`).\n   *   `format_align_horizontal` is NOT a valid Material Symbol — falling\n   *   back to the ligature renders the raw uppercase text.\n   * @param {{bus?: object, elementUid?: string, formatterKey?: string}} [options]\n   *   Optional D13 v5 dual-view bus wiring. When all three fields are\n   *   present and `bus` exposes `on(event, fn) → disposer` + `emit(event, payload)`\n   *   (CanvasHighlightBus contract), the control subscribes to\n   *   `formatter:change` and also emits on user clicks. Omit for callsites\n   *   whose formatter key is not shared with another surface.\n   */\n  function AlignControl(label, value, callback) {\n    var possibleValues = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ['left', 'justify', 'center', 'right'];\n    var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n    _classCallCheck(this, AlignControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n\n    // W1.1b dual-view bus wiring. _busSource is stamped on every emit so\n    // our own subscriber filter can drop self-echoes deterministically.\n    this._options = options || {};\n    this._busOff = null;\n    this._busSource = 'sidebar-align-control:' + this.id;\n    this.options = possibleValues.map(function (entry) {\n      if (entry && _typeof(entry) === 'object') {\n        return {\n          icon: entry.icon,\n          value: entry.value\n        };\n      }\n      return {\n        icon: \"format_align_\".concat(entry),\n        value: entry\n      };\n    });\n    this.domNode = document.createElement(\"div\");\n    this.render();\n    this._attachBusSubscription();\n  }\n  return _createClass(AlignControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var buttons = this.options.map(function (option) {\n        var isActive = _this.value === option.value;\n        return \"\\n        <button type=\\\"button\\\"\\n                class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n                role=\\\"radio\\\"\\n                aria-checked=\\\"\").concat(isActive, \"\\\"\\n                data-value=\\\"\").concat(option.value, \"\\\"\\n                data-tooltip=\\\"\").concat(option.value, \"\\\"\\n                aria-label=\\\"\").concat(option.value, \"\\\"\\n                tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n          <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(option.icon, \"</span>\\n        </button>\\n      \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n            \").concat(buttons, \"\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      var group = this.domNode.querySelector('.bjs-segmented');\n      if (!group) return;\n      group.addEventListener('click', function (e) {\n        var btn = e.target.closest('.bjs-segmented-btn');\n        if (!btn || !group.contains(btn)) return;\n        _this2._selectValue(btn.dataset.value, {\n          focus: true\n        });\n      });\n      group.addEventListener('keydown', function (e) {\n        if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n        e.preventDefault();\n        var buttons = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n        var currentIndex = buttons.findIndex(function (b) {\n          return b.classList.contains('is-active');\n        });\n        var nextIndex = currentIndex;\n        if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n          nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n        } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n          nextIndex = (currentIndex + 1) % buttons.length;\n        } else if (e.key === 'Home') {\n          nextIndex = 0;\n        } else if (e.key === 'End') {\n          nextIndex = buttons.length - 1;\n        }\n        var nextBtn = buttons[nextIndex];\n        if (nextBtn) _this2._selectValue(nextBtn.dataset.value, {\n          focus: true\n        });\n      });\n    }\n  }, {\n    key: \"_selectValue\",\n    value: function _selectValue(value) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$focus = _ref.focus,\n        focus = _ref$focus === void 0 ? false : _ref$focus;\n      if (value === this.value) return;\n      this.value = value;\n      this._updateActiveState();\n      if (focus) {\n        var active = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n        if (active) active.focus();\n      }\n      this._fireCallback();\n      // Broadcast so inline toolbar / other subscribers mirror this user\n      // action. `source` lets our own subscriber skip the echo.\n      this._emitBus();\n    }\n  }, {\n    key: \"_updateActiveState\",\n    value: function _updateActiveState() {\n      var _this3 = this;\n      this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var isActive = btn.dataset.value === _this3.value;\n        btn.classList.toggle('is-active', isActive);\n        btn.setAttribute('aria-checked', String(isActive));\n        btn.setAttribute('tabindex', isActive ? '0' : '-1');\n      });\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    /**\n     * External entry point. Used by both legacy callers (pre-W1.1b, no\n     * `options`) and the W1.1b bus subscriber (with `{ silent: true }` so\n     * the subscribed-side mirror does NOT refire the callback — otherwise\n     * the formatter would be written twice and any future subscriber would\n     * see duplicate emits.\n     *\n     * Legacy callsite contract is preserved: a bare `setValue(x)` still\n     * fires the callback exactly as before.\n     */\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref2$silent = _ref2.silent,\n        silent = _ref2$silent === void 0 ? false : _ref2$silent;\n      if (newValue === this.value) return;\n      this.value = newValue;\n      this._updateActiveState();\n      if (silent) return;\n      this._fireCallback();\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n\n    /** Control teardown — drops the bus subscription. Called by\n     *  `Builder.renderElementControls` (Phase 1.8 SA I14) on sidebar rebuild. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._busOff) {\n        this._busOff();\n        this._busOff = null;\n      }\n    }\n\n    // ─── private ──────────────────────────────────────────────────────────\n  }, {\n    key: \"_fireCallback\",\n    value: function _fireCallback() {\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n  }, {\n    key: \"_attachBusSubscription\",\n    value: function _attachBusSubscription() {\n      var _this4 = this;\n      var _this$_options = this._options,\n        bus = _this$_options.bus,\n        elementUid = _this$_options.elementUid,\n        formatterKey = _this$_options.formatterKey;\n      if (!bus || !elementUid || !formatterKey) return;\n      if (typeof bus.on !== 'function') return;\n      this._busOff = bus.on('formatter:change', function (payload) {\n        if (!payload) return;\n        if (payload.elementUid !== elementUid) return;\n        if (payload.key !== formatterKey) return;\n        if (payload.source === _this4._busSource) return;\n        // Silent setValue — UI updates, callback does NOT fire (the other\n        // surface already wrote the formatter; refiring would double-write\n        // and re-broadcast causing an emit storm).\n        _this4.setValue(payload.value, {\n          silent: true\n        });\n      });\n    }\n  }, {\n    key: \"_emitBus\",\n    value: function _emitBus() {\n      var _this$_options2 = this._options,\n        bus = _this$_options2.bus,\n        elementUid = _this$_options2.elementUid,\n        formatterKey = _this$_options2.formatterKey;\n      if (!bus || !elementUid || !formatterKey) return;\n      if (typeof bus.emit !== 'function') return;\n      bus.emit('formatter:change', {\n        elementUid: elementUid,\n        key: formatterKey,\n        value: this.value,\n        source: this._busSource\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AlignControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/AlignControl.js?");

/***/ }),

/***/ "./src/includes/BJS.js":
/*!*****************************!*\
  !*** ./src/includes/BJS.js ***!
  \*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/**\n * BJS — debug namespace (Phase 1.9).\n *\n * Single entry-point for framework-internal logging. Gated by\n * `window.__bjsDebug = true` (off by default). Keeps diagnostic noise out\n * of production consoles while giving developers a one-liner to turn on\n * detailed overlay/control/element lifecycle tracing.\n *\n *   // In a DevTools console, to trace overlay lifecycle:\n *   window.__bjsDebug = true\n *\n *   // Back off:\n *   window.__bjsDebug = false\n *\n * Severity levels:\n *   - BJS.log   — lifecycle + info events (overlay mounted, listener registered)\n *   - BJS.warn  — recoverable misuse (re-entrant sync, template drift)\n *   - BJS.error — errors that were caught by an error boundary\n *\n * warn + error are ALWAYS surfaced (even when __bjsDebug is off) because\n * they're recoverable-but-noteworthy conditions users + support need to\n * see. Only `log` is debug-gated.\n */\n\nfunction dbg() {\n  return typeof window !== 'undefined' && window.__bjsDebug === true;\n}\nvar BJS = {\n  log: function log(tag) {\n    var _console;\n    if (!dbg()) return;\n    // eslint-disable-next-line no-console\n    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n      args[_key - 1] = arguments[_key];\n    }\n    (_console = console).log.apply(_console, [\"[bjs] \".concat(tag)].concat(args));\n  },\n  warn: function warn(tag) {\n    var _console2;\n    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n      args[_key2 - 1] = arguments[_key2];\n    }\n    // eslint-disable-next-line no-console\n    (_console2 = console).warn.apply(_console2, [\"[bjs] \".concat(tag)].concat(args));\n  },\n  error: function error(tag) {\n    var _console3;\n    for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n      args[_key3 - 1] = arguments[_key3];\n    }\n    // eslint-disable-next-line no-console\n    (_console3 = console).error.apply(_console3, [\"[bjs] \".concat(tag)].concat(args));\n  },\n  /** Wrap a fn so errors are caught + logged under `tag` instead of\n   *  propagating. Returns a function with the same signature. Useful for\n   *  user-installed callbacks (overlay render, control subscribers) where\n   *  one bug shouldn't crash the framework. */\n  safely: function safely(tag, fn) {\n    return function bjsSafeWrapper() {\n      try {\n        for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n          args[_key4] = arguments[_key4];\n        }\n        return fn.apply(this, args);\n      } catch (err) {\n        BJS.error(tag, err);\n        return undefined;\n      }\n    };\n  }\n};\n\n// Expose on window so DevTools users can enable/disable without imports.\nif (typeof window !== 'undefined') {\n  window.BJS = BJS;\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BJS);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BJS.js?");

/***/ }),

/***/ "./src/includes/BackgroundControl.js":
/*!*******************************************!*\
  !*** ./src/includes/BackgroundControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n// BackgroundControl v2 — interactive background editor.\n//\n// Sections (top → bottom, all collapsible into one panel):\n//   1. Section header (title + desc)                       — always visible\n//   2. Color                                               — swatch + hex input\n//   3. Image (live preview, drag focus, scroll zoom)       — toggle per-section\n//   4. Size (chips: Cover · Contain · Original · custom %) — image-gated\n//   5. Repeat (chips: None · Tile · Tile X · Tile Y)       — image-gated\n//   6. Gradient (type · 2 colors · angle · opacity stop)   — toggle per-section\n//   7. Effects (opacity · blend mode · filter sliders)     — toggle per-section\n//   8. Reset button\n//\n// Public API (backward compatible — existing 12 consumer elements keep working):\n//   new BackgroundControl(label, values, callback, options)\n//   callback.setBackground(values) — receives composed values\n//   values shape IN: { color, image, size, position, toRepeat,\n//                      opacity?, blendMode?, filter?, gradient? }\n//   values shape OUT (getValues): same + internalPosition, posX%, posY%\n//                                 image IS COMPOSED (gradient + url) when gradient is on\n//\n// CSS namespace: .bbg-*  (self-scoped, no Bootstrap dependency).\n//\n// Design mirrors ImageCropControl for consistency — same preview/drag/zoom/chips patterns.\n\n\n\nvar BackgroundControl = /*#__PURE__*/function () {\n  function BackgroundControl(label) {\n    var values = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, BackgroundControl);\n    this.label = label || _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.background_settings');\n    this.id = '_bbg_' + Math.random().toString(36).substr(2, 9);\n    this.callback = callback;\n\n    // Feature flags — all on by default. Consumers can pass options.features\n    // (array) to hide sections, e.g. { features: ['color','image','repeat'] }.\n    var DEFAULT_FEATURES = ['color', 'image', 'size', 'repeat', 'gradient', 'effects'];\n    this.features = Array.isArray(options.features) && options.features.length ? options.features : DEFAULT_FEATURES;\n\n    // Flatten consumer values into our state.\n    this.state = this._normalizeIn(values);\n    this.domNode = document.createElement('div');\n    this.domNode.className = 'BackgroundControl bbg-root';\n    this._dragging = false;\n    this._lastFocusedField = null;\n    this.render();\n  }\n\n  // -------------------- input/output helpers --------------------\n  return _createClass(BackgroundControl, [{\n    key: \"_normalizeIn\",\n    value: function _normalizeIn(values) {\n      // position \"top-left\" / \"center\" → internal form + posX%/posY%\n      var pos = values.position || 'center';\n      var posX = values.posX !== undefined ? this._clampPct(values.posX) : this._posToPct(pos, 'x');\n      var posY = values.posY !== undefined ? this._clampPct(values.posY) : this._posToPct(pos, 'y');\n\n      // Detect if the incoming `image` was a composite (gradient or url).\n      // We extract the raw URL (if any) for the Image section preview/input,\n      // keeping the control truthful about what's actually persisted.\n      var rawImg = this._extractImageUrl(values.image);\n\n      // Gradient: either explicit `gradient` object or parsed from `image` if it's a gradient.\n      var gradient = values.gradient && _typeof(values.gradient) === 'object' ? this._normalizeGradient(values.gradient) : this._parseGradientFromImage(values.image) || this._defaultGradient();\n      return {\n        color: values.color || '',\n        image: rawImg,\n        sizeMode: this._sizeMode(values.size),\n        // 'cover' | 'contain' | 'custom'\n        sizePct: this._sizePct(values.size),\n        // 10-400 when mode=custom\n        posX: posX,\n        posY: posY,\n        repeat: this._normalizeRepeat(values),\n        opacity: values.opacity === undefined || values.opacity === null ? 100 : this._clampPct(values.opacity),\n        blendMode: values.blendMode || 'normal',\n        filter: this._normalizeFilter(values.filter),\n        gradient: gradient\n      };\n    }\n  }, {\n    key: \"_sizeMode\",\n    value: function _sizeMode(v) {\n      if (v === 'cover' || v === 'contain') return v;\n      return 'custom';\n    }\n  }, {\n    key: \"_sizePct\",\n    value: function _sizePct(v) {\n      if (typeof v === 'number') return Math.max(10, Math.min(400, v));\n      if (typeof v === 'string') {\n        if (v === 'cover' || v === 'contain') return 100;\n        var n = parseInt(String(v).replace('%', ''), 10);\n        return Number.isFinite(n) ? Math.max(10, Math.min(400, n)) : 100;\n      }\n      return 100;\n    }\n  }, {\n    key: \"_normalizeRepeat\",\n    value: function _normalizeRepeat(values) {\n      // Legacy: toRepeat:true/false. Modern: repeat:'no-repeat'|'repeat'|'repeat-x'|'repeat-y'\n      if (values.repeat) return values.repeat;\n      return values.toRepeat ? 'repeat' : 'no-repeat';\n    }\n  }, {\n    key: \"_normalizeFilter\",\n    value: function _normalizeFilter(f) {\n      var def = {\n        blur: 0,\n        brightness: 100,\n        contrast: 100,\n        saturate: 100,\n        grayscale: 0\n      };\n      if (!f || _typeof(f) !== 'object') return def;\n      return {\n        blur: this._clampN(f.blur, 0, 20, 0),\n        brightness: this._clampN(f.brightness, 0, 200, 100),\n        contrast: this._clampN(f.contrast, 0, 200, 100),\n        saturate: this._clampN(f.saturate, 0, 200, 100),\n        grayscale: this._clampN(f.grayscale, 0, 100, 0)\n      };\n    }\n  }, {\n    key: \"_normalizeGradient\",\n    value: function _normalizeGradient(g) {\n      return {\n        enabled: !!g.enabled,\n        type: g.type === 'radial' ? 'radial' : 'linear',\n        angle: this._clampN(g.angle, 0, 360, 180),\n        color1: g.color1 || '#ffffff',\n        color2: g.color2 || '#000000',\n        stop1: this._clampN(g.stop1, 0, 100, 0),\n        stop2: this._clampN(g.stop2, 0, 100, 100)\n      };\n    }\n  }, {\n    key: \"_defaultGradient\",\n    value: function _defaultGradient() {\n      return {\n        enabled: false,\n        type: 'linear',\n        angle: 180,\n        color1: '#8b5cf6',\n        color2: '#ec4899',\n        stop1: 0,\n        stop2: 100\n      };\n    }\n  }, {\n    key: \"_parseGradientFromImage\",\n    value: function _parseGradientFromImage(img) {\n      if (typeof img !== 'string') return null;\n      var m = img.trim().match(/^(linear|radial)-gradient\\s*\\(([^)]*)\\)/i);\n      if (!m) return null;\n      var type = m[1].toLowerCase();\n      var inner = m[2];\n      // linear-gradient(180deg, #aaa 0%, #bbb 100%)   — best-effort parse\n      var parts = inner.split(',').map(function (s) {\n        return s.trim();\n      });\n      var g = this._defaultGradient();\n      g.enabled = true;\n      g.type = type === 'radial' ? 'radial' : 'linear';\n      if (type === 'linear' && parts.length >= 3 && /deg|rad|turn/.test(parts[0])) {\n        var ang = parseFloat(parts[0]);\n        if (Number.isFinite(ang)) g.angle = (ang % 360 + 360) % 360;\n        parts.shift();\n      }\n      if (parts[0]) {\n        var _this$_splitStop = this._splitStop(parts[0]),\n          _this$_splitStop2 = _slicedToArray(_this$_splitStop, 2),\n          c = _this$_splitStop2[0],\n          p = _this$_splitStop2[1];\n        if (c) g.color1 = c;\n        if (p !== null) g.stop1 = p;\n      }\n      if (parts[1]) {\n        var _this$_splitStop3 = this._splitStop(parts[1]),\n          _this$_splitStop4 = _slicedToArray(_this$_splitStop3, 2),\n          _c = _this$_splitStop4[0],\n          _p = _this$_splitStop4[1];\n        if (_c) g.color2 = _c;\n        if (_p !== null) g.stop2 = _p;\n      }\n      return g;\n    }\n  }, {\n    key: \"_splitStop\",\n    value: function _splitStop(str) {\n      var m = str.match(/^(\\S+)\\s*(\\d+)%$/);\n      if (m) return [m[1], parseInt(m[2], 10)];\n      return [str, null];\n    }\n  }, {\n    key: \"_extractImageUrl\",\n    value: function _extractImageUrl(img) {\n      if (!img || typeof img !== 'string') return '';\n      var trimmed = img.trim();\n      // If it's purely a gradient (no url(...)), image URL is empty.\n      if (/^(linear|radial|conic)-gradient\\s*\\(/i.test(trimmed) && !/\\burl\\s*\\(/i.test(trimmed)) {\n        return '';\n      }\n      // Extract url(...) if present. Take the LAST url() (composite \"grad, url(...)\" has url at end).\n      var urls = _toConsumableArray(trimmed.matchAll(/url\\s*\\(\\s*(['\"]?)([^'\")]+)\\1\\s*\\)/gi));\n      if (urls.length) return urls[urls.length - 1][2];\n      return trimmed;\n    }\n  }, {\n    key: \"_clampN\",\n    value: function _clampN(v, min, max, def) {\n      var n = parseFloat(v);\n      if (!Number.isFinite(n)) return def;\n      return Math.max(min, Math.min(max, n));\n    }\n  }, {\n    key: \"_clampPct\",\n    value: function _clampPct(v) {\n      var n = parseFloat(v);\n      if (!Number.isFinite(n)) return 50;\n      return Math.max(0, Math.min(100, n));\n    }\n  }, {\n    key: \"_posToPct\",\n    value: function _posToPct(pos, axis) {\n      var s = String(pos || '').trim();\n      // Percent form: \"33% 67%\" / \"50% 50%\" — split into X then Y\n      var pctMatch = s.match(/(-?\\d+(?:\\.\\d+)?)\\s*%\\s+(-?\\d+(?:\\.\\d+)?)\\s*%/);\n      if (pctMatch) {\n        return axis === 'x' ? this._clampPct(parseFloat(pctMatch[1])) : this._clampPct(parseFloat(pctMatch[2]));\n      }\n      // Single percent (axis-specific, e.g. \"50%\") — apply to both axes\n      var single = s.match(/^(-?\\d+(?:\\.\\d+)?)\\s*%$/);\n      if (single) return this._clampPct(parseFloat(single[1]));\n      // Keyword form\n      if (axis === 'x') {\n        if (s.includes('left')) return 0;\n        if (s.includes('right')) return 100;\n        return 50;\n      }\n      if (s.includes('top')) return 0;\n      if (s.includes('bottom')) return 100;\n      return 50;\n    }\n  }, {\n    key: \"_pctToPos\",\n    value: function _pctToPos(x, y) {\n      // Snap to named keywords when at exact edges (0/50/100) for legacy compat.\n      var sx = x === 0 ? 'left' : x === 100 ? 'right' : x === 50 ? 'center' : null;\n      var sy = y === 0 ? 'top' : y === 100 ? 'bottom' : y === 50 ? 'center' : null;\n      if (sx === 'center' && sy === 'center') return 'center';\n      if (sx && sy) return \"\".concat(sy, \"-\").concat(sx);\n      // Non-snapped: emit CSS percent\n      return \"\".concat(x, \"% \").concat(y, \"%\");\n    }\n\n    // Output shape — preserves backward-compat with pre-v2 consumer callbacks.\n  }, {\n    key: \"getValues\",\n    value: function getValues() {\n      var s = this.state;\n      var cssImage = this._composeCssBackgroundImage();\n      // Emit as CSS-ready string — 'cover'/'contain' or 'N%'. This is what\n      // callers pipe straight into formatter.setFormat('background_size').\n      // (Formatter has no unit auto-add for background-size, so we commit the % here.)\n      var cssSize = s.sizeMode === 'custom' ? \"\".concat(s.sizePct, \"%\") : s.sizeMode;\n      var cssPosition = this._pctToPos(Math.round(s.posX), Math.round(s.posY));\n      var filterStr = this._composeFilter();\n      return {\n        color: s.color,\n        image: cssImage,\n        // composed (gradient + url) — legacy consumers pipe into background_image\n        rawImage: s.image,\n        // raw url (for re-hydration)\n        size: cssSize,\n        // 'cover' | 'contain' | number\n        position: cssPosition,\n        // legacy keyword form\n        internalPosition: cssPosition,\n        // back-compat alias\n        posX: Math.round(s.posX),\n        posY: Math.round(s.posY),\n        repeat: s.repeat,\n        toRepeat: s.repeat === 'repeat' || s.repeat === 'repeat-x' || s.repeat === 'repeat-y',\n        // legacy\n        opacity: s.opacity / 100,\n        // element-level opacity (0..1)\n        opacityPct: Math.round(s.opacity),\n        blendMode: s.blendMode,\n        filter: filterStr,\n        // composed CSS filter string ('' when inert)\n        filterRaw: _objectSpread({}, s.filter),\n        gradient: _objectSpread({}, s.gradient)\n      };\n    }\n  }, {\n    key: \"_composeCssBackgroundImage\",\n    value: function _composeCssBackgroundImage() {\n      var s = this.state;\n      var gradStr = s.gradient.enabled ? this._gradientCss() : '';\n      var urlStr = s.image ? \"url(\".concat(s.image, \")\") : '';\n      if (gradStr && urlStr) return \"\".concat(gradStr, \", \").concat(urlStr);\n      return gradStr || urlStr || '';\n    }\n  }, {\n    key: \"_gradientCss\",\n    value: function _gradientCss() {\n      var g = this.state.gradient;\n      var stops = \"\".concat(g.color1, \" \").concat(g.stop1, \"%, \").concat(g.color2, \" \").concat(g.stop2, \"%\");\n      if (g.type === 'radial') {\n        return \"radial-gradient(circle at center, \".concat(stops, \")\");\n      }\n      return \"linear-gradient(\".concat(g.angle, \"deg, \").concat(stops, \")\");\n    }\n  }, {\n    key: \"_composeFilter\",\n    value: function _composeFilter() {\n      var f = this.state.filter;\n      var parts = [];\n      if (f.blur > 0) parts.push(\"blur(\".concat(f.blur, \"px)\"));\n      if (f.brightness !== 100) parts.push(\"brightness(\".concat(f.brightness, \"%)\"));\n      if (f.contrast !== 100) parts.push(\"contrast(\".concat(f.contrast, \"%)\"));\n      if (f.saturate !== 100) parts.push(\"saturate(\".concat(f.saturate, \"%)\"));\n      if (f.grayscale > 0) parts.push(\"grayscale(\".concat(f.grayscale, \"%)\"));\n      return parts.join(' ');\n    }\n  }, {\n    key: \"_emit\",\n    value: function _emit() {\n      if (this.callback && typeof this.callback.setBackground === 'function') {\n        this.callback.setBackground(this.getValues());\n      }\n    }\n\n    // -------------------- URL helpers (match v1) --------------------\n  }, {\n    key: \"resolveImageUrl\",\n    value: function resolveImageUrl(url) {\n      var _this$host;\n      var n = this._normalizeImageReference(url);\n      if (!n) return '';\n      if (n.startsWith('/theme/assets/')) return n;\n      if (/^https?:\\/\\//i.test(n) || n.startsWith('/assets/') || n.startsWith('#') || n.startsWith('[') || n.startsWith('{') || n.startsWith('data:image')) return n;\n      if (typeof ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.transferMediaAbsUrl) === 'function') {\n        return this.host.transferMediaAbsUrl(n);\n      }\n      return n;\n    }\n  }, {\n    key: \"toStoredImageUrl\",\n    value: function toStoredImageUrl(url) {\n      var _this$host2;\n      var n = this._normalizeImageReference(url);\n      if (!n) return '';\n      var themed = this._extractThemeAssetPath(n);\n      if (themed) return themed;\n      if ((_this$host2 = this.host) !== null && _this$host2 !== void 0 && _this$host2.themeMediaUrl) {\n        var prefix = this.host.themeMediaUrl.replace(/\\/$/, '') + '/';\n        if (prefix !== '/' && n.startsWith(prefix)) return n.slice(prefix.length);\n      }\n      return n;\n    }\n  }, {\n    key: \"_normalizeImageReference\",\n    value: function _normalizeImageReference(url) {\n      if (!url || typeof url !== 'string') return '';\n      var v = url.trim();\n      var m = v.match(/^url\\((.*)\\)$/i);\n      if (m) v = m[1].trim();\n      return v.replace(/^['\"]|['\"]$/g, '');\n    }\n  }, {\n    key: \"_extractThemeAssetPath\",\n    value: function _extractThemeAssetPath(url) {\n      var n = this._normalizeImageReference(url);\n      if (!n) return '';\n      var m1 = n.match(/^\\/theme\\/assets\\/[^/]+\\/f\\/(.+)$/);\n      if (m1) return m1[1];\n      var m2 = n.match(/^\\/?(master|others|assets|image)\\/.+$/);\n      if (m2) return n.replace(/^\\/+/, '');\n      return '';\n    }\n\n    // -------------------- rendering --------------------\n\n    /** Builder hook — fires after host injection + DOM mount. Re-render\n     *  so resolveImageUrl() / toStoredImageUrl() can route through\n     *  this.host.transferMediaAbsUrl + this.host.themeMediaUrl now that\n     *  host is set. The constructor's initial render uses the raw stored\n     *  path as a fallback (host?.X chains gracefully) — afterRender()\n     *  upgrades the preview to the per-instance absolute URL. */\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {\n      this.render();\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var has = function has(f) {\n        return _this.features.includes(f);\n      };\n      var s = this.state;\n      var id = this.id;\n      var previewImg = this.resolveImageUrl(s.image);\n      var hasImage = !!previewImg;\n      var effectsActive = s.opacity !== 100 || s.blendMode !== 'normal' || this._composeFilter() !== '';\n      this.domNode.innerHTML = \"\\n            <style>\".concat(this._styles(), \"</style>\\n            <div class=\\\"bbg-panel\\\" id=\\\"panel_\").concat(id, \"\\\">\\n\\n                <div class=\\\"bbg-header\\\">\\n                    <div class=\\\"bbg-title\\\">\").concat(this.label, \"</div>\\n                    <div class=\\\"bbg-desc\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('background.desc'), \"</div>\\n                </div>\\n\\n                \").concat(has('color') ? \"\\n                <div class=\\\"bbg-section\\\" data-section=\\\"color\\\">\\n                    <div id=\\\"bbgColorHost_\".concat(id, \"\\\" class=\\\"bbg-color-host\\\"></div>\\n                </div>\") : '', \"\\n\\n                \").concat(has('image') ? \"\\n                <div class=\\\"bbg-section\\\" data-section=\\\"image\\\">\\n                    <div class=\\\"bbg-section-head\\\">\\n                        <span class=\\\"bbg-section-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.image'), \"</span>\\n                    </div>\\n\\n                    <div class=\\\"bbg-image-hero\\\">\\n                        <div class=\\\"bbg-preview-wrap \").concat(hasImage ? '' : 'is-empty', \"\\\" data-role=\\\"preview-wrap\\\">\\n                            <div class=\\\"bbg-preview\\\" data-role=\\\"preview\\\"\\n                                 style=\\\"\").concat(this._previewStyle(previewImg), \"\\\">\\n                                \").concat(hasImage ? \"<div class=\\\"bbg-focus-dot\\\" style=\\\"left:\".concat(s.posX, \"%; top:\").concat(s.posY, \"%;\\\"></div>\\n                                <div class=\\\"bbg-grid\\\" aria-hidden=\\\"true\\\"><span></span><span></span><span></span><span></span></div>\") : \"<div class=\\\"bbg-empty-hint\\\">\\n                                    <svg width=\\\"22\\\" height=\\\"22\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" aria-hidden=\\\"true\\\">\\n                                        <rect x=\\\"3\\\" y=\\\"5\\\" width=\\\"18\\\" height=\\\"14\\\" rx=\\\"2\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\"/>\\n                                        <circle cx=\\\"9\\\" cy=\\\"11\\\" r=\\\"1.6\\\" fill=\\\"currentColor\\\"/>\\n                                        <path d=\\\"M3 17l5-5 4 4 3-3 6 6\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\" stroke-linejoin=\\\"round\\\"/>\\n                                    </svg>\\n                                </div>\", \"\\n                            </div>\\n                        </div>\\n                        <div class=\\\"bbg-image-side\\\">\\n                            <div class=\\\"bbg-image-info\\\" data-role=\\\"image-info\\\">\\n                                <span class=\\\"bbg-image-filename \").concat(hasImage ? '' : 'is-muted', \"\\\" data-role=\\\"filename\\\">\").concat(hasImage ? '' : _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.no_image'), \"</span>\\n                                <span class=\\\"bbg-image-meta\\\" data-role=\\\"meta\\\">\").concat(hasImage ? '' : _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.no_image_hint'), \"</span>\\n                            </div>\\n                            <div class=\\\"bbg-image-actions\\\">\\n                                <button type=\\\"button\\\" class=\\\"bbg-action-btn\\\" data-action=\\\"upload\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.upload'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.upload'), \"\\\">\\n                                    <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\"><path d=\\\"M8 2v9M8 2L4 6M8 2l4 4M3 13h10\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg>\\n                                </button>\\n                                <button type=\\\"button\\\" class=\\\"bbg-action-btn\\\" data-action=\\\"paste-url\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.paste_url'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.paste_url'), \"\\\">\\n                                    <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\"><path d=\\\"M7 9a2.5 2.5 0 0 1 0-3.5l2-2a2.5 2.5 0 0 1 3.5 3.5L11 8.5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/><path d=\\\"M9 7a2.5 2.5 0 0 1 0 3.5l-2 2a2.5 2.5 0 0 1-3.5-3.5L5 7.5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/></svg>\\n                                </button>\\n                                <button type=\\\"button\\\" class=\\\"bbg-action-btn bbg-action-btn--danger \").concat(hasImage ? '' : 'is-disabled', \"\\\" data-action=\\\"remove\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.remove'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.remove'), \"\\\" \").concat(hasImage ? '' : 'disabled', \">\\n                                    <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\"><path d=\\\"M3 5h10M6 5V3h4v2M5 5l1 9h4l1-9\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg>\\n                                </button>\\n                            </div>\\n                        </div>\\n                    </div>\\n\\n                    <div class=\\\"bbg-url-row \").concat(this._urlRowVisible ? 'is-open' : 'is-hidden', \"\\\" data-role=\\\"url-row\\\">\\n                        <input type=\\\"text\\\" class=\\\"bbg-url-input\\\" data-role=\\\"url\\\"\\n                               placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.enter_url'), \"\\\"\\n                               value=\\\"\").concat(hasImage ? this.toStoredImageUrl(s.image) : '', \"\\\">\\n                    </div>\\n\\n                    \").concat(has('size') ? \"\\n                    <div class=\\\"bbg-sub\\\" \".concat(hasImage ? '' : 'hidden', \" data-role=\\\"size-sub\\\">\\n                        <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size'), \"</div>\\n                        <div class=\\\"bbg-chips\\\" data-role=\\\"size-chips\\\">\\n                            \").concat(this._sizeChipsHtml(), \"\\n                        </div>\\n                        <div class=\\\"bbg-row \").concat(s.sizeMode === 'custom' ? '' : 'is-muted', \"\\\" data-role=\\\"size-custom\\\">\\n                            <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size_custom'), \"</label>\\n                            <div class=\\\"bbg-slider-wrap\\\">\\n                                <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"sizePct\\\"\\n                                       min=\\\"10\\\" max=\\\"400\\\" step=\\\"1\\\" value=\\\"\").concat(s.sizePct, \"\\\"\\n                                       style=\\\"--pct:\").concat((s.sizePct - 10) / (400 - 10) * 100, \"%\\\">\\n                            </div>\\n                            <div class=\\\"bbg-value-wrap\\\">\\n                                <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"sizePct-num\\\"\\n                                       min=\\\"10\\\" max=\\\"400\\\" step=\\\"1\\\" value=\\\"\").concat(s.sizePct, \"\\\">\\n                                <span class=\\\"bbg-unit\\\">%</span>\\n                            </div>\\n                        </div>\\n                    </div>\") : '', \"\\n\\n                    <div class=\\\"bbg-sub\\\" \").concat(hasImage ? '' : 'hidden', \" data-role=\\\"position-sub\\\">\\n                        <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.focus'), \"</div>\\n                        <div class=\\\"bbg-row\\\">\\n                            <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.focus_x'), \"</label>\\n                            <div class=\\\"bbg-slider-wrap\\\">\\n                                <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"posX\\\"\\n                                       min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.posX, \"\\\"\\n                                       style=\\\"--pct:\").concat(s.posX, \"%\\\">\\n                            </div>\\n                            <div class=\\\"bbg-value-wrap\\\">\\n                                <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"posX-num\\\"\\n                                       min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(Math.round(s.posX), \"\\\">\\n                                <span class=\\\"bbg-unit\\\">%</span>\\n                            </div>\\n                        </div>\\n                        <div class=\\\"bbg-row\\\">\\n                            <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.focus_y'), \"</label>\\n                            <div class=\\\"bbg-slider-wrap\\\">\\n                                <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"posY\\\"\\n                                       min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.posY, \"\\\"\\n                                       style=\\\"--pct:\").concat(s.posY, \"%\\\">\\n                            </div>\\n                            <div class=\\\"bbg-value-wrap\\\">\\n                                <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"posY-num\\\"\\n                                       min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(Math.round(s.posY), \"\\\">\\n                                <span class=\\\"bbg-unit\\\">%</span>\\n                            </div>\\n                        </div>\\n                    </div>\\n\\n                    \").concat(has('repeat') ? \"\\n                    <div class=\\\"bbg-sub\\\" \".concat(hasImage ? '' : 'hidden', \" data-role=\\\"repeat-sub\\\">\\n                        <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat'), \"</div>\\n                        <div class=\\\"bbg-chips\\\" data-role=\\\"repeat-chips\\\">\\n                            \").concat(this._repeatChipsHtml(), \"\\n                        </div>\\n                    </div>\") : '', \"\\n                </div>\") : '', \"\\n\\n                \").concat(has('gradient') ? \"\\n                <div class=\\\"bbg-section\\\" data-section=\\\"gradient\\\">\\n                    <div class=\\\"bbg-section-head\\\">\\n                        <span class=\\\"bbg-section-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient'), \"</span>\\n                        <label class=\\\"bbg-toggle\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_hint'), \"\\\">\\n                            <input type=\\\"checkbox\\\" class=\\\"bbg-toggle-input\\\" data-role=\\\"gradient-toggle\\\" \").concat(s.gradient.enabled ? 'checked' : '', \">\\n                            <span class=\\\"bbg-toggle-slider\\\"></span>\\n                        </label>\\n                    </div>\\n                    <div class=\\\"bbg-sub-body\\\" \").concat(s.gradient.enabled ? '' : 'hidden', \" data-role=\\\"gradient-body\\\">\\n                        <div class=\\\"bbg-gradient-preview\\\" data-role=\\\"gradient-preview\\\"\\n                             style=\\\"background:\").concat(this._gradientCss(), \";\\\"></div>\\n\\n                        <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_type'), \"</div>\\n                        <div class=\\\"bbg-chips\\\" data-role=\\\"gradient-type-chips\\\">\\n                            <button type=\\\"button\\\" class=\\\"bbg-chip \").concat(s.gradient.type === 'linear' ? 'is-active' : '', \"\\\" data-gtype=\\\"linear\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_linear'), \"</button>\\n                            <button type=\\\"button\\\" class=\\\"bbg-chip \").concat(s.gradient.type === 'radial' ? 'is-active' : '', \"\\\" data-gtype=\\\"radial\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_radial'), \"</button>\\n                        </div>\\n\\n                        <div class=\\\"bbg-row \").concat(s.gradient.type === 'linear' ? '' : 'is-muted', \"\\\" data-role=\\\"gradient-angle-row\\\">\\n                            <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_angle'), \"</label>\\n                            <div class=\\\"bbg-slider-wrap\\\">\\n                                <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"gradient-angle\\\"\\n                                       min=\\\"0\\\" max=\\\"360\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.angle, \"\\\"\\n                                       style=\\\"--pct:\").concat(s.gradient.angle / 360 * 100, \"%\\\">\\n                            </div>\\n                            <div class=\\\"bbg-value-wrap\\\">\\n                                <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"gradient-angle-num\\\"\\n                                       min=\\\"0\\\" max=\\\"360\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.angle, \"\\\">\\n                                <span class=\\\"bbg-unit\\\">\\xB0</span>\\n                            </div>\\n                        </div>\\n\\n                        <div class=\\\"bbg-gradient-stops\\\">\\n                            <div class=\\\"bbg-gradient-stop\\\">\\n                                <div class=\\\"bbg-stop-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_color_1'), \"</div>\\n                                <div class=\\\"bbg-stop-row\\\">\\n                                    <label class=\\\"bbg-swatch-wrap\\\">\\n                                        <input type=\\\"color\\\" class=\\\"bbg-swatch-input\\\" data-role=\\\"gradient-color1\\\" value=\\\"\").concat(s.gradient.color1, \"\\\">\\n                                        <span class=\\\"bbg-swatch\\\" style=\\\"background:\").concat(s.gradient.color1, \";\\\"></span>\\n                                    </label>\\n                                    <input type=\\\"text\\\" class=\\\"bbg-hex-input\\\" data-role=\\\"gradient-color1-hex\\\" value=\\\"\").concat(s.gradient.color1, \"\\\">\\n                                    <input type=\\\"number\\\" class=\\\"bbg-value-input bbg-value-input--mini\\\" data-role=\\\"gradient-stop1\\\" min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.stop1, \"\\\">\\n                                    <span class=\\\"bbg-unit\\\">%</span>\\n                                </div>\\n                            </div>\\n                            <div class=\\\"bbg-gradient-stop\\\">\\n                                <div class=\\\"bbg-stop-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_color_2'), \"</div>\\n                                <div class=\\\"bbg-stop-row\\\">\\n                                    <label class=\\\"bbg-swatch-wrap\\\">\\n                                        <input type=\\\"color\\\" class=\\\"bbg-swatch-input\\\" data-role=\\\"gradient-color2\\\" value=\\\"\").concat(s.gradient.color2, \"\\\">\\n                                        <span class=\\\"bbg-swatch\\\" style=\\\"background:\").concat(s.gradient.color2, \";\\\"></span>\\n                                    </label>\\n                                    <input type=\\\"text\\\" class=\\\"bbg-hex-input\\\" data-role=\\\"gradient-color2-hex\\\" value=\\\"\").concat(s.gradient.color2, \"\\\">\\n                                    <input type=\\\"number\\\" class=\\\"bbg-value-input bbg-value-input--mini\\\" data-role=\\\"gradient-stop2\\\" min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.gradient.stop2, \"\\\">\\n                                    <span class=\\\"bbg-unit\\\">%</span>\\n                                </div>\\n                            </div>\\n                        </div>\\n\\n                        <div class=\\\"bbg-gradient-presets\\\">\\n                            <div class=\\\"bbg-sub-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.gradient_presets'), \"</div>\\n                            <div class=\\\"bbg-preset-grid\\\" data-role=\\\"gradient-preset-grid\\\">\\n                                \").concat(this._gradientPresetsHtml(), \"\\n                            </div>\\n                        </div>\\n                    </div>\\n                </div>\") : '', \"\\n\\n                \").concat(has('effects') ? \"\\n                <div class=\\\"bbg-section\\\" data-section=\\\"effects\\\">\\n                    <div class=\\\"bbg-section-head\\\">\\n                        <span class=\\\"bbg-section-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.effects'), \"</span>\\n                        \").concat(effectsActive ? \"<span class=\\\"bbg-active-pill\\\" data-tooltip=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.effects_active'), \"\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.active'), \"</span>\") : '', \"\\n                    </div>\\n                    <div class=\\\"bbg-info\\\">\\n                        <span class=\\\"bbg-info-icon\\\" aria-hidden=\\\"true\\\">\\n                            <svg width=\\\"13\\\" height=\\\"13\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\"><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\"/><path d=\\\"M12 8v5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\" stroke-linecap=\\\"round\\\"/><circle cx=\\\"12\\\" cy=\\\"16.2\\\" r=\\\"1\\\" fill=\\\"currentColor\\\"/></svg>\\n                        </span>\\n                        <span class=\\\"bbg-info-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.effects_email_warning'), \"</span>\\n                    </div>\\n\\n                    <div class=\\\"bbg-row\\\">\\n                        <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.opacity'), \"</label>\\n                        <div class=\\\"bbg-slider-wrap\\\">\\n                            <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"opacity\\\"\\n                                   min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(s.opacity, \"\\\"\\n                                   style=\\\"--pct:\").concat(s.opacity, \"%\\\">\\n                        </div>\\n                        <div class=\\\"bbg-value-wrap\\\">\\n                            <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"opacity-num\\\"\\n                                   min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(Math.round(s.opacity), \"\\\">\\n                            <span class=\\\"bbg-unit\\\">%</span>\\n                        </div>\\n                    </div>\\n\\n                    <div class=\\\"bbg-row\\\">\\n                        <label class=\\\"bbg-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.blend_mode'), \"</label>\\n                        <select class=\\\"bbg-select\\\" data-role=\\\"blendMode\\\">\\n                            \").concat(this._blendOptionsHtml(), \"\\n                        </select>\\n                    </div>\\n\\n                    \").concat(['blur', 'brightness', 'contrast', 'saturate', 'grayscale'].map(function (k) {\n        return _this._filterRowHtml(k);\n      }).join(''), \"\\n\\n                    <div class=\\\"bbg-actions\\\">\\n                        <button type=\\\"button\\\" class=\\\"bbg-text-btn\\\" data-action=\\\"reset-effects\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.reset_effects'), \"</button>\\n                    </div>\\n                </div>\") : '', \"\\n\\n                <div class=\\\"bbg-footer\\\">\\n                    <button type=\\\"button\\\" class=\\\"bbg-reset-all\\\" data-action=\\\"reset-all\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.reset_all'), \"\\\">\\n                        <svg width=\\\"11\\\" height=\\\"11\\\" viewBox=\\\"0 0 12 12\\\" fill=\\\"none\\\"><path d=\\\"M2 6a4 4 0 1 0 1.2-2.83\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/><path d=\\\"M2 2v3h3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg>\\n                        \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.reset_all'), \"\\n                    </button>\\n                </div>\\n            </div>\\n        \");\n      this._mountColorPicker();\n      this._attachListeners();\n      if (hasImage) this._updateImageMeta(this.resolveImageUrl(s.image));\n    }\n  }, {\n    key: \"_previewStyle\",\n    value: function _previewStyle(previewImg) {\n      var s = this.state;\n      if (!previewImg) return 'background:repeating-conic-gradient(#eef2f7 0% 25%, #fff 0% 50%) 50% / 16px 16px;';\n      var sz = s.sizeMode === 'custom' ? \"\".concat(s.sizePct, \"%\") : s.sizeMode;\n      return [\"background-image:url('\".concat(previewImg, \"')\"), \"background-repeat:\".concat(s.repeat), \"background-size:\".concat(sz), \"background-position:\".concat(s.posX, \"% \").concat(s.posY, \"%\")].join(';');\n    }\n  }, {\n    key: \"_sizeChipsHtml\",\n    value: function _sizeChipsHtml() {\n      var s = this.state;\n      var presets = [{\n        mode: 'cover',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size_cover')\n      }, {\n        mode: 'contain',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.size_contain')\n      }, {\n        mode: 'custom',\n        pct: 50,\n        label: '50%'\n      }, {\n        mode: 'custom',\n        pct: 100,\n        label: '100%'\n      }, {\n        mode: 'custom',\n        pct: 150,\n        label: '150%'\n      }, {\n        mode: 'custom',\n        pct: 200,\n        label: '200%'\n      }];\n      return presets.map(function (p) {\n        var isActive = p.mode === 'cover' || p.mode === 'contain' ? s.sizeMode === p.mode : s.sizeMode === 'custom' && s.sizePct === p.pct;\n        var dataAttrs = p.mode === 'custom' ? \"data-size-mode=\\\"custom\\\" data-size-pct=\\\"\".concat(p.pct, \"\\\"\") : \"data-size-mode=\\\"\".concat(p.mode, \"\\\"\");\n        return \"<button type=\\\"button\\\" class=\\\"bbg-chip\".concat(isActive ? ' is-active' : '', \"\\\" \").concat(dataAttrs, \">\").concat(p.label, \"</button>\");\n      }).join('');\n    }\n  }, {\n    key: \"_repeatChipsHtml\",\n    value: function _repeatChipsHtml() {\n      var s = this.state;\n      var presets = [{\n        v: 'no-repeat',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_none'),\n        icon: 'M4 4h8v8H4z'\n      }, {\n        v: 'repeat',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_tile'),\n        icon: 'M2 2h5v5H2zM9 2h5v5H9zM2 9h5v5H2zM9 9h5v5H9z'\n      }, {\n        v: 'repeat-x',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_x'),\n        icon: 'M2 5h4v6H2zM7 5h4v6H7zM12 5h4v6h-4z'\n      }, {\n        v: 'repeat-y',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.repeat_y'),\n        icon: 'M5 2h6v4H5zM5 7h6v4H5zM5 12h6v4H5z'\n      }];\n      return presets.map(function (p) {\n        var isActive = s.repeat === p.v;\n        return \"<button type=\\\"button\\\" class=\\\"bbg-chip bbg-chip--icon\".concat(isActive ? ' is-active' : '', \"\\\" data-repeat=\\\"\").concat(p.v, \"\\\" data-tooltip=\\\"\").concat(p.label, \"\\\">\\n                <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"currentColor\\\" aria-hidden=\\\"true\\\"><path d=\\\"\").concat(p.icon, \"\\\"/></svg>\\n                <span>\").concat(p.label, \"</span>\\n            </button>\");\n      }).join('');\n    }\n  }, {\n    key: \"_gradientPresetsHtml\",\n    value: function _gradientPresetsHtml() {\n      var presets = [{\n        c1: '#8b5cf6',\n        c2: '#ec4899',\n        angle: 180\n      },\n      // purple-pink\n      {\n        c1: '#3b82f6',\n        c2: '#06b6d4',\n        angle: 135\n      },\n      // blue-cyan\n      {\n        c1: '#f59e0b',\n        c2: '#ef4444',\n        angle: 180\n      },\n      // sunset\n      {\n        c1: '#10b981',\n        c2: '#3b82f6',\n        angle: 180\n      },\n      // emerald-blue\n      {\n        c1: '#0f172a',\n        c2: '#334155',\n        angle: 180\n      },\n      // slate\n      {\n        c1: '#fef3c7',\n        c2: '#fb923c',\n        angle: 180\n      },\n      // cream-orange\n      {\n        c1: '#0ea5e9',\n        c2: '#6366f1',\n        angle: 225\n      },\n      // sky-indigo\n      {\n        c1: '#f9fafb',\n        c2: '#e5e7eb',\n        angle: 180\n      } // soft gray\n      ];\n      return presets.map(function (p, i) {\n        var css = \"linear-gradient(\".concat(p.angle, \"deg, \").concat(p.c1, \" 0%, \").concat(p.c2, \" 100%)\");\n        return \"<button type=\\\"button\\\" class=\\\"bbg-preset-chip\\\" data-gpreset=\\\"\".concat(i, \"\\\"\\n                data-gc1=\\\"\").concat(p.c1, \"\\\" data-gc2=\\\"\").concat(p.c2, \"\\\" data-gangle=\\\"\").concat(p.angle, \"\\\"\\n                style=\\\"background:\").concat(css, \";\\\" data-tooltip=\\\"\").concat(p.c1, \" \\u2192 \").concat(p.c2, \"\\\"></button>\");\n      }).join('');\n    }\n  }, {\n    key: \"_blendOptionsHtml\",\n    value: function _blendOptionsHtml() {\n      var _this2 = this;\n      var modes = ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'soft-light', 'hard-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity'];\n      return modes.map(function (m) {\n        return \"<option value=\\\"\".concat(m, \"\\\" \").concat(_this2.state.blendMode === m ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.blend_' + m.replace('-', '_')), \"</option>\");\n      }).join('');\n    }\n  }, {\n    key: \"_filterRowHtml\",\n    value: function _filterRowHtml(role) {\n      var s = this.state;\n      var cfg = {\n        blur: {\n          min: 0,\n          max: 20,\n          step: 0.5,\n          unit: 'px',\n          def: 0\n        },\n        brightness: {\n          min: 0,\n          max: 200,\n          step: 1,\n          unit: '%',\n          def: 100\n        },\n        contrast: {\n          min: 0,\n          max: 200,\n          step: 1,\n          unit: '%',\n          def: 100\n        },\n        saturate: {\n          min: 0,\n          max: 200,\n          step: 1,\n          unit: '%',\n          def: 100\n        },\n        grayscale: {\n          min: 0,\n          max: 100,\n          step: 1,\n          unit: '%',\n          def: 0\n        }\n      }[role];\n      var v = s.filter[role];\n      var pct = (v - cfg.min) / (cfg.max - cfg.min) * 100;\n      return \"\\n            <div class=\\\"bbg-row\\\">\\n                <label class=\\\"bbg-row-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.filter_' + role), \"</label>\\n                <div class=\\\"bbg-slider-wrap\\\">\\n                    <input type=\\\"range\\\" class=\\\"bbg-slider\\\" data-role=\\\"filter-\").concat(role, \"\\\"\\n                           min=\\\"\").concat(cfg.min, \"\\\" max=\\\"\").concat(cfg.max, \"\\\" step=\\\"\").concat(cfg.step, \"\\\" value=\\\"\").concat(v, \"\\\"\\n                           style=\\\"--pct:\").concat(pct, \"%\\\">\\n                </div>\\n                <div class=\\\"bbg-value-wrap\\\">\\n                    <input type=\\\"number\\\" class=\\\"bbg-value-input\\\" data-role=\\\"filter-\").concat(role, \"-num\\\"\\n                           min=\\\"\").concat(cfg.min, \"\\\" max=\\\"\").concat(cfg.max, \"\\\" step=\\\"\").concat(cfg.step, \"\\\" value=\\\"\").concat(v, \"\\\">\\n                    <span class=\\\"bbg-unit\\\">\").concat(cfg.unit, \"</span>\\n                </div>\\n            </div>\");\n    }\n  }, {\n    key: \"_mountColorPicker\",\n    value: function _mountColorPicker() {\n      var _this3 = this;\n      var host = this.domNode.querySelector(\"#bbgColorHost_\".concat(this.id));\n      if (!host) return;\n      this.colorPicker = new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.color'), this.state.color, function (newColor) {\n        _this3.state.color = newColor || '';\n        _this3._emit();\n      });\n      host.appendChild(this.colorPicker.domNode);\n    }\n\n    // -------------------- listeners --------------------\n  }, {\n    key: \"_attachListeners\",\n    value: function _attachListeners() {\n      var _this4 = this;\n      var root = this.domNode;\n      var q = function q(sel) {\n        return root.querySelector(sel);\n      };\n      var qa = function qa(sel) {\n        return root.querySelectorAll(sel);\n      };\n\n      // --- Image actions ---\n      var uploadBtn = q('[data-action=\"upload\"]');\n      if (uploadBtn) uploadBtn.addEventListener('click', function () {\n        return _this4._promptFileUpload();\n      });\n      var pasteBtn = q('[data-action=\"paste-url\"]');\n      if (pasteBtn) pasteBtn.addEventListener('click', function () {\n        return _this4._toggleUrlRow();\n      });\n      var removeBtn = q('[data-action=\"remove\"]');\n      if (removeBtn) removeBtn.addEventListener('click', function () {\n        return _this4._removeImage();\n      });\n      var urlInput = q('[data-role=\"url\"]');\n      if (urlInput) {\n        var t = null;\n        urlInput.addEventListener('input', function (e) {\n          _this4.state.image = e.target.value;\n          clearTimeout(t);\n          t = setTimeout(function () {\n            _this4._softRefreshImage();\n            _this4._emit();\n          }, 300);\n        });\n        urlInput.addEventListener('blur', function () {\n          _this4._softRefreshImage();\n          _this4._emit();\n        });\n      }\n\n      // --- Preview drag + wheel ---\n      this._wirePreviewDrag();\n\n      // --- Size chips ---\n      qa('[data-role=\"size-chips\"] .bbg-chip').forEach(function (chip) {\n        chip.addEventListener('click', function () {\n          var mode = chip.dataset.sizeMode;\n          if (mode === 'custom') {\n            _this4.state.sizeMode = 'custom';\n            _this4.state.sizePct = parseInt(chip.dataset.sizePct, 10) || 100;\n          } else {\n            _this4.state.sizeMode = mode;\n          }\n          _this4._refreshPreview();\n          _this4._refreshSizeUi();\n          _this4._emit();\n        });\n      });\n\n      // --- Size slider ---\n      this._wireSliderRow('sizePct', function (v) {\n        _this4.state.sizeMode = 'custom';\n        _this4.state.sizePct = Math.round(v);\n        _this4._refreshPreview();\n        _this4._refreshSizeChipsActive();\n      });\n\n      // --- Focus sliders ---\n      this._wireSliderRow('posX', function (v) {\n        _this4.state.posX = Math.round(v);\n        _this4._refreshPreview();\n      });\n      this._wireSliderRow('posY', function (v) {\n        _this4.state.posY = Math.round(v);\n        _this4._refreshPreview();\n      });\n\n      // --- Repeat chips ---\n      qa('[data-role=\"repeat-chips\"] .bbg-chip').forEach(function (chip) {\n        chip.addEventListener('click', function () {\n          _this4.state.repeat = chip.dataset.repeat;\n          qa('[data-role=\"repeat-chips\"] .bbg-chip').forEach(function (c) {\n            return c.classList.toggle('is-active', c === chip);\n          });\n          _this4._refreshPreview();\n          _this4._emit();\n        });\n      });\n\n      // --- Gradient toggle ---\n      var gToggle = q('[data-role=\"gradient-toggle\"]');\n      if (gToggle) gToggle.addEventListener('change', function (e) {\n        _this4.state.gradient.enabled = e.target.checked;\n        _this4._refreshGradientBodyVisibility();\n        _this4._emit();\n      });\n\n      // --- Gradient type chips ---\n      qa('[data-role=\"gradient-type-chips\"] .bbg-chip').forEach(function (chip) {\n        chip.addEventListener('click', function () {\n          _this4.state.gradient.type = chip.dataset.gtype;\n          qa('[data-role=\"gradient-type-chips\"] .bbg-chip').forEach(function (c) {\n            return c.classList.toggle('is-active', c === chip);\n          });\n          _this4._refreshGradientPreview();\n          _this4._refreshGradientAngleRowMuted();\n          _this4._emit();\n        });\n      });\n\n      // --- Gradient angle slider ---\n      this._wireSliderRow('gradient-angle', function (v) {\n        _this4.state.gradient.angle = Math.round(v);\n        _this4._refreshGradientPreview();\n      });\n\n      // --- Gradient color swatches + hex ---\n      ['color1', 'color2'].forEach(function (which) {\n        var swatch = q(\"[data-role=\\\"gradient-\".concat(which, \"\\\"]\"));\n        var hex = q(\"[data-role=\\\"gradient-\".concat(which, \"-hex\\\"]\"));\n        var stopNum = q(\"[data-role=\\\"gradient-stop\".concat(which === 'color1' ? '1' : '2', \"\\\"]\"));\n        if (swatch) swatch.addEventListener('input', function (e) {\n          var v = e.target.value;\n          _this4.state.gradient[which] = v;\n          if (hex) hex.value = v;\n          swatch.parentElement.querySelector('.bbg-swatch').style.background = v;\n          _this4._refreshGradientPreview();\n          _this4._emit();\n        });\n        if (hex) {\n          var commit = function commit() {\n            var v = (hex.value || '').trim();\n            if (/^#?[0-9a-f]{3,8}$/i.test(v)) {\n              var normalized = v.startsWith('#') ? v : '#' + v;\n              _this4.state.gradient[which] = normalized;\n              hex.value = normalized;\n              if (swatch) swatch.value = normalized;\n              swatch.parentElement.querySelector('.bbg-swatch').style.background = normalized;\n              hex.classList.remove('is-invalid');\n              _this4._refreshGradientPreview();\n              _this4._emit();\n            } else if (v !== '') {\n              hex.classList.add('is-invalid');\n            }\n          };\n          hex.addEventListener('blur', commit);\n          hex.addEventListener('keydown', function (e) {\n            if (e.key === 'Enter') {\n              e.preventDefault();\n              commit();\n            }\n          });\n        }\n        if (stopNum) {\n          stopNum.addEventListener('input', function (e) {\n            var v = parseInt(e.target.value, 10);\n            if (!Number.isFinite(v)) return;\n            var key = which === 'color1' ? 'stop1' : 'stop2';\n            _this4.state.gradient[key] = Math.max(0, Math.min(100, v));\n            _this4._refreshGradientPreview();\n            _this4._emit();\n          });\n        }\n      });\n\n      // --- Gradient presets ---\n      qa('[data-role=\"gradient-preset-grid\"] .bbg-preset-chip').forEach(function (chip) {\n        chip.addEventListener('click', function () {\n          var c1 = chip.dataset.gc1;\n          var c2 = chip.dataset.gc2;\n          var angle = parseInt(chip.dataset.gangle, 10);\n          _this4.state.gradient.color1 = c1;\n          _this4.state.gradient.color2 = c2;\n          _this4.state.gradient.angle = Number.isFinite(angle) ? angle : 180;\n          _this4.state.gradient.stop1 = 0;\n          _this4.state.gradient.stop2 = 100;\n          _this4.state.gradient.enabled = true;\n          _this4.render();\n          _this4._emit();\n        });\n      });\n\n      // --- Opacity ---\n      this._wireSliderRow('opacity', function (v) {\n        _this4.state.opacity = Math.round(v);\n        _this4._refreshEffectsActivePill();\n      });\n\n      // --- Blend mode ---\n      var blend = q('[data-role=\"blendMode\"]');\n      if (blend) blend.addEventListener('change', function (e) {\n        _this4.state.blendMode = e.target.value;\n        _this4._refreshEffectsActivePill();\n        _this4._emit();\n      });\n\n      // --- Filter sliders ---\n      ['blur', 'brightness', 'contrast', 'saturate', 'grayscale'].forEach(function (key) {\n        _this4._wireSliderRow('filter-' + key, function (v) {\n          _this4.state.filter[key] = key === 'blur' ? Math.round(v * 10) / 10 : Math.round(v);\n          _this4._refreshEffectsActivePill();\n        });\n      });\n\n      // --- Reset buttons ---\n      var resetEffects = q('[data-action=\"reset-effects\"]');\n      if (resetEffects) resetEffects.addEventListener('click', function () {\n        _this4.state.opacity = 100;\n        _this4.state.blendMode = 'normal';\n        _this4.state.filter = _this4._normalizeFilter();\n        _this4.render();\n        _this4._emit();\n      });\n      var resetAll = q('[data-action=\"reset-all\"]');\n      if (resetAll) resetAll.addEventListener('click', function () {\n        var keepColor = _this4.state.color;\n        _this4.state = _this4._normalizeIn({\n          color: keepColor\n        });\n        _this4.render();\n        _this4._emit();\n      });\n    }\n  }, {\n    key: \"_wireSliderRow\",\n    value: function _wireSliderRow(role, onChange) {\n      var _this5 = this;\n      var slider = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"\\\"]\"));\n      var numInput = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n      if (!slider || !numInput) return;\n      var min = parseFloat(slider.min);\n      var max = parseFloat(slider.max);\n      var syncPct = function syncPct() {\n        var pct = (parseFloat(slider.value) - min) / (max - min) * 100;\n        slider.style.setProperty('--pct', pct + '%');\n      };\n      var debounce = null;\n      slider.addEventListener('input', function (e) {\n        var v = parseFloat(e.target.value);\n        numInput.value = v;\n        onChange(v);\n        syncPct();\n        clearTimeout(debounce);\n        debounce = setTimeout(function () {\n          return _this5._emit();\n        }, 80);\n      });\n      numInput.addEventListener('input', function (e) {\n        var v = parseFloat(e.target.value);\n        if (!Number.isFinite(v)) return;\n        var clamped = Math.max(min, Math.min(max, v));\n        slider.value = clamped;\n        onChange(clamped);\n        syncPct();\n        clearTimeout(debounce);\n        debounce = setTimeout(function () {\n          return _this5._emit();\n        }, 150);\n      });\n      numInput.addEventListener('blur', function (e) {\n        var v = parseFloat(e.target.value);\n        if (!Number.isFinite(v)) v = parseFloat(slider.value);\n        v = Math.max(min, Math.min(max, v));\n        slider.value = v;\n        numInput.value = v;\n        onChange(v);\n        syncPct();\n        _this5._emit();\n      });\n    }\n  }, {\n    key: \"_wirePreviewDrag\",\n    value: function _wirePreviewDrag() {\n      var _this6 = this;\n      var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n      if (!preview || !this.state.image) return;\n      var move = function move(clientX, clientY) {\n        var rect = preview.getBoundingClientRect();\n        var x = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));\n        var y = Math.max(0, Math.min(100, (clientY - rect.top) / rect.height * 100));\n        _this6.state.posX = Math.round(x);\n        _this6.state.posY = Math.round(y);\n        _this6._syncSlider('posX');\n        _this6._syncSlider('posY');\n        _this6._refreshPreview();\n      };\n      var onDown = function onDown(e) {\n        e.preventDefault();\n        _this6._dragging = true;\n        preview.classList.add('is-dragging');\n        var ev = e.touches ? e.touches[0] : e;\n        move(ev.clientX, ev.clientY);\n      };\n      var onMove = function onMove(e) {\n        if (!_this6._dragging) return;\n        var ev = e.touches ? e.touches[0] : e;\n        move(ev.clientX, ev.clientY);\n      };\n      var onUp = function onUp() {\n        if (!_this6._dragging) return;\n        _this6._dragging = false;\n        preview.classList.remove('is-dragging');\n        _this6._emit();\n      };\n      preview.addEventListener('mousedown', onDown);\n      window.addEventListener('mousemove', onMove);\n      window.addEventListener('mouseup', onUp);\n      preview.addEventListener('touchstart', onDown, {\n        passive: false\n      });\n      window.addEventListener('touchmove', onMove, {\n        passive: false\n      });\n      window.addEventListener('touchend', onUp);\n\n      // Wheel zoom → adjust sizePct\n      preview.addEventListener('wheel', function (e) {\n        e.preventDefault();\n        var delta = e.deltaY > 0 ? -10 : 10;\n        var next = Math.max(10, Math.min(400, _this6.state.sizePct + delta));\n        _this6.state.sizeMode = 'custom';\n        _this6.state.sizePct = next;\n        _this6._syncSlider('sizePct');\n        _this6._refreshSizeChipsActive();\n        _this6._refreshPreview();\n        _this6._emit();\n      }, {\n        passive: false\n      });\n    }\n  }, {\n    key: \"_syncSlider\",\n    value: function _syncSlider(role) {\n      var slider = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"\\\"]\"));\n      var numInput = this.domNode.querySelector(\"[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n      var v = role === 'sizePct' ? this.state.sizePct : this.state[role];\n      if (slider) {\n        slider.value = v;\n        var min = parseFloat(slider.min);\n        var max = parseFloat(slider.max);\n        slider.style.setProperty('--pct', (v - min) / (max - min) * 100 + '%');\n      }\n      if (numInput) numInput.value = Math.round(v);\n    }\n\n    // -------------------- structure-preserving refreshes --------------------\n  }, {\n    key: \"_refreshPreview\",\n    value: function _refreshPreview() {\n      var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n      var previewImg = this.resolveImageUrl(this.state.image);\n      if (!preview) return;\n      preview.setAttribute('style', this._previewStyle(previewImg));\n      var dot = preview.querySelector('.bbg-focus-dot');\n      if (dot) {\n        dot.style.left = this.state.posX + '%';\n        dot.style.top = this.state.posY + '%';\n      }\n    }\n  }, {\n    key: \"_refreshSizeUi\",\n    value: function _refreshSizeUi() {\n      this._refreshSizeChipsActive();\n      var custom = this.domNode.querySelector('[data-role=\"size-custom\"]');\n      if (custom) custom.classList.toggle('is-muted', this.state.sizeMode !== 'custom');\n      this._syncSlider('sizePct');\n    }\n  }, {\n    key: \"_refreshSizeChipsActive\",\n    value: function _refreshSizeChipsActive() {\n      var _this7 = this;\n      this.domNode.querySelectorAll('[data-role=\"size-chips\"] .bbg-chip').forEach(function (c) {\n        var mode = c.dataset.sizeMode;\n        var pct = parseInt(c.dataset.sizePct, 10);\n        var isActive = mode === 'custom' ? _this7.state.sizeMode === 'custom' && _this7.state.sizePct === pct : _this7.state.sizeMode === mode;\n        c.classList.toggle('is-active', !!isActive);\n      });\n    }\n  }, {\n    key: \"_refreshGradientPreview\",\n    value: function _refreshGradientPreview() {\n      var box = this.domNode.querySelector('[data-role=\"gradient-preview\"]');\n      if (box) box.style.background = this._gradientCss();\n    }\n  }, {\n    key: \"_refreshGradientBodyVisibility\",\n    value: function _refreshGradientBodyVisibility() {\n      var body = this.domNode.querySelector('[data-role=\"gradient-body\"]');\n      if (body) {\n        if (this.state.gradient.enabled) body.removeAttribute('hidden');else body.setAttribute('hidden', '');\n      }\n    }\n  }, {\n    key: \"_refreshGradientAngleRowMuted\",\n    value: function _refreshGradientAngleRowMuted() {\n      var row = this.domNode.querySelector('[data-role=\"gradient-angle-row\"]');\n      if (row) row.classList.toggle('is-muted', this.state.gradient.type !== 'linear');\n    }\n  }, {\n    key: \"_refreshEffectsActivePill\",\n    value: function _refreshEffectsActivePill() {\n      var head = this.domNode.querySelector('[data-section=\"effects\"] .bbg-section-head');\n      if (!head) return;\n      var existing = head.querySelector('.bbg-active-pill');\n      var active = this.state.opacity !== 100 || this.state.blendMode !== 'normal' || this._composeFilter() !== '';\n      if (active && !existing) {\n        var span = document.createElement('span');\n        span.className = 'bbg-active-pill';\n        span.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.active');\n        head.appendChild(span);\n      } else if (!active && existing) {\n        existing.remove();\n      }\n    }\n\n    // -------------------- image handlers --------------------\n  }, {\n    key: \"_promptFileUpload\",\n    value: function _promptFileUpload() {\n      var _this8 = this;\n      var input = document.createElement('input');\n      input.type = 'file';\n      input.accept = 'image/*';\n      input.addEventListener('change', function (e) {\n        var f = e.target.files && e.target.files[0];\n        if (!f) return;\n        var reader = new FileReader();\n        reader.onload = function () {\n          _this8.state.image = reader.result;\n          _this8.render();\n          _this8._emit();\n        };\n        reader.onerror = function () {\n          _this8._showImageError(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.image_read_failed'));\n        };\n        reader.readAsDataURL(f);\n      });\n      input.click();\n    }\n  }, {\n    key: \"_toggleUrlRow\",\n    value: function _toggleUrlRow() {\n      var row = this.domNode.querySelector('[data-role=\"url-row\"]');\n      if (!row) return;\n      this._urlRowVisible = !row.classList.contains('is-open');\n      row.classList.toggle('is-open', this._urlRowVisible);\n      row.classList.toggle('is-hidden', !this._urlRowVisible);\n      if (this._urlRowVisible) {\n        var input = row.querySelector('input');\n        if (input) input.focus();\n      }\n    }\n  }, {\n    key: \"_removeImage\",\n    value: function _removeImage() {\n      this.state.image = '';\n      this.state.posX = 50;\n      this.state.posY = 50;\n      this.render();\n      this._emit();\n    }\n  }, {\n    key: \"_softRefreshImage\",\n    value: function _softRefreshImage() {\n      // Re-render the image section without destroying focus on the URL input.\n      // We update the preview background in-place + update info row.\n      var previewWrap = this.domNode.querySelector('[data-role=\"preview-wrap\"]');\n      var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n      var subs = this.domNode.querySelectorAll('.bbg-section[data-section=\"image\"] .bbg-sub');\n      var removeBtn = this.domNode.querySelector('[data-action=\"remove\"]');\n      var hasImage = !!this.state.image;\n      if (previewWrap) previewWrap.classList.toggle('is-empty', !hasImage);\n      if (preview) preview.setAttribute('style', this._previewStyle(this.resolveImageUrl(this.state.image)));\n      subs.forEach(function (sub) {\n        if (hasImage) sub.removeAttribute('hidden');else sub.setAttribute('hidden', '');\n      });\n      if (removeBtn) {\n        removeBtn.disabled = !hasImage;\n        removeBtn.classList.toggle('is-disabled', !hasImage);\n      }\n\n      // If preview switched from empty → populated (or vice versa), the inner\n      // layout differs (empty hint vs focus dot + grid; info-text content also\n      // flips between static empty hint and dynamic filename/meta). Full\n      // re-render is required in that case; otherwise stay in-place.\n      if (preview) {\n        var hasDot = preview.querySelector('.bbg-focus-dot');\n        if (hasImage && !hasDot) this.render();else if (!hasImage && hasDot) this.render();\n      }\n      if (hasImage) this._updateImageMeta(this.resolveImageUrl(this.state.image));\n    }\n  }, {\n    key: \"_updateImageMeta\",\n    value: function () {\n      var _updateImageMeta2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(url) {\n        var filename, meta, approxBytes, res, blob, img, objUrl, rawName, ext, dims, size;\n        return _regeneratorRuntime().wrap(function _callee$(_context) {\n          while (1) switch (_context.prev = _context.next) {\n            case 0:\n              filename = this.domNode.querySelector('[data-role=\"filename\"]');\n              meta = this.domNode.querySelector('[data-role=\"meta\"]');\n              if (url) {\n                _context.next = 4;\n                break;\n              }\n              return _context.abrupt(\"return\");\n            case 4:\n              if (filename) filename.classList.remove('is-muted');\n              if (!url.startsWith('data:')) {\n                _context.next = 9;\n                break;\n              }\n              if (filename) filename.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.embedded');\n              if (meta) {\n                approxBytes = Math.ceil((url.length - url.indexOf(',') - 1) * 0.75);\n                meta.textContent = this._formatBytes(approxBytes);\n              }\n              return _context.abrupt(\"return\");\n            case 9:\n              _context.prev = 9;\n              _context.next = 12;\n              return fetch(url, {\n                credentials: 'same-origin'\n              });\n            case 12:\n              res = _context.sent;\n              if (res.ok) {\n                _context.next = 15;\n                break;\n              }\n              throw new Error('Fetch failed: ' + res.status);\n            case 15:\n              _context.next = 17;\n              return res.blob();\n            case 17:\n              blob = _context.sent;\n              img = new Image();\n              objUrl = URL.createObjectURL(blob);\n              _context.next = 22;\n              return new Promise(function (resolve, reject) {\n                img.onload = resolve;\n                img.onerror = function () {\n                  return reject(new Error('Invalid image'));\n                };\n                img.src = objUrl;\n              });\n            case 22:\n              URL.revokeObjectURL(objUrl);\n              rawName = (url.split('/').pop() || '').split('?')[0] || _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('bbg.no_image');\n              ext = (rawName.split('.').pop() || '').toUpperCase();\n              dims = \"\".concat(img.width, \"\\xD7\").concat(img.height);\n              size = this._formatBytes(blob.size);\n              if (filename) filename.textContent = decodeURIComponent(rawName);\n              if (meta) meta.textContent = ext && ext.length <= 4 ? \"\".concat(dims, \" \\xB7 \").concat(ext, \" \\xB7 \").concat(size) : \"\".concat(dims, \" \\xB7 \").concat(size);\n              _context.next = 35;\n              break;\n            case 31:\n              _context.prev = 31;\n              _context.t0 = _context[\"catch\"](9);\n              if (filename) filename.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('image.invalid_image');\n              if (meta) meta.textContent = _context.t0 && _context.t0.message || '';\n            case 35:\n            case \"end\":\n              return _context.stop();\n          }\n        }, _callee, this, [[9, 31]]);\n      }));\n      function _updateImageMeta(_x) {\n        return _updateImageMeta2.apply(this, arguments);\n      }\n      return _updateImageMeta;\n    }()\n  }, {\n    key: \"_formatBytes\",\n    value: function _formatBytes(bytes) {\n      if (!bytes || bytes < 0) return '0 B';\n      if (bytes < 1024) return \"\".concat(bytes, \" B\");\n      if (bytes < 1024 * 1024) return \"\".concat((bytes / 1024).toFixed(1), \" kB\");\n      return \"\".concat((bytes / (1024 * 1024)).toFixed(2), \" MB\");\n    }\n  }, {\n    key: \"_showImageError\",\n    value: function _showImageError(msg) {\n      var info = this.domNode.querySelector('[data-role=\"image-info\"]');\n      if (info) {\n        info.removeAttribute('hidden');\n        info.innerHTML = \"<span class=\\\"bbg-image-filename is-error\\\">\".concat(msg, \"</span>\");\n      }\n    }\n\n    // -------------------- inline styles --------------------\n  }, {\n    key: \"_styles\",\n    value: function _styles() {\n      return \"\\n            .bbg-root { font-family: inherit; }\\n            .bbg-panel { display: flex; flex-direction: column; gap: 0; padding: 0; color: #111827; }\\n            .bbg-header { padding: 12px 16px 4px; }\\n            .bbg-title { font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #374151; }\\n            .bbg-desc { font-size: 11px; color: #6b7280; margin-top: 2px; }\\n\\n            .bbg-section { padding: 10px 16px; border-top: 1px solid #f1f5f9; }\\n            .bbg-section:first-of-type { border-top: 0; }\\n            .bbg-section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 8px; }\\n            .bbg-section-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: #374151; }\\n            .bbg-sub { padding-top: 10px; margin-top: 10px; border-top: 1px dashed #eef2f7; }\\n            .bbg-sub-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; margin-bottom: 6px; }\\n            .bbg-sub-body { margin-top: 8px; }\\n\\n            /* ColorPickerControl lives inside .bbg-section (which already has\\n               padding: 10px 16px). Neutralise the nested .bjs-control-row's own\\n               padding so the row aligns flush with the section's section-label. */\\n            .bbg-color-host > * { padding: 0 !important; }\\n            .bbg-color-host .bjs-control-row { padding: 0 !important; }\\n\\n            /* Image hero \\u2014 2-column: large preview (~50%) | info + actions */\\n            .bbg-image-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: stretch; }\\n            .bbg-preview-wrap { position: relative; min-width: 0; }\\n            .bbg-preview { position: relative; width: 100%; aspect-ratio: 4/3; border-radius: 8px; overflow: hidden;\\n                border: 1px solid #e5e7eb; cursor: crosshair; user-select: none; touch-action: none; transition: border-color .15s ease;\\n                background-color: #f9fafb; }\\n            .bbg-preview:hover { border-color: #cbd5e1; }\\n            .bbg-preview.is-dragging { border-color: #3b82f6; cursor: grabbing; }\\n            .bbg-preview-wrap.is-empty .bbg-preview { cursor: default; background-image: linear-gradient(45deg, #f1f5f9 25%, transparent 25%), linear-gradient(-45deg, #f1f5f9 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f1f5f9 75%), linear-gradient(-45deg, transparent 75%, #f1f5f9 75%); background-size: 12px 12px; background-position: 0 0, 0 6px, 6px -6px, -6px 0; }\\n            .bbg-empty-hint { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #94a3b8; pointer-events: none; }\\n            .bbg-focus-dot { position: absolute; width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 3px solid #3b82f6;\\n                transform: translate(-50%, -50%); box-shadow: 0 2px 6px rgba(0,0,0,.25); pointer-events: none; transition: left .02s linear, top .02s linear; }\\n            .bbg-grid { position: absolute; inset: 0; pointer-events: none; }\\n            .bbg-grid span { position: absolute; background: rgba(255,255,255,.5); }\\n            .bbg-grid span:nth-child(1) { left: 33.333%; top: 0; width: 1px; height: 100%; }\\n            .bbg-grid span:nth-child(2) { left: 66.666%; top: 0; width: 1px; height: 100%; }\\n            .bbg-grid span:nth-child(3) { top: 33.333%; left: 0; height: 1px; width: 100%; }\\n            .bbg-grid span:nth-child(4) { top: 66.666%; left: 0; height: 1px; width: 100%; }\\n\\n            /* Side column: info on top, actions on bottom */\\n            .bbg-image-side { display: flex; flex-direction: column; justify-content: space-between; gap: 8px; min-width: 0; }\\n\\n            /* Image info \\u2014 inline, no background panel; stacks filename + meta */\\n            .bbg-image-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }\\n            .bbg-image-filename { color: #111827; font-weight: 600; font-size: 12px; line-height: 1.3;\\n                display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; word-break: break-all; }\\n            .bbg-image-filename.is-muted { color: #6b7280; font-weight: 500; }\\n            .bbg-image-filename.is-error { color: #dc2626; }\\n            .bbg-image-meta { color: #6b7280; font-family: ui-monospace, SFMono-Regular, Monaco, monospace; font-size: 10.5px; line-height: 1.3;\\n                white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\\n\\n            /* Image actions \\u2014 icon-only square buttons (labels would crowd the 50%\\n               right column; aria-label + title tooltips carry the text). */\\n            .bbg-image-actions { display: flex; gap: 6px; }\\n            .bbg-action-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center;\\n                height: 32px; border: 1px solid #e5e7eb; background: #fff; border-radius: 6px;\\n                color: #374151; cursor: pointer; transition: all .15s ease; }\\n            .bbg-action-btn:hover:not(:disabled) { border-color: #cbd5e1; background: #f9fafb; color: #111827; }\\n            .bbg-action-btn:disabled, .bbg-action-btn.is-disabled { opacity: .45; cursor: not-allowed; }\\n            .bbg-action-btn--danger:hover:not(:disabled) { color: #dc2626; border-color: #fecaca; background: #fef2f2; }\\n\\n            /* URL row */\\n            .bbg-url-row { overflow: hidden; transition: max-height .18s ease, margin-top .18s ease, opacity .18s ease; }\\n            .bbg-url-row.is-hidden { max-height: 0; margin-top: 0; opacity: 0; }\\n            .bbg-url-row.is-open { max-height: 60px; margin-top: 8px; opacity: 1; }\\n            .bbg-url-input { width: 100%; padding: 7px 10px; border: 1px solid #e5e7eb; border-radius: 6px; font-size: 12px;\\n                background: #fff; color: #111827; transition: border-color .15s ease; }\\n            .bbg-url-input:focus { outline: 0; border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,.1); }\\n\\n            /* Chips */\\n            .bbg-chips { display: flex; flex-wrap: wrap; gap: 5px; }\\n            .bbg-chip { padding: 6px 10px; border: 1px solid #e5e7eb; background: #fff; border-radius: 5px; font-size: 11px; font-weight: 500;\\n                color: #374151; cursor: pointer; transition: all .15s ease; white-space: nowrap; line-height: 1.2; }\\n            .bbg-chip:hover { border-color: #cbd5e1; background: #f9fafb; }\\n            .bbg-chip.is-active { background: #111827; border-color: #111827; color: #fff; }\\n            .bbg-chip--icon { display: inline-flex; align-items: center; gap: 5px; }\\n            .bbg-chip--icon svg { opacity: .7; }\\n            .bbg-chip.is-active svg { opacity: 1; }\\n\\n            /* Rows (slider + numeric input) */\\n            .bbg-row { display: grid; grid-template-columns: 70px 1fr 72px; align-items: center; gap: 8px; padding: 5px 0; }\\n            .bbg-row.is-muted { opacity: .4; pointer-events: none; }\\n            .bbg-row-label { font-size: 11px; color: #4b5563; font-weight: 500; }\\n            .bbg-slider-wrap { position: relative; padding: 0 2px; }\\n            .bbg-slider { width: 100%; height: 4px; border-radius: 2px; appearance: none; -webkit-appearance: none; cursor: pointer;\\n                background: linear-gradient(to right, #111827 0%, #111827 var(--pct, 0%), #e5e7eb var(--pct, 0%), #e5e7eb 100%); }\\n            .bbg-slider::-webkit-slider-thumb { appearance: none; -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;\\n                background: #fff; border: 2px solid #111827; cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.15); transition: transform .1s ease; }\\n            .bbg-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }\\n            .bbg-slider::-moz-range-thumb { width: 14px; height: 14px; border-radius: 50%; background: #fff; border: 2px solid #111827;\\n                cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.15); }\\n            .bbg-value-wrap { display: flex; align-items: center; gap: 2px; padding: 4px 6px; border: 1px solid #e5e7eb; border-radius: 5px;\\n                background: #fff; transition: border-color .15s ease; }\\n            .bbg-value-wrap:focus-within { border-color: #3b82f6; }\\n            .bbg-value-input { width: 100%; border: 0; outline: 0; background: transparent; font-size: 11px; color: #111827; padding: 0;\\n                text-align: right; font-variant-numeric: tabular-nums; }\\n            .bbg-value-input::-webkit-inner-spin-button, .bbg-value-input::-webkit-outer-spin-button { appearance: none; -webkit-appearance: none; margin: 0; }\\n            .bbg-value-input--mini { width: 40px; }\\n            .bbg-unit { font-size: 10px; color: #9ca3af; user-select: none; }\\n\\n            /* Select */\\n            .bbg-select { width: 100%; padding: 6px 10px; border: 1px solid #e5e7eb; border-radius: 5px; font-size: 11px; background: #fff;\\n                color: #111827; cursor: pointer; appearance: none; -webkit-appearance: none;\\n                background-image: url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236b7280' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E\\\");\\n                background-repeat: no-repeat; background-position: right 10px center; padding-right: 26px; }\\n            .bbg-select:focus { outline: 0; border-color: #3b82f6; }\\n\\n            /* Toggle */\\n            .bbg-toggle { position: relative; display: inline-block; width: 32px; height: 18px; cursor: pointer; flex-shrink: 0; }\\n            .bbg-toggle-input { opacity: 0; width: 0; height: 0; position: absolute; }\\n            .bbg-toggle-slider { position: absolute; inset: 0; background: #e5e7eb; border-radius: 10px; transition: background .15s ease; }\\n            .bbg-toggle-slider::before { content: ''; position: absolute; width: 14px; height: 14px; left: 2px; top: 2px;\\n                background: #fff; border-radius: 50%; transition: transform .15s ease; box-shadow: 0 1px 3px rgba(0,0,0,.2); }\\n            .bbg-toggle-input:checked + .bbg-toggle-slider { background: #111827; }\\n            .bbg-toggle-input:checked + .bbg-toggle-slider::before { transform: translateX(14px); }\\n\\n            /* Gradient */\\n            .bbg-gradient-preview { width: 100%; aspect-ratio: 8/1; min-height: 32px; border-radius: 6px; margin-bottom: 10px;\\n                border: 1px solid #e5e7eb; }\\n            .bbg-gradient-stops { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }\\n            .bbg-gradient-stop { display: flex; flex-direction: column; gap: 4px; }\\n            .bbg-stop-label { font-size: 10px; color: #6b7280; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }\\n            .bbg-stop-row { display: flex; align-items: center; gap: 6px; }\\n            .bbg-swatch-wrap { position: relative; width: 28px; height: 28px; border-radius: 5px; border: 1px solid #e5e7eb; overflow: hidden;\\n                cursor: pointer; flex-shrink: 0; }\\n            .bbg-swatch-input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; padding: 0; border: 0; }\\n            .bbg-swatch { position: absolute; inset: 0; }\\n            .bbg-hex-input { flex: 1; min-width: 0; padding: 5px 8px; border: 1px solid #e5e7eb; border-radius: 5px; font-size: 11px;\\n                font-family: ui-monospace, SFMono-Regular, Monaco, monospace; background: #fff; color: #111827;\\n                text-transform: lowercase; transition: border-color .15s ease; }\\n            .bbg-hex-input:focus { outline: 0; border-color: #3b82f6; }\\n            .bbg-hex-input.is-invalid { border-color: #dc2626; background: #fef2f2; }\\n\\n            .bbg-gradient-presets { margin-top: 12px; }\\n            .bbg-preset-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; }\\n            .bbg-preset-chip { aspect-ratio: 1; border: 1px solid #e5e7eb; border-radius: 5px; cursor: pointer; padding: 0;\\n                transition: transform .1s ease, border-color .15s ease; }\\n            .bbg-preset-chip:hover { transform: scale(1.08); border-color: #cbd5e1; }\\n\\n            /* Effects */\\n            .bbg-info { display: flex; align-items: flex-start; gap: 6px; padding: 8px 10px; background: #fffbeb; border: 1px solid #fef3c7;\\n                border-radius: 6px; margin-bottom: 10px; color: #92400e; font-size: 10px; line-height: 1.4; }\\n            .bbg-info-icon { flex-shrink: 0; margin-top: 1px; display: inline-flex; }\\n            .bbg-active-pill { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;\\n                padding: 2px 6px; background: #dcfce7; color: #166534; border-radius: 3px; }\\n\\n            .bbg-actions { display: flex; justify-content: flex-end; margin-top: 8px; }\\n            .bbg-text-btn { background: transparent; border: 0; color: #6b7280; font-size: 11px; cursor: pointer; padding: 4px 6px;\\n                border-radius: 4px; transition: all .15s ease; }\\n            .bbg-text-btn:hover { color: #111827; background: #f3f4f6; }\\n\\n            /* Footer */\\n            .bbg-footer { padding: 10px 16px; border-top: 1px solid #f1f5f9; display: flex; justify-content: flex-end; }\\n            .bbg-reset-all { display: inline-flex; align-items: center; gap: 4px; padding: 5px 10px; background: transparent;\\n                border: 1px solid #e5e7eb; border-radius: 5px; font-size: 11px; color: #6b7280; cursor: pointer; transition: all .15s ease; }\\n            .bbg-reset-all:hover { color: #dc2626; border-color: #fecaca; background: #fef2f2; }\\n\\n            /* Dark theme inherits via iframe body; use data-theme if host provides it */\\n            :host-context([data-theme=\\\"dark\\\"]) .bbg-title,\\n            [data-theme=\\\"dark\\\"] .bbg-root .bbg-title { color: #e5e7eb; }\\n        \";\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BackgroundControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BackgroundControl.js?");

/***/ }),

/***/ "./src/includes/BaseControl.js":
/*!*************************************!*\
  !*** ./src/includes/BaseControl.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * BaseControl — base class for sidebar Controls (Phase 1.8 — SA I14).\n *\n * Historically BuilderJS controls were plain classes with no shared base —\n * each author invented its own lifecycle. That was fine at low volume but\n * broke down once dual-view controls (overlay + sidebar editing the same\n * state) needed to subscribe to element state changes. Subscriptions leak\n * unless every Control reliably tears them down when the sidebar rebuilds.\n *\n * BaseControl introduces a single `destroy()` lifecycle hook.\n * `Builder.renderElementControls` calls `destroy()` on every outgoing control\n * before building the new sidebar, so any disposer stashed via\n * `this._disposers.push(fn)` runs automatically.\n *\n * Not every Control must extend BaseControl — plain (stateless) controls\n * don't need a destroy hook, and Builder.renderElementControls guards the\n * destroy call with `typeof ctrl.destroy === 'function'`. But EVERY Control\n * that subscribes to element state (via addSyncListener) MUST extend\n * BaseControl OR implement destroy() themselves.\n *\n * See docs/core/OVERLAY.md §14 · docs/core/CONTROL_DEFINITION.md · docs/archived/OVERLAY_HARDENING_PLAN.md Phase 1.8.\n */\nvar BaseControl = /*#__PURE__*/function () {\n  function BaseControl() {\n    _classCallCheck(this, BaseControl);\n    // List of dispose fns to run on destroy — sync-listener removers,\n    // DOM listener removers, observer disconnect, etc.\n    this._disposers = [];\n    this._destroyed = false;\n\n    /**\n     * Back-reference to the owning Builder. Set by\n     * Builder.renderElementControls when this control is emitted by\n     * an element's getControls(). NOT guaranteed inside the\n     * constructor — defer host-dependent setup to afterRender() or\n     * to event handlers. See BUILDER.md \"Host Injection\" lesson.\n     */\n    this.host = null;\n  }\n\n  /** Stash a dispose fn — will be called in destroy().\n   *  Returns the fn for caller convenience (so chained registration works). */\n  return _createClass(BaseControl, [{\n    key: \"addDisposer\",\n    value: function addDisposer(fn) {\n      if (typeof fn !== 'function') return fn;\n      this._disposers.push(fn);\n      return fn;\n    }\n\n    /** Control teardown — called by Builder.renderElementControls when the\n     *  sidebar rebuilds OR by explicit ownership code. Idempotent. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._destroyed) return;\n      this._destroyed = true;\n      var list = this._disposers || [];\n      this._disposers = [];\n      var _iterator = _createForOfIteratorHelper(list),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var fn = _step.value;\n          try {\n            fn();\n          } catch (err) {\n            // eslint-disable-next-line no-console\n            console.error(\"[bjs:control] \".concat(this.constructor.name, \".destroy disposer threw:\"), err);\n          }\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n    }\n\n    /** Convenience — subscribe to element state-change notifications + auto\n     *  dispose on destroy. Shortcut for the 3-line pattern most controls use. */\n  }, {\n    key: \"bindSyncListener\",\n    value: function bindSyncListener(element, name, fn) {\n      if (!element || typeof element.addSyncListener !== 'function') return;\n      this.addDisposer(element.addSyncListener(name, fn));\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseControl.js?");

/***/ }),

/***/ "./src/includes/BaseElement.js":
/*!*************************************!*\
  !*** ./src/includes/BaseElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BuilderjsPopup.js */ \"./src/includes/BuilderjsPopup.js\");\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ui/holedBoxClipPath.js */ \"./src/includes/ui/holedBoxClipPath.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n\nvar BaseElement = /*#__PURE__*/function () {\n  function BaseElement() {\n    _classCallCheck(this, BaseElement);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n\n    /**\n     * Back-reference to the owning Builder. Set by Builder._adopt() AFTER\n     * parse, BEFORE render. Available in render(), afterMount(),\n     * getControls(), event handlers.\n     *\n     * NOT guaranteed inside constructor or static parse() — code that\n     * runs in those phases must defer to render()/afterMount() if it\n     * needs host. See Lesson \"Host Injection\" in BUILDER.md.\n     */\n    this.host = null;\n    this.formats = {\n      background_color: null,\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      padding_top: 0,\n      padding_right: 0,\n      padding_bottom: 0,\n      padding_left: 0,\n      // size settings\n      width: '560',\n      height: '315'\n    };\n    // Canvas overlays — live BaseOverlay instances mounted via getOverlays().\n    // Default `getOverlays()` returns [] so zero runtime work for every\n    // element that doesn't opt in. See docs/core/OVERLAY.md + docs/archived/OVERLAY_PLAN.md.\n    this.overlays = [];\n\n    // Dual-view sync listeners (Phase 1.8 — SA invariant I13).\n    // A Map<name, fn> so subscriptions are addressable by name (helpful for\n    // debug logging) and so the same Control registering twice stomps\n    // itself instead of double-firing. `_inSyncCascade` is a re-entrancy\n    // lock: if a listener triggers element.render() (accident or bad code),\n    // the nested notify chain is short-circuited and logged.\n    // See docs/core/OVERLAY.md §13 and docs/archived/OVERLAY_HARDENING_PLAN.md Phase 1.8.\n    this._syncListeners = new Map();\n    this._inSyncCascade = false;\n\n    // TEXT_INLINE_PLAN W0.2b — inline-edit registry. Subclass calls\n    // `this.registerInlineEdit('text')` (or whatever property name)\n    // in its constructor; BaseElement.afterRender() auto-wires the\n    // contenteditable + marker + input listener on every render.\n    this._inlineEditRegistry = new Map();\n  }\n\n  /* ─── Dual-View Sync Observer (Phase 1.8 — SA I13) ─────────────────────\n   *\n   *  Usage — Control side:\n   *      constructor(label, value, callback) {\n   *          this._disposeSync = value.element.addSyncListener(\n   *              'MyControl',\n   *              () => this.syncFromExternal()\n   *          );\n   *      }\n   *      destroy() {\n   *          if (this._disposeSync) this._disposeSync();\n   *          super.destroy();\n   *      }\n   *\n   *  Usage — Element side:\n   *      render() {\n   *          // ... build DOM ...\n   *          this.notifySyncListeners();     // call LAST\n   *          return this.domNode;\n   *      }\n   *\n   *  Invariants:\n   *    I13a. syncFn MUST be idempotent — render() may fire for reasons\n   *          unrelated to the state the Control cares about.\n   *    I13b. syncFn MUST NOT call element.render() (guarded anyway by the\n   *          re-entrancy lock, but the warning makes the mistake visible).\n   *    I13c. Disposer MUST be called on Control destroy — Builder.\n   *          renderElementControls auto-calls destroy() on outgoing controls\n   *          (SA I14). Forgetting leads to subscriptions that outlive the\n   *          Control instance → phantom DOM writes into orphaned panels.\n   */\n\n  /** Register a sync listener. Returns a disposer fn — call in Control destroy. */\n  return _createClass(BaseElement, [{\n    key: \"addSyncListener\",\n    value: function addSyncListener(name, fn) {\n      var _this = this;\n      if (typeof fn !== 'function') throw new Error('addSyncListener: fn must be a function');\n      this._syncListeners.set(name, fn);\n      return function () {\n        return _this.removeSyncListener(name);\n      };\n    }\n  }, {\n    key: \"removeSyncListener\",\n    value: function removeSyncListener(name) {\n      this._syncListeners[\"delete\"](name);\n    }\n\n    /** Debug helper — wrap a state object in a Proxy that WARNS when the\n     *  property is replaced (e.g. `element.crop = {...}` instead of\n     *  `Object.assign(element.crop, {...})`). Only active when\n     *  `window.__bjsDebug === true`; no-op in production.\n     *\n     *  Usage in element constructor:\n     *      this.crop = this._debugStateObject('crop', { enabled: false, ... });\n     *\n     *  Result in debug mode: setting `element.crop = {...}` directly fires\n     *  a loud console.warn pointing at the stack trace — catches reference\n     *  violations (SA I13 R1) at dev time instead of in production. */\n  }, {\n    key: \"_debugStateObject\",\n    value: function _debugStateObject(fieldName, obj) {\n      var _this2 = this;\n      if (typeof window === 'undefined' || window.__bjsDebug !== true) return obj;\n      // Intentionally hands back the raw object in prod. In debug, wrap a\n      // setter trap on THIS that warns when the field is replaced.\n      var klass = this.getClassName();\n      var _wrap = function wrap() {\n        Object.defineProperty(_this2, fieldName, {\n          configurable: true,\n          get: function get() {\n            return obj;\n          },\n          set: function set(next) {\n            _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].warn(\"state:replace\", \"\".concat(klass, \".\").concat(fieldName, \" was reassigned (should be mutated in place \") + \"via Object.assign \\u2014 SA I13 R1). Re-wrapping the new object.\", new Error().stack);\n            obj = next;\n            _wrap();\n          }\n        });\n      };\n      _wrap();\n      return obj;\n    }\n\n    /** Fire every registered listener. Elements that opt into dual-view call\n     *  this at the END of their render(). Re-entrancy is guarded: if a listener\n     *  re-calls render() (which would re-enter this fn), the nested cascade is\n     *  skipped + logged. */\n  }, {\n    key: \"notifySyncListeners\",\n    value: function notifySyncListeners() {\n      if (!this._syncListeners || this._syncListeners.size === 0) return;\n      if (this._inSyncCascade) {\n        // Phase 1.9: use BJS.warn so the re-entrancy warning is on in all\n        // environments (not gated by __bjsDebug). Re-entrancy is always a\n        // bug worth surfacing, even in production.\n        _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].warn(\"sync:reentrant\", \"\".concat(this.getClassName(), \" \\u2014 a sync listener called element.render(). \") + \"Skipping nested cascade. See docs/core/OVERLAY.md \\xA713 invariant I13b.\");\n        return;\n      }\n      this._inSyncCascade = true;\n      try {\n        var _iterator = _createForOfIteratorHelper(this._syncListeners),\n          _step;\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var _step$value = _slicedToArray(_step.value, 2),\n              name = _step$value[0],\n              fn = _step$value[1];\n            try {\n              fn(this);\n            } catch (err) {\n              // Phase 1.9 (SA I15) — listener throw is isolated; the\n              // loop continues so other listeners still fire.\n              _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].error(\"sync:listener \\\"\".concat(name, \"\\\" on \").concat(this.getClassName()), err);\n            }\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      } finally {\n        this._inSyncCascade = false;\n      }\n    }\n    /* ───────────────────────────────────────────────────────────────────── */\n  }, {\n    key: \"getClassName\",\n    value: function getClassName() {\n      return this.constructor.name;\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return this.getClassName();\n    }\n\n    /* ─── Render lifecycle (TEXT_INLINE_PLAN W0.2a — Template Method H1) ───\n     *\n     *  BaseElement owns the outer render() lifecycle. Subclasses override\n     *  `_doRender()` (and optionally `afterRender()`) — they do NOT override\n     *  `render()` directly except for legitimate pre/post wrap scenarios\n     *  (e.g. PricingCardElement strips stale attrs before calling super.render()).\n     *\n     *  Lifecycle:\n     *      render()\n     *        → _initDomNode()             // idempotent scaffold (<div builder-element=\"...\">)\n     *        → _doRender()                // subclass populates innerHTML / appends children\n     *        → afterRender()              // base hook (W0.2b will wire inline-edit here)\n     *        → notifySyncListeners()      // dual-view sync (auto-fires; subclass no longer calls)\n     *        → return this.domNode\n     *\n     *  Why H1 Template Method (not super.render() / not monkey-patch):\n     *    — Single owner of lifecycle = single change point for future cross-cuts.\n     *    — Subclass override surface is the smallest possible (`_doRender`).\n     *    — Auto-fired notifySyncListeners prevents the 2024-style drift where\n     *      element-specific render() bodies forgot to call it.\n     *\n     *  See docs/plans/TEXT_INLINE_PLAN.md §3 W0.2a + §10 decision #13.\n     */\n  }, {\n    key: \"_initDomNode\",\n    value: function _initDomNode() {\n      if (this.domNode) return;\n      this.domNode = document.createElement('div');\n      this.domNode.setAttribute('builder-element', this.getClassName());\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      this._initDomNode();\n      this._doRender();\n      this.afterRender();\n      this.notifySyncListeners();\n      return this.domNode;\n    }\n\n    /** Subclass MUST override — populate this.domNode (innerHTML, children).\n     *  Default no-op + dev warning if a subclass forgot to migrate from the\n     *  pre-W0.2a `render()` pattern. Failure is visible (T6). */\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // eslint-disable-next-line no-console\n      console.warn(\"[lifecycle] \".concat(this.getClassName(), \" did not override _doRender(). \") + \"Pre-W0.2a elements defined render() directly \\u2014 migrate the body to \" + \"_doRender(). See docs/core/ELEMENT_DEFINITION.md (render lifecycle).\");\n    }\n\n    /** Hook fired after _doRender() and before notifySyncListeners(). Wires\n     *  the inline-edit framework (W0.2b). Subclass overrides MUST call\n     *  super.afterRender() if they add their own logic. */\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {\n      this._wireInlineEdit();\n    }\n    /* ───────────────────────────────────────────────────────────────────── */\n\n    /* ─── Inline-edit framework (TEXT_INLINE_PLAN W0.2b) ───────────────────\n     *\n     *  Subclass opt-in: call `this.registerInlineEdit('text')` in the\n     *  constructor (AFTER `super()` AND AFTER `this.text = text` so Guard C's\n     *  `in this` check sees the property). On every render() the base will:\n     *\n     *    1. Scan `this.domNode` for `[inline-edit=\"<param>\"]` nodes (template-\n     *       authored).\n     *    2. Cross-validate three sources of truth — registry ↔ template attr ↔\n     *       this[param] property — and throw with an actionable message on any\n     *       mismatch (Guard A / B / C). Failure is visible (HARD RULE T6).\n     *    3. Wire `contenteditable=\"true\"`, stamp the\n     *       `data-bjs-inline-text=\"<this.id>\"` marker (consumed by W0.3 +\n     *       every W1-W6 selection-aware overlay), and add an `input` listener\n     *       that mirrors `node.innerHTML` back to `this[param]` and re-renders\n     *       sidebar controls.\n     */\n\n    /** Register a property name as inline-editable. Validates input + dedupes.\n     *  See `_wireInlineEdit()` for the lifecycle that consumes the registry. */\n  }, {\n    key: \"registerInlineEdit\",\n    value: function registerInlineEdit(param) {\n      var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      if (typeof param !== 'string' || param.length === 0) {\n        throw new Error(\"\".concat(this.getClassName(), \".registerInlineEdit(param): \") + \"param must be a non-empty string. Got: \".concat(_typeof(param), \" \").concat(JSON.stringify(param)));\n      }\n      this._inlineEditRegistry.set(param, opts);\n    }\n\n    /** Backward-compat computed getter — some callers still read\n     *  `this.inlineEditParams` (CheckoutSimpleElement.inlineEditableAttributes()).\n     *  Returns the live keys of `_inlineEditRegistry`. Prefer `_inlineEditRegistry`\n     *  in new code. */\n  }, {\n    key: \"inlineEditParams\",\n    get: function get() {\n      return Array.from(this._inlineEditRegistry.keys());\n    }\n\n    /** Auto-fired from `afterRender()`. Iterates the registry, runs the 3-guard\n     *  validation, and wires the editable surfaces. No-op when registry is empty\n     *  (CheckoutElement / CheckoutSimpleElement / non-text elements). */\n  }, {\n    key: \"_wireInlineEdit\",\n    value: function _wireInlineEdit() {\n      var _this3 = this;\n      if (!this._inlineEditRegistry || this._inlineEditRegistry.size === 0) return;\n      if (!this.domNode) return;\n\n      // Guard A — template attrs that have no matching registry entry.\n      // Detects \"template says inline-edit='foo' but element never registered foo\".\n      var templateNodes = this.domNode.querySelectorAll('[inline-edit]');\n      var _iterator2 = _createForOfIteratorHelper(templateNodes),\n        _step2;\n      try {\n        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n          var node = _step2.value;\n          var attr = node.getAttribute('inline-edit');\n          if (!this._inlineEditRegistry.has(attr)) {\n            throw new Error(\"\".concat(this.getClassName(), \": template has [inline-edit=\\\"\").concat(attr, \"\\\"] \") + \"but the element never called registerInlineEdit(\\\"\".concat(attr, \"\\\"). \") + \"Fix: either remove the inline-edit attribute from the template, \" + \"or add 'this.registerInlineEdit(\\\"\".concat(attr, \"\\\")' to the constructor.\"));\n          }\n        }\n      } catch (err) {\n        _iterator2.e(err);\n      } finally {\n        _iterator2.f();\n      }\n      var _iterator3 = _createForOfIteratorHelper(this._inlineEditRegistry),\n        _step3;\n      try {\n        var _loop = function _loop() {\n          var _step3$value = _slicedToArray(_step3.value, 1),\n            param = _step3$value[0];\n          var node = _this3.domNode.querySelector(\"[inline-edit=\\\"\".concat(param, \"\\\"]\"));\n\n          // Guard B — registry entry without a matching template node.\n          if (!node) {\n            throw new Error(\"\".concat(_this3.getClassName(), \": registerInlineEdit(\\\"\").concat(param, \"\\\") was called \") + \"but the template has no [inline-edit=\\\"\".concat(param, \"\\\"] node. \") + \"Fix: either add 'inline-edit=\\\"\".concat(param, \"\\\"' to the template, \") + \"or remove the registerInlineEdit(\\\"\".concat(param, \"\\\") call.\"));\n          }\n\n          // Guard C — registry entry whose property doesn't exist or is a method.\n          // Methods can't be edited inline (innerHTML would clobber the function).\n          if (!(param in _this3) || typeof _this3[param] === 'function') {\n            throw new Error(\"\".concat(_this3.getClassName(), \": registerInlineEdit(\\\"\").concat(param, \"\\\") was called \") + \"but this.\".concat(param, \" does not exist or is a method. \") + \"Fix: ensure the constructor sets 'this.\".concat(param, \" = \\u2026' BEFORE \") + \"the registerInlineEdit call (Guard C requires the property to exist).\");\n          }\n\n          // Wire — contenteditable + marker + input listener.\n          node.setAttribute('contenteditable', 'true');\n          // W0.3 + every selection-aware overlay reads this marker to scope\n          // selectionchange + intercept events to text-editing surfaces only.\n          node.setAttribute('data-bjs-inline-text', _this3.id);\n          node.addEventListener('input', function () {\n            var _this3$host;\n            // INLINE-EDIT INVARIANT (HARD RULE T11 — 2026-05-20):\n            //   - The inline-edit host (`<p>` / `<h*>`) MUST only contain\n            //     INLINE descendants (`<span>` / `<strong>` / `<em>` /\n            //     `<a>` / `<br>` / …). NO `<div>` / `<p>` / `<h*>` /\n            //     `<ul>` / etc. inside.\n            //   - HTML5 fragment parsing silently auto-closes the host\n            //     when it encounters a block-level child, so a `<div>`\n            //     left in `this.text` round-trips through the parser as\n            //     a SIBLING of the host on the next `innerHTML =` —\n            //     stripping the host's inline `style` from the visible\n            //     content. Customer-visible symptom: paragraph loses\n            //     font-weight + text-align after an unrelated\n            //     structural mutation (delete/add block).\n            //\n            //   - Chrome's contenteditable default-paragraph-separator\n            //     is `'div'` — every Enter inserts a `<div>` block\n            //     child by default. Firefox/Safari behave similarly.\n            //     `Builder._setupIframe` calls\n            //     `iframeDoc.execCommand('defaultParagraphSeparator',\n            //     false, 'br')` to flip this to `<br>` (Chrome/FF), but\n            //     Safari ignores that flag — defence-in-depth requires\n            //     this DOM-level normalize too.\n            //\n            // Strategy: clone the host, run `InlineSanitizer.normalize`\n            // (which unwraps every block-level descendant + canonicalises\n            // `<b>→<strong>` + collapses empty spans), then capture the\n            // CLONE's innerHTML into `this.text`. The LIVE host is NOT\n            // mutated — touching the live DOM mid-keystroke would\n            // disrupt the user's caret/range. The live state stays\n            // visually intact (with `<div>` if Chrome inserted one);\n            // the next `_doRender()` writes the sanitised text back,\n            // which is when the user would see a visual hop if the\n            // host had block children. In practice the host's\n            // applyFormatStyles fast-path is used during edits and full\n            // `_doRender` only fires from `parse()`/cascade re-renders\n            // — by then `this.text` is already inline-clean.\n            var captured;\n            try {\n              var clone = node.cloneNode(true);\n              _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"].normalize(clone);\n              captured = clone.innerHTML;\n            } catch (err) {\n              _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].error('BaseElement:input-normalize', err);\n              captured = node.innerHTML;\n            }\n            _this3[param] = captured;\n            if (typeof ((_this3$host = _this3.host) === null || _this3$host === void 0 ? void 0 : _this3$host.renderElementControls) === 'function') {\n              _this3.host.renderElementControls(_this3);\n            }\n          });\n          // TEXT_INLINE_PLAN W2.2 / HARD RULE T9 — intercept native paste\n          // (⌘V / Ctrl+V / right-click Paste) and route the clipboard\n          // payload through `InlineSanitizer.sanitize({ mode })` BEFORE\n          // the browser's default paste mutates the DOM. Without this,\n          // Office / Google Docs / Outlook paste lands `mso-*` attrs +\n          // block tags + `<font>` legacy markup directly inside the\n          // inline-text host — violating T9 whitelist and breaking\n          // round-trip invariants.\n          //\n          // ClipboardEvent.clipboardData is always accessible on a\n          // NATIVE paste event (no permission prompt, no secure-context\n          // requirement) — unlike the async `navigator.clipboard.read()`\n          // API the W2.2 More menu's Paste items use. That makes ⌘V the\n          // reliable paste path for users in restricted environments\n          // (HTTP iframes, focus-sensitive contexts, unprivileged tabs).\n          node.addEventListener('paste', function (e) {\n            var cd = e.clipboardData || node.ownerDocument.defaultView && node.ownerDocument.defaultView.clipboardData;\n            if (!cd) return; // allow default for environments without clipboardData (legacy IE etc.)\n            var html = typeof cd.getData === 'function' ? cd.getData('text/html') : '';\n            var text = typeof cd.getData === 'function' ? cd.getData('text/plain') : '';\n            if (!html && !text) return; // files / images / empty — let default handle\n            e.preventDefault();\n            var mode = typeof _this3.getOutputMode === 'function' && _this3.getOutputMode() === 'email-safe' ? 'email-safe' : 'page';\n            var toInsert;\n            if (html) {\n              toInsert = _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"].sanitize(html, {\n                mode: mode\n              });\n            } else {\n              // Plain text → escape HTML specials + convert newlines to <br>.\n              toInsert = String(text).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;').replace(/\\r?\\n/g, '<br>');\n            }\n            if (!toInsert) return;\n            try {\n              node.ownerDocument.execCommand('insertHTML', false, toInsert);\n            } catch (err) {\n              _BJS_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].error('BaseElement:paste', err);\n            }\n          });\n        };\n        for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n          _loop();\n        }\n      } catch (err) {\n        _iterator3.e(err);\n      } finally {\n        _iterator3.f();\n      }\n    }\n    /* ───────────────────────────────────────────────────────────────────── */\n  }, {\n    key: \"isHoverable\",\n    value: function isHoverable() {\n      return true;\n    }\n  }, {\n    key: \"isDroppable\",\n    value: function isDroppable() {\n      return false;\n    }\n  }, {\n    key: \"canDropInside\",\n    value: function canDropInside() {\n      return false;\n    }\n  }, {\n    key: \"canDropBefore\",\n    value: function canDropBefore() {\n      return false;\n    }\n  }, {\n    key: \"canDropAfter\",\n    value: function canDropAfter() {\n      return false;\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      return [\n      // CheckboxControl\n      new CheckboxControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.optimized_mobile'),\n      // descriptoin,\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.optimized_mobile_desc'),\n      // value\n      true,\n      // callback — placeholder (overridden by element subclasses)\n      {\n        setValue: function setValue(value) {\n          _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].alert({\n            title: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.optimized_mobile'),\n            message: String(value),\n            kind: 'info'\n          });\n        }\n      }),\n      // CheckboxControl\n      new CheckboxControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.compat_mode'),\n      // descriptoin,\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.compat_mode_desc'),\n      // value\n      true,\n      // callback — placeholder (overridden by element subclasses)\n      {\n        setValue: function setValue(value) {\n          _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].alert({\n            title: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.compat_mode'),\n            message: String(value),\n            kind: 'info'\n          });\n        }\n      })];\n    }\n\n    /* ─── Skeletons (TEXT_INLINE_PLAN W0.2c — A2 pure design) ─────────────\n     *\n     *  Three centralizing helpers. Subclasses use `super.X()` to extend.\n     *\n     *  W0.2c design decision (§7 discovery): chose A2 pure for renderTemplate —\n     *  reads `this.template` implicitly (element identity ↔ template = 1:1\n     *  invariant), returns html string with NO side effect (subclass writes\n     *  innerHTML explicitly). Single signature, single responsibility. The\n     *  pre-W0.2c 2-arg form `renderTemplate(template, options)` is REMOVED —\n     *  no caller passed a template name other than `this.template` (audited\n     *  28/28 sites). Per-render template swap is impossible by design — if\n     *  needed, set `this.template = newName` then call render(). Forces\n     *  explicit identity change, blocks accidental render mismatch.\n     */\n\n    /** Required template-var allowlist. Subclasses override\n     *  `this.requiredTemplateKeys = ['url', 'text']` in the constructor.\n     *  `renderTemplate(vars)` throws if any required key is missing from\n     *  the merged vars (HARD RULE T6 — failure visible). */\n  }, {\n    key: \"requiredTemplateKeys\",\n    get: function get() {\n      var _this$_requiredTempla;\n      return (_this$_requiredTempla = this._requiredTemplateKeys) !== null && _this$_requiredTempla !== void 0 ? _this$_requiredTempla : [];\n    },\n    set: function set(value) {\n      this._requiredTemplateKeys = value;\n    }\n\n    /** Pure: resolve `this.template` against vars + return html. Auto-merges\n     *  defaults (`formatter`, `text`) when defined on the instance. NO\n     *  side effect — caller writes `this.domNode.innerHTML = …` explicitly.\n     *\n     *  Three layers of validation (HARD RULE T6 — failure visible):\n     *    Guard T  — `this.template` must be a non-empty string (else throw\n     *               with element class name in message).\n     *    Guard V  — every key in `this.requiredTemplateKeys` must be present\n     *               in the merged vars passed to the engine.\n     *    Design-W — preserved pre-W0.2c warning when the template html body\n     *               doesn't reference a declared required key.\n     */\n  }, {\n    key: \"renderTemplate\",\n    value: function renderTemplate() {\n      var _this4 = this;\n      var vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      // Guard T — element identity ↔ template invariant. Catches the\n      // \"constructor forgot to set this.template\" bug at the FIRST render\n      // with an element-class-specific message (vs. the generic\n      // `Template \"undefined\" not found` from builder.getTemplate).\n      if (typeof this.template !== 'string' || this.template.length === 0) {\n        throw new Error(\"\".concat(this.getClassName(), \".renderTemplate: this.template is missing or \") + \"not a string (got: \".concat(_typeof(this.template), \" \").concat(JSON.stringify(this.template), \"). \") + \"Set this.template = '<TemplateName>' in the constructor BEFORE render() \" + \"runs. Element identity \\u2194 template is a 1:1 invariant.\");\n      }\n      var merged = {};\n      if (this.formatter !== undefined) merged.formatter = this.formatter;\n      if (this.text !== undefined) merged.text = this.text;\n      Object.assign(merged, vars);\n\n      // Guard V — every required key must be present in the merged vars\n      // passed to the template engine.\n      var required = this.requiredTemplateKeys || [];\n      var _iterator4 = _createForOfIteratorHelper(required),\n        _step4;\n      try {\n        for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {\n          var key = _step4.value;\n          if (!(key in merged)) {\n            throw new Error(\"\".concat(this.getClassName(), \".renderTemplate: requiredTemplateKey \\\"\").concat(key, \"\\\" \") + \"missing from vars. Either pass { \".concat(key, \": \\u2026 } or remove \\\"\").concat(key, \"\\\" from \") + \"requiredTemplateKeys.\");\n          }\n        }\n\n        // Design-W — preserved pre-W0.2c warning. Catches templates that\n        // declare a required key but don't actually reference it (theme\n        // author drift).\n      } catch (err) {\n        _iterator4.e(err);\n      } finally {\n        _iterator4.f();\n      }\n      var html = this.host.getTemplate(this.template);\n      this.host.validateKeysUsage(html, required, function (unusedKeys) {\n        // eslint-disable-next-line no-console\n        console.log(\"*****DESIGN ERROR: [\".concat(_this4.getClassName(), \"] Template \") + \"\\\"\".concat(_this4.template, \"\\\" does not use the following required keys: \") + \"\".concat(unusedKeys.join(', ')));\n      });\n      return this.host.renderTemplate(this.template, merged);\n    }\n\n    /** Baseline serialization. Subclasses extend via:\n     *      getData() {\n     *          return { ...super.getData(), text: this.text, ... };\n     *      }\n     *  `formats` is included only if the element has a formatter. */\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      var data = {\n        name: this.getClassName(),\n        template: this.template\n      };\n      if (this.formatter && typeof this.formatter.getFormats === 'function') {\n        data.formats = this.formatter.getFormats();\n      }\n      return data;\n    }\n\n    /** Static helper for `static parse(data)` bodies. Pulls `data.formats`\n     *  into the formatter (when both exist). Returns the instance for chaining:\n     *      static parse(data) {\n     *          return this.parseFormats(new this(data.template, data.text), data);\n     *      }\n     */\n  }, {\n    key: \"duplicate\",\n    value: /* ───────────────────────────────────────────────────────────────────── */\n\n    function duplicate() {\n      var cloned = ElementFactory.createElement(this.getData());\n      // Host injection — `cloned` came from a fresh `.parse()` and has\n      // not yet been adopted. `this.host._adopt(cloned)` walks the new\n      // subtree before insert so its overlays + nested children also\n      // pick up the back-reference.\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(cloned);\n      }\n      this.container.insertElementAfter(this, cloned);\n\n      // @todo: dependency\n      this.host.selectElement(cloned);\n\n      // PLAN_UNDO_REDO — structural mutation, explicit commit.\n      // HistoryManager silences commits during its own apply via _applying.\n      // `getName()` returns the human-readable display name (subclass\n      // override like ImageElement.getName() → \"Image\") — that's what\n      // surfaces in the history dropdown label.\n      if (this.host.history) {\n        this.host.history.commit('history.structure_duplicate', {\n          change: 'structure:duplicate',\n          elementType: this.getName(),\n          source: 'action-bar'\n        });\n      }\n    }\n  }, {\n    key: \"fadeOut\",\n    value: function fadeOut() {\n      var _this$host;\n      var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;\n      var callback = arguments.length > 1 ? arguments[1] : undefined;\n      var element = this.domNode;\n\n      // Defensive — element may not be in the DOM yet (called before render\n      // completes, or after the element has been removed). Skip animation\n      // and fire callback immediately so caller flow continues.\n      if (!element) {\n        if (typeof callback === 'function') callback();\n        return;\n      }\n\n      // PLAN_UNDO_REDO — skip mount/unmount animation during history apply.\n      // Re-playing 300ms fade-out across every removed element on undo would\n      // freeze the UI. Jump straight to final state.\n      if ((_this$host = this.host) !== null && _this$host !== void 0 && (_this$host = _this$host.history) !== null && _this$host !== void 0 && _this$host._applying) {\n        if (typeof callback === 'function') callback();\n        return;\n      }\n\n      // Get computed height to allow transition from fixed height to 0\n      var computedStyle = getComputedStyle(element);\n      var height = element.offsetHeight;\n      element.style.height = height + 'px';\n      element.style.overflow = 'hidden'; // Prevent content overflow during height transition\n\n      // Set up the transition\n      element.style.transition = \"opacity \".concat(duration, \"ms, transform \").concat(duration, \"ms, height \").concat(duration, \"ms\");\n      element.style.opacity = '1';\n      element.style.transform = 'translateX(0)';\n      var _handleTransitionEnd = function handleTransitionEnd(event) {\n        // Wait for all transitions to complete\n        if (event.propertyName !== 'height') return;\n        element.removeEventListener('transitionend', _handleTransitionEnd);\n        element.style.display = 'none';\n        if (typeof callback === 'function') {\n          callback();\n        }\n      };\n      element.addEventListener('transitionend', _handleTransitionEnd);\n\n      // Trigger animation\n      requestAnimationFrame(function () {\n        void element.offsetWidth; // Force reflow\n        element.style.opacity = '0';\n        element.style.transform = 'translateX(100px)';\n        element.style.height = '0px';\n      });\n    }\n  }, {\n    key: \"fadeIn\",\n    value: function fadeIn() {\n      var _this$host2;\n      var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 300;\n      var callback = arguments.length > 1 ? arguments[1] : undefined;\n      var element = this.domNode;\n\n      // Defensive — element may not be mounted yet. Skip animation and fire\n      // callback so the caller flow continues without crashing.\n      if (!element) {\n        if (typeof callback === 'function') callback();\n        return;\n      }\n\n      // PLAN_UNDO_REDO — skip mount animation during history apply. Re-playing\n      // every block's 300ms fade-in on undo/redo looks like broken jank.\n      if ((_this$host2 = this.host) !== null && _this$host2 !== void 0 && (_this$host2 = _this$host2.history) !== null && _this$host2 !== void 0 && _this$host2._applying) {\n        if (typeof callback === 'function') callback();\n        return;\n      }\n\n      // Remove any lingering transitionend listeners\n      element.removeEventListener('transitionend', element._fadeInTransitionEnd);\n\n      // Reset display and initial state\n      element.style.display = '';\n      element.style.overflow = 'hidden';\n      element.style.opacity = '0';\n      element.style.transform = 'translateX(100px)';\n      element.style.height = '0px';\n\n      // Force reflow to apply initial styles\n      void element.offsetWidth;\n\n      // Measure full height to transition to\n      var targetHeight = element.scrollHeight;\n\n      // Apply transition styles\n      element.style.transition = \"opacity \".concat(duration, \"ms ease, transform \").concat(duration, \"ms ease, height \").concat(duration, \"ms ease\");\n\n      // Define the transition end handler\n      var _handleTransitionEnd2 = function handleTransitionEnd(event) {\n        if (event.propertyName !== 'height') return;\n        element.removeEventListener('transitionend', _handleTransitionEnd2);\n        element.style.overflow = ''; // Reset overflow\n        element.style.height = ''; // Let height be auto after transition\n\n        if (typeof callback === 'function') {\n          callback();\n        }\n      };\n\n      // Attach and store the handler (to avoid duplicates)\n      element._fadeInTransitionEnd = _handleTransitionEnd2;\n      element.addEventListener('transitionend', _handleTransitionEnd2);\n\n      // Animate to visible state\n      requestAnimationFrame(function () {\n        element.style.opacity = '1';\n        element.style.transform = 'translateX(0)';\n        element.style.height = targetHeight + 'px';\n      });\n    }\n  }, {\n    key: \"remove\",\n    value: function remove() {\n      var _this5 = this;\n      if (this.host.getSelectedElement() === this) {\n        this.host.unselect();\n      }\n\n      // Capture display name BEFORE fadeOut — subclass override like\n      // ImageElement.getName() → \"Image\" (not \"ImageElement\"). Stays\n      // valid after removal but we snapshot for clarity.\n      var elementType = this.getName();\n      this.fadeOut(300, function () {\n        // remove alement from all\n        _this5.host.uiManager.removeDraggableItem(_this5);\n        _this5.host.uiManager.removeElement(_this5);\n        _this5.host.uiManager.dragOveringElements = [];\n        _this5.host.uiManager.hoveringElements = [];\n\n        // remove all effects\n        _this5.removeHoverHightlight();\n        _this5.removeSelectedHighlight();\n        _this5.removeDropHighlight();\n        _this5.removeContainerHightlight();\n        _this5.removeContainerDropHightlight();\n\n        // Tear down any overlays still mounted on this element (all triggers).\n        // Overlays register window.document scroll/resize listeners through\n        // matchingDomNode — without this call they'd keep firing against a\n        // removed element. See docs/core/OVERLAY.md §3 + §4.I5.\n        _this5.unmountOverlays('*');\n        if (_this5.getDragAnchor && typeof _this5.getDragAnchor === 'function' && _this5.getDragAnchor()) {\n          _this5.getDragAnchor().remove();\n        }\n\n        // remove from container\n        _this5.container.removeElement(_this5);\n\n        // PLAN_UNDO_REDO — structural mutation is now final (after fadeOut\n        // completes + container.render()). Explicit commit so undo restores\n        // the element. Silenced by HistoryManager._applying if this remove\n        // is itself a redo step.\n        if (_this5.host.history) {\n          _this5.host.history.commit('history.structure_remove', {\n            change: 'structure:remove',\n            elementUid: _this5.id,\n            elementType: elementType,\n            source: 'action-bar'\n          });\n        }\n\n        // CD-3 (AIBuilder Wave 4) — emit element:removed at the\n        // structure-mutation chokepoint, NOT through HistoryManager (which\n        // dedupes identical-data commits). Layers tree (Wave 14) +\n        // collaborative editing (Wave 85) need every remove regardless of\n        // history dedupe.\n        if (_this5.host.events && _this5.id != null) {\n          var _window$Builder$EVENT, _window$Builder;\n          _this5.host.events.emit((_window$Builder$EVENT = (_window$Builder = window.Builder) === null || _window$Builder === void 0 || (_window$Builder = _window$Builder.EVENTS) === null || _window$Builder === void 0 ? void 0 : _window$Builder.ELEMENT_REMOVED) !== null && _window$Builder$EVENT !== void 0 ? _window$Builder$EVENT : 'element:removed', {\n            elementUid: _this5.id,\n            elementType: elementType\n          });\n        }\n      });\n    }\n\n    // ─── Canvas Overlay hooks (Phase 1.1) ───────────────────────────────\n    //\n    // See docs/core/OVERLAY.md for spec, docs/archived/OVERLAY_PLAN.md §3.2 for phase scope.\n    //\n    // Default `getOverlays()` returns [] — every element that doesn't opt in\n    // executes zero new work. `mount/unmountOverlays` are guarded by that\n    // default, so Builder.selectElement / UIManager.mouseover paths short-\n    // circuit with `if (getOverlays().length)` or produce empty for-loops.\n    //\n    // Subclasses override getOverlays() to return an array of BaseOverlay\n    // subclass instances. See ImageElement/GridElement/CellElement/BlockElement\n    // in later phases for examples.\n\n    /** Return canvas overlay instances for this element.\n     *  Override in subclasses — default is [] (additive-only safety). */\n  }, {\n    key: \"getOverlays\",\n    value: function getOverlays() {\n      return [];\n    }\n\n    /**\n     * Return this element's child elements as a flat array.\n     *\n     * Used by Builder._adopt() to recurse the element tree post-parse and\n     * assign `host` on every Element + its overlays. Override in container\n     * elements (Page/Block/Grid/Cell) to return their child arrays.\n     *\n     * Default: leaf — no children. See Lesson \"Host Injection\" in\n     * BUILDER.md.\n     */\n  }, {\n    key: \"getChildren\",\n    value: function getChildren() {\n      return [];\n    }\n\n    /** Mount overlays whose getTrigger() === trigger. Called by Builder\n     *  (select) and UIManager (hover) — do not call manually.\n     *\n     *  Idempotent: if an overlay of this trigger is already mounted, this is\n     *  a no-op. UIManager.mouseover fires repeatedly while cursor moves inside\n     *  the same element — without idempotence, this.overlays would grow\n     *  unboundedly per hover session. */\n  }, {\n    key: \"mountOverlays\",\n    value: function mountOverlays(trigger) {\n      var _this6 = this;\n      // Idempotence: already have live overlays of this trigger → skip.\n      if (this.overlays.some(function (ov) {\n        return ov.getTrigger() === trigger && ov.mounted;\n      })) {\n        return;\n      }\n      this.getOverlays().forEach(function (overlay) {\n        if (overlay.getTrigger() === trigger) {\n          // Host injection — getOverlays() constructed a fresh\n          // overlay; assign host BEFORE mount() so afterMount()\n          // can read host.options / host.events. Inherits from\n          // this element's host (set by Builder._adopt()).\n          overlay.host = _this6.host;\n\n          // Edit-mode filter — when trigger is 'edit', skip overlays whose\n          // declared edit mode doesn't match this.editMode. Overlays that\n          // omit getEditMode() (or return null) are mode-agnostic and\n          // mount on every edit-trigger fire (back-compat with overlays\n          // pre-dating the multi-mode design).\n          if (trigger === 'edit' && typeof overlay.getEditMode === 'function' && overlay.getEditMode() !== null && overlay.getEditMode() !== _this6.editMode) {\n            return;\n          }\n          // Sanity: trigger 'hover' on non-hoverable element silently wastes\n          // a mount because UIManager.mouseover bails at isHoverable check.\n          // Log a warning so developers catch this at dev time. See §4.I7.\n          if (trigger === 'hover' && typeof _this6.isHoverable === 'function' && !_this6.isHoverable()) {\n            // eslint-disable-next-line no-console\n            console.warn(\"[overlay] \".concat(_this6.getClassName(), \" declared a 'hover' trigger overlay \") + \"but isHoverable()=false \\u2014 UIManager.mouseover will never mount it. \" + \"Attach the affordance to the parent container's overlay instead. \" + \"See docs/core/OVERLAY.md \\xA77.3 + \\xA74.I7.\");\n          }\n          overlay.mount();\n          _this6.overlays.push(overlay);\n        }\n      });\n    }\n\n    /** Unmount (and destroy) overlays matching trigger ('*' = all). */\n  }, {\n    key: \"unmountOverlays\",\n    value: function unmountOverlays() {\n      var trigger = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '*';\n      this.overlays = this.overlays.filter(function (overlay) {\n        if (trigger === '*' || overlay.getTrigger() === trigger) {\n          overlay.destroy();\n          return false; // remove from list\n        }\n        return true; // keep\n      });\n    }\n\n    /** Enter a named edit mode — mounts 'edit'-trigger overlays whose\n     *  `getEditMode()` matches `modeName` (or whose `getEditMode()` is\n     *  absent / null, meaning \"any mode\"). Without the mode filter, every\n     *  edit-trigger overlay mounted on every enterEditMode call — a single\n     *  element with both a Crop popup and a Resize popup would mount BOTH\n     *  on `enterEditMode('crop')`, overlapping the modal mask. */\n  }, {\n    key: \"enterEditMode\",\n    value: function enterEditMode(modeName) {\n      if (this.editMode === modeName) return; // idempotent (§12 OVERLAY.md)\n      // Tear down any currently-active edit overlay before swapping mode\n      // so back-to-back enterEditMode('crop') → enterEditMode('resize')\n      // doesn't leave the crop popup mounted underneath.\n      if (this.editMode) this.unmountOverlays('edit');\n      this.editMode = modeName;\n      this.mountOverlays('edit');\n    }\n\n    /** Exit edit mode — unmounts 'edit' overlays + one-shot sidebar sync.\n     *  Single renderElementControls is OK here (boundary transition, not\n     *  a hot-path loop — see §7 OVERLAY.md rule 1 exception). */\n  }, {\n    key: \"exitEditMode\",\n    value: function exitEditMode() {\n      var _this$host3, _this$host3$getSelect;\n      this.unmountOverlays('edit');\n      this.editMode = null;\n      if (((_this$host3 = this.host) === null || _this$host3 === void 0 || (_this$host3$getSelect = _this$host3.getSelectedElement) === null || _this$host3$getSelect === void 0 ? void 0 : _this$host3$getSelect.call(_this$host3)) === this) {\n        // Only re-render the sidebar if this element is actually selected\n        // — otherwise we'd thrash an unrelated panel.\n        this.host.renderElementControls(this);\n      }\n    }\n  }, {\n    key: \"transferMediaAbsUrl\",\n    value: function transferMediaAbsUrl(url) {\n      // Null-tolerant: parse-only elements (created via `ElementClass.parse(json)`\n      // outside a Builder tree, e.g. legacy-JSON migration tests) never get\n      // adopted, so `this.host` is null. Return the URL unchanged in that case\n      // — without a host there's no themeMediaUrl to prepend anyway. Adopted\n      // elements (the production path through Builder._adopt) route through\n      // host.transferMediaAbsUrl as before.\n      if (!this.host) return url;\n      return this.host.transferMediaAbsUrl(url);\n    }\n\n    /* Matching Position & Size of domNode and the box */\n  }, {\n    key: \"matchingDomNode\",\n    value: function matchingDomNode(box) {\n      var _this7 = this;\n      var padding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n      var setPosSize = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n      var afterPosSize = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n      //\n      if (!box) {\n        return;\n      }\n\n      // Canvas-clip helper — clips the overlay paint area to the host\n      // Builder's `mainContainer` rect so hover / selection / drop\n      // highlights never bleed past the canvas edge into surrounding\n      // chrome (sidebars, header, footer, adjacent Builder instances).\n      // Runs AFTER setPosSize so b.getBoundingClientRect() reflects the\n      // freshly-applied inline top/left/width/height. Opt-out via the\n      // `.bjs-ovl-no-clip` class — used by `.actions-box` so the pill\n      // toolbar can still float above the canvas top edge.\n      // See BUILDER.md \"Canvas-clip contract\" + OVERLAY.md §24.\n      var _applyCanvasClip = function _applyCanvasClip() {\n        // Prefer the walk-up-resolved clip container (handles the\n        // common case where `mainContainer` scrolls along with the\n        // iframe inside a higher-up overflow:auto viewport — see\n        // Builder._resolveClipContainer). Falls back to mainContainer\n        // when the resolver returned `mainContainer` itself or when\n        // host is missing (parse-only elements).\n        var clip = _this7.host && (_this7.host._resolvedClipContainer || _this7.host.mainContainer) || null;\n        if (!clip || box.classList.contains('bjs-ovl-no-clip')) {\n          if (box.style.clipPath) box.style.clipPath = '';\n          return;\n        }\n        var c = clip.getBoundingClientRect();\n        var b = box.getBoundingClientRect();\n\n        // Express the clip region as the CANVAS rect in box-relative\n        // coordinates, via `polygon()`. Two reasons we cannot use the\n        // simpler `inset(t r b l)` form:\n        //\n        //   1. `inset()` values clamp to >= 0 — they always cut INWARD\n        //      from the box's own border-box. So `inset(0 0 0 0)` clips\n        //      ::before / ::after that intentionally paints OUTSIDE the\n        //      box (e.g. `.drop-after-box::before` uses `bottom: -10px`,\n        //      `.drop-before-box::before` uses `top: -10px` to draw a\n        //      dashed rounded pill that STRADDLES the seam between two\n        //      blocks). Half of the pill lives outside the box rect by\n        //      design; the legacy inset form silently cut it off, so the\n        //      drop indicator rendered as a half-pill instead of a full\n        //      one (reported 2026-05-14: \"drop after/before highlight\n        //      bị che mất 1 nửa\").\n        //\n        //   2. The previous fix tried to early-out by skipping clip-path\n        //      when t=r=bo=l=0, but as soon as ANY edge of the box even\n        //      slightly overflowed the canvas (subpixel drift on\n        //      scroll/resize, or the box hugging a canvas edge), the\n        //      inset returned and re-clipped all four box edges — so\n        //      the pseudo cut-off reappeared whenever the user had\n        //      scrolled the canvas in the slightest.\n        //\n        // `polygon()` accepts negative coordinates, so the clip region\n        // can extend OUTSIDE the box's border-box on the sides that are\n        // still inside the canvas. Pseudos paint freely up to the\n        // canvas edge; only the parts that genuinely overflow the\n        // canvas get cut. This is the canvas-edge protection that the\n        // helper was always supposed to provide; the inset form was a\n        // box-edge approximation that happened to be wrong for any\n        // overlay with outside-the-box pseudos.\n        //\n        // No regression for overlays whose pseudos live INSIDE the box\n        // (`.selected-box::before { inset: 0 }`, `.hovering-box::before`,\n        // etc.) — their paint area is contained, so widening the clip\n        // beyond the box is a no-op for them. Box-shadows that already\n        // extended past the box (`var(--bjs-selection-shadow)`) are now\n        // visible up to the canvas edge instead of being truncated at\n        // the box's border — a strict improvement.\n        var leftPx = c.left - b.left;\n        var topPx = c.top - b.top;\n        var rightPx = c.right - b.left;\n        var bottomPx = c.bottom - b.top;\n        box.style.clipPath = \"polygon(\".concat(leftPx, \"px \").concat(topPx, \"px, \").concat(rightPx, \"px \").concat(topPx, \"px, \") + \"\".concat(rightPx, \"px \").concat(bottomPx, \"px, \").concat(leftPx, \"px \").concat(bottomPx, \"px)\");\n      };\n      if (!setPosSize) {\n        setPosSize = function setPosSize() {\n          // Get the bounding rect of the domNode inside the iframe\n          var domRect = _this7.domNode.getBoundingClientRect();\n\n          // Get the iframe element that contains the domNode\n          var iframe = _this7.domNode.ownerDocument.defaultView.frameElement;\n          var iframeRect = iframe.getBoundingClientRect();\n\n          // Calculate absolute position of domNode relative to main window\n          var absoluteTop = iframeRect.top + domRect.top;\n          var absoluteLeft = iframeRect.left + domRect.left;\n\n          // Set the hoveringBox's position and size\n          Object.assign(box.style, {\n            position: 'fixed',\n            top: \"\".concat(absoluteTop - padding, \"px\"),\n            left: \"\".concat(absoluteLeft - padding, \"px\"),\n            width: \"\".concat(domRect.width + padding * 2, \"px\"),\n            height: \"\".concat(domRect.height + padding * 2, \"px\")\n          });\n          if (afterPosSize) {\n            afterPosSize();\n          }\n          _applyCanvasClip();\n        };\n      } else {\n        // Caller supplied a custom positioner (e.g. .actions-box uses\n        // ToolbarPositioner; container-highlight 4-box system uses an\n        // afterPosSize-style sub-layout). Wrap so canvas-clip still\n        // fires AFTER their positioning runs — single source of truth\n        // for the clip pass, regardless of who computes top/left.\n        var _userSetPosSize = setPosSize;\n        setPosSize = function setPosSize() {\n          _userSetPosSize();\n          _applyCanvasClip();\n        };\n      }\n      setPosSize();\n\n      //\n      if (!box.events) {\n        // === IFRAME SCROLL & RESIZE ===\n        var iframeWindow = this.domNode.ownerDocument.defaultView;\n        var iframeDocument = this.domNode.ownerDocument;\n\n        // Named handlers so __disconnectObservers can actually remove them.\n        // Pre-Phase-1.1 these were anonymous arrow functions → no\n        // removeEventListener path → every box leaked 4 window listeners.\n        // See docs/archived/OVERLAY_PLAN.md §4.I8 for the full story.\n        var onIframeScroll = function onIframeScroll() {\n          setPosSize();\n        };\n        var onIframeResize = function onIframeResize() {\n          setPosSize();\n        };\n        var onParentScroll = function onParentScroll() {\n          setPosSize();\n        };\n        var onParentResize = function onParentResize() {\n          setPosSize();\n        };\n        iframeWindow.addEventListener('scroll', onIframeScroll, true);\n        iframeWindow.addEventListener('resize', onIframeResize);\n\n        // Optional: also watch for DOM mutations (e.g., added/removed elements)\n        var mutationObserver = new iframeWindow.MutationObserver(function () {\n          setPosSize();\n        });\n        mutationObserver.observe(iframeDocument.body, {\n          childList: true,\n          subtree: true,\n          attributes: true\n        });\n\n        // Async layout changes (e.g. <video>/<img> natural size arriving\n        // with loaded bytes, or CSS-driven content reflow) don't produce\n        // a DOM mutation — only a layout change. ResizeObserver catches\n        // both the element's own box resize and subtree reflow, so the\n        // selection/hover overlay stays glued to the domNode even when\n        // nothing in the DOM changed. Reported 2026-04-17 (VideoElement\n        // empty-state/error-overlay height change was invisible to the\n        // MutationObserver).\n        var resizeObserver = null;\n        if (typeof iframeWindow.ResizeObserver === 'function') {\n          resizeObserver = new iframeWindow.ResizeObserver(function () {\n            setPosSize();\n          });\n          resizeObserver.observe(this.domNode);\n        }\n\n        // Outer Document\n        window.document.addEventListener('scroll', onParentScroll, true);\n        window.document.addEventListener('resize', onParentResize);\n\n        // Canvas-clip reflow hook — register `setPosSize` with the\n        // Builder's mainContainer-level reflow set so a pure\n        // mainContainer resize (sidebar collapse, chrome variant\n        // swap, parent-page layout shift that doesn't change the\n        // iframe element's children's rects) still re-ticks every\n        // mounted overlay's clip pass. Single ResizeObserver per\n        // Builder, scattered hooks. See Builder._reflowHooks +\n        // _mainContainerResizeObserver.\n        var reflowHooks = this.host && this.host._reflowHooks;\n        if (reflowHooks) {\n          reflowHooks.add(setPosSize);\n        }\n        box.events = true;\n        // Expose teardowns so remove*Highlight() callers (and future\n        // element-specific cleanup paths) can release observers without\n        // leaking iframe-scoped closures when the element is removed.\n        box.__disconnectObservers = function () {\n          if (mutationObserver) mutationObserver.disconnect();\n          if (resizeObserver) resizeObserver.disconnect();\n          // Phase 1.1 leak fix (§4.I8): remove the 4 window-scoped\n          // scroll/resize listeners this invocation of matchingDomNode\n          // added. Pre-fix, these accumulated forever.\n          try {\n            iframeWindow.removeEventListener('scroll', onIframeScroll, true);\n          } catch (_) {}\n          try {\n            iframeWindow.removeEventListener('resize', onIframeResize);\n          } catch (_) {}\n          try {\n            window.document.removeEventListener('scroll', onParentScroll, true);\n          } catch (_) {}\n          try {\n            window.document.removeEventListener('resize', onParentResize);\n          } catch (_) {}\n          // Canvas-clip reflow hook — release the per-overlay\n          // setPosSize from the Builder-level set so a removed\n          // overlay can't keep firing on mainContainer resize.\n          if (reflowHooks) {\n            try {\n              reflowHooks[\"delete\"](setPosSize);\n            } catch (_) {}\n          }\n        };\n      }\n    }\n  }, {\n    key: \"setFormat\",\n    value: function setFormat(format, value) {\n      this.formats[format] = value;\n    }\n  }, {\n    key: \"getFormat\",\n    value: function getFormat(format) {\n      var _this$formats$format;\n      var dValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n      return (_this$formats$format = this.formats[format]) !== null && _this$formats$format !== void 0 ? _this$formats$format : dValue;\n    }\n\n    /* HOVERING EFFECTS */\n  }, {\n    key: \"addHoverHightlight\",\n    value: function addHoverHightlight() {\n      var _this$host4,\n        _this8 = this;\n      // PLAN_EFFECT W2.1 — the currently-selected element already\n      // shows a selection outline via `.selected-box`; painting a\n      // hover outline on top creates double-outline visual noise\n      // (user feedback 2026-04-19 \"tránh messup\"). Predicate is\n      // defensive: covers both the direct UIManager call path AND\n      // any future caller that forgets to check selection state.\n      if (typeof ((_this$host4 = this.host) === null || _this$host4 === void 0 ? void 0 : _this$host4.getSelectedElement) === 'function' && this.host.getSelectedElement() === this) {\n        // Also tear down any lingering hover overlay from a prior\n        // mousemove frame — the selection just landed and the\n        // hover should be gone instantly, not after the 50 ms\n        // debounce tail.\n        this.removeHoverHightlight();\n        return;\n      }\n      if (!this.hoveringBox) {\n        var _this$host5;\n        this.hoveringBox = document.createElement('div');\n        this.hoveringBox.classList.add('hovering-box');\n\n        // Element-type chip (W2.2 — hidden by default; gated on\n        // `body.bjs-hover-type-badge-on`).\n        var labelHtml = \"<div class=\\\"hovering-label\\\">\".concat(this.getName(), \"</div>\");\n\n        // PLAN_EFFECT W2.3 — Inspect-mode children (hidden by default;\n        // gated on `body.bjs-inspect-active` AND `body.bjs-inspect-\n        // mode-on` together via CSS — both must be true to render).\n        // Geometry is recomputed by `_layoutHoverInspect()` below on\n        // every reflow via the same `__layoutHook` channel\n        // matchingDomNode exposes.\n        //\n        // Layout per-side:\n        //   .bjs-hover-inspect-content — content rect (inside padding)\n        //   .bjs-hover-inspect-pad-{top|right|bottom|left} — 4 strips\n        //   .bjs-hover-inspect-dim — \"W × H\" chip on the content rect\n        var inspectHtml = \"\\n                <div class=\\\"bjs-hover-inspect-content\\\"></div>\\n                <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-top\\\"></div>\\n                <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-right\\\"></div>\\n                <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-bottom\\\"></div>\\n                <div class=\\\"bjs-hover-inspect-pad bjs-hover-inspect-pad-left\\\"></div>\\n                <div class=\\\"bjs-hover-inspect-dim\\\"></div>\\n            \";\n        this.hoveringBox.innerHTML = labelHtml + inspectHtml;\n\n        // PLAN_EFFECT W2.3 — if Alt is currently held when this hover\n        // mounts, paint inspect-on from frame ZERO. Otherwise the\n        // user would see one quiet-hover frame before the global\n        // listener catches up. State lives on `host._inspectAltDown`\n        // (NOT body class) — see HARD RULE C revised.\n        if ((_this$host5 = this.host) !== null && _this$host5 !== void 0 && _this$host5._inspectAltDown) {\n          this.hoveringBox.classList.add('bjs-inspect-active');\n        }\n        document.body.appendChild(this.hoveringBox);\n      }\n\n      // Re-position on every reflow. The 4th `afterPosSize` arg runs\n      // AFTER the box has been positioned + sized, so we can safely\n      // read width/height for the inspect-overlay layout. The hook\n      // runs even when inspect mode is OFF (cost is one\n      // getComputedStyle per reflow); CSS hides the children when\n      // the inspect body classes aren't present, so the no-op cost\n      // is negligible.\n      this.matchingDomNode(this.hoveringBox, 0, null, function () {\n        _this8._layoutHoverInspect();\n      });\n    }\n\n    /**\n     * PLAN_EFFECT W2.3 — Inspect-mode child layout.\n     *\n     * Reads computed padding from the hovered element + sizes the 4\n     * `.bjs-hover-inspect-pad-*` strips + `.bjs-hover-inspect-content`\n     * rect + `.bjs-hover-inspect-dim` chip accordingly. Called from\n     * the `matchingDomNode` layout hook on every reflow.\n     *\n     * Why getComputedStyle and not formatter? Hover overlay paints on\n     * EVERY hoverable element, not just elements with our padding-\n     * format contract. Computed style works uniformly across every\n     * element, including text nodes inside containers we don't own.\n     */\n  }, {\n    key: \"_layoutHoverInspect\",\n    value: function _layoutHoverInspect() {\n      var _this9 = this;\n      if (!this.hoveringBox || !this.domNode) return;\n      var dom = this.domNode;\n      var cs = dom.ownerDocument.defaultView.getComputedStyle(dom);\n      var pt = parseFloat(cs.paddingTop) || 0;\n      var pr = parseFloat(cs.paddingRight) || 0;\n      var pb = parseFloat(cs.paddingBottom) || 0;\n      var pl = parseFloat(cs.paddingLeft) || 0;\n\n      // Use the hover-box's own rect (it already matches the element\n      // via matchingDomNode) instead of dom.getBoundingClientRect()\n      // — avoids the iframe → viewport translation since hover-box\n      // is already in viewport coords.\n      var W = parseFloat(this.hoveringBox.style.width) || this.hoveringBox.offsetWidth;\n      var H = parseFloat(this.hoveringBox.style.height) || this.hoveringBox.offsetHeight;\n      var contentW = Math.max(0, W - pl - pr);\n      var contentH = Math.max(0, H - pt - pb);\n      var set = function set(cls, style) {\n        var el = _this9.hoveringBox.querySelector('.' + cls);\n        if (el) Object.assign(el.style, style);\n      };\n      set('bjs-hover-inspect-content', {\n        top: pt + 'px',\n        left: pl + 'px',\n        width: contentW + 'px',\n        height: contentH + 'px'\n      });\n      set('bjs-hover-inspect-pad-top', {\n        top: '0',\n        left: '0',\n        width: '100%',\n        height: pt + 'px'\n      });\n      set('bjs-hover-inspect-pad-right', {\n        top: pt + 'px',\n        right: '0',\n        width: pr + 'px',\n        height: contentH + 'px'\n      });\n      set('bjs-hover-inspect-pad-bottom', {\n        bottom: '0',\n        left: '0',\n        width: '100%',\n        height: pb + 'px'\n      });\n      set('bjs-hover-inspect-pad-left', {\n        top: pt + 'px',\n        left: '0',\n        width: pl + 'px',\n        height: contentH + 'px'\n      });\n      var dim = this.hoveringBox.querySelector('.bjs-hover-inspect-dim');\n      if (dim) {\n        dim.textContent = \"\".concat(Math.round(W), \" \\xD7 \").concat(Math.round(H));\n      }\n    }\n  }, {\n    key: \"removeHoverHightlight\",\n    value: function removeHoverHightlight() {\n      if (this.hoveringBox) {\n        if (typeof this.hoveringBox.__disconnectObservers === 'function') {\n          this.hoveringBox.__disconnectObservers();\n        }\n        this.hoveringBox.remove();\n      }\n      this.hoveringBox = null;\n    }\n\n    /* SELECTED EFFECTS */\n  }, {\n    key: \"addSelectedHighlight\",\n    value: function addSelectedHighlight() {\n      var _this10 = this;\n      // render selected outbound\n      if (!this.selectedBox) {\n        this.selectedBox = document.createElement('div');\n        this.selectedBox.classList.add('selected-box');\n\n        // Append it to the body\n        document.body.appendChild(this.selectedBox);\n\n        //\n        this.matchingDomNode(this.selectedBox, 5);\n      }\n\n      // Render actions\n      if (!this.actionsBox) {\n        this.actionsBox = document.createElement('div');\n        this.actionsBox.classList.add('actions-box');\n        this.actionsBox.classList.add('d-flex');\n        this.actionsBox.classList.add('align-items-center');\n        // Opt out of canvas-clip — the toolbar pill MUST escape the\n        // canvas top edge (its preferred-side=\"above\" places it\n        // 9 px above the selection outline; clipping would chop the\n        // pill off when the selected element sits at canvas top).\n        // See OVERLAY.md §24 Canvas-clip contract.\n        this.actionsBox.classList.add('bjs-ovl-no-clip');\n        // Append it to the body\n        document.body.appendChild(this.actionsBox);\n        // \n        this.matchingDomNode(this.actionsBox, 5, function () {\n          if (!_this10.actionsBox) {\n            return;\n          }\n\n          // Viewport-space element rect — same math as every other\n          // overlay, see OVERLAY.md §4 I2 for the single-source\n          // rule. `absoluteTop` / `absoluteLeft` are passed unchanged\n          // to the positioner below.\n          var domRect = _this10.domNode.getBoundingClientRect();\n          var iframe = _this10.domNode.ownerDocument.defaultView.frameElement;\n          var iframeRect = iframe.getBoundingClientRect();\n          var absoluteTop = iframeRect.top + domRect.top;\n          var absoluteLeft = iframeRect.left + domRect.left;\n\n          // PLAN_EFFECT W1.2 (final) — the `.actions-box` is now a\n          // SINGLE unified pill docked to the element's left edge.\n          // Name section + actions section live inside one pill\n          // chrome with an internal vertical divider (see CSS).\n          // JS owns only: top / left positioning (via\n          // ToolbarPositioner) + diagnostic data-attrs (`data-side`,\n          // `data-did-flip`, `data-did-clamp`) so CSS can tint the\n          // pill when the positioner picked the non-preferred side.\n          // Width + height flow from CSS (intrinsic `max-content`);\n          // the 240 / 30 values below feed the positioner only for\n          // horizontal-clamp + flip math.\n          var toolbar = {\n            width: 240,\n            height: 36\n          };\n          // 9 px gap = tight visible air-gap between pill and the\n          // `.selected-box` outline+halo (halo ~3 px outward). Reduced\n          // from 14 → 9 after user feedback 2026-04-19 — pulls the\n          // pill 5 px closer to the element on BOTH `above` (pill\n          // shifts DOWN) and `below` (pill shifts UP) branches.\n          var gap = 9;\n\n          // -1 px horizontal inset so the pill's left edge lines up\n          // with the selection outline's visible left edge — the\n          // `.selected-box` uses `outline-offset: -1px`, so its\n          // visual outer edge sits at `element.left - ~1 px`.\n          // Without this nudge the pill shows as slightly indented\n          // from the outline (user feedback 2026-04-19).\n          var pos = _this10.host.toolbarPositioner.compute({\n            elementRect: {\n              top: absoluteTop,\n              left: absoluteLeft - 1,\n              width: domRect.width,\n              height: domRect.height\n            },\n            toolbar: toolbar,\n            viewport: {\n              width: window.innerWidth,\n              height: window.innerHeight\n            },\n            gap: gap,\n            preferredSide: 'above'\n          });\n          _this10.actionsBox.dataset.side = pos.side;\n          _this10.actionsBox.dataset.didFlip = String(pos.didFlip);\n          _this10.actionsBox.dataset.didClamp = String(pos.didClamp);\n          Object.assign(_this10.actionsBox.style, {\n            position: 'fixed',\n            top: \"\".concat(pos.top, \"px\"),\n            left: \"\".concat(pos.left, \"px\")\n            // width / height intentionally absent — let CSS drive\n            // intrinsic sizing so the pill fits its own contents.\n          });\n        });\n\n        // Label\n        this.actionsBoxLabel = document.createElement('h6');\n        this.actionsBoxLabel.classList.add('ms-2');\n        this.actionsBoxLabel.classList.add('m-0');\n        this.actionsBoxLabel.classList.add('text-light');\n        this.actionsBoxLabel.innerHTML = '<span class=\"d-flex align-items-center\"><span class=\"material-symbols-rounded me-2\">apps</span>' + this.getName() + '</span>';\n        this.actionsBox.appendChild(this.actionsBoxLabel);\n        this.actionsBoxInner = document.createElement('div');\n        this.actionsBoxInner.classList.add('actions-box-inner');\n        this.actionsBoxInner.classList.add('btn-group');\n        this.actionsBoxInner.classList.add('border');\n        this.actionsBoxInner.classList.add('ms-auto');\n        this.actionsBoxInner.classList.add('me-2');\n        this.actionsBoxInner = document.createElement('div');\n        this.actionsBoxInner.classList.add('actions-box-inner');\n        this.actionsBoxInner.classList.add('btn-group');\n        // this.actionsBoxInner.classList.add('border');\n        this.actionsBoxInner.classList.add('ms-auto');\n        // Append it to the body\n        this.actionsBox.appendChild(this.actionsBoxInner);\n        this.getActions().forEach(function (action) {\n          var actionButton = document.createElement('button');\n          actionButton.setAttribute('class', 'element-action-item btn btn-light p-1 d-flex align-items-center');\n          actionButton.setAttribute('data-tooltip', action.label);\n          actionButton.setAttribute('aria-label', action.label);\n          actionButton.innerHTML = \"\\n                    <span class=\\\"material-symbols-rounded fs-5\\\">\" + action.icon + \"</span>\\n                \";\n          _this10.actionsBoxInner.appendChild(actionButton);\n\n          // events\n          actionButton.addEventListener('click', function () {\n            action.run();\n          });\n        });\n\n        // PLAN_EFFECT W1.4 — focus-dim toggle inside every pill so the\n        // feature is always one click from the selected element, not\n        // hidden behind a keyboard shortcut only. Click flips state,\n        // button `is-active` class mirrors the current state. Uses the\n        // shared `contrast` Material icon.\n        this._appendFocusDimToggle(this.actionsBoxInner);\n      }\n    }\n\n    /** Helper shared by BaseElement + ImageElement (via super) — appends a\n     *  focus-dim toggle button into the given actions-box-inner container.\n     *  Icon swaps between `light_mode` (sun — focus-dim OFF, page bright)\n     *  and `dark_mode` (moon — focus-dim ON, page dimmed). No active-state\n     *  fill; icon change alone communicates state, which reads cleaner\n     *  than a filled chip (user feedback 2026-04-19 \"button thô quá\"). */\n  }, {\n    key: \"_appendFocusDimToggle\",\n    value: function _appendFocusDimToggle(container) {\n      var _this11 = this;\n      if (!container) return;\n      var btn = document.createElement('button');\n      btn.setAttribute('class', 'element-action-item btn btn-light p-1 d-flex align-items-center bjs-focus-dim-toggle');\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded fs-5';\n      btn.appendChild(icon);\n      var sync = function sync() {\n        var _this11$host;\n        var on = typeof ((_this11$host = _this11.host) === null || _this11$host === void 0 ? void 0 : _this11$host.isFocusDim) === 'function' && _this11.host.isFocusDim();\n        icon.textContent = on ? 'dark_mode' : 'light_mode';\n        var _tipText = (on ? 'Focus mode: ON' : 'Focus mode: OFF') + ' (⌘/Ctrl+.)';\n        btn.setAttribute('data-tooltip', _tipText);\n        btn.setAttribute('aria-label', _tipText);\n        btn.setAttribute('aria-pressed', on ? 'true' : 'false');\n      };\n      sync();\n      btn.addEventListener('click', function (e) {\n        var _this11$host2;\n        e.stopPropagation();\n        if (typeof ((_this11$host2 = _this11.host) === null || _this11$host2 === void 0 ? void 0 : _this11$host2.toggleFocusDim) === 'function') {\n          _this11.host.toggleFocusDim();\n          sync();\n        }\n      });\n      container.appendChild(btn);\n    }\n  }, {\n    key: \"removeSelectedHighlight\",\n    value: function removeSelectedHighlight() {\n      // remove selected outbound\n      if (this.selectedBox) {\n        if (typeof this.selectedBox.__disconnectObservers === 'function') {\n          this.selectedBox.__disconnectObservers();\n        }\n        this.selectedBox.remove();\n      }\n      this.selectedBox = null;\n\n      // remove selected actions\n      if (this.actionsBox) {\n        if (typeof this.actionsBox.__disconnectObservers === 'function') {\n          this.actionsBox.__disconnectObservers();\n        }\n        this.actionsBox.remove();\n      }\n      this.actionsBox = null;\n    }\n  }, {\n    key: \"getActions\",\n    value: function getActions() {\n      var _this12 = this;\n      var actions = [{\n        icon: 'content_copy',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.copy'),\n        run: function run() {\n          _this12.duplicate();\n        }\n      }, {\n        icon: 'delete',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.remove'),\n        run: function run() {\n          _this12.remove(); // @todo dependency\n        }\n      }];\n      if (this.container) {\n        actions.unshift({\n          icon: 'arrow_circle_up',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.select_parent'),\n          run: function run() {\n            _this12.host.selectElement(_this12.container); // @todo dependency\n          }\n        });\n      }\n      actions.push({\n        icon: 'remove_selection',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.unselect'),\n        run: function run() {\n          _this12.host.unselect();\n        }\n      });\n      return actions;\n    }\n\n    /* DROP INSIDE EFFECTS */\n  }, {\n    key: \"addDropBeforeHighlight\",\n    value: function addDropBeforeHighlight() {\n      // remove other effects\n      this.removeDropHighlight();\n      if (!this.dropBeforeBox) {\n        this.dropBeforeBox = document.createElement('div');\n        this.dropBeforeBox.classList.add('drop-before-box');\n\n        // Append it to the body\n        document.body.appendChild(this.dropBeforeBox);\n      }\n      this.matchingDomNode(this.dropBeforeBox);\n    }\n  }, {\n    key: \"addDropAfterHighlight\",\n    value: function addDropAfterHighlight() {\n      // remove other effects\n      this.removeDropHighlight();\n      if (!this.dropAfterBox) {\n        this.dropAfterBox = document.createElement('div');\n        this.dropAfterBox.classList.add('drop-after-box');\n\n        // Append it to the body\n        document.body.appendChild(this.dropAfterBox);\n      }\n      this.matchingDomNode(this.dropAfterBox);\n    }\n  }, {\n    key: \"addDropInsideHighlight\",\n    value: function addDropInsideHighlight() {\n      // remove other effects\n      this.removeDropHighlight();\n      if (!this.dropInsideBox) {\n        this.dropInsideBox = document.createElement('div');\n        this.dropInsideBox.classList.add('drop-inside-box');\n\n        // Append it to the body\n        document.body.appendChild(this.dropInsideBox);\n      }\n      this.matchingDomNode(this.dropInsideBox);\n    }\n  }, {\n    key: \"removeDropHighlight\",\n    value: function removeDropHighlight() {\n      // remove drop inside\n      if (this.dropInsideBox) {\n        if (typeof this.dropInsideBox.__disconnectObservers === 'function') {\n          this.dropInsideBox.__disconnectObservers();\n        }\n        this.dropInsideBox.remove();\n      }\n      this.dropInsideBox = null;\n\n      // remove drop before\n      if (this.dropBeforeBox) {\n        if (typeof this.dropBeforeBox.__disconnectObservers === 'function') {\n          this.dropBeforeBox.__disconnectObservers();\n        }\n        this.dropBeforeBox.remove();\n      }\n      this.dropBeforeBox = null;\n\n      // remove drop after\n      if (this.dropAfterBox) {\n        if (typeof this.dropAfterBox.__disconnectObservers === 'function') {\n          this.dropAfterBox.__disconnectObservers();\n        }\n        this.dropAfterBox.remove();\n      }\n      this.dropAfterBox = null;\n    }\n  }, {\n    key: \"addContainerHightlight\",\n    value: function addContainerHightlight(element) {\n      var _this13 = this;\n      // Skip the hover container-highlight when THIS container is already\n      // part of the current selection — either THIS is the selected\n      // element (redundant with its own selection outline — user feedback\n      // 2026-04-19 image 2) or THIS is the parent of the selected child\n      // (selection already communicates \"active\"; adding hover chrome on\n      // top reads as noise). Bailing out early avoids spawning boxes\n      // we'll immediately remove.\n      var _selectedForGuard = this.host.getSelectedElement();\n      if (_selectedForGuard && (_selectedForGuard === this || _selectedForGuard.container === this)) {\n        this.removeContainerHightlight();\n        return;\n      }\n      if (!this.containerBox) {\n        this.containerBox = document.createElement('div');\n        this.containerBox.classList.add('container-box');\n\n        // //\n        // this.containerBox.innerHTML = `\n        //     <div class=\"container-label\">`+this.getClassName()+`</div>\n        // `;\n\n        // Append it to the body\n        document.body.appendChild(this.containerBox);\n      }\n      this.matchingDomNode(this.containerBox);\n      if (!this.containerHighlightBox) {\n        this.containerHighlightBox = document.createElement('div');\n        this.containerHighlightBox.classList.add('container-selected-highlight-box');\n        // Mount the full-rect hatch layer via the holed-box primitive\n        // (.bjs-holed-box.--hatch + inline clip-path). Single gradient,\n        // single origin — stripes flow continuously across every seam.\n        // Helper `holedBoxClipPath` handles the winding-trick polygon;\n        // see src/includes/ui/holedBoxClipPath.js + docs/plans/HOLED_BOX.md.\n        this.containerHighlightBox.innerHTML = \"\\n                <div class=\\\"bjs-holed-box bjs-holed-box--hatch\\\" data-role=\\\"hatch\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-1\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-2\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-3\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-4\\\"></div>\\n            \";\n\n        // Append it to the body\n        document.body.appendChild(this.containerHighlightBox);\n      }\n      this.matchingDomNode(this.containerHighlightBox, 0, null, function () {\n        if (!_this13.containerHighlightBox) {\n          return;\n        }\n\n        // Use iframe-relative rects from the same coordinate space to avoid\n        // cross-document subpixel rounding differences between browsers.\n        // Both domNodes live inside the same iframe, so their getBoundingClientRect\n        // values are directly comparable without converting through iframeRect.\n        var childRect = element.domNode.getBoundingClientRect();\n        var containerDomRect = _this13.domNode.getBoundingClientRect();\n\n        // Padding areas between the container and child element.\n        // Math.max(0, ...) guards against negative values from subpixel rounding —\n        // a negative width/height is invalid CSS and browsers silently ignore it,\n        // causing the CSS class default (width:100%) to take effect instead.\n        var topPadding = Math.max(0, childRect.top - containerDomRect.top);\n        var rightPadding = Math.max(0, containerDomRect.right - childRect.right);\n        var bottomPadding = Math.max(0, containerDomRect.bottom - childRect.bottom);\n        var leftPadding = Math.max(0, childRect.left - containerDomRect.left);\n        var childWidth = childRect.width;\n        var containerWidth = containerDomRect.width;\n        var containerHeight = containerDomRect.height;\n\n        // Box 1 — top strip, top-left corner at (leftPadding, 0)\n        var box1 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-1');\n        box1.style.height = topPadding + 'px';\n        box1.style.left = leftPadding + 'px';\n        box1.style.width = childWidth + 'px';\n\n        // Box 2 — right strip, top-left corner at (containerWidth - rightPadding, 0)\n        var box2 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-2');\n        box2.style.width = rightPadding + 'px';\n\n        // Box 3 — bottom strip, top-left corner at (leftPadding, containerHeight - bottomPadding)\n        var box3 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-3');\n        box3.style.height = bottomPadding + 'px';\n        box3.style.left = leftPadding + 'px';\n        box3.style.width = childWidth + 'px';\n\n        // Box 4 — left strip, top-left corner at (0, 0)\n        var box4 = _this13.containerHighlightBox.querySelector('.container-selected-highlight-box-4');\n        box4.style.width = leftPadding + 'px';\n\n        // Holed-box hatch frame — carve the child rect out of a full\n        // container hatch via clip-path. Helper handles the winding\n        // trick; see src/includes/ui/holedBoxClipPath.js.\n        var hatch = _this13.containerHighlightBox.querySelector('[data-role=\"hatch\"]');\n        if (hatch) {\n          hatch.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"])({\n            width: containerWidth,\n            height: containerHeight\n          }, {\n            left: leftPadding,\n            top: topPadding,\n            right: containerWidth - rightPadding,\n            bottom: containerHeight - bottomPadding\n          });\n        }\n      });\n    }\n  }, {\n    key: \"removeContainerHightlight\",\n    value: function removeContainerHightlight() {\n      if (this.containerBox) {\n        if (typeof this.containerBox.__disconnectObservers === 'function') {\n          this.containerBox.__disconnectObservers();\n        }\n        this.containerBox.remove();\n      }\n      this.containerBox = null;\n      if (this.containerHighlightBox) {\n        if (typeof this.containerHighlightBox.__disconnectObservers === 'function') {\n          this.containerHighlightBox.__disconnectObservers();\n        }\n        this.containerHighlightBox.remove();\n      }\n      this.containerHighlightBox = null;\n    }\n  }, {\n    key: \"addContainerSelectedHightlight\",\n    value: function addContainerSelectedHightlight(element) {\n      var _this14 = this;\n      this.removeContainerHightlight();\n      if (!this.containerSelectedBox) {\n        this.containerSelectedBox = document.createElement('div');\n        this.containerSelectedBox.classList.add('container-selected-highlight-box');\n        this.containerSelectedBox.innerHTML = \"\\n                <div class=\\\"bjs-holed-box bjs-holed-box--hatch\\\" data-role=\\\"hatch\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-1\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-2\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-3\\\"></div>\\n                <div class=\\\"inside-box container-selected-highlight-box-4\\\"></div>\\n            \";\n\n        // //\n        // this.containerBox.innerHTML = `\n        //     <div class=\"container-label\">`+this.getClassName()+`</div>\n        // `;\n\n        // Append it to the body\n        document.body.appendChild(this.containerSelectedBox);\n      }\n      this.matchingDomNode(this.containerSelectedBox, 0, null, function () {\n        if (!_this14.containerSelectedBox) {\n          return;\n        }\n\n        // Same iframe-relative rect approach as addContainerHightlight —\n        // avoids cross-document subpixel rounding that breaks Chrome.\n        var childRect = element.domNode.getBoundingClientRect();\n        var containerDomRect = _this14.domNode.getBoundingClientRect();\n        var topPadding = Math.max(0, childRect.top - containerDomRect.top);\n        var rightPadding = Math.max(0, containerDomRect.right - childRect.right);\n        var bottomPadding = Math.max(0, containerDomRect.bottom - childRect.bottom);\n        var leftPadding = Math.max(0, childRect.left - containerDomRect.left);\n        var childWidth = childRect.width;\n        var containerWidth = containerDomRect.width;\n        var containerHeight = containerDomRect.height;\n\n        // Box 1 — top strip, top-left corner at (leftPadding, 0)\n        var box1 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-1');\n        box1.style.height = topPadding + 'px';\n        box1.style.left = leftPadding + 'px';\n        box1.style.width = childWidth + 'px';\n\n        // Box 2 — right strip, top-left corner at (containerWidth - rightPadding, 0)\n        var box2 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-2');\n        box2.style.width = rightPadding + 'px';\n\n        // Box 3 — bottom strip, top-left corner at (leftPadding, containerHeight - bottomPadding)\n        var box3 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-3');\n        box3.style.height = bottomPadding + 'px';\n        box3.style.left = leftPadding + 'px';\n        box3.style.width = childWidth + 'px';\n\n        // Box 4 — left strip, top-left corner at (0, 0)\n        var box4 = _this14.containerSelectedBox.querySelector('.container-selected-highlight-box-4');\n        box4.style.width = leftPadding + 'px';\n\n        // Holed-box hatch frame — see addContainerHightlight for the\n        // full rationale. Single gradient + clip-path = no seam jog.\n        var hatch = _this14.containerSelectedBox.querySelector('[data-role=\"hatch\"]');\n        if (hatch) {\n          hatch.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"])({\n            width: containerWidth,\n            height: containerHeight\n          }, {\n            left: leftPadding,\n            top: topPadding,\n            right: containerWidth - rightPadding,\n            bottom: containerHeight - bottomPadding\n          });\n        }\n      });\n    }\n  }, {\n    key: \"removeContainerSelectedHightlight\",\n    value: function removeContainerSelectedHightlight() {\n      if (this.containerSelectedBox) {\n        if (typeof this.containerSelectedBox.__disconnectObservers === 'function') {\n          this.containerSelectedBox.__disconnectObservers();\n        }\n        this.containerSelectedBox.remove();\n      }\n      this.containerSelectedBox = null;\n    }\n  }, {\n    key: \"addContainerDropHightlight\",\n    value: function addContainerDropHightlight() {\n      if (!this.containerDropBox) {\n        this.containerDropBox = document.createElement('div');\n        this.containerDropBox.classList.add('container-drop-box');\n\n        // //\n        // this.containerDropBox.innerHTML = `\n        //     <div class=\"container-label\">`+this.getClassName()+`</div>\n        // `;\n\n        // Append it to the body\n        document.body.appendChild(this.containerDropBox);\n      }\n      this.matchingDomNode(this.containerDropBox);\n    }\n  }, {\n    key: \"removeContainerDropHightlight\",\n    value: function removeContainerDropHightlight() {\n      if (this.containerDropBox) {\n        if (typeof this.containerDropBox.__disconnectObservers === 'function') {\n          this.containerDropBox.__disconnectObservers();\n        }\n        this.containerDropBox.remove();\n      }\n      this.containerDropBox = null;\n    }\n  }, {\n    key: \"checkIfThePositionIsBefore\",\n    value: function checkIfThePositionIsBefore(clientX, clientY) {\n      var hoveredBlock = this.domNode;\n      var hoveredBlockRect = hoveredBlock.getBoundingClientRect();\n      return clientY < hoveredBlockRect.top + hoveredBlockRect.height / 2;\n    }\n\n    // W0.2b — legacy `applyInlineEdit()` method removed. The new framework\n    // (`registerInlineEdit` + auto-fired `_wireInlineEdit` from `afterRender`)\n    // replaces both the legacy method AND the per-element wire blocks. See\n    // docs/core/ELEMENT_DEFINITION.md → \"Inline editing — registerInlineEdit\"\n    // and BUILDER.md Lesson 49.\n  }], [{\n    key: \"parseFormats\",\n    value: function parseFormats(instance, data) {\n      if (instance && instance.formatter && data && data.formats && typeof instance.formatter.parseFormats === 'function') {\n        instance.formatter.parseFormats(data.formats);\n      }\n      return instance;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseElement.js?");

/***/ }),

/***/ "./src/includes/BaseOverlay.js":
/*!*************************************!*\
  !*** ./src/includes/BaseOverlay.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * BaseOverlay — base class for canvas overlays.\n *\n * See docs/core/OVERLAY.md for full design spec.\n * See docs/archived/OVERLAY_PLAN.md for phased implementation + SA invariants.\n *\n * Overlays are the on-canvas sibling of Controls:\n *   Controls edit the element from the sidebar (getControls()).\n *   Overlays edit the element from the canvas  (getOverlays()).\n *\n * Subclasses MUST:\n *   - override render() to build this.domNode\n *   - optionally override getTrigger() ('select' | 'hover' | 'always' | 'edit')\n *   - optionally override position() — but always delegate to\n *     this.element.matchingDomNode() for iframe-aware positioning\n *\n * Subclasses MUST NOT:\n *   - appendChild to the iframe document (overlays live in parent document.body)\n *   - call builder.renderElementControls() in pointer/keystroke handlers (NO-FLICKER)\n *   - duplicate iframe math (use matchingDomNode)\n *\n * Phase 1.9 (SA I15) — Error isolation: mount + destroy wrap render() /\n * beforeDestroy() in try/catch so a bug in one overlay can't kill element\n * lifecycle. A failed mount leaves mounted=false + domNode=null so the\n * element is still selectable. Errors route to BJS.error with the overlay\n * class name as tag.\n */\n\nvar BaseOverlay = /*#__PURE__*/function () {\n  function BaseOverlay(element) {\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, BaseOverlay);\n    this.element = element; // owning Element\n    this.opts = opts; // subclass-specific config\n    this.domNode = null; // floating box; created by render(), appended by mount()\n    this.mounted = false;\n\n    /**\n     * Back-reference to the owning Builder. Set by Builder._adopt()\n     * which walks element.overlays after parse. Available in\n     * afterMount(), event handlers, beforeDestroy(). NOT guaranteed\n     * inside the overlay constructor — defer host-dependent setup\n     * to afterMount(). See BUILDER.md \"Host Injection\" lesson.\n     */\n    this.host = null;\n  }\n\n  // ─── Subclasses override ─────────────────────────────────────\n\n  /** Declare when this overlay should be mounted. */\n  return _createClass(BaseOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    } // 'select' | 'hover' | 'always' | 'edit'\n\n    /** Build this.domNode and bind DOM/pointer events.\n     *  Do NOT append to document here — mount() does that. */\n  }, {\n    key: \"render\",\n    value: function render() {\n      throw new Error('BaseOverlay.render() is abstract — subclass must build this.domNode');\n    }\n\n    /** Called after this.domNode is appended and first positioned. Safe to\n     *  do size-dependent init here (child layout, scroll-to, focus). */\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {}\n\n    /** Called right before this.domNode is removed. Use to flush pending\n     *  state, clear timers, release resources, remove document-level listeners. */\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {}\n\n    // ─── Framework-provided (usually not overridden) ────────────\n  }, {\n    key: \"mount\",\n    value: function mount() {\n      if (this.mounted) return;\n      var tag = \"overlay:\".concat(this.constructor.name, \":mount\");\n      try {\n        if (!this.domNode) this.render();\n        if (!this.domNode) throw new Error('render() returned without assigning this.domNode');\n        // Namespace marker so UIManager's parent-doc hover-clear exemption\n        // (§4.I6) can identify overlay nodes and skip the clear.\n        this.domNode.classList.add('bjs-ovl');\n        // Always append to parent document (never iframe). This is what\n        // makes iframe-boundary pointer capture work (§4.I10).\n        document.body.appendChild(this.domNode);\n        this.position();\n        this.mounted = true;\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log(tag, this.element && this.element.id);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(tag, err);\n        // Roll back partial state so the element stays selectable.\n        if (this.domNode && this.domNode.parentNode) {\n          try {\n            this.domNode.parentNode.removeChild(this.domNode);\n          } catch (_) {/* no-op */}\n        }\n        this.domNode = null;\n        this.mounted = false;\n        return;\n      }\n      // afterMount is a separate try so a broken afterMount doesn't unmount\n      // a successfully-rendered overlay.\n      try {\n        this.afterMount();\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(\"overlay:\".concat(this.constructor.name, \":afterMount\"), err);\n      }\n    }\n\n    /** Default position: full-element box with zero padding.\n     *  Override to anchor to a sub-region — but always delegate to\n     *  this.element.matchingDomNode() (§4.I8 centralised positioning). */\n  }, {\n    key: \"position\",\n    value: function position() {\n      this.element.matchingDomNode(this.domNode, 0);\n    }\n  }, {\n    key: \"show\",\n    value: function show() {\n      if (this.domNode) this.domNode.style.display = '';\n    }\n  }, {\n    key: \"hide\",\n    value: function hide() {\n      if (this.domNode) this.domNode.style.display = 'none';\n    }\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (!this.domNode) return;\n      var tag = \"overlay:\".concat(this.constructor.name, \":destroy\");\n      // beforeDestroy is caught so a broken hook can't leave observers\n      // attached — the unmount path below still runs.\n      try {\n        this.beforeDestroy();\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(\"\".concat(tag, \":beforeDestroy\"), err);\n      }\n      try {\n        // Release observers attached by matchingDomNode (MutationObserver +\n        // ResizeObserver + window.document + iframeWindow scroll/resize).\n        if (typeof this.domNode.__disconnectObservers === 'function') {\n          this.domNode.__disconnectObservers();\n        }\n        this.domNode.remove();\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log(tag, this.element && this.element.id);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(tag, err);\n      } finally {\n        this.domNode = null;\n        this.mounted = false;\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseOverlay.js?");

/***/ }),

/***/ "./src/includes/BaseWidget.js":
/*!************************************!*\
  !*** ./src/includes/BaseWidget.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar BaseWidget = /*#__PURE__*/function () {\n  function BaseWidget() {\n    _classCallCheck(this, BaseWidget);\n    this.domNode = null;\n\n    // new Block for this widget\n    this.block = new BlockElement('Block');\n  }\n  return _createClass(BaseWidget, [{\n    key: \"render\",\n    value: function render() {\n      var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'icon';\n      if (!this.domNode) {\n        // Default UI box\n        var widgetDiv = document.createElement('div');\n        this.domNode = widgetDiv;\n      } else {\n        this.domNode.innerHTML = '';\n      }\n\n      //\n      if (type === 'icon') {\n        this.domNode.setAttribute('widget-class', this.constructor.name);\n        this.domNode.className = 'widget-item';\n        var iconDiv = document.createElement('div');\n        iconDiv.innerHTML = '<span class=\"material-symbols-rounded widget-icon\">' + this.getIcon() + '</span>';\n        iconDiv.className = 'widget-icon-box';\n        this.domNode.appendChild(iconDiv);\n        var labelDiv = document.createElement('div');\n        labelDiv.className = 'widget-label';\n        labelDiv.textContent = this.getName();\n        this.domNode.appendChild(labelDiv);\n      } else if (type === 'image') {\n        this.domNode.setAttribute('widget-class', this.constructor.name);\n        this.domNode.className = 'widget-item widget-item-image';\n        var imageDiv = document.createElement('div');\n        var imgSrc = this.getImageUrl();\n        imageDiv.innerHTML = '<img src=\"' + imgSrc + '\" alt=\"' + this.getName() + '\" class=\"widget-image-box\"/>';\n        this.domNode.appendChild(imageDiv);\n\n        // const labelDiv = document.createElement('div');\n        // labelDiv.className = 'widget-label';\n        // labelDiv.textContent = this.getName();\n        // this.domNode.appendChild(labelDiv);\n      }\n      return this.domNode;\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return null;\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'extension';\n    }\n  }, {\n    key: \"addDragAnchor\",\n    value: function addDragAnchor() {}\n  }, {\n    key: \"getDragAnchor\",\n    value: function getDragAnchor() {\n      this.domNode.setAttribute('draggable', 'true');\n      return this.domNode;\n    }\n  }, {\n    key: \"hideDragAnchor\",\n    value: function hideDragAnchor() {\n      // do nothing\n    }\n  }, {\n    key: \"showDragAnchor\",\n    value: function showDragAnchor() {\n      // do nothing\n    }\n  }, {\n    key: \"removeAfterDrop\",\n    value: function removeAfterDrop() {\n      return false;\n    }\n  }, {\n    key: \"canDropOn\",\n    value: function canDropOn(element) {\n      if (!element.isDroppable()) return false;\n\n      // Grid-inside-Cell restriction.\n      //\n      // Widgets carry a wrapping Block (this.block) whose .elements[] holds\n      // the widget's actual content. When a widget contains a GridElement\n      // (ImageTextLeftWidget, ImageTextRightWidget, ImageTextDoubleWidget,\n      // GridWidget, TextLeftWidget/TextDoubleWidget, PricingCardsWidget,\n      // CheckoutWidget, RSSWidget, MenuWidget, …) it cannot legally land\n      // INSIDE a Cell — nested Grids inside Cells are blocked by the\n      // schema (CellElement.isDroppable=true is for child-Block targets;\n      // Block-with-Grid sibling of an inner Block inside a Cell would\n      // still be a Grid nested inside a Cell once the wrapping Block\n      // gets adopted). Without this guard, UIManager.getTopDragOveringElement\n      // picks the INNERMOST droppable (the inner Block inside the Cell)\n      // and shows the drop indicator at HALF canvas width — the user\n      // reads that as \"the indicator is half-clipped\" because they\n      // expected the indicator at the OUTER 2-col block (full canvas\n      // width) where the drop would actually make sense.\n      //\n      // Pre-fix this method read `this.getElements()` which doesn't exist\n      // on BaseWidget — `getElements` is a BlockElement method. The check\n      // silently returned an empty array and the restriction never fired\n      // (2026-05-14: \"drop after/before highlight bị che mất 1 nửa\").\n      // Fix: walk `this.block.elements` (the widget's actual content) and\n      // also recurse one level into nested Grids to cover widgets whose\n      // Grid lives at a deeper depth.\n      if (this._widgetContainsGrid() && this._targetIsInsideCell(element)) {\n        return false;\n      }\n      return true;\n    }\n\n    /** True when the widget's wrapping block (or any direct child of it)\n     *  is/contains a GridElement. Recursion intentionally shallow — every\n     *  shipped widget either has the Grid at depth 1 or doesn't have one\n     *  at all; deep recursion would mis-fire on Grid-rich page samples\n     *  reused inside other widgets and we have no such case today. */\n  }, {\n    key: \"_widgetContainsGrid\",\n    value: function _widgetContainsGrid() {\n      if (!this.block || !Array.isArray(this.block.elements)) return false;\n      return this.block.elements.some(function (el) {\n        return el && typeof el.getClassName === 'function' && el.getClassName() === 'GridElement';\n      });\n    }\n\n    /** True when `target` is a CellElement (or a descendant whose\n     *  container chain reaches a Cell within 3 hops — covers the\n     *  Block-inside-Cell case the original commented intent referred to). */\n  }, {\n    key: \"_targetIsInsideCell\",\n    value: function _targetIsInsideCell(target) {\n      var node = target;\n      for (var depth = 0; node && depth < 4; depth++) {\n        if (typeof node.getClassName === 'function' && node.getClassName() === 'CellElement') return true;\n        node = node.container;\n      }\n      return false;\n    }\n  }, {\n    key: \"renderBlock\",\n    value: function renderBlock() {\n      // Clone a new block\n      var block = BlockElement.parse(this.block.getData());\n      return block;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BaseWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BaseWidget.js?");

/***/ }),

/***/ "./src/includes/BlockElement.js":
/*!**************************************!*\
  !*** ./src/includes/BlockElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _overlays_BlockDragAnchorOverlay_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./overlays/BlockDragAnchorOverlay.js */ \"./src/includes/overlays/BlockDragAnchorOverlay.js\");\n/* harmony import */ var _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\nvar BlockElement = /*#__PURE__*/function (_BaseElement) {\n  function BlockElement(template) {\n    var _this;\n    _classCallCheck(this, BlockElement);\n    _this = _callSuper(this, BlockElement); // Call the parent class constructor\n    _this.container = null;\n    _this.elements = [];\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['elements'];\n\n    // Formatter\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n      // background\n      background_color: null,\n      background_image: null,\n      background_position: null,\n      background_size: null,\n      background_repeat: null,\n      background_blend_mode: null,\n      opacity: null,\n      filter: null,\n      // border\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_width: null,\n      border_left_style: null,\n      border_left_color: null,\n      // border radius\n      border_radius: null,\n      // padding\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null\n\n      // NOTE: margin intentionally removed 2026-04-17.\n      // BlockElement is a container; margin between blocks was\n      // confusing next to the padding control (users routinely\n      // picked the wrong one). External block spacing is now\n      // always the parent's responsibility — use the Page's\n      // `block_gap` between siblings, or the Cell's padding.\n      // Existing sample JSON with margin_* keys loads cleanly\n      // (Formatter.parseFormats skips unknown keys); a migration\n      // script (scripts/migrate-block-margin-to-padding.cjs)\n      // converts margin_* → padding_* on the same block so the\n      // visual stays intact after re-save.\n    });\n    _this.template = template;\n    return _this;\n  }\n  _inherits(BlockElement, _BaseElement);\n  return _createClass(BlockElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.block');\n    }\n  }, {\n    key: \"isDroppable\",\n    value: function isDroppable() {\n      return true;\n    }\n  }, {\n    key: \"canDropAfter\",\n    value: function canDropAfter() {\n      return this.isDroppable();\n    }\n  }, {\n    key: \"canDropBefore\",\n    value: function canDropBefore() {\n      return this.isDroppable();\n    }\n\n    /**\n     * Cheap in-place style patch — PLAN_EFFECT W3.1 + SA I5.\n     *\n     * BlockElement.template.html wraps children in a single styled div:\n     *     <div style=\"<%- formatter.toStyleStringAll() %>\"> ... </div>\n     *\n     * applyFormatStyles() updates only that wrapper's inline `style`\n     * attribute. Child element DOM + UIManager registrations are left\n     * intact. Any observer anchored to the Block (e.g. the\n     * PaddingVisualizerOverlay's ResizeObserver via matchingDomNode)\n     * sees a normal layout change and re-positions — no teardown /\n     * remount cycle, so no flicker on the canvas.\n     *\n     * Use this for every formatter-only mutation (padding, margin,\n     * background, border) from a Control callback. Fall back to\n     * render() only when the mutation actually changes child structure\n     * (add/remove elements, template swap).\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var inner = this.domNode.firstElementChild;\n      if (!inner) {\n        this.render();\n        return;\n      }\n      inner.setAttribute('style', this.formatter.toStyleStringAll());\n    }\n\n    /**\n     * PLAN_EFFECT W3.7 — cascade-aware padding read.\n     *\n     * Returns the EFFECTIVE padding for a side:\n     *   - This block's own formatter value if it's a non-null number.\n     *   - Otherwise, walk up to the page and read\n     *     `page.block_padding_${side}` (the Page's \"Block default\n     *     padding\" setting, cascaded to every block without an\n     *     explicit padding). Matches the CSS cascade the Page template\n     *     already applies at render time.\n     *   - Zero as a last resort.\n     *\n     * Used by the PaddingVisualizerOverlay via `opts.readSide` so the\n     * on-canvas visualisation reflects what users SEE in the browser,\n     * not just what's stored in their own formatter. Without this, a\n     * block with no explicit padding would draw zero-width regions on\n     * canvas while the rendered page actually shows e.g. 20px from the\n     * page's default.\n     */\n  }, {\n    key: \"getEffectivePadding\",\n    value: function getEffectivePadding(side) {\n      var own = this.formatter.getFormat(\"padding_\".concat(side));\n      if (own !== null && own !== undefined && own !== '') {\n        var n = Number(own);\n        if (!Number.isNaN(n)) return n;\n      }\n\n      // Walk up the container chain to find the PageElement.\n      var ctx = this.container;\n      while (ctx) {\n        if (ctx.getClassName && ctx.getClassName() === 'PageElement') {\n          var v = ctx[\"block_padding_\".concat(side)];\n          var _n = Number(v);\n          return Number.isNaN(_n) ? 0 : _n;\n        }\n        ctx = ctx.container;\n      }\n      return 0;\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      var _this2 = this;\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        elements: this.elements.map(function (element) {\n          return '<div element-anchor=\"' + element.id + '\">' + element.id + '</div>';\n        }).join('')\n      });\n\n      // render elements inside\n      this.elements.forEach(function (element) {\n        var anchor = _this2.domNode.querySelector('[element-anchor=\"' + element.id + '\"]');\n\n        // render block\n        var domNode = element.render();\n\n        // Dome append child\n        anchor.parentNode.insertBefore(domNode, anchor);\n\n        //\n        anchor.remove();\n\n        //\n        _this2.host.uiManager.addElement(element);\n      });\n    }\n  }, {\n    key: \"append\",\n    value: function append(element) {\n      // private\n      // set element container\n      element.container = this;\n      // Host injection — adopt the new element + its subtree.\n      // No-op when this block isn't yet adopted (host null) — the\n      // outer `_adopt(block)` from the insertion site will recurse and\n      // reach the appended element through getChildren().\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(element);\n      }\n      this.elements.push(element);\n    }\n  }, {\n    key: \"appendElements\",\n    value: function appendElements(elements) {\n      var _this3 = this;\n      elements.forEach(function (element) {\n        _this3.append(element);\n      });\n    }\n  }, {\n    key: \"getElements\",\n    value: function getElements() {\n      // Return the elements\n      return this.elements;\n    }\n\n    /** Host-injection recursion hook — returns this block's elements so\n     *  Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n     *  Injection\" lesson. */\n  }, {\n    key: \"getChildren\",\n    value: function getChildren() {\n      return this.elements || [];\n    }\n  }, {\n    key: \"renderBlock\",\n    value: function renderBlock() {\n      // Clone a new block\n      var block = this.constructor.parse(this.getData());\n      return block;\n    }\n\n    /**\n     * Surgical remove — BUILDER.md Lesson 21 + customer fix 2026-05-20.\n     *\n     * Pre-fix this called `this.render()`, which wipes block innerHTML and\n     * re-renders EVERY sibling element from scratch. Each child's\n     * `_doRender()` then assigned `this.domNode.innerHTML = …`, round-\n     * tripping `this.text` through the HTML5 fragment parser. With\n     * customer content that contained `<div>` block children (Chrome's\n     * default-paragraph-separator behaviour) this DROPPED their inline\n     * `font-weight` / `text-align` / `font-family` because the parser\n     * silently auto-closed the host `<p>` at the first `<div>`. Even\n     * after `defaultParagraphSeparator = 'br'` + `InlineSanitizer.normalize`\n     * defence-in-depth (see BaseElement._wireInlineEdit input listener)\n     * the cascade re-render is wasteful — every untouched sibling pays\n     * the cost of `innerHTML =` and the host blade's MutationObserver\n     * pushes one history entry per mutation in the cascade.\n     *\n     * Surgical path: drop the element from the array, detach its\n     * domNode, cascade up if the block went empty. Sibling DOM is\n     * untouched — contenteditable cursors, sidebar control closures,\n     * overlay anchors, UIManager registrations all survive byte-perfect.\n     */\n  }, {\n    key: \"removeElement\",\n    value: function removeElement(element) {\n      var idx = this.elements.indexOf(element);\n      if (idx === -1) return;\n      this.elements.splice(idx, 1);\n      if (element.domNode && element.domNode.parentNode) {\n        element.domNode.remove();\n      }\n\n      // Cascade up: if this block is now empty, remove it too. Same\n      // contract as the pre-fix path — `this.remove()` initiates a\n      // fadeOut → container.removeElement on the parent (PageElement)\n      // → another surgical pass.\n      if (!this.elements.length) {\n        this.remove();\n      }\n    }\n  }, {\n    key: \"insertElementAfter\",\n    value: function insertElementAfter(element, newElement) {\n      // set element container\n      newElement.container = this;\n      // Host injection — adopt before insert (in case caller hasn't).\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(newElement);\n      }\n      var idx = this.elements.indexOf(element);\n      if (idx === -1) return;\n      this.elements.splice(idx + 1, 0, newElement);\n\n      // Surgical DOM insert — render the NEW element only, splice into\n      // the right position. Siblings' DOM stays untouched (see\n      // `removeElement` rationale above).\n      var renderedDom = newElement.render();\n      var anchor = element.domNode;\n      if (anchor && anchor.parentNode) {\n        anchor.parentNode.insertBefore(renderedDom, anchor.nextSibling);\n      } else if (this.domNode) {\n        // Fallback — anchor missing for some reason; append at end so\n        // the new element is at least mounted.\n        this.domNode.firstElementChild ? this.domNode.firstElementChild.appendChild(renderedDom) : this.domNode.appendChild(renderedDom);\n      }\n      if (this.host && this.host.uiManager) {\n        this.host.uiManager.addElement(newElement);\n      }\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(BlockElement, \"getData\", this, 3)([])), {}, {\n        elements: this.elements.map(function (element) {\n          return element.getData();\n        })\n      });\n    }\n  }, {\n    key: \"getContainerStyleControls\",\n    value: function getContainerStyleControls() {\n      var _this4 = this;\n      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      var paddingLabel = options.paddingLabel || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_padding');\n      return [new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color', '#ffffff'),\n        image: this.formatter.getFormat('background_image', ''),\n        position: this.formatter.getFormat('background_position', 'center'),\n        size: this.formatter.getFormat('background_size', '100'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n        blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n        opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n        filter: this.formatter.getFormat('filter', '')\n      }, {\n        setBackground: function setBackground(values) {\n          _this4.formatter.setFormat('background_color', values.color);\n          _this4.formatter.setFormat('background_image', values.image);\n          _this4.formatter.setFormat('background_position', values.position);\n          _this4.formatter.setFormat('background_size', typeof values.size === 'number' ? values.size : values.size);\n          _this4.formatter.setFormat('background_repeat', values.repeat);\n          _this4.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n          _this4.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n          _this4.formatter.setFormat('filter', values.filter || null);\n          _this4.render();\n        }\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this4.formatter.setFormat('border_top_style', border_top_style);\n          _this4.formatter.setFormat('border_top_width', border_top_width);\n          _this4.formatter.setFormat('border_top_color', border_top_color);\n          _this4.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this4.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this4.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this4.formatter.setFormat('border_left_style', border_left_style);\n          _this4.formatter.setFormat('border_left_width', border_left_width);\n          _this4.formatter.setFormat('border_left_color', border_left_color);\n          _this4.formatter.setFormat('border_right_style', border_right_style);\n          _this4.formatter.setFormat('border_right_width', border_right_width);\n          _this4.formatter.setFormat('border_right_color', border_right_color);\n          _this4.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this4.formatter.setFormat('border_radius', v);\n          // PLAN_EFFECT W3.1 — cheap in-place style patch instead\n          // of full render(). Overlays keep their anchors; no\n          // flicker.\n          _this4.applyFormatStyles();\n        }\n      }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](paddingLabel, {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      }, {\n        setValues: function setValues(values) {\n          _this4.formatter.setFormat('padding_top', values.top);\n          _this4.formatter.setFormat('padding_right', values.right);\n          _this4.formatter.setFormat('padding_bottom', values.bottom);\n          _this4.formatter.setFormat('padding_left', values.left);\n          _this4.applyFormatStyles();\n        }\n      },\n      // Host-injection — control reads bus + pinSet off\n      // `this.host` directly. No prop-drilling needed.\n      {\n        elementUid: this.id\n      })\n      // Margin control removed 2026-04-17 — see formatter comment.\n      ];\n    }\n\n    /**\n     * W3.8b — deprecated. PageElement.getControls() already provides the\n     * Block Padding control under its `block_padding` namespace (see\n     * PageElement.js ~line 467). Keeping this method as a no-op so existing\n     * `...this.getPageSettingsControls()` callers stay byte-compatible;\n     * remove in a future tidy pass.\n     */\n  }, {\n    key: \"getPageSettingsControls\",\n    value: function getPageSettingsControls() {\n      return [];\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      return [].concat(_toConsumableArray(this.getContainerStyleControls()), _toConsumableArray(this.getPageSettingsControls()));\n    }\n  }, {\n    key: \"getOverlays\",\n    value:\n    /**\n     * Canvas overlays (Phase 1.6 — replaces hand-rolled createDragAnchor).\n     *\n     * Trigger 'hover' — BlockDragAnchorOverlay mounts via\n     * UIManager.mouseover → mountOverlays('hover'), unmounts via the\n     * 50 ms debounce flush in UIManager.mouseout (SA invariant I1 —\n     * debounce stays load-bearing for iframe-boundary idle-hover).\n     *\n     * The overlay owns its own `dragstart` handler (via NativeDragHandleOverlay)\n     * and hands off to `uiManager.dragStart(block)` in its onDragStart hook.\n     * `UIManager.addDraggableItem` detects this via `usesOverlayDragAnchor()`\n     * and skips the legacy anchor-wiring path. Widgets continue to use the\n     * legacy path (their domNode itself is the draggable).\n     *\n     * ⚠️ BLOCK-IN-CELL RULE (preserved from legacy — user report 2026-04-18):\n     * Only TOP-LEVEL page blocks are draggable. A block nested inside a\n     * CellElement has no drag anchor because moving it out of the cell\n     * would break the containing grid's layout semantics (widgets are the\n     * only things that can enter cells; once a block is in a cell it stays\n     * there). The legacy rule was enforced implicitly by only registering\n     * top-level blocks via `PageElement.render → addDraggableItem`. The\n     * overlay path — where `getOverlays()` is called on every hover — must\n     * enforce this explicitly OR else hovering an inner block mounts an\n     * anchor that has no valid drop target anywhere.\n     *\n     * See docs/core/OVERLAY.md §7.4 + docs/archived/OVERLAY_PLAN.md §3.7 + §5 D54.\n     */\n    function getOverlays() {\n      var _this5 = this;\n      var overlays = [];\n\n      // Drag anchor — trigger 'hover' — top-level blocks only (inner\n      // blocks can't be dragged out of their cell).\n      if (!this._isInsideCell()) {\n        overlays.push(new _overlays_BlockDragAnchorOverlay_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](this));\n      }\n\n      // PLAN_EFFECT W3.1 — padding visualiser — trigger 'select'.\n      // Always emit; the overlay self-disposes in afterMount() when\n      // host's usePaddingVisualizer flag is off. Why: getOverlays()\n      // runs during parse — `this.host` is null then, so a flag\n      // check here would always skip. The flag gate moved to\n      // PaddingVisualizerOverlay (commit 4 + 6 of host-injection\n      // refactor).\n      //\n      // W3.7 — `opts.readSide` pipes the cascade-aware effective\n      // padding into the overlay. If the block's own formatter is\n      // null, the overlay still draws the inherited page.block_padding\n      // value — matching what the user sees rendered on canvas.\n      overlays.push(new _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](this, {\n        readSide: function readSide(side) {\n          return _this5.getEffectivePadding(side);\n        }\n      }));\n      return overlays;\n    }\n\n    /**\n     * Capability flag consumed by `UIManager.addDraggableItem`. When true,\n     * UIManager skips calling `addDragAnchor()` / binding a shared dragstart\n     * handler — the BlockDragAnchorOverlay wires its own dragstart on\n     * every mount (trigger 'hover'). Keeps widgets on the legacy path by\n     * leaving the default `BaseElement` behavior (method missing → falsy).\n     * Also falls back to legacy-path-skipped for inner blocks (see §D54).\n     */\n  }, {\n    key: \"usesOverlayDragAnchor\",\n    value: function usesOverlayDragAnchor() {\n      return !this._isInsideCell();\n    }\n\n    /**\n     * True if this block's direct container is a CellElement. Legacy rule:\n     * only top-level page blocks are draggable; blocks inside cells are\n     * fixed-in-place. Preserves the implicit legacy invariant explicitly\n     * now that `getOverlays()` is authoritative for anchor visibility.\n     */\n  }, {\n    key: \"_isInsideCell\",\n    value: function _isInsideCell() {\n      return !!(this.container && typeof this.container.getClassName === 'function' && this.container.getClassName() === 'CellElement');\n    }\n  }, {\n    key: \"canDropOn\",\n    value: function canDropOn(element) {\n      // Existing blocks cannot be dragged into cells — only widgets can.\n      // PricingCardElement (2026-04-18) is a CellElement subclass serving as\n      // a pricing-card container; same rule applies. FormContainerCell is\n      // deliberately left out: it also extends CellElement but has always\n      // accepted block drags (form-area append UX); do not tighten that.\n      var cellTypes = ['CellElement', 'PricingCardElement'];\n      if (cellTypes.includes(element.getClassName())) {\n        return false;\n      }\n      if (element.container && cellTypes.includes(element.container.getClassName())) {\n        return false;\n      }\n      return element.isDroppable();\n    }\n  }, {\n    key: \"removeAfterDrop\",\n    value: function removeAfterDrop() {\n      return true;\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new this(data.template);\n      var elems = Array.isArray(data.elements) ? data.elements : [];\n      e.appendElements(elems.map(function (item) {\n        return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(item);\n      }));\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BlockElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BlockElement.js?");

/***/ }),

/***/ "./src/includes/BorderControl.js":
/*!***************************************!*\
  !*** ./src/includes/BorderControl.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * BorderControl — per-side border editor (style / width / color).\n *\n * Phase 3 refactor (2026-04-19) —\n *   Replaces the Phase-2.12b composite with a showcase-aligned\n *   pro-grade editor: mode segmented (All / Split), quick presets\n *   (None / Thin / Medium / Thick), icon-based style picker with\n *   real stroke previews, canonical `.bjs-number-step` + `.bjs-number-\n *   value` + `.bjs-color-input` (swatch + hex) primitives, and a\n *   live 72px preview tile that mirrors the current values.\n *\n *   Root-cause of the visible-broken stepper: the old render wrote\n *   `.bjs-number-input-btn` / `.bjs-number-input-value` (non-canonical\n *   class names that have no CSS). The canonical primitives in\n *   builder.css are `.bjs-number-step` and `.bjs-number-value`. Using\n *   them inherits all the hover / focus / disabled / dark-mode styling\n *   for free.\n *\n * Backward-compat (non-negotiable, do not break):\n *   - Data contract: reads/writes the same 12 flat keys\n *     `border_{top|right|bottom|left}_{style|width|color}`.\n *   - Callback shape: still invokes `callback.setBorder(top_style,\n *     top_width, top_color, bottom_style, bottom_width, bottom_color,\n *     left_style, left_width, left_color, right_style, right_width,\n *     right_color)` with the same 12-arg signature + positional order\n *     the 13 existing consumers (Block / Button / Image / TextInput /\n *     HTML / Video / Youtube / Alert / Label / SubmitButton / RSS /\n *     Cell / Table) rely on.\n *   - All `[data-role=\"…\"]` hooks used by e2e specs are preserved\n *     (header, body, all-sides, per-side, style, width, color, minus,\n *     plus). New roles added for the new affordances (mode-all,\n *     mode-split, preset, copy-to-all, reset, preview-tile, color-hex,\n *     color-preview).\n *\n * New opt-in contract (`opts` arg, ignored by legacy callers):\n *   - `opts.onChange({ top, right, bottom, left })` — preferred, object-\n *     shaped patch (each side = `{ style, width, color }`).\n *   - `opts.showPreview` (default true).\n *   - `opts.namespace` — lets a single element host two independent\n *     BorderControl instances that don't cross-talk (e.g. inner border\n *     vs outer border).\n *\n * No-flicker rule (BUILDER.md Lesson 19):\n *   `_emitValues()` / `_syncUI()` / `_syncPreview()` NEVER re-`innerHTML`\n *   the control during pointer/keystroke events — they only mutate\n *   `input.value`, toggle `aria-checked` / `hidden` / `is-active`, and\n *   set inline `style` on the preview tile in-place. Mode switch\n *   (All ↔ Split) is the single permitted rebuild and still only\n *   toggles `hidden` between two pre-rendered containers — no DOM\n *   churn.\n */\n\nvar SIDES = ['top', 'right', 'bottom', 'left'];\n\n// Visible style choices in the icon segmented. Five CSS styles that\n// render reliably in modern email clients + modern browsers. Legacy\n// CSS styles (groove / ridge / inset / outset / hidden) are read +\n// preserved from data but not exposed in the icon picker — follow-up\n// epic can surface them via a `More styles` overflow if demand exists.\nvar STYLE_CHOICES = ['solid', 'dashed', 'dotted', 'double', 'none'];\n\n// SVG stroke previews for each style — 20×14 viewBox, currentColor\n// so the icon inherits the segmented button's text color (flips to\n// white when active). Kept inline so the control has no external\n// asset dependency.\nvar STYLE_PREVIEW_SVG = {\n  solid: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"7\" x2=\"20\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"2\"/></svg>',\n  dashed: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"7\" x2=\"20\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-dasharray=\"4 2.5\"/></svg>',\n  dotted: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"7\" x2=\"20\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-dasharray=\"0.5 3\"/></svg>',\n  \"double\": '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"2\" y1=\"5\" x2=\"20\" y2=\"5\" stroke=\"currentColor\" stroke-width=\"1.5\"/><line x1=\"2\" y1=\"9\" x2=\"20\" y2=\"9\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>',\n  none: '<svg width=\"22\" height=\"14\" viewBox=\"0 0 22 14\" aria-hidden=\"true\"><line x1=\"3\" y1=\"11\" x2=\"19\" y2=\"3\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.7\"/></svg>'\n};\n\n// Preset widths. Chosen to cover the common range — None, hairline,\n// default, hero. `style: null` means \"don't change\", only the width\n// (and color if unset) gets applied.\nvar PRESETS = {\n  none: {\n    style: 'none',\n    width: 0,\n    applyColor: false\n  },\n  thin: {\n    style: 'solid',\n    width: 1,\n    applyColor: false\n  },\n  medium: {\n    style: 'solid',\n    width: 2,\n    applyColor: false\n  },\n  thick: {\n    style: 'solid',\n    width: 4,\n    applyColor: false\n  }\n};\nvar HEX_FULL = /^#[0-9a-f]{6}$/i;\nvar HEX_SHORT = /^#[0-9a-f]{3}$/i;\nfunction normaliseHex(value) {\n  if (!value) return '';\n  var v = String(value).trim().toLowerCase();\n  if (HEX_FULL.test(v)) return v;\n  if (HEX_SHORT.test(v)) {\n    return '#' + v.slice(1).split('').map(function (c) {\n      return c + c;\n    }).join('');\n  }\n  var withHash = v.startsWith('#') ? v : '#' + v;\n  if (HEX_FULL.test(withHash)) return withHash;\n  if (HEX_SHORT.test(withHash)) {\n    return '#' + withHash.slice(1).split('').map(function (c) {\n      return c + c;\n    }).join('');\n  }\n  return null; // invalid\n}\nvar BorderControl = /*#__PURE__*/function () {\n  /**\n   * @param {string} label    Title for the section header.\n   * @param {object} values   { border_{top|right|bottom|left}_{style|width|color}: … }\n   * @param {object} callback { setBorder(…12 args): Function } — legacy.\n   * @param {object} [opts]   { onChange, showPreview, namespace }\n   */\n  function BorderControl(label, values, callback) {\n    var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, BorderControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.values = values || {};\n    this.callback = callback;\n    this.opts = opts || {};\n    this.showPreview = this.opts.showPreview !== false;\n    this.namespace = this.opts.namespace || 'border';\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-border-control');\n    this.domNode.setAttribute('data-namespace', this.namespace);\n    this.isCollapsed = false;\n    this.showPerSide = !this._allSidesSame();\n    this.focusedSide = null; // used for preview highlight + preset targeting in Split\n\n    this.render();\n  }\n\n  /** True when every side has the same style/width/color — drives the\n   *  auto-select between All (uniform) and Split modes on first mount\n   *  so the author sees their actual data immediately. */\n  return _createClass(BorderControl, [{\n    key: \"_allSidesSame\",\n    value: function _allSidesSame() {\n      var v = this.values;\n      var first = {\n        style: v[\"border_\".concat(SIDES[0], \"_style\")] || 'none',\n        width: parseInt(v[\"border_\".concat(SIDES[0], \"_width\")], 10) || 0,\n        color: (v[\"border_\".concat(SIDES[0], \"_color\")] || '#000000').toLowerCase()\n      };\n      return SIDES.every(function (s) {\n        var style = v[\"border_\".concat(s, \"_style\")] || 'none';\n        var width = parseInt(v[\"border_\".concat(s, \"_width\")], 10) || 0;\n        var color = (v[\"border_\".concat(s, \"_color\")] || '#000000').toLowerCase();\n        return style === first.style && width === first.width && color === first.color;\n      });\n    }\n  }, {\n    key: \"_readSide\",\n    value: function _readSide(side) {\n      var v = this.values;\n      return {\n        style: v[\"border_\".concat(side, \"_style\")] || 'solid',\n        width: parseInt(v[\"border_\".concat(side, \"_width\")], 10) || 0,\n        color: v[\"border_\".concat(side, \"_color\")] || '#000000'\n      };\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var rowsAll = this._renderUniformBody();\n      var rowsSplit = this._renderSplitBody();\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-section-header bjs-border-control-header\\\" data-role=\\\"header\\\" role=\\\"button\\\" tabindex=\\\"0\\\" aria-expanded=\\\"\".concat(!this.isCollapsed, \"\\\">\\n                <div class=\\\"bjs-border-control-header-text\\\">\\n                    <span class=\\\"bjs-section-header-title\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.title'), \"</span>\\n                    <span class=\\\"bjs-section-header-desc\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.description'), \"</span>\\n                </div>\\n                <div class=\\\"bjs-border-control-header-actions\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-border-control-reset\\\" data-role=\\\"reset\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.reset', 'Reset borders'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.reset', 'Reset borders'), \"\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">restart_alt</span>\\n                    </button>\\n                    <span class=\\\"material-symbols-rounded bjs-section-header-caret\\\" aria-hidden=\\\"true\\\">keyboard_arrow_down</span>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-border-control-body\\\" data-role=\\\"body\\\" \").concat(this.isCollapsed ? 'hidden' : '', \">\\n                <div class=\\\"bjs-border-control-mode-row\\\">\\n                    <span class=\\\"bjs-border-control-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_label', 'Mode'), \"</span>\\n                    <div class=\\\"bjs-segmented bjs-border-mode-seg\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_label', 'Mode'), \"\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-segmented-btn \").concat(!this.showPerSide ? 'is-active' : '', \"\\\" data-role=\\\"mode-all\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(!this.showPerSide, \"\\\" tabindex=\\\"\").concat(!this.showPerSide ? '0' : '-1', \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">border_outer</span>\\n                            <span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_all', 'All'), \"</span>\\n                        </button>\\n                        <button type=\\\"button\\\" class=\\\"bjs-segmented-btn \").concat(this.showPerSide ? 'is-active' : '', \"\\\" data-role=\\\"mode-split\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(this.showPerSide, \"\\\" tabindex=\\\"\").concat(this.showPerSide ? '0' : '-1', \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">border_all</span>\\n                            <span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.mode_split', 'Split'), \"</span>\\n                        </button>\\n                    </div>\\n                </div>\\n\\n                <div class=\\\"bjs-border-control-preset-row\\\">\\n                    <span class=\\\"bjs-border-control-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_label', 'Preset'), \"</span>\\n                    <div class=\\\"bjs-segmented bjs-border-preset-seg\\\" role=\\\"group\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_label', 'Preset'), \"\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"none\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_none', 'None'), \"</button>\\n                        <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"thin\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_thin', 'Thin'), \"</button>\\n                        <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"medium\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_medium', 'Medium'), \"</button>\\n                        <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\\\" data-role=\\\"preset\\\" data-preset=\\\"thick\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preset_thick', 'Thick'), \"</button>\\n                    </div>\\n                </div>\\n\\n                <div class=\\\"bjs-border-control-rows bjs-border-control-rows--uniform\\\" data-role=\\\"all-sides\\\" \").concat(this.showPerSide ? 'hidden' : '', \">\\n                    \").concat(rowsAll, \"\\n                </div>\\n\\n                <div class=\\\"bjs-border-control-rows bjs-border-control-rows--split\\\" data-role=\\\"per-side\\\" \").concat(this.showPerSide ? '' : 'hidden', \">\\n                    \").concat(rowsSplit, \"\\n                </div>\\n            </div>\\n        \");\n      this._bindEvents();\n      this._syncUI();\n    }\n  }, {\n    key: \"_renderUniformBody\",\n    value: function _renderUniformBody() {\n      var state = this._readSide('top'); // authoritative when sides are in sync\n      return \"\\n            <div class=\\\"bjs-border-control-uniform-body\\\">\\n                <div class=\\\"bjs-border-control-row\\\" data-side=\\\"all\\\">\\n                    <span class=\\\"bjs-border-control-side-label\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.all_sides', 'All sides'), \"</span>\\n                    \").concat(this._renderRowInputs('all', state, {\n        compact: false,\n        withCopy: false\n      }), \"\\n                </div>\\n                \").concat(this.showPreview ? this._renderPreview('uniform') : '', \"\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_renderSplitBody\",\n    value: function _renderSplitBody() {\n      var _this = this;\n      var rows = SIDES.map(function (side) {\n        return \"\\n            <div class=\\\"bjs-border-control-row bjs-border-control-row--compact\\\" data-side=\\\"\".concat(side, \"\\\">\\n                <div class=\\\"bjs-border-control-side-column\\\">\\n                    <span class=\\\"bjs-border-control-side-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.' + side, side.charAt(0).toUpperCase() + side.slice(1)), \"</span>\\n                    <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-border-copy-btn\\\" data-role=\\\"copy-to-all\\\"\\n                            data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\"\\n                            aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">content_copy</span>\\n                    </button>\\n                </div>\\n                \").concat(_this._renderRowInputs(side, _this._readSide(side), {\n          compact: true,\n          withCopy: false\n        }), \"\\n            </div>\\n        \");\n      }).join('');\n      return \"\\n            <div class=\\\"bjs-border-control-split-body\\\">\\n                <div class=\\\"bjs-border-control-split-rows\\\">\\n                    \".concat(rows, \"\\n                </div>\\n                \").concat(this.showPreview ? this._renderPreview('split') : '', \"\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_renderRowInputs\",\n    value: function _renderRowInputs(side, state, _ref) {\n      var compact = _ref.compact,\n        withCopy = _ref.withCopy;\n      var styleBtns = STYLE_CHOICES.map(function (s) {\n        return \"\\n            <button type=\\\"button\\\"\\n                    class=\\\"bjs-segmented-btn bjs-border-style-btn \".concat(state.style === s ? 'is-active' : '', \"\\\"\\n                    data-role=\\\"style\\\" data-style=\\\"\").concat(s, \"\\\"\\n                    role=\\\"radio\\\" aria-checked=\\\"\").concat(state.style === s, \"\\\"\\n                    data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.style_' + s, s), \"\\\"\\n                    aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.style_' + s, s), \"\\\"\\n                    tabindex=\\\"\").concat(state.style === s ? '0' : '-1', \"\\\">\\n                \").concat(STYLE_PREVIEW_SVG[s], \"\\n            </button>\\n        \");\n      }).join('');\n      var copyBtn = withCopy ? \"\\n            <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-border-copy-btn\\\" data-role=\\\"copy-to-all\\\"\\n                    data-tooltip=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\"\\n                    aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.copy_to_all', 'Copy this side to all sides'), \"\\\">\\n                <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">content_copy</span>\\n            </button>\\n        \") : '';\n      return \"\\n            <div class=\\\"bjs-border-control-inputs \".concat(compact ? 'bjs-border-control-inputs--compact' : '', \"\\\">\\n                <div class=\\\"bjs-segmented bjs-border-style-seg\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.style_label', 'Border style'), \"\\\">\\n                    \").concat(styleBtns, \"\\n                </div>\\n                <div class=\\\"bjs-number-input bjs-border-width-input\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-role=\\\"minus\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('number.decrement', 'Decrease'), \"\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">remove</span>\\n                    </button>\\n                    <input type=\\\"number\\\" class=\\\"bjs-number-value\\\" data-role=\\\"width\\\" value=\\\"\").concat(state.width, \"\\\" min=\\\"0\\\" max=\\\"999\\\" step=\\\"1\\\" aria-valuemin=\\\"0\\\" aria-valuemax=\\\"999\\\" aria-valuenow=\\\"\").concat(state.width, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.width_label', 'Border width (px)'), \"\\\">\\n                    <span class=\\\"bjs-number-unit\\\" aria-hidden=\\\"true\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.width_unit', 'px'), \"</span>\\n                    <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-role=\\\"plus\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('number.increment', 'Increase'), \"\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">add</span>\\n                    </button>\\n                </div>\\n                <div class=\\\"bjs-color-input bjs-border-color-input\\\">\\n                    <label class=\\\"bjs-color-swatch\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.color_label', 'Border color'), \"\\\">\\n                        <input type=\\\"color\\\" class=\\\"bjs-color-native\\\" data-role=\\\"color\\\" value=\\\"\").concat(state.color, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.color_label', 'Border color'), \"\\\">\\n                        <span class=\\\"bjs-color-preview\\\" data-role=\\\"color-preview\\\"></span>\\n                    </label>\\n                    <input type=\\\"text\\\" class=\\\"bjs-color-hex\\\" data-role=\\\"color-hex\\\" value=\\\"\").concat(state.color, \"\\\" placeholder=\\\"#000000\\\" maxlength=\\\"7\\\" autocomplete=\\\"off\\\" spellcheck=\\\"false\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.color_label', 'Border color'), \"\\\">\\n                </div>\\n                \").concat(copyBtn, \"\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_renderPreview\",\n    value: function _renderPreview(mode) {\n      return \"\\n            <div class=\\\"bjs-border-control-preview bjs-border-control-preview--\".concat(mode, \"\\\" data-role=\\\"preview\\\" aria-hidden=\\\"true\\\">\\n                <div class=\\\"bjs-border-control-preview-tile\\\" data-role=\\\"preview-tile\\\"></div>\\n                <span class=\\\"bjs-border-control-preview-caption\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preview_aria', 'Preview'), \"</span>\\n            </div>\\n            <span class=\\\"bjs-sr-only\\\" aria-live=\\\"polite\\\" data-role=\\\"preview-announce\\\"></span>\\n        \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      var root = this.domNode;\n      var header = root.querySelector('[data-role=\"header\"]');\n      var body = root.querySelector('[data-role=\"body\"]');\n\n      // Header collapse — click + keyboard.\n      var toggleCollapsed = function toggleCollapsed() {\n        _this2.isCollapsed = !_this2.isCollapsed;\n        header.setAttribute('aria-expanded', String(!_this2.isCollapsed));\n        if (_this2.isCollapsed) body.setAttribute('hidden', '');else body.removeAttribute('hidden');\n      };\n      header.addEventListener('click', function (e) {\n        // Don't collapse when the reset icon-btn inside the header is\n        // clicked — it's an independent affordance.\n        if (e.target.closest('[data-role=\"reset\"]')) return;\n        toggleCollapsed();\n      });\n      header.addEventListener('keydown', function (e) {\n        if (e.key === 'Enter' || e.key === ' ') {\n          if (e.target.closest('[data-role=\"reset\"]')) return;\n          e.preventDefault();\n          toggleCollapsed();\n        }\n      });\n\n      // Reset — clears all 4 sides.\n      var resetBtn = root.querySelector('[data-role=\"reset\"]');\n      if (resetBtn) {\n        resetBtn.addEventListener('click', function (e) {\n          e.stopPropagation();\n          SIDES.forEach(function (s) {\n            _this2.values[\"border_\".concat(s, \"_style\")] = 'none';\n            _this2.values[\"border_\".concat(s, \"_width\")] = 0;\n            _this2.values[\"border_\".concat(s, \"_color\")] = '#000000';\n          });\n          _this2._syncUI();\n          _this2._emitValues(/*fromUI*/false);\n        });\n      }\n\n      // Mode segmented — flip between uniform and split bodies.\n      this._bindModeSegmented(root);\n\n      // Preset chips.\n      this._bindPresets(root);\n\n      // Row-level handlers — style icons, width stepper + input, color.\n      root.querySelectorAll('.bjs-border-control-row').forEach(function (row) {\n        return _this2._bindRow(row);\n      });\n      this._syncColorPreviews();\n      this._syncPreview();\n    }\n  }, {\n    key: \"_bindModeSegmented\",\n    value: function _bindModeSegmented(root) {\n      var _this3 = this;\n      var all = root.querySelector('[data-role=\"mode-all\"]');\n      var split = root.querySelector('[data-role=\"mode-split\"]');\n      var allBody = root.querySelector('[data-role=\"all-sides\"]');\n      var splitBody = root.querySelector('[data-role=\"per-side\"]');\n      var select = function select(toSplit) {\n        _this3.showPerSide = toSplit;\n        all.classList.toggle('is-active', !toSplit);\n        split.classList.toggle('is-active', toSplit);\n        all.setAttribute('aria-checked', String(!toSplit));\n        split.setAttribute('aria-checked', String(toSplit));\n        all.setAttribute('tabindex', toSplit ? '-1' : '0');\n        split.setAttribute('tabindex', toSplit ? '0' : '-1');\n        if (toSplit) {\n          allBody.setAttribute('hidden', '');\n          splitBody.removeAttribute('hidden');\n        } else {\n          splitBody.setAttribute('hidden', '');\n          allBody.removeAttribute('hidden');\n        }\n        // When switching from split → all, broadcast top's values so\n        // all sides converge (matches the \"All sides\" semantic).\n        if (!toSplit) {\n          var src = _this3._readSide('top');\n          SIDES.forEach(function (s) {\n            _this3.values[\"border_\".concat(s, \"_style\")] = src.style;\n            _this3.values[\"border_\".concat(s, \"_width\")] = src.width;\n            _this3.values[\"border_\".concat(s, \"_color\")] = src.color;\n          });\n          _this3._syncUI();\n          _this3._emitValues(false);\n        } else {\n          _this3._syncUI();\n        }\n      };\n      all.addEventListener('click', function () {\n        return select(false);\n      });\n      split.addEventListener('click', function () {\n        return select(true);\n      });\n\n      // Arrow-key nav inside the segmented group.\n      var onKey = function onKey(btns) {\n        return function (e) {\n          var idx = btns.indexOf(document.activeElement);\n          if (idx === -1) return;\n          if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n            e.preventDefault();\n            btns[(idx + 1) % btns.length].focus();\n            btns[(idx + 1) % btns.length].click();\n          } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n            e.preventDefault();\n            btns[(idx - 1 + btns.length) % btns.length].focus();\n            btns[(idx - 1 + btns.length) % btns.length].click();\n          }\n        };\n      };\n      var modeBtns = [all, split];\n      [all, split].forEach(function (b) {\n        return b.addEventListener('keydown', onKey(modeBtns));\n      });\n    }\n  }, {\n    key: \"_bindPresets\",\n    value: function _bindPresets(root) {\n      var _this4 = this;\n      root.querySelectorAll('[data-role=\"preset\"]').forEach(function (btn) {\n        btn.addEventListener('click', function (e) {\n          var key = btn.getAttribute('data-preset');\n          var preset = PRESETS[key];\n          if (!preset) return;\n          var targetSides = _this4.showPerSide && _this4.focusedSide ? [_this4.focusedSide] : SIDES;\n          // Alt/Option held on a preset chip = apply to all sides\n          // regardless of focused side. (Power-user shortcut.)\n          var apply = e.altKey ? SIDES : targetSides;\n          apply.forEach(function (s) {\n            _this4.values[\"border_\".concat(s, \"_style\")] = preset.style;\n            _this4.values[\"border_\".concat(s, \"_width\")] = preset.width;\n            // Only overwrite color when it's currently the default black\n            // and we're applying a non-none preset — so preset doesn't\n            // clobber a user-picked color.\n          });\n          // Flash visual feedback on the pressed chip.\n          btn.classList.add('is-flash');\n          setTimeout(function () {\n            return btn.classList.remove('is-flash');\n          }, 220);\n          _this4._syncUI();\n          _this4._emitValues(false);\n        });\n      });\n    }\n  }, {\n    key: \"_bindRow\",\n    value: function _bindRow(row) {\n      var _this5 = this;\n      var side = row.getAttribute('data-side');\n\n      // Style icon segmented.\n      row.querySelectorAll('[data-role=\"style\"]').forEach(function (btn) {\n        btn.addEventListener('click', function () {\n          var value = btn.getAttribute('data-style');\n          _this5._setRowStyle(row, value);\n          _this5._emitValues(false);\n        });\n        btn.addEventListener('keydown', function (e) {\n          var btns = Array.from(row.querySelectorAll('[data-role=\"style\"]'));\n          var idx = btns.indexOf(document.activeElement);\n          if (idx === -1) return;\n          if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n            e.preventDefault();\n            var nxt = btns[(idx + 1) % btns.length];\n            nxt.focus();\n            nxt.click();\n          } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n            e.preventDefault();\n            var prv = btns[(idx - 1 + btns.length) % btns.length];\n            prv.focus();\n            prv.click();\n          }\n        });\n      });\n\n      // Width — stepper + input + keyboard shortcuts.\n      var width = row.querySelector('[data-role=\"width\"]');\n      var minus = row.querySelector('[data-role=\"minus\"]');\n      var plus = row.querySelector('[data-role=\"plus\"]');\n      var clampWidth = function clampWidth(v) {\n        return Math.max(0, Math.min(999, parseInt(v, 10) || 0));\n      };\n      var bumpWidth = function bumpWidth(delta) {\n        width.value = clampWidth(parseInt(width.value, 10) + delta);\n        width.setAttribute('aria-valuenow', width.value);\n        _this5._emitValues(true);\n      };\n      minus.addEventListener('click', function () {\n        return bumpWidth(-1);\n      });\n      plus.addEventListener('click', function () {\n        return bumpWidth(1);\n      });\n      width.addEventListener('input', function () {\n        width.setAttribute('aria-valuenow', width.value || '0');\n        _this5._emitValues(true);\n      });\n      width.addEventListener('blur', function () {\n        width.value = clampWidth(width.value);\n        width.setAttribute('aria-valuenow', width.value);\n        _this5._emitValues(true);\n      });\n      width.addEventListener('keydown', function (e) {\n        if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n          e.preventDefault();\n          var step = e.shiftKey ? 10 : 1;\n          bumpWidth(e.key === 'ArrowUp' ? step : -step);\n        }\n      });\n\n      // Color — native picker + hex textbox.\n      var color = row.querySelector('[data-role=\"color\"]');\n      var hex = row.querySelector('[data-role=\"color-hex\"]');\n      color.addEventListener('input', function () {\n        hex.value = color.value.toLowerCase();\n        hex.classList.remove('is-error');\n        _this5._syncColorPreviews();\n        _this5._emitValues(true);\n      });\n      hex.addEventListener('input', function () {\n        var normalised = normaliseHex(hex.value);\n        if (normalised) {\n          hex.classList.remove('is-error');\n          color.value = normalised;\n          _this5._syncColorPreviews();\n          _this5._emitValues(true);\n        } else {\n          // Keep showing the typed value; flag as error so the user\n          // sees it's invalid (red border on the hex input).\n          hex.classList.add('is-error');\n        }\n      });\n      hex.addEventListener('blur', function () {\n        var normalised = normaliseHex(hex.value);\n        if (!normalised) {\n          // Revert to the currently-stored color on blur so we never\n          // persist an invalid value.\n          hex.value = color.value;\n          hex.classList.remove('is-error');\n        } else {\n          hex.value = normalised;\n        }\n      });\n\n      // Focus tracking for preview-highlight + preset targeting.\n      row.addEventListener('focusin', function () {\n        _this5.focusedSide = side;\n        _this5._syncPreviewHighlight();\n      });\n      row.addEventListener('mouseenter', function () {\n        _this5.focusedSide = side;\n        _this5._syncPreviewHighlight();\n      });\n      row.addEventListener('mouseleave', function () {\n        _this5.focusedSide = null;\n        _this5._syncPreviewHighlight();\n      });\n\n      // Copy-to-all.\n      var copy = row.querySelector('[data-role=\"copy-to-all\"]');\n      if (copy) {\n        copy.addEventListener('click', function () {\n          var src = _this5._readRowValues(row);\n          SIDES.forEach(function (s) {\n            _this5.values[\"border_\".concat(s, \"_style\")] = src.style;\n            _this5.values[\"border_\".concat(s, \"_width\")] = src.width;\n            _this5.values[\"border_\".concat(s, \"_color\")] = src.color;\n          });\n          copy.classList.add('is-flash');\n          setTimeout(function () {\n            return copy.classList.remove('is-flash');\n          }, 220);\n          _this5._syncUI();\n          _this5._emitValues(false);\n        });\n      }\n    }\n\n    /** In-place style selection — toggles aria-checked + is-active on the\n     *  row's style buttons + updates tabindex for roving-focus; no innerHTML. */\n  }, {\n    key: \"_setRowStyle\",\n    value: function _setRowStyle(row, value) {\n      row.querySelectorAll('[data-role=\"style\"]').forEach(function (b) {\n        var match = b.getAttribute('data-style') === value;\n        b.classList.toggle('is-active', match);\n        b.setAttribute('aria-checked', String(match));\n        b.setAttribute('tabindex', match ? '0' : '-1');\n      });\n    }\n  }, {\n    key: \"_readRowValues\",\n    value: function _readRowValues(row) {\n      var styleBtn = row.querySelector('[data-role=\"style\"].is-active') || row.querySelector('[data-role=\"style\"]');\n      var style = styleBtn ? styleBtn.getAttribute('data-style') : 'solid';\n      var width = Math.max(0, Math.min(999, parseInt(row.querySelector('[data-role=\"width\"]').value, 10) || 0));\n      var color = row.querySelector('[data-role=\"color\"]').value || '#000000';\n      return {\n        style: style,\n        width: width,\n        color: color\n      };\n    }\n\n    /** Populate UI from this.values (mutates input.value + aria + toggle\n     *  .is-active; never innerHTML). Keeps focus intact. */\n  }, {\n    key: \"_syncUI\",\n    value: function _syncUI() {\n      var _this6 = this;\n      var allRow = this.domNode.querySelector('[data-role=\"all-sides\"] .bjs-border-control-row');\n      if (allRow) this._writeSideToRow(allRow, this._readSide('top'));\n      SIDES.forEach(function (side) {\n        var row = _this6.domNode.querySelector(\"[data-role=\\\"per-side\\\"] .bjs-border-control-row[data-side=\\\"\".concat(side, \"\\\"]\"));\n        if (row) _this6._writeSideToRow(row, _this6._readSide(side));\n      });\n      this._syncColorPreviews();\n      this._syncPreview();\n    }\n  }, {\n    key: \"_writeSideToRow\",\n    value: function _writeSideToRow(row, state) {\n      // Style icons.\n      row.querySelectorAll('[data-role=\"style\"]').forEach(function (b) {\n        var match = b.getAttribute('data-style') === state.style;\n        b.classList.toggle('is-active', match);\n        b.setAttribute('aria-checked', String(match));\n        b.setAttribute('tabindex', match ? '0' : '-1');\n      });\n      // Width.\n      var w = row.querySelector('[data-role=\"width\"]');\n      if (w) {\n        w.value = state.width;\n        w.setAttribute('aria-valuenow', state.width);\n      }\n      // Color.\n      var c = row.querySelector('[data-role=\"color\"]');\n      var h = row.querySelector('[data-role=\"color-hex\"]');\n      if (c) c.value = state.color;\n      if (h) {\n        h.value = state.color;\n        h.classList.remove('is-error');\n      }\n    }\n  }, {\n    key: \"_syncColorPreviews\",\n    value: function _syncColorPreviews() {\n      this.domNode.querySelectorAll('.bjs-border-control-row').forEach(function (row) {\n        var inp = row.querySelector('[data-role=\"color\"]');\n        var pre = row.querySelector('[data-role=\"color-preview\"]');\n        if (inp && pre) pre.style.setProperty('--bjs-color-current', inp.value || 'transparent');\n      });\n    }\n\n    /** Mutate inline style on the preview tile(s) — NEVER rebuild. */\n  }, {\n    key: \"_syncPreview\",\n    value: function _syncPreview() {\n      var _this7 = this;\n      if (!this.showPreview) return;\n      this.domNode.querySelectorAll('[data-role=\"preview-tile\"]').forEach(function (tile) {\n        var sides = SIDES.map(function (s) {\n          return _objectSpread({\n            side: s\n          }, _this7._readSide(s));\n        });\n        sides.forEach(function (_ref2) {\n          var side = _ref2.side,\n            style = _ref2.style,\n            width = _ref2.width,\n            color = _ref2.color;\n          // `none` with 0 width collapses visually; the tile's own\n          // base border (from CSS) keeps the box visible so the user\n          // still sees something to edit.\n          tile.style[\"border\".concat(side.charAt(0).toUpperCase() + side.slice(1))] = \"\".concat(width, \"px \").concat(style === 'none' ? 'none' : style, \" \").concat(color);\n        });\n      });\n      var ann = this.domNode.querySelector('[data-role=\"preview-announce\"]');\n      if (ann) {\n        var top = this._readSide('top');\n        ann.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.preview_announce', \"Border: \".concat(top.style, \" \").concat(top.width, \"px \").concat(top.color));\n      }\n      this._syncPreviewHighlight();\n    }\n  }, {\n    key: \"_syncPreviewHighlight\",\n    value: function _syncPreviewHighlight() {\n      var _this8 = this;\n      var tiles = this.domNode.querySelectorAll('[data-role=\"preview-tile\"]');\n      tiles.forEach(function (t) {\n        return t.setAttribute('data-highlight', _this8.focusedSide || '');\n      });\n    }\n\n    /** Read UI, update this.values, invoke legacy setBorder(…12) +\n     *  optional opts.onChange(patch). `fromUI=true` means the caller\n     *  is a live input event (keystroke/stepper) — we STILL invoke the\n     *  callback but skip `_syncUI()` to preserve focus. */\n  }, {\n    key: \"_emitValues\",\n    value: function _emitValues(fromUI) {\n      var _this9 = this;\n      var patch = {\n        top: null,\n        right: null,\n        bottom: null,\n        left: null\n      };\n      if (!this.showPerSide) {\n        var row = this.domNode.querySelector('[data-role=\"all-sides\"] .bjs-border-control-row');\n        if (!row) return;\n        var side = this._readRowValues(row);\n        SIDES.forEach(function (s) {\n          _this9.values[\"border_\".concat(s, \"_style\")] = side.style;\n          _this9.values[\"border_\".concat(s, \"_width\")] = side.width;\n          _this9.values[\"border_\".concat(s, \"_color\")] = side.color;\n          patch[s] = _objectSpread({}, side);\n        });\n      } else {\n        SIDES.forEach(function (s) {\n          var row = _this9.domNode.querySelector(\"[data-role=\\\"per-side\\\"] .bjs-border-control-row[data-side=\\\"\".concat(s, \"\\\"]\"));\n          if (!row) return;\n          var v = _this9._readRowValues(row);\n          _this9.values[\"border_\".concat(s, \"_style\")] = v.style;\n          _this9.values[\"border_\".concat(s, \"_width\")] = v.width;\n          _this9.values[\"border_\".concat(s, \"_color\")] = v.color;\n          patch[s] = _objectSpread({}, v);\n        });\n      }\n      this._syncPreview();\n      if (this.callback && typeof this.callback.setBorder === 'function') {\n        this.callback.setBorder(this.values.border_top_style, this.values.border_top_width, this.values.border_top_color, this.values.border_bottom_style, this.values.border_bottom_width, this.values.border_bottom_color, this.values.border_left_style, this.values.border_left_width, this.values.border_left_color, this.values.border_right_style, this.values.border_right_width, this.values.border_right_color);\n      }\n      if (this.opts && typeof this.opts.onChange === 'function') {\n        this.opts.onChange(patch);\n      }\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BorderControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BorderControl.js?");

/***/ }),

/***/ "./src/includes/BorderRadiusControl.js":
/*!*********************************************!*\
  !*** ./src/includes/BorderRadiusControl.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar MIN = 0;\nvar MAX = 200;\nvar DEBOUNCE_MS = 100;\nvar BorderRadiusControl = /*#__PURE__*/function () {\n  function BorderRadiusControl() {\n    var label = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Radius';\n    var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n    var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {\n      setRadius: function setRadius() {}\n    };\n    _classCallCheck(this, BorderRadiusControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = this._clamp(value);\n    this.callback = callback;\n    this.debounceTimeout = null;\n    this.domNode = document.createElement('div');\n    this.render();\n  }\n  return _createClass(BorderRadiusControl, [{\n    key: \"render\",\n    value: function render() {\n      var pct = (this.value - MIN) / (MAX - MIN) * 100;\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-slider\\\">\\n                        <input type=\\\"range\\\" class=\\\"bjs-slider-track\\\"\\n                            min=\\\"\").concat(MIN, \"\\\" max=\\\"\").concat(MAX, \"\\\" step=\\\"1\\\" value=\\\"\").concat(this.value, \"\\\"\\n                            id=\\\"\").concat(this.id, \"\\\" aria-label=\\\"\").concat(this.label, \"\\\"\\n                            style=\\\"--pct: \").concat(pct, \"%\\\">\\n                        <div class=\\\"bjs-slider-value\\\">\\n                            <input type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n                                min=\\\"\").concat(MIN, \"\\\" max=\\\"\").concat(MAX, \"\\\" step=\\\"1\\\" value=\\\"\").concat(this.value, \"\\\"\\n                                aria-label=\\\"\").concat(this.label, \" (px)\\\">\\n                            <span class=\\\"bjs-number-unit\\\">px</span>\\n                        </div>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      var rangeInput = this.domNode.querySelector('.bjs-slider-track');\n      var numberInput = this.domNode.querySelector('.bjs-number-value');\n      rangeInput.addEventListener('input', function () {\n        _this._setValue(parseInt(rangeInput.value, 10) || 0, {\n          source: 'range'\n        });\n      });\n      numberInput.addEventListener('input', function () {\n        // Allow intermediate empty string while typing — commit on blur.\n        var raw = numberInput.value;\n        if (raw === '') return;\n        _this._setValue(parseInt(raw, 10) || 0, {\n          source: 'number'\n        });\n      });\n      numberInput.addEventListener('blur', function () {\n        // Empty commits to MIN; ensures the field never stays blank.\n        if (numberInput.value === '') {\n          _this._setValue(MIN, {\n            source: 'number'\n          });\n        }\n      });\n    }\n  }, {\n    key: \"_setValue\",\n    value: function _setValue(raw) {\n      var _this2 = this;\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        source = _ref.source;\n      var clamped = this._clamp(raw);\n      this.value = clamped;\n      var rangeInput = this.domNode.querySelector('.bjs-slider-track');\n      var numberInput = this.domNode.querySelector('.bjs-number-value');\n      if (rangeInput && source !== 'range') rangeInput.value = clamped;\n      if (numberInput && source !== 'number') numberInput.value = clamped;\n\n      // Sync the track-fill CSS var so the filled portion matches the thumb.\n      if (rangeInput) {\n        var pct = (clamped - MIN) / (MAX - MIN) * 100;\n        rangeInput.style.setProperty('--pct', pct + '%');\n      }\n      clearTimeout(this.debounceTimeout);\n      this.debounceTimeout = setTimeout(function () {\n        if (_this2.callback && typeof _this2.callback.setRadius === 'function') {\n          _this2.callback.setRadius(_this2.value);\n        }\n      }, DEBOUNCE_MS);\n    }\n  }, {\n    key: \"_clamp\",\n    value: function _clamp(n) {\n      var num = typeof n === 'number' ? n : parseInt(n, 10) || 0;\n      return Math.max(MIN, Math.min(MAX, num));\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var clamped = this._clamp(newValue);\n      if (clamped === this.value) return;\n      this.value = clamped;\n      var rangeInput = this.domNode.querySelector('.bjs-slider-track');\n      var numberInput = this.domNode.querySelector('.bjs-number-value');\n      if (rangeInput) rangeInput.value = clamped;\n      if (numberInput) numberInput.value = clamped;\n      if (rangeInput) {\n        var pct = (clamped - MIN) / (MAX - MIN) * 100;\n        rangeInput.style.setProperty('--pct', pct + '%');\n      }\n      if (this.callback && typeof this.callback.setRadius === 'function') {\n        this.callback.setRadius(this.value);\n      }\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BorderRadiusControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BorderRadiusControl.js?");

/***/ }),

/***/ "./src/includes/Builder.js":
/*!*********************************!*\
  !*** ./src/includes/Builder.js ***!
  \*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _PageElement_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PageElement.js */ \"./src/includes/PageElement.js\");\n/* harmony import */ var _UIManager_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./UIManager.js */ \"./src/includes/UIManager.js\");\n/* harmony import */ var _SettingsTabManager_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SettingsTabManager.js */ \"./src/includes/SettingsTabManager.js\");\n/* harmony import */ var _BuilderJsonStructureValidator_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BuilderJsonStructureValidator.js */ \"./src/includes/BuilderJsonStructureValidator.js\");\n/* harmony import */ var _EventEmitter_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./EventEmitter.js */ \"./src/includes/EventEmitter.js\");\n/* harmony import */ var _ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ui/holedBoxClipPath.js */ \"./src/includes/ui/holedBoxClipPath.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./TextSelectionTracker.js */ \"./src/includes/TextSelectionTracker.js\");\n/* harmony import */ var _overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./overlays/TextInlineToolbarOverlay.js */ \"./src/includes/overlays/TextInlineToolbarOverlay.js\");\n/* harmony import */ var _TextInlineKeyboardShortcuts_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextInlineKeyboardShortcuts.js */ \"./src/includes/TextInlineKeyboardShortcuts.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BuilderjsPopup.js */ \"./src/includes/BuilderjsPopup.js\");\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _HistoryManager_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./HistoryManager.js */ \"./src/includes/HistoryManager.js\");\n/* harmony import */ var _HistoryWidget_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./HistoryWidget.js */ \"./src/includes/HistoryWidget.js\");\n/* harmony import */ var _TooltipManager_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./TooltipManager.js */ \"./src/includes/TooltipManager.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar Builder = /*#__PURE__*/function () {\n  function Builder(options) {\n    var _this$options$loadAss,\n      _this = this,\n      _options$historyMaxSi,\n      _options$historyDebou,\n      _options$historyCoale,\n      _options$historyAutoC;\n    _classCallCheck(this, Builder);\n    // Keep the raw options object around so feature flags flow through\n    // without every caller having to re-pluck fields. PLAN_EFFECT flags\n    // (usePaddingVisualizer, usePaddingRulers, etc.) are read off\n    // `builder.options.*` by their consumers.\n    //\n    // PLAN_EFFECT defaults — explicit `false` from the caller still\n    // wins. Default ON during dev so the demo + downstream hosts both\n    // see the feature out of the box. Production callers can disable\n    // by passing `{ usePaddingVisualizer: false }`.\n    this.options = Object.assign({\n      usePaddingVisualizer: true\n    }, options || {});\n\n    // W6.A.A.5 — peer-dependency auto-injection. The engine hard-depends\n    // on two runtime peer-deps that dist/builder.{js,css} doesn't ship:\n    //\n    //   1. Material Symbols Rounded font — referenced as\n    //      `.material-symbols-rounded` in src/builder.css (24+ rules)\n    //      and Builder.js innerHTML (breadcrumb · panel-parent · widgets\n    //      palette · every overlay icon). Without it, glyphs render as\n    //      raw ligature text (\"arrow_drop_down\", \"edit\", \"code\") all\n    //      across the chrome.\n    //   2. Bootstrap JS bundle — Builder.js + SAlert.js call\n    //      `new bootstrap.Modal(...)` on Change-Theme / Asset-Upload /\n    //      Alert flows. Without it, those clicks throw `bootstrap is\n    //      not defined`.\n    //\n    // Both are auto-injected at construction time iff missing. Idempotent\n    // (skip when already present). Air-gap / China deployments opt out\n    // via `new Builder({ loadAssets: false })` and self-host.\n    //\n    // Default: 'auto' (inject if missing). Pass `false` to skip entirely.\n    // No `'force'` mode — multiple Builder instances on one page never\n    // need a re-inject.\n    this._ensurePeerAssets((_this$options$loadAss = this.options.loadAssets) !== null && _this$options$loadAss !== void 0 ? _this$options$loadAss : 'auto');\n\n    // PLAN_EFFECT W2.3 — Alt-hold inspect runtime state. Mirrors the\n    // global Alt key — set by `_inspectModeInit()` listeners, read by\n    // `BaseElement.addHoverHightlight()` so a NEW hover that mounts\n    // mid-Alt-hold gets the inspect class on first paint. Lives on\n    // the Builder instance (NOT body class) per the \"scope to overlay,\n    // not page\" rule — a sibling host page on the same domain is not\n    // affected.\n    this._inspectAltDown = false;\n\n    // PLAN_EFFECT W3.2 — session-scoped per-element pin state. Lives\n    // only on the running Builder instance, never serialized to\n    // template JSON. Membership = \"keep the padding visualiser rich\n    // whenever this element is selected, regardless of panel focus\".\n    this._pinnedPaddingElements = new Set();\n\n    // Host-injection state — promoted to explicit constructor init so\n    // every Builder instance owns its own slots from t=0 (was previously\n    // lazily created by ColorPickerControl / ImageControl on first use,\n    // which broke multi-instance because the slots were attached via\n    // bare-builder reach-in to whichever instance happened to be set\n    // as the page-level global). See Lesson \"Host Injection\" in\n    // BUILDER.md.\n    this._activeControls = {};\n    this._recentElementColors = [];\n\n    // i18n initialization\n    _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].init(options.translations);\n\n    // Container resolution.\n    //\n    // `mainContainer` (canvas) is REQUIRED — every Builder mounts a canvas.\n    // `widgetsContainer` and `settingsContainer` are OPTIONAL: pass `null`\n    // / `undefined` (or a selector that resolves to no element) and the\n    // corresponding sub-system simply does not mount. Cookbook chrome\n    // presets (W6 Phase C.B) rely on this to drop sidebars without\n    // forcing the buyer to ship hidden orphan `<div>`s.\n    //\n    // Existing 3-container callers (demo/builder.php and the W6 Phase B\n    // examples) pass valid selectors and behave identically — the null is\n    // strictly additive. See DISCOVERIES.md D13.A.A.1 for the design\n    // rationale (W6.A.A.1, 2026-05-07).\n    this.mainContainer = window.document.querySelector(options.mainContainer);\n    this.settingsContainer = options.settingsContainer ? window.document.querySelector(options.settingsContainer) : null;\n    this.widgetsContainer = options.widgetsContainer ? window.document.querySelector(options.widgetsContainer) : null;\n\n    // Canvas-clip reflow set + observer (2026-05-09).\n    //\n    // Every overlay positioner registered through\n    // `BaseElement.matchingDomNode` adds its `setPosSize` closure to\n    // this set on first mount and removes it from `__disconnectObservers`.\n    // The clip-container ResizeObserver iterates the set on every\n    // resize so a pure chrome-driven layout shift (sidebar collapse,\n    // chrome-variant swap, parent column reflow that doesn't change\n    // iframe-internal element rects) still re-ticks every overlay's\n    // clip pass + position. Single observer per Builder; per-overlay\n    // hooks. Multi-Builder safe because each Builder owns its own\n    // set + observer.\n    //\n    // ── Clip-container resolution (walk-up rule) ──────────────────\n    // Buyers typically wire `mainContainer` to a div they own\n    // (`#MainContainer` in demo/builder.php, `.bjs-mb__canvas` slot\n    // in cookbook variants). That div often does NOT have its own\n    // overflow boundary — the SCROLL viewport sits one or more\n    // ancestors up (e.g. `.demo-builder__canvas` with `overflow:\n    // auto` in demo/builder.php). When the viewport scrolls, the\n    // iframe inside `mainContainer` slides past topnav / sticky\n    // chrome — its rect (and `mainContainer`'s rect) become\n    // negative-top, but the chrome stays put. Clipping to\n    // `mainContainer` does NOTHING in that frame because both rects\n    // share the same offset. We need to clip to the FIRST ancestor\n    // whose overflow clips paint (auto / scroll / hidden) — that's\n    // the actual canvas viewport.\n    //\n    // If no such ancestor is found, fall back to `mainContainer`\n    // itself (full-page builder where there's no chrome above the\n    // canvas — clip is a no-op).\n    //\n    // See BUILDER.md \"Canvas-clip contract\" + OVERLAY.md §24.\n    this._reflowHooks = new Set();\n    this._mainContainerResizeObserver = null;\n    this._resolvedClipContainer = this._resolveClipContainer();\n    var _clipTarget = this._resolvedClipContainer || this.mainContainer;\n    if (_clipTarget && typeof ResizeObserver === 'function') {\n      this._mainContainerResizeObserver = new ResizeObserver(function () {\n        var _iterator = _createForOfIteratorHelper(_this._reflowHooks),\n          _step;\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var hook = _step.value;\n            try {\n              hook();\n            } catch (_) {/* per-overlay error must not break others */}\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      });\n      this._mainContainerResizeObserver.observe(_clipTarget);\n    }\n    this.assetUploadHandler = options.assetUploadHandler;\n    // AI Task framework — explicit URL per feature. Each consumer\n    // wires their own AI endpoint; the demo wires the BuilderJS AI\n    // showcase URLs by default.\n    // Shape: { inlineRewriteUrl?, chatboxUrl?, pageGeneratorUrl?, enabled?, csrfToken? }\n    // Per-feature enable: omit/null the URL. Per-installation disable: enabled=false.\n    this.ai = options.ai || {};\n    this.rssHandler = options.rssHandler || null;\n\n    // themeMediaUrl — Base URL pointing to the theme's media/assets directory.\n    // Set by load(). Used to resolve relative asset paths (images, fonts, etc.)\n    // stored in template JSON into absolute URLs for rendering in the iframe.\n    //\n    // How it works:\n    //   1. Template JSON stores paths RELATIVE to the theme folder:\n    //        \"image\": \"assets/profile_image/avatar.png\"\n    //        \"background\": \"assets/backgrounds/header-bg.jpg\"\n    //\n    //   2. At render time, transferMediaAbsUrl() prepends themeMediaUrl:\n    //        \"assets/profile_image/avatar.png\"\n    //        → \"https://app.example.com/templates/000abc/assets/profile_image/avatar.png\"\n    //\n    //   3. At save/export time, getHtmlWithRelativeLinks() strips themeMediaUrl\n    //      back out, so the saved HTML stays portable (relative paths only).\n    //\n    // Example values from a SaaS host:\n    //   - Email builder:  \"https://app.example.com/p/templates/000abc\"\n    //                     (e.g. a Template model's public URL)\n    //   - Form builder:   \"https://app.example.com/p/templates/000def\"\n    //   - Demo/dev:       \"themes/default\" (relative to demo page)\n    //\n    // Also used by BackgroundControl to convert absolute URLs back to relative\n    // when saving background image values (strips themeMediaUrl prefix).\n    //\n    // Key rule: paths like \"assets/profile_image/photo.jpg\" are RELATIVE —\n    // they live inside the template's storage folder. themeMediaUrl is the\n    // root that makes them absolute for the browser.\n    this.themeMediaUrl = null;\n    this.themeConfigs = null;\n    this.templates = {};\n\n    // helpers\n    this.iframe = null;\n\n    // PageElement\n    this.pageElement = new _PageElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"](this);\n\n    // Initialize parameters\n    this.mode = 'preview';\n    this.selectedElement = null;\n\n    // Initialize UI Manager\n    this.uiManager = new _UIManager_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](this);\n\n    // Global pub/sub on every Builder instance. Started life as\n    // `CanvasHighlightBus` for control↔overlay signalling (W0.1; events\n    // 'region:focus' / 'region:blur'); CD-3 (AIBuilder Wave 4) generalised\n    // it into `EventEmitter` so host apps can drive autosave + dirty\n    // tickers off the same bus the History system already publishes on.\n    // Canonical events table: docs/core/USAGE.md \"Event bus (CD-3)\".\n    // `document:changed` is debounced inside the bus so a typing burst\n    // collapses into ONE host-visible signal (default 120ms — ~2 frames\n    // at 60Hz, coalesces typing without lagging perceptual feedback).\n    // Host overrides via `new Builder({ eventDebounceMs: ... })`.\n    var eventDebounceMs = typeof options.eventDebounceMs === 'number' ? options.eventDebounceMs : 120;\n    this.events = new _EventEmitter_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\n      debounce: _defineProperty({}, Builder.EVENTS.DOCUMENT_CHANGED, eventDebounceMs)\n    });\n\n    // PLAN_EFFECT W0.3 — pure geometry utility for smart-flipped,\n    // horizontally-clamped floating toolbars. Stateless; exposing the\n    // class here is inert until W1.1 wires the actionsBox positioner\n    // behind `useSmartToolbarPosition`. See docs/core/OVERLAY.md \"Toolbar\n    // Positioner\".\n    this.toolbarPositioner = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"];\n\n    // TooltipManager — singleton DOM tooltip that portals into\n    // <body> so it escapes every ancestor overflow clip (sidebar,\n    // popovers, canvas wrappers). Installed once on first Builder\n    // construction; subsequent instances share the same manager.\n    // Reads `data-tooltip` / `data-tooltip-placement` /\n    // `data-tooltip-align` attrs from every button in the chrome.\n    this.tooltipManager = (0,_TooltipManager_js__WEBPACK_IMPORTED_MODULE_16__.getTooltipManager)();\n\n    // PLAN_EFFECT W1.4 — focus-dim mode state.\n    // `bjs:focus-dim` in localStorage persists the user toggle\n    // across reloads. `_focusDimInit()` is called from `load()`\n    // after the iframe is ready so the stored value re-applies.\n    this._focusDim = false;\n    this._focusDimKeyHandler = null;\n\n    // TEXT_INLINE_PLAN W0.3 — single canvas-wide selection tracker.\n    // Instantiated + attached by `_textSelectionInit()` once the iframe\n    // document is available. Kept as a `Builder` field so both overlays\n    // and tests can reach it (`builder.textSelectionTracker.getCurrent()`).\n    this.textSelectionTracker = null;\n\n    // TEXT_INLINE_PLAN W1.1 — floating inline-text formatting toolbar.\n    // Singleton owned by the Builder; subscribes to `text-selection:*`\n    // bus events emitted by the W0.3 tracker. Mount/unmount is driven\n    // by selection changes (HARD RULE T1) — never by element click.\n    // Instantiated + attached in `_textInlineToolbarInit()` after the\n    // tracker is live.\n    this._textInlineToolbar = null;\n\n    // saveUrl for save() method\n    this.saveUrl = options.saveUrl || null;\n\n    // ─── History (undo/redo) ──────────────────────────────────────\n    // PLAN_UNDO_REDO W7.3 — HistoryManager lives on the builder\n    // instance. Widget default-on (opt-out via historyUI: false).\n    // Shortcuts default-on (Ctrl/⌘Z, Ctrl/⌘⇧Z). See\n    // docs/plans/PLAN_UNDO_REDO.md.\n    this.history = new _HistoryManager_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this, {\n      maxSize: (_options$historyMaxSi = options.historyMaxSize) !== null && _options$historyMaxSi !== void 0 ? _options$historyMaxSi : 50,\n      debounceMs: (_options$historyDebou = options.historyDebounceMs) !== null && _options$historyDebou !== void 0 ? _options$historyDebou : 400,\n      coalesceMs: (_options$historyCoale = options.historyCoalesceMs) !== null && _options$historyCoale !== void 0 ? _options$historyCoale : 600,\n      autoCloseTxMs: (_options$historyAutoC = options.historyAutoCloseTxMs) !== null && _options$historyAutoC !== void 0 ? _options$historyAutoC : 5000\n    });\n    this._historyWidget = null; // instantiated after load() so\n    // mainContainer has final layout\n    this._historyKeyHandler = null;\n\n    // central structure validator for load/parse path\n    this.structureValidator = new _BuilderJsonStructureValidator_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]();\n\n    // filemanager plugin\n    if (options.fileManager) {\n      this.fileManager = options.fileManager;\n    }\n  }\n\n  /**\n   * Adopt an element subtree: recursively sets `host` on the element,\n   * its children (via getChildren()), and any overlays it has emitted\n   * (`element.overlays`). Called once after a subtree is parsed,\n   * before render / mount.\n   *\n   * Why: Host injection — every Element/Overlay/Control needs a\n   * back-reference to its owning Builder for bus / flags / shared\n   * state. Walking the tree post-parse keeps `static parse(data)`\n   * signature unchanged (CD-1).\n   *\n   * Idempotent — re-adopting an already-adopted element is a no-op,\n   * so it's safe to call multiple times along an insertion path.\n   *\n   * @param {BaseElement} element  root of the subtree to adopt\n   */\n  /**\n   * Resolve the canvas-clip surface (2026-05-09).\n   *\n   * Walks up from `mainContainer` until the first ancestor whose\n   * computed `overflow{,X,Y}` is one of `auto / scroll / hidden`.\n   * That ancestor IS the actual canvas viewport — anything painted\n   * past its border-box gets clipped by the browser's own overflow\n   * machinery, so it's the SAME boundary the user sees.\n   *\n   * Why not just use `mainContainer`? In demo/builder.php (and any\n   * real-world chrome with a topnav / sticky header), `mainContainer`\n   * is the iframe wrapper that scrolls along with the iframe inside\n   * a higher-up scroll viewport. When the user scrolls down, the\n   * iframe rect AND mainContainer rect both go negative-top in\n   * unison — clipping to mainContainer is a no-op against itself in\n   * that frame. The actual viewport is `.demo-builder__canvas`\n   * (overflow: auto) sitting below the topnav.\n   *\n   * Cookbook variants where buyers wire `mainContainer` to a fully\n   * self-contained card / floating panel (their own overflow:hidden)\n   * find the boundary at depth 0 (mainContainer itself).\n   *\n   * Falls back to `mainContainer` if no scroll-clipping ancestor is\n   * found (full-page builder where the viewport == document — clip\n   * becomes a visual no-op which is correct for that case).\n   *\n   * @returns {HTMLElement|null} the resolved clip surface\n   */\n  return _createClass(Builder, [{\n    key: \"_resolveClipContainer\",\n    value: function _resolveClipContainer() {\n      if (!this.mainContainer) return null;\n      var el = this.mainContainer;\n      while (el && el !== document.body && el !== document.documentElement) {\n        var cs = window.getComputedStyle(el);\n        var ov = (cs.overflow || '') + (cs.overflowX || '') + (cs.overflowY || '');\n        if (/(auto|scroll|hidden)/.test(ov)) {\n          return el;\n        }\n        el = el.parentElement;\n      }\n      return this.mainContainer;\n    }\n  }, {\n    key: \"_adopt\",\n    value: function _adopt(element) {\n      if (!element || element.host === this) return;\n      element.host = this;\n      // Propagate host into the element's formatter so its\n      // `background_image: url(...)` resolution can route through\n      // host.transferMediaAbsUrl per-instance (was a bare-builder\n      // reach-in pre-host-injection W3 batch).\n      if (element.formatter && typeof element.formatter._setHost === 'function') {\n        element.formatter._setHost(this);\n      }\n      if (Array.isArray(element.overlays)) {\n        var _iterator2 = _createForOfIteratorHelper(element.overlays),\n          _step2;\n        try {\n          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n            var o = _step2.value;\n            if (o) o.host = this;\n          }\n        } catch (err) {\n          _iterator2.e(err);\n        } finally {\n          _iterator2.f();\n        }\n      }\n      var kids = typeof element.getChildren === 'function' ? element.getChildren() : [];\n      var _iterator3 = _createForOfIteratorHelper(kids),\n        _step3;\n      try {\n        for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n          var k = _step3.value;\n          this._adopt(k);\n        }\n      } catch (err) {\n        _iterator3.e(err);\n      } finally {\n        _iterator3.f();\n      }\n    }\n\n    /**\n     * W6.A.A.5 — auto-inject the engine's peer-dep CDN tags if absent.\n     *\n     * Detects whether the host page already loaded Material Symbols\n     * Rounded (font) + Bootstrap JS (behavior) and injects matching\n     * `<link>` / `<script>` tags into `document.head` if not. Idempotent:\n     * subsequent Builder instances on the same page skip both checks.\n     *\n     * Detection rules (kept loose to avoid false-negatives across CDN\n     * mirrors / version pins / self-hosted variants):\n     *   - Material Symbols Rounded: any `<link>` whose `href` contains\n     *     `Material+Symbols+Rounded` (case-insensitive). Matches Google\n     *     Fonts URL + the typical self-host filename.\n     *   - Bootstrap JS: `window.bootstrap?.Modal` is a function. Matches\n     *     bundle, separate-popper-and-bootstrap, and self-hosted variants.\n     *\n     * Race notes:\n     *   - Material Symbols is purely visual; late load swaps glyphs in\n     *     when ready (the `display=block` fontface descriptor pins the\n     *     glyph slot until ready, no FOUT shimmer).\n     *   - Bootstrap JS load is async (~80KB over CDN, <500ms typical).\n     *     The engine never opens a modal during boot — only on user-\n     *     triggered actions like Change-Theme / Asset-Upload, by which\n     *     time the bundle has loaded. Users clicking within the first\n     *     ~500ms hit a `bootstrap is not defined` error; acceptable\n     *     tradeoff vs. forcing every buyer to remember the script tag.\n     *\n     * @param {'auto'|false} mode — 'auto' to inject if missing,\n     *                              false to skip entirely (air-gap / self-host).\n     */\n  }, {\n    key: \"_ensurePeerAssets\",\n    value: function _ensurePeerAssets(mode) {\n      if (mode === false || typeof document === 'undefined') return;\n      var head = document.head;\n      if (!head) return;\n\n      // ── Material Symbols Rounded ──────────────────────────────────\n      var hasIconFont = Array.from(head.querySelectorAll('link[rel=\"stylesheet\"]')).some(function (l) {\n        return /Material\\+Symbols\\+Rounded/i.test(l.href || '');\n      });\n      if (!hasIconFont) {\n        var link = document.createElement('link');\n        link.rel = 'stylesheet';\n        link.href = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&display=block';\n        link.dataset.bjsAutoinject = 'icon-font';\n        head.appendChild(link);\n      }\n\n      // ── Bootstrap JS (modal/alert behavior) ───────────────────────\n      var hasBootstrapJs = typeof window !== 'undefined' && window.bootstrap && typeof window.bootstrap.Modal === 'function';\n      if (!hasBootstrapJs) {\n        // Don't double-inject if a prior Builder instance already added\n        // the script (still loading). Mark via data attribute.\n        var alreadyInjecting = head.querySelector('script[data-bjs-autoinject=\"bootstrap-js\"]');\n        if (!alreadyInjecting) {\n          var script = document.createElement('script');\n          script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js';\n          script.defer = true;\n          script.dataset.bjsAutoinject = 'bootstrap-js';\n          head.appendChild(script);\n        }\n      }\n    }\n\n    /**\n     * Save the current page content.\n     * Sends the generated HTML and JSON data to the configured saveUrl via Ajax POST.\n     *\n     * @returns {Promise<Object>} The JSON response from the server.\n     */\n  }, {\n    key: \"save\",\n    value: (function () {\n      var _save = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n        var html, data, payload, response;\n        return _regeneratorRuntime().wrap(function _callee$(_context) {\n          while (1) switch (_context.prev = _context.next) {\n            case 0:\n              if (this.saveUrl) {\n                _context.next = 2;\n                break;\n              }\n              throw new Error('saveUrl is not configured. Pass it in the constructor options.');\n            case 2:\n              html = this.getHtml();\n              data = this.getData();\n              payload = new URLSearchParams();\n              payload.append('html', html);\n              payload.append('data', JSON.stringify(data));\n              _context.next = 9;\n              return fetch(this.saveUrl, {\n                method: 'POST',\n                headers: {\n                  'Content-Type': 'application/x-www-form-urlencoded'\n                },\n                body: payload.toString()\n              });\n            case 9:\n              response = _context.sent;\n              return _context.abrupt(\"return\", response.json());\n            case 11:\n            case \"end\":\n              return _context.stop();\n          }\n        }, _callee, this);\n      }));\n      function save() {\n        return _save.apply(this, arguments);\n      }\n      return save;\n    }()\n    /* ─── PLAN_EFFECT W1.4 — focus-dim mode ─────────────────────────\n     *\n     * Host apps toggle \"focus mode\" via these three methods. When ON,\n     * the iframe body receives a `.bjs-focus-dim` class — CSS in the\n     * injected debug-css helper then applies `filter: brightness(…)`\n     * to all content while counter-brightening the `[data-bjs-\n     * selected=\"true\"]` element so the selection pops off the dimmed\n     * canvas. State persists in `localStorage` under the key\n     * `bjs:focus-dim` so the user's preference survives reload.\n     *\n     * Keyboard shortcut `⌘/Ctrl+.` is registered at `load()` time via\n     * `_focusDimInit()` and torn down automatically on any future\n     * `destroy()` path (via `_focusDimKeyHandler`).\n     *\n     * Honors `prefers-reduced-motion` — no filter transition when the\n     * user requested reduced motion.\n     */\n    )\n  }, {\n    key: \"isFocusDim\",\n    value: function isFocusDim() {\n      return this._focusDim === true;\n    }\n  }, {\n    key: \"setFocusDim\",\n    value: function setFocusDim(on) {\n      var next = !!on;\n      if (this._focusDim === next) return;\n      this._focusDim = next;\n      this._applyFocusDim();\n      try {\n        localStorage.setItem('bjs:focus-dim', next ? '1' : '0');\n      } catch (_) {}\n    }\n  }, {\n    key: \"toggleFocusDim\",\n    value: function toggleFocusDim() {\n      this.setFocusDim(!this._focusDim);\n    }\n\n    /** Apply / remove the `.bjs-focus-dim` class on the iframe body +\n     *  mirror the flag onto the MAIN document.body as\n     *  `bjs-focus-dim-active` so main-window CSS (e.g. .selected-box\n     *  outline rules) can react — then (un)mount the spotlight\n     *  panels. Idempotent; safe to call pre-iframe-mount. */\n  }, {\n    key: \"_applyFocusDim\",\n    value: function _applyFocusDim() {\n      // Mirror onto main document body so `.selected-box` (which\n      // lives in main window, not iframe) can read the state. User\n      // feedback 2026-04-19: square outline when dim is ON avoids\n      // the 4-corner bright gaps where the square 4-panel cutout\n      // meets a rounded outline.\n      try {\n        document.body.classList.toggle('bjs-focus-dim-active', this._focusDim);\n      } catch (_) {}\n      var doc = this.iframe && this.iframe.contentDocument;\n      if (doc && doc.body) {\n        doc.body.classList.toggle('bjs-focus-dim', this._focusDim);\n      }\n\n      // Mount / unmount the spotlight based on state + selection.\n      if (this._focusDim && this.getSelectedElement()) {\n        this._mountFocusSpotlight(this.getSelectedElement());\n      } else {\n        this._unmountFocusSpotlight();\n      }\n    }\n\n    /** Mount 4 dim panels surrounding the selected element's rect\n     *  inside the iframe body. Each panel carries backdrop-filter:\n     *  blur + a dark tint; the spotlight rect itself has no panel\n     *  over it so it stays razor-sharp. PAD (5 px) matches\n     *  `.selected-box`'s matchingDomNode(5) so the bright region\n     *  ends precisely at the outline's visible edge. */\n  }, {\n    key: \"_mountFocusSpotlight\",\n    value: function _mountFocusSpotlight(element) {\n      var _this2 = this;\n      if (!element || !element.domNode) return;\n      var doc = element.domNode.ownerDocument;\n      if (!doc || !doc.body) return;\n\n      // Single-element holed-box — same primitive as hover / select\n      // container-highlight + padding visualiser. `clip-path: polygon(...)`\n      // carves the selected element's rect out of a full-viewport `--dim`\n      // layer so the element stays razor-sharp while the rest of the\n      // canvas is dimmed.\n      //\n      // NO `--blur` here. The backdrop-filter + clip-path combination\n      // hits a Chrome / Safari compositing quirk where the filter\n      // buffer spans the element's whole bounding box before clipping\n      // — the filtered snapshot then leaks into the hole area and the\n      // element appears blurred through it. The dim-only surface is\n      // lighter (1 element vs 4), architecturally consistent with the\n      // other 3 primitive callsites, and \"turn off the lights\" reads\n      // clearly without the blur. Added note in docs/plans/HOLED_BOX.md §\n      // \"backdrop-filter gotcha\" so future requests to re-add blur\n      // land on the 4-panel fallback pattern instead.\n      if (!this._focusSpotlightPanel) {\n        var p = doc.createElement('div');\n        p.className = 'bjs-holed-box bjs-holed-box--dim bjs-focus-dim-spot';\n        // `.bjs-holed-box` uses `inset: 0` relative to the containing\n        // block; override here to anchor to the viewport explicitly\n        // via `position: fixed` so we cover the full iframe no matter\n        // where the body layout puts things.\n        p.style.position = 'fixed';\n        p.style.top = '0';\n        p.style.left = '0';\n        p.style.width = '100%';\n        p.style.height = '100%';\n        p.style.zIndex = '999998';\n        p.style.pointerEvents = 'none';\n        doc.body.appendChild(p);\n        this._focusSpotlightPanel = p;\n      }\n      var PAD = 5;\n      var setPos = function setPos() {\n        var p = _this2._focusSpotlightPanel;\n        if (!p || !element.domNode) return;\n        var r = element.domNode.getBoundingClientRect();\n        var iwin = doc.defaultView;\n        var vw = iwin.innerWidth;\n        var vh = iwin.innerHeight;\n        var t = Math.max(0, r.top - PAD);\n        var l = Math.max(0, r.left - PAD);\n        var w = r.width + PAD * 2;\n        var h = r.height + PAD * 2;\n        // Holed-box polygon: outer = viewport rect, hole = selected\n        // element rect inflated by PAD to clear its outline.\n        p.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"])({\n          width: vw,\n          height: vh\n        }, {\n          left: l,\n          top: t,\n          right: l + w,\n          bottom: t + h\n        });\n      };\n      setPos();\n\n      // Tear down any prior observer set (element may have been re-\n      // selected with a different domNode after an inner render).\n      this._disposeFocusSpotlightObservers();\n      var iwin = doc.defaultView;\n      var onScroll = function onScroll() {\n        return setPos();\n      };\n      var onResize = function onResize() {\n        return setPos();\n      };\n      iwin.addEventListener('scroll', onScroll, true);\n      iwin.addEventListener('resize', onResize);\n      window.addEventListener('scroll', onScroll, true);\n      window.addEventListener('resize', onResize);\n      var mo = null;\n      var ro = null;\n      try {\n        mo = new iwin.MutationObserver(function () {\n          return setPos();\n        });\n        mo.observe(doc.body, {\n          childList: true,\n          subtree: true,\n          attributes: true\n        });\n        if (typeof iwin.ResizeObserver === 'function') {\n          ro = new iwin.ResizeObserver(function () {\n            return setPos();\n          });\n          ro.observe(element.domNode);\n        }\n      } catch (_) {/* dead iframe — ignore */}\n      this._focusSpotlightDispose = function () {\n        try {\n          iwin.removeEventListener('scroll', onScroll, true);\n        } catch (_) {}\n        try {\n          iwin.removeEventListener('resize', onResize);\n        } catch (_) {}\n        try {\n          window.removeEventListener('scroll', onScroll, true);\n        } catch (_) {}\n        try {\n          window.removeEventListener('resize', onResize);\n        } catch (_) {}\n        try {\n          if (mo) mo.disconnect();\n        } catch (_) {}\n        try {\n          if (ro) ro.disconnect();\n        } catch (_) {}\n      };\n    }\n  }, {\n    key: \"_unmountFocusSpotlight\",\n    value: function _unmountFocusSpotlight() {\n      this._disposeFocusSpotlightObservers();\n      if (this._focusSpotlightPanels) {\n        for (var _i = 0, _Object$values = Object.values(this._focusSpotlightPanels); _i < _Object$values.length; _i++) {\n          var p = _Object$values[_i];\n          try {\n            p.remove();\n          } catch (_) {}\n        }\n        this._focusSpotlightPanels = null;\n      }\n      // Back-compat clean-up — the brief single-holed-box iteration\n      // stored on this._focusSpotlightPanel. Drop any stale instance\n      // left over from a hot-reload boundary across the refactor.\n      if (this._focusSpotlightPanel) {\n        try {\n          this._focusSpotlightPanel.remove();\n        } catch (_) {}\n        this._focusSpotlightPanel = null;\n      }\n    }\n  }, {\n    key: \"_disposeFocusSpotlightObservers\",\n    value: function _disposeFocusSpotlightObservers() {\n      if (typeof this._focusSpotlightDispose === 'function') {\n        try {\n          this._focusSpotlightDispose();\n        } catch (_) {}\n        this._focusSpotlightDispose = null;\n      }\n    }\n\n    /** Wire up persistence + keyboard shortcut. Called once after the\n     *  iframe content is loaded + the first `_injectIframeHelpers()`\n     *  has run (so the CSS rules are already in the head). */\n  }, {\n    key: \"_focusDimInit\",\n    value: function _focusDimInit() {\n      var _this3 = this;\n      // Restore persisted value, if any.\n      try {\n        var stored = localStorage.getItem('bjs:focus-dim');\n        if (stored === '1') this._focusDim = true;\n      } catch (_) {}\n      this._applyFocusDim();\n\n      // `⌘/Ctrl+.` toggles. Only on the OUTER document — not inside\n      // the iframe — so typing `.` into an inline-edit contentedit-\n      // able never steals the shortcut. Handler guards against\n      // inputs / textareas / contentEditable in the outer chrome\n      // too (for the settings sidebar).\n      if (this._focusDimKeyHandler) {\n        document.removeEventListener('keydown', this._focusDimKeyHandler, true);\n      }\n      this._focusDimKeyHandler = function (e) {\n        var isToggle = (e.metaKey || e.ctrlKey) && e.key === '.' && !e.shiftKey && !e.altKey;\n        if (!isToggle) return;\n        var tgt = e.target;\n        if (tgt && (tgt.tagName === 'INPUT' || tgt.tagName === 'TEXTAREA' || tgt.isContentEditable === true)) {\n          return;\n        }\n        e.preventDefault();\n        _this3.toggleFocusDim();\n      };\n      document.addEventListener('keydown', this._focusDimKeyHandler, true);\n    }\n\n    /* ─── PLAN_EFFECT W2.3 — Alt-hold \"Inspect mode\" ──────────────────\n     *\n     * Tracks Alt key state on BOTH the outer document and the iframe\n     * document. While Alt is held + the user is NOT in a text-edit\n     * context, applies `.bjs-inspect-active` to the currently mounted\n     * `.hovering-box` (and stores the boolean on `this._inspectAltDown`\n     * so a NEW hover that starts mid-Alt-hold paints inspect-on on\n     * first frame).\n     *\n     * Why both documents?\n     * - Outer document: covers Alt held while sidebar / topbar focused.\n     * - Iframe document: covers Alt held while mouse is over the canvas\n     *   (most common case — without this, the iframe steals key events).\n     *\n     * Auto-clear on:\n     * - keyup of Alt\n     * - window blur (user switched apps with Alt held)\n     * - text-edit context gained (focus on input / textarea /\n     *   contentEditable) — the class drops immediately so the user\n     *   never sees inspect overlays while typing.\n     *\n     * Why class on `.hovering-box` (not body)?\n     * The Builder is a guest in the host page. Mutating `document.body`\n     * pollutes a surface the host owns and may style — class collisions,\n     * unrelated CSS rules tripping on it, devtools confusion. Scoping\n     * the inspect state to the overlay element itself keeps every\n     * Builder side-effect inside the Builder's own DOM. See HARD RULE C\n     * (revised 2026-04-19) in BUILDER.md for the full rationale.\n     */\n  }, {\n    key: \"_inspectModeInit\",\n    value: function _inspectModeInit() {\n      var _this4 = this;\n      var isInTextEdit = function isInTextEdit() {\n        var a = document.activeElement;\n        if (!a) return false;\n        if (a.tagName === 'INPUT' || a.tagName === 'TEXTAREA') return true;\n        if (a.isContentEditable === true) return true;\n        return false;\n      };\n      var setActive = function setActive(on) {\n        _this4._inspectAltDown = !!on;\n        // Apply to the currently mounted hover overlay (only one at a\n        // time per UIManager). Idempotent class toggle — cheap.\n        try {\n          var boxes = document.querySelectorAll('.hovering-box');\n          var _iterator4 = _createForOfIteratorHelper(boxes),\n            _step4;\n          try {\n            for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {\n              var b = _step4.value;\n              b.classList.toggle('bjs-inspect-active', _this4._inspectAltDown);\n            }\n          } catch (err) {\n            _iterator4.e(err);\n          } finally {\n            _iterator4.f();\n          }\n        } catch (_) {}\n      };\n      var onKeyDown = function onKeyDown(e) {\n        if (e.key !== 'Alt' && !e.altKey) return;\n        if (isInTextEdit()) return;\n        setActive(true);\n      };\n      var onKeyUp = function onKeyUp(e) {\n        // `e.key === 'Alt'` handles the explicit Alt release. Also\n        // clear if any other key release happens with `e.altKey`\n        // false — covers the Tab-out / Cmd-Tab edge case.\n        if (e.key === 'Alt' || !e.altKey) {\n          setActive(false);\n        }\n      };\n      var onBlur = function onBlur() {\n        return setActive(false);\n      };\n\n      // Outer document.\n      document.addEventListener('keydown', onKeyDown, true);\n      document.addEventListener('keyup', onKeyUp, true);\n      window.addEventListener('blur', onBlur);\n\n      // Iframe document. The iframe may not exist yet at construct\n      // time — wire up after `load()` mounts it. Re-wire on every\n      // PageElement.render() too, since the iframe document survives\n      // but listeners are persistent (we attach to the same document\n      // object the iframe mounts into).\n      var wireIframe = function wireIframe() {\n        var idoc = _this4.iframe && _this4.iframe.contentDocument;\n        if (!idoc || idoc.__bjsInspectWired) return;\n        idoc.addEventListener('keydown', onKeyDown, true);\n        idoc.addEventListener('keyup', onKeyUp, true);\n        idoc.__bjsInspectWired = true;\n      };\n      setTimeout(wireIframe, 0);\n      window.addEventListener('focus', wireIframe);\n    }\n\n    /* ─── TEXT_INLINE_PLAN W0.3 — selection tracker bootstrap ──── */\n  }, {\n    key: \"_textSelectionInit\",\n    value: function _textSelectionInit() {\n      var idoc = this.iframe && this.iframe.contentDocument;\n      if (!idoc) return;\n\n      // If load() is called twice (dev hot-reload, rebind tests), tear\n      // down the previous tracker first so we don't leak two listener\n      // chains on the same document.\n      if (this.textSelectionTracker) {\n        this.textSelectionTracker.destroy();\n        this.textSelectionTracker = null;\n      }\n      this.textSelectionTracker = new _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"]({\n        doc: idoc,\n        bus: this.events\n      });\n      this.textSelectionTracker.attach();\n    }\n\n    /* ─── TEXT_INLINE_PLAN W1.1 — inline toolbar bootstrap ────────── */\n  }, {\n    key: \"_textInlineToolbarInit\",\n    value: function _textInlineToolbarInit() {\n      // Tear down + rebuild on hot reload so we don't leak two\n      // subscribers on the same bus.\n      if (this._textInlineToolbar) {\n        this._textInlineToolbar.destroy();\n        this._textInlineToolbar = null;\n      }\n      this._textInlineToolbar = new _overlays_TextInlineToolbarOverlay_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](this);\n      this._textInlineToolbar.attach();\n    }\n\n    /* ─── TEXT_INLINE_PLAN W6.3 — keyboard shortcut bootstrap ──── */\n  }, {\n    key: \"_textInlineShortcutsInit\",\n    value: function _textInlineShortcutsInit() {\n      // Tear down + rebuild on hot reload; same iframe-attach pattern\n      // as TextSelectionTracker / TextInlineToolbarOverlay so a second\n      // `load()` call doesn't leak listener pairs on the same document.\n      if (this._textInlineShortcuts) {\n        this._textInlineShortcuts.destroy();\n        this._textInlineShortcuts = null;\n      }\n      this._textInlineShortcuts = new _TextInlineKeyboardShortcuts_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](this);\n      this._textInlineShortcuts.attach();\n    }\n\n    /* ─── PLAN_UNDO_REDO W7.3 — History bootstrap ───────────────── */\n  }, {\n    key: \"_historyInit\",\n    value: function _historyInit() {\n      var _this5 = this;\n      if (this.options.historyEnabled === false) return;\n\n      // 1. Baseline snapshot — one entry for the freshly loaded state.\n      this.history.pushBaseline();\n\n      // 2. Bind iframe + settings debounce fallback. Small delay so\n      //    the iframe document is definitely attached + listeners on\n      //    the document survive subsequent re-renders (PageElement\n      //    only replaces <head>, not the document itself).\n      setTimeout(function () {\n        return _this5.history.bindDebounceFallback();\n      }, 0);\n\n      // 2a. Subscribe to region:focus / region:blur so debounce commits\n      //     can attach \"which property was focused\" context. Currently\n      //     only PaddingMarginControl emits these, but any future control\n      //     that opts in gets the benefit for free.\n      this.history.bindRegionFocusTracking();\n\n      // 3. Mount floating widget (opt-out: historyUI: false).\n      if (this.options.historyUI !== false) {\n        this._historyWidget = new _HistoryWidget_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](this, {\n          position: this.options.historyUIPosition || 'bottom-left',\n          minimal: !!this.options.historyUIMinimal,\n          className: this.options.historyUIClassName || ''\n        });\n        this._historyWidget.mount();\n      }\n\n      // 4. Keyboard shortcuts — Ctrl/⌘Z · Ctrl/⌘⇧Z · Ctrl+Y. Wired\n      //    on OUTER document with capture phase, skips text-edit\n      //    contexts (matches _focusDimInit pattern).\n      if (this.options.historyShortcuts === false) return;\n      if (this._historyKeyHandler) {\n        document.removeEventListener('keydown', this._historyKeyHandler, true);\n      }\n      this._historyKeyHandler = function (e) {\n        var mod = e.metaKey || e.ctrlKey;\n        if (!mod) return;\n        var k = (e.key || '').toLowerCase();\n        var isUndo = k === 'z' && !e.shiftKey && !e.altKey;\n        var isRedo = k === 'z' && e.shiftKey && !e.altKey || k === 'y' && !e.shiftKey;\n        if (!isUndo && !isRedo) return;\n\n        // Skip text-edit contexts — let the browser / editor native\n        // undo/redo handle it first. Page-level undo only fires\n        // from the canvas / sidebar / topbar.\n        var tgt = e.target;\n        if (tgt && (tgt.tagName === 'INPUT' || tgt.tagName === 'TEXTAREA' || tgt.isContentEditable === true)) {\n          return;\n        }\n        e.preventDefault();\n        if (isUndo) _this5.undo();else _this5.redo();\n      };\n      document.addEventListener('keydown', this._historyKeyHandler, true);\n    }\n\n    /** Public undo shortcut. Returns a promise that resolves when apply completes. */\n  }, {\n    key: \"undo\",\n    value: function undo() {\n      return this.history.undo();\n    }\n    /** Public redo shortcut. Returns a promise that resolves when apply completes. */\n  }, {\n    key: \"redo\",\n    value: function redo() {\n      return this.history.redo();\n    }\n  }, {\n    key: \"canUndo\",\n    value: function canUndo() {\n      return this.history.canUndo();\n    }\n  }, {\n    key: \"canRedo\",\n    value: function canRedo() {\n      return this.history.canRedo();\n    }\n\n    /* ───────────────────────────────────────────────────────────── */\n\n    /**\n     * Load the builder with prepared data.\n     * This is the primary entry point — all consumers (builder.php, host\n     * server templates) pre-load theme templates and page data on the\n     * server, then call load() directly.\n     *\n     * @param {Object} themeJson - Page JSON data (the content to render).\n     * @param {Object} themeTemplatesJson - Pre-loaded template HTML: { \"Page\": \"<html>...\", \"Block\": \"<div>...\", ... }.\n     * @param {Object} themeConfigData - Parsed theme index.json (name, pages, templates metadata).\n     * @param {string} themeMediaUrl - Base URL for resolving relative asset/media paths to absolute URLs.\n     * @param {Function} [callback] - Optional callback after load completes.\n     */\n  }, {\n    key: \"load\",\n    value: (function () {\n      var _load = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(themeJson, themeTemplatesJson, themeConfigData, themeMediaUrl, callback) {\n        return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n          while (1) switch (_context2.prev = _context2.next) {\n            case 0:\n              this.data = themeJson;\n              this.themeMediaUrl = themeMediaUrl;\n              this.themeConfigs = themeConfigData;\n\n              // Store pre-loaded templates directly — zero HTTP fetches\n              this.templates = themeTemplatesJson;\n\n              // validate structure\n              this.validateStructure(this.data);\n\n              // widgets box — consumer adds widgets via builder.widgetsBox.addWidget() in callback.\n              // W6.A.A.1: when `widgetsContainer` is null (no sidebar), `widgetsBox`\n              // stays null too. Callers that opt out of the sidebar must not call\n              // `widgetsBox.addWidget(...)` — there is no widget palette to add to.\n              this.widgetsBox = this.widgetsContainer ? new WidgetsBox(this.widgetsContainer, this) : null;\n\n              // init iframe\n              _context2.next = 8;\n              return this.initIframe();\n            case 8:\n              _context2.next = 10;\n              return this.render();\n            case 10:\n              // Auto-resize iframe height to match content — must run AFTER render()\n              // because render() uses iframeDoc.write() which replaces the document.\n              // _setupIframeAutoResize → _injectIframeHelpers injects ALL builder-mode\n              // helper CSS (autosize overrides + debug-css for cursor / scrollbar /\n              // contenteditable focus-ring suppression / etc.) in one idempotent\n              // pass that re-runs on every PageElement.render() head replacement.\n              this._setupIframeAutoResize();\n\n              // apply mode: normal or for debugging\n              this.applyMode();\n\n              // PLAN_EFFECT W1.4 — restore persisted focus-dim state + wire\n              // keyboard shortcut. Runs AFTER _setupIframeAutoResize so the\n              // iframe head already has the `.bjs-focus-dim` CSS injected.\n              this._focusDimInit();\n\n              // PLAN_EFFECT W2.3 — wire the global Alt-key tracker for the\n              // Alt-hold inspect overlay. Always wired (no flag) — the inspect\n              // chrome ships default-on, and toggling state is hot path during\n              // hover. State lives on `this._inspectAltDown`; the listener\n              // re-applies the `.bjs-inspect-active` class to the active\n              // `.hovering-box` overlay (NOT body — see W2.3 design note in\n              // BUILDER.md HARD RULE C).\n              this._inspectModeInit();\n\n              // TEXT_INLINE_PLAN W0.3 — attach the canvas-wide selection\n              // tracker. Runs AFTER render() so `iframe.contentDocument` is the\n              // final one PageElement.render() wrote to (PageElement replaces\n              // <head>/<body>, not the document itself — listeners installed\n              // here survive every subsequent re-render).\n              this._textSelectionInit();\n\n              // TEXT_INLINE_PLAN W1.1 — mount the singleton inline toolbar.\n              // Subscribes to the tracker's bus events; DOM is created on\n              // first selection, destroyed on clear. Must run AFTER the\n              // tracker is attached so the bus exists.\n              this._textInlineToolbarInit();\n\n              // TEXT_INLINE_PLAN W6.3 — attach the inline-text keyboard\n              // shortcut dispatcher (⌘B/I/U/⇧X/K/⇧K/⌥C/⌥V/\\/⇧L/E/R/J). Capture-\n              // phase listener on the iframe document, scoped to\n              // `[data-bjs-inline-text]` focus. Must run AFTER toolbar init\n              // so ⌘K can route through `_textInlineToolbar._toggleLinkPopover`.\n              this._textInlineShortcutsInit();\n\n              // PLAN_UNDO_REDO W7.3 — bootstrap history AFTER render + UI\n              // managers are live. Pushes baseline snapshot, binds iframe /\n              // settings debounce fallback, mounts the floating widget, wires\n              // Ctrl/⌘Z shortcuts. Guarded by `options.historyEnabled`\n              // (default TRUE). See docs/plans/PLAN_UNDO_REDO.md.\n              this._historyInit();\n\n              // callback after initialization\n              if (callback) {\n                callback();\n              }\n            case 19:\n            case \"end\":\n              return _context2.stop();\n          }\n        }, _callee2, this);\n      }));\n      function load(_x, _x2, _x3, _x4, _x5) {\n        return _load.apply(this, arguments);\n      }\n      return load;\n    }())\n  }, {\n    key: \"getCurrentCapabilityName\",\n    value: function getCurrentCapabilityName() {\n      var _this$data;\n      switch ((_this$data = this.data) === null || _this$data === void 0 ? void 0 : _this$data.template) {\n        case 'Form':\n          return 'form';\n        default:\n          return 'page';\n      }\n    }\n  }, {\n    key: \"hasTemplate\",\n    value: function hasTemplate(templateName) {\n      return this.templates[templateName];\n    }\n  }, {\n    key: \"getTemplate\",\n    value: function getTemplate(templateName) {\n      if (!this.templates[templateName]) {\n        // Fire-and-forget themed alert. We still throw synchronously so\n        // the caller's error-handling path runs as before — the popup\n        // is just a nicer visual signal for the user.\n        _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].alert({\n          title: _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.template_not_found_title', 'Template not found'),\n          message: _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.template_not_found_msg', 'Template \"{name}\" could not be located in the current theme.').replace('{name}', templateName),\n          kind: 'error'\n        });\n        throw new Error(\"Template \\\"\".concat(templateName, \"\\\" not found\"));\n      }\n      return this.templates[templateName];\n    }\n  }, {\n    key: \"initIframe\",\n    value: function () {\n      var _initIframe = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {\n        return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n          while (1) switch (_context3.prev = _context3.next) {\n            case 0:\n              // Create an iframe and append it to the body\n              this.iframe = document.createElement('iframe');\n              this.iframe.style.width = '100%';\n              this.iframe.style.border = 'none';\n              this.iframe.style.backgroundColor = '#FFFFFF';\n              this.iframe.classList.add('shadow');\n              this.mainContainer.appendChild(this.iframe);\n\n              // Access the iframe document\n              this.iframeDoc = this.iframe.contentDocument || this.iframe.contentWindow.document;\n            case 7:\n            case \"end\":\n              return _context3.stop();\n          }\n        }, _callee3, this);\n      }));\n      function initIframe() {\n        return _initIframe.apply(this, arguments);\n      }\n      return initIframe;\n    }()\n    /**\n     * Auto-resize: keep iframe height === actual content height (no excess,\n     * no shortage). The builder canvas (iframe) never has its own scrollbar;\n     * scrolling is handled by the outer wrapper.\n     *\n     * FEEDBACK-LOOP TRAPS — both fixed by _injectIframeHelpers():\n     *  (a) Page.template.html sets `min-height: 100vh` on PageElement.\n     *      Inside an iframe, 100vh === iframe height. With auto-resize syncing\n     *      iframe height → page height, ANY page padding/margin grows the\n     *      iframe forever (page = max(content, 100vh) + padding → iframe →\n     *      100vh grows → page grows → loop).\n     *  (b) The empty-page placeholder in PageElement.render() previously used\n     *      inline `height: 100vh`. Same loop trigger when page padding > 0.\n     *\n     *  Both are fixed by injecting a builder-helper <style> that overrides\n     *  min-height on PageElement and pins the placeholder to a fixed\n     *  min-height. Crucially, this helper must be RE-INJECTED after every\n     *  PageElement.render() because that path replaces iframeDoc.head.innerHTML\n     *  wholesale (see PageElement.render() else branch).\n     */\n  }, {\n    key: \"_setupIframeAutoResize\",\n    value: function _setupIframeAutoResize() {\n      var iframe = this.iframe;\n\n      /**\n       * Measure actual content height by summing the natural heights of\n       * body's direct children using offsetTop + offsetHeight.\n       *\n       * Why not scrollHeight?\n       *   PageElement has min-height: 100vh in template CSS. Inside an\n       *   iframe, 100vh = iframe height. scrollHeight reflects that,\n       *   creating a feedback loop. (We override min-height via\n       *   _injectIframeHelpers, but scrollHeight can also pick up other\n       *   100vh children, so offsetTop+offsetHeight stays the safer path.)\n       *\n       * Why not getBoundingClientRect()?\n       *   rect.top is viewport-relative. If the page uses flex centering\n       *   (align-items: center), children shift vertically as iframe grows,\n       *   causing rect.top to grow → measured height grows → loop.\n       *\n       * offsetTop + offsetHeight are relative to the offsetParent (body),\n       * independent of iframe height and flex centering.\n       */\n      var getContentHeight = function getContentHeight() {\n        var doc = iframe.contentDocument;\n        if (!doc || !doc.body) return 0;\n        var maxBottom = 0;\n        var children = doc.body.children;\n        for (var i = 0; i < children.length; i++) {\n          var child = children[i];\n          // Skip script/style/hidden elements\n          if (child.tagName === 'SCRIPT' || child.tagName === 'STYLE') continue;\n          var bottom = child.offsetTop + child.offsetHeight;\n          if (bottom > maxBottom) maxBottom = bottom;\n        }\n\n        // Account for body margin\n        var bodyStyle = doc.defaultView.getComputedStyle(doc.body);\n        var marginTop = parseFloat(bodyStyle.marginTop) || 0;\n        var marginBottom = parseFloat(bodyStyle.marginBottom) || 0;\n        return Math.ceil(maxBottom + marginTop + marginBottom);\n      };\n      var lastHeight = 0;\n      var syncHeight = function syncHeight() {\n        var h = getContentHeight();\n        if (h > 0 && h !== lastHeight) {\n          lastHeight = h;\n          iframe.style.height = h + 'px';\n        }\n      };\n\n      // Re-injection hook: PageElement.render() calls _injectIframeHelpers()\n      // after every head replacement, so syncHeight always sees the\n      // overridden min-height and converges immediately.\n      this._injectIframeHelpers();\n\n      // Iframe height = exactly content height. No artificial minHeight —\n      // the empty-page placeholder (min-height: 480px, see PageElement.render)\n      // gives empty pages a reasonable visual footprint without coupling to\n      // viewport units.\n      iframe.style.minHeight = '0';\n\n      // Poll for height changes every 200ms.\n      // MutationObserver cannot observe across document boundaries,\n      // and injected scripts in iframes created via document.write()\n      // may not execute. Polling is lightweight (compares one integer)\n      // and works reliably across all browsers.\n      setInterval(syncHeight, 200);\n\n      // Sync on parent window resize (responsive mode switches)\n      window.addEventListener('resize', syncHeight);\n\n      // Initial sync\n      syncHeight();\n    }\n\n    /**\n     * Re-inject all iframe-only helper styles. Called once after the initial\n     * render (from _setupIframeAutoResize) and again from PageElement.render()\n     * after every head replacement.\n     *\n     * IDEMPOTENT: each style block is tagged with a unique data-helper-id so\n     * we can detect \"already injected\" and bail. Cheap to call repeatedly.\n     *\n     * MUST CARRY data-control=\"builder-helper\" so getHtml() strips them on\n     * export — they exist purely for the editor canvas, not the rendered email.\n     */\n  }, {\n    key: \"_injectIframeHelpers\",\n    value: function _injectIframeHelpers() {\n      var doc = this.iframeDoc;\n      if (!doc || !doc.head) return;\n\n      // Stable across head replacement (documentElement is not replaced\n      // when we do head.innerHTML = ...). Set defensively each call so\n      // any code that resets it gets corrected.\n      if (doc.documentElement) {\n        doc.documentElement.style.overflow = 'hidden';\n      }\n\n      // Auto-size override. Override `min-height: 100vh` from Page.template.html\n      // and pin the empty-page placeholder to a fixed min-height so neither\n      // can drive the iframe-height feedback loop when the user adds page\n      // padding or margins.\n      if (!doc.head.querySelector('style[data-helper-id=\"autosize-overrides\"]')) {\n        var style = doc.createElement('style');\n        style.setAttribute('data-control', 'builder-helper');\n        style.setAttribute('data-helper-id', 'autosize-overrides');\n        style.textContent = \"\\n                [builder-element=\\\"PageElement\\\"] { min-height: 0 !important; }\\n                [data-control=\\\"page-empty-placeholder\\\"] {\\n                    height: auto !important;\\n                    min-height: 480px !important;\\n                }\\n            \";\n        doc.head.appendChild(style);\n      }\n\n      // Debug / builder-mode CSS (cursor styling, scrollbar theming,\n      // design-mode layout colors, inline-edit focus-ring suppression,\n      // input pointer-events). Originally lived in a\n      // one-shot loadDebugCss() called at init. But PageElement.render()'s\n      // else branch does `head.innerHTML = doc.head.innerHTML` which WIPES\n      // every style tag — including this one. Result: after any re-render\n      // (add block, reorder, save), clicking into a [contenteditable]\n      // inline-edit `<p>` / `<h*>` / `<a>` surfaced the browser-default\n      // focus ring (blue in Chrome and Safari). The fix is to colocate\n      // this CSS with the other iframe helpers so it rides the idempotent\n      // re-injection path triggered by PageElement.render().\n      //\n      // Keep data-helper-id=\"debug-css\" stable — it's the dedupe key.\n      if (!doc.head.querySelector('style[data-helper-id=\"debug-css\"]')) {\n        var _style = doc.createElement('style');\n        _style.setAttribute('data-control', 'builder-helper');\n        _style.setAttribute('data-helper-id', 'debug-css');\n        _style.textContent = this._getDebugCss();\n        doc.head.appendChild(_style);\n      }\n\n      // Flip the contenteditable line-break separator from `<div>` (Chrome\n      // / Safari default) to `<br>`. Without this, every Enter inside a\n      // `<p inline-edit=\"text\">` inserts a `<div>` block child — which\n      // round-trips through the HTML5 fragment parser as a SIBLING of the\n      // `<p>` on the next `innerHTML =` assignment (parser auto-closes\n      // `<p>` when it sees a `<div>`). Result: paragraph-level inline\n      // styles (font-weight, text-align, font-family) disappear from the\n      // visible content. See InlineSanitizer.BLOCK_LEVEL_TAGS + the\n      // BaseElement._wireInlineEdit input listener for the DOM-level\n      // defence-in-depth that handles Safari (which ignores this flag).\n      //\n      // Idempotent — execCommand may overwrite on repeated calls, but\n      // calling repeatedly is safe + cheap. Wrapped in try/catch because\n      // older Safari throws InvalidStateError when invoked outside an\n      // active editing context; the DOM-level normalize catches the\n      // fallout there.\n      try {\n        doc.execCommand('defaultParagraphSeparator', false, 'br');\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].warn('builder:defaultParagraphSeparator', err);\n      }\n    }\n  }, {\n    key: \"render\",\n    value: function () {\n      var _render = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {\n        return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n          while (1) switch (_context4.prev = _context4.next) {\n            case 0:\n              // parse page data\n              this.pageElement.parse(this.data);\n\n              // Host injection — walk the freshly-parsed tree and assign\n              // `host = this` on every element + overlay BEFORE render runs,\n              // so Element/Overlay code can reach `this.host.{events,options,…}`\n              // from the very first render() / afterMount() pass.\n              this._adopt(this.pageElement);\n\n              // Load and inject the PageElement theme\n              this.pageElement.render();\n            case 3:\n            case \"end\":\n              return _context4.stop();\n          }\n        }, _callee4, this);\n      }));\n      function render() {\n        return _render.apply(this, arguments);\n      }\n      return render;\n    }()\n  }, {\n    key: \"loadCSS\",\n    value: function () {\n      var _loadCSS = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(cssPath) {\n        var response;\n        return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n          while (1) switch (_context5.prev = _context5.next) {\n            case 0:\n              _context5.next = 2;\n              return fetch(cssPath);\n            case 2:\n              response = _context5.sent;\n              if (response.ok) {\n                _context5.next = 5;\n                break;\n              }\n              throw new Error(\"Failed to load CSS from \".concat(cssPath));\n            case 5:\n              _context5.next = 7;\n              return response.text();\n            case 7:\n              return _context5.abrupt(\"return\", _context5.sent);\n            case 8:\n            case \"end\":\n              return _context5.stop();\n          }\n        }, _callee5);\n      }));\n      function loadCSS(_x6) {\n        return _loadCSS.apply(this, arguments);\n      }\n      return loadCSS;\n    }()\n  }, {\n    key: \"insertElements\",\n    value: function insertElements(elements) {\n      this.pageElement.appendElements(elements);\n      this.pageElement.render();\n    }\n  }, {\n    key: \"clear\",\n    value: function clear() {\n      var _this6 = this;\n      // PLAN_UNDO_REDO — programmatic page wipe. F1 + F3 fix:\n      //   - removeAllBlocks no longer leaks N per-block `structure_remove`\n      //     commits (clean teardown bypasses BaseElement.remove).\n      //   - We still wrap in `silent()` as a defense-in-depth so any\n      //     future commit added to the teardown path is suppressed; then\n      //     emit ONE `history.clear` summary so the user can undo the\n      //     clear in one step (without it, clear was effectively\n      //     irreversible after F1 silenced the leak).\n      if (this.history) {\n        this.history.silent(function () {\n          return _this6.pageElement.clear();\n        });\n        this.history.commit('history.page_clear', {\n          source: 'builder.clear',\n          change: 'page:clear'\n        });\n      } else {\n        this.pageElement.clear();\n      }\n    }\n  }, {\n    key: \"validateStructure\",\n    value: function validateStructure(data) {\n      try {\n        this.structureValidator.validate(data);\n      } catch (error) {\n        console.warn('Builder JSON validation:', error.message);\n      }\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, {\n        theme: this.themeConfigs.name\n      }), this.pageElement.getData());\n    }\n\n    /**\n     * Sanitise + strip editor-only artefacts from a CLONED export root.\n     *\n     * Single source of truth for the `getHtml()` / `getRenderedBlocks()`\n     * pipelines (HARD RULE T12 — export-output consistency). Pre-2026-05-20\n     * each method open-coded its own cleanup, which drifted: `getRenderedBlocks`\n     * was missing the `inline-edit` host normalize pass + mutated live\n     * DOM directly. Centralising here guarantees:\n     *\n     *   1. Every export path strips the same set of editor-only attrs +\n     *      builder-helper nodes — no surprises when a new export consumer\n     *      ships (AIBuilder Wave N, \"Save\", \"Preview\", \"Export HTML\",\n     *      etc.).\n     *   2. HARD RULE T11 holds for every export — every `[inline-edit]`\n     *      host is run through `InlineSanitizer.normalize` so block-level\n     *      descendants (Chrome's contenteditable Enter-inserted `<div>`s)\n     *      get unwrapped to inline `<br>` BEFORE serialization. Without\n     *      this, saved HTML round-trips through the HTML5 fragment parser\n     *      as `<p>…<div>…</div></p>` → auto-close → orphan siblings →\n     *      lost inline style on the host. See BUILDER.md Lesson 88.\n     *\n     * ⚠ NEVER pass a live iframe node here — this method mutates `root`\n     * in place. Callers MUST clone first. (Past incident: stripping\n     * [data-control=\"builder-helper\"] in place wiped the autosize-overrides\n     * `<style>` from the live iframe head; with that gone, Page.template.html's\n     * `min-height: 100vh` snapped back and the auto-resize poll grew the\n     * iframe forever after every Save click. Clone-then-clean is the\n     * only safe pattern.)\n     *\n     * @param {HTMLElement} root  CLONED root (document element, body, or\n     *                            any container whose subtree should be\n     *                            sanitised for export).\n     */\n  }, {\n    key: \"_sanitiseForExport\",\n    value: function _sanitiseForExport(root) {\n      if (!root) return;\n      // Order is intentional:\n      //   1. Inline-edit normalize MUST run BEFORE stripping\n      //      `inline-edit` attr — that's how we identify hosts.\n      //   2. Builder-helper removal runs ANY time before serialization;\n      //      placed after normalize so we don't accidentally drop\n      //      content the normalize pass touches (it doesn't, but the\n      //      order makes the contract obvious).\n      //   3. Editor-only attr strip runs LAST so the inline-edit\n      //      attribute survives long enough for step 1 to find hosts.\n      root.querySelectorAll('[inline-edit]').forEach(function (host) {\n        try {\n          _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"].normalize(host);\n        } catch (err) {\n          _BJS_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].error('builder:sanitiseForExport-normalize', err);\n        }\n      });\n      root.querySelectorAll('[data-control=\"builder-helper\"]').forEach(function (el) {\n        return el.remove();\n      });\n\n      // NOTE: `builder-element` is intentionally kept — Page.template.html\n      // uses `[builder-element=\"PageElement\"]` / `[builder-element=\"BlockElement\"]`\n      // selectors in the generated `<style>` block for container-width\n      // constraints, block gap, block padding, and default background\n      // color. Removing it breaks all layout rules in the served HTML.\n      root.querySelectorAll('[contenteditable]').forEach(function (el) {\n        return el.removeAttribute('contenteditable');\n      });\n      root.querySelectorAll('[inline-edit]').forEach(function (el) {\n        return el.removeAttribute('inline-edit');\n      });\n      // W0.2b runtime marker stamped on every inline-edit host so\n      // selection-aware overlays can scope their listeners. Saved HTML\n      // has no use for it.\n      root.querySelectorAll('[data-bjs-inline-text]').forEach(function (el) {\n        return el.removeAttribute('data-bjs-inline-text');\n      });\n    }\n  }, {\n    key: \"getHtml\",\n    value: function getHtml() {\n      // Clone the entire document — see `_sanitiseForExport` doc for the\n      // \"never mutate live iframe DOM\" invariant + the autosize-overrides\n      // past incident that motivated it.\n      var htmlDoc = this.iframe.contentDocument.documentElement.cloneNode(true);\n      this._sanitiseForExport(htmlDoc);\n\n      // Strip editor-only inline `overflow: hidden` that _injectIframeHelpers()\n      // pins onto <html> to stop the editor iframe from double-scrolling. It's\n      // on documentElement itself (not a child), so the querySelectorAll\n      // filters inside `_sanitiseForExport` can't catch it. Leaving it would\n      // bake `<html style=\"overflow: hidden;\">` into exported HTML → breaks\n      // scroll on campaign web-view / email preview.\n      htmlDoc.style.removeProperty('overflow');\n      if (!htmlDoc.getAttribute('style') || !htmlDoc.getAttribute('style').trim()) {\n        htmlDoc.removeAttribute('style');\n      }\n      return htmlDoc.outerHTML;\n    }\n\n    /**\n     * Get rendered HTML with all asset URLs converted back to relative paths.\n     *\n     * During editing, transferMediaAbsUrl() converts relative paths to absolute:\n     *   \"assets/profile_image/avatar.png\" → \"https://app.example.com/p/templates/000abc/assets/profile_image/avatar.png\"\n     *\n     * This method reverses that — strips the themeMediaUrl prefix so saved HTML\n     * stays portable and works regardless of domain or template URL changes:\n     *   \"https://app.example.com/p/templates/000abc/assets/profile_image/avatar.png\" → \"assets/profile_image/avatar.png\"\n     *\n     * @returns {string} HTML with relative asset paths (ready for database storage).\n     */\n  }, {\n    key: \"getHtmlWithRelativeLinks\",\n    value: function getHtmlWithRelativeLinks() {\n      var html = this.getHtml();\n      html = html.replace(new RegExp(this.themeMediaUrl + '/', 'g'), '');\n      return html;\n    }\n  }, {\n    key: \"getSelectedElement\",\n    value: function getSelectedElement() {\n      return this.selectedElement;\n    }\n  }, {\n    key: \"setSelectedElement\",\n    value: function setSelectedElement(element) {\n      this.selectedElement = element;\n    }\n  }, {\n    key: \"selectElement\",\n    value: function selectElement(element) {\n      // unselect\n      this.unselect();\n\n      // set element\n      this.setSelectedElement(element);\n\n      // render settings box\n      this.renderElementControls(element);\n\n      // PLAN_EFFECT W2.1 — tear down any hover overlay lingering on\n      // the element we just selected. Without this, the mouseout\n      // debounce (50 ms) leaves a hover outline on top of the new\n      // selection outline for one frame → visible \"double outline\n      // messup\" (user feedback 2026-04-19). Idempotent if no hover\n      // was live.\n      element.removeHoverHightlight();\n\n      // PLAN_EFFECT W2.1b — also tear down the container padding-\n      // region highlight on the parent. Without this, the green-\n      // striped padding pattern on the parent container lingers\n      // until the user moves the mouse, even though the child is\n      // now selected (user feedback 2026-04-19 \"container highlight\n      // hover gì đó remove ngay khi remove cái highlight luôn nha\").\n      if (element.container && typeof element.container.removeContainerHightlight === 'function') {\n        element.container.removeContainerHightlight();\n      }\n\n      // PLAN_EFFECT W1.4 — mark the element's iframe DOM node with\n      // `data-bjs-selected=\"true\"` (kept for legacy tests / ARIA)\n      // and, if focus-dim is currently ON, mount the spotlight\n      // overlay over this element's rect. The spotlight's box-\n      // shadow dims everything in the iframe OUTSIDE the rect so\n      // the selected element + its parent section both read as\n      // bright against a dimmed surround.\n      if (element.domNode) {\n        element.domNode.setAttribute('data-bjs-selected', 'true');\n      }\n      this._applyFocusDim();\n\n      // Add selected class\n      element.addSelectedHighlight();\n\n      // Canvas overlays — mount any overlay declared with trigger 'select'.\n      // Default getOverlays() returns [] so zero work for opt-out elements.\n      // See docs/core/OVERLAY.md §3 + docs/archived/OVERLAY_PLAN.md §3.2.\n      element.mountOverlays('select');\n\n      // @todo depenency: open settings tab.\n      // W6.A.A.1: cookbook presets that omit the settings sidebar also omit\n      // `window.sidebarTabManager` — guard the openTab call so selection\n      // still works (overlays + highlight) without a sidebar to switch.\n      if (window.sidebarTabManager) {\n        window.sidebarTabManager.openTab(document.querySelector('[data-tab=\"controls\"]'));\n      }\n      if (window.smenu) {\n        window.smenu.openTab(document.querySelector('[data-smenu=\"design\"]'));\n      }\n    }\n  }, {\n    key: \"unselect\",\n    value: function unselect() {\n      if (!this.getSelectedElement()) {\n        return; // no selected > do nothing\n      }\n\n      // Tear down any 'select'-trigger overlays before removing the highlight.\n      // Ordering: unmount overlays FIRST, then existing highlight removal\n      // — matchingDomNode observers may fire between the two, and\n      // overlay DOM should be gone by the time the hover state shifts.\n      this.getSelectedElement().unmountOverlays('select');\n\n      // Phase 1.8 (SA I14) — dispose currently-active sidebar controls\n      // when nothing is selected. Without this, the last-selected element's\n      // controls would keep their sync subscriptions alive until another\n      // element is selected. unselect() is a natural teardown point.\n      var prevControls = this._activeControlList || [];\n      var _iterator5 = _createForOfIteratorHelper(prevControls),\n        _step5;\n      try {\n        for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {\n          var ctrl = _step5.value;\n          if (ctrl && typeof ctrl.destroy === 'function') {\n            try {\n              ctrl.destroy();\n            } catch (_) {/* no-op */}\n          }\n        }\n      } catch (err) {\n        _iterator5.e(err);\n      } finally {\n        _iterator5.f();\n      }\n      this._activeControlList = [];\n\n      // remove selected effect\n      this.getSelectedElement().removeSelectedHighlight();\n\n      // PLAN_EFFECT W1.4 — clear selection marker + tear down any\n      // spotlight overlay mounted for this element.\n      var prev = this.getSelectedElement();\n      if (prev && prev.domNode) {\n        prev.domNode.removeAttribute('data-bjs-selected');\n      }\n      this._unmountFocusSpotlight();\n\n      // ──────────────────────────────────────────────────────────────────\n      // CRITICAL — clear `selectedElement` AFTER all per-element teardown.\n      // Without this, the field stays pointing at the just-unselected\n      // element, and downstream code that conditionalises on\n      // `getSelectedElement()` reads stale state.\n      //\n      // Concrete regression (2026-05-05, \"hover lost on re-hover after\n      // toolbar Unselect\"): UIManager.mouseover applies the W2.1b\n      // \"skip container highlight when hovered === selected\" rule\n      // (UIManager.js around line 283). With selectedElement still set\n      // to the just-unselected element X, the rule misfires for X\n      // exclusively — re-hovering X removes the container highlight\n      // instead of adding it. Y (any other element) is unaffected\n      // because Y !== stale X. Selecting another element Z masks the\n      // bug because selectElement→setSelectedElement(Z) overwrites the\n      // stale field.\n      //\n      // Order matters: this null-set MUST come AFTER the per-element\n      // teardown calls above (they read getSelectedElement() to know\n      // what to teardown) but BEFORE any UI state that observes\n      // \"no selection\" (sidebar tab open, future bus events, etc).\n      // ──────────────────────────────────────────────────────────────────\n      this.setSelectedElement(null);\n\n      // @todo depenency: open widgets tab.\n      // W6.A.A.1: same null-tolerance guard as selectElement.\n      if (window.sidebarTabManager) {\n        window.sidebarTabManager.openTab(document.querySelector('[data-tab=\"widgets\"]'));\n      }\n      if (window.smenu) {\n        window.smenu.openTab(document.querySelector('[data-smenu=\"design\"]'));\n      }\n    }\n  }, {\n    key: \"getMode\",\n    value: function getMode() {\n      return this.mode;\n    }\n  }, {\n    key: \"setMode\",\n    value: function setMode(mode) {\n      // W6.A.A.4: emit `mode:changed` so cookbook chrome presets can\n      // reactively update header pills / status indicators without\n      // polling the mode field. Idempotent calls (`setMode(currentMode)`)\n      // STILL fire — subscribers must handle that themselves; we keep\n      // the emit unconditional for symmetry with the existing pattern\n      // (any state-mutation call triggers its event regardless of whether\n      // the value really changed).\n      var from = this.mode;\n      this.mode = mode;\n      this.applyMode();\n      this.events.emit(Builder.EVENTS.MODE_CHANGED, {\n        from: from,\n        to: mode\n      });\n    }\n  }, {\n    key: \"applyMode\",\n    value: function applyMode() {\n      if (this.getMode() === 'design') {\n        this.iframe.contentDocument.body.classList.add('builder-mode-design');\n      } else {\n        this.iframe.contentDocument.body.classList.remove('builder-mode-design');\n      }\n    }\n  }, {\n    key: \"removeElement\",\n    value: function removeElement(element) {\n      // unselect if the element is selected\n      if (this.getSelectedElement() == element) {\n        this.unselect();\n      }\n\n      // Capture identity BEFORE the remove tears down the element graph —\n      // post-remove the node may already be detached and helpers stop\n      // resolving cleanly.\n      var elementUid = element ? element.id : null;\n      var elementType = element && typeof element.getName === 'function' ? element.getName() : undefined;\n\n      // do remove\n      this.pageElement.removeElement(element);\n\n      // CD-3 — element:removed fires raw (no debounce) so host listeners\n      // (Wave 4 SavedTicker, future Wave 14 Layers tree) can react in the\n      // same frame. The structure:remove history commit independently fires\n      // history:commit + document:changed (debounced) via HistoryManager.\n      if (elementUid != null) {\n        this.events.emit(Builder.EVENTS.ELEMENT_REMOVED, {\n          elementUid: elementUid,\n          elementType: elementType\n        });\n      }\n    }\n  }, {\n    key: \"renderElementControls\",\n    value: function renderElementControls(element) {\n      var _this7 = this;\n      // W6.A.A.1: cookbook presets without a settings sidebar pass\n      // `settingsContainer: null` — element selection still mounts overlays\n      // + applies the highlight, but there is no panel to render controls\n      // into. Bail before any DOM work; sync subscriptions stay disposed\n      // by the unselect path so nothing leaks across selections.\n      if (!this.settingsContainer) {\n        this._activeControlList = [];\n        return;\n      }\n      var container = this.settingsContainer;\n\n      // Phase 1.8 (SA invariant I14) — dispose outgoing controls BEFORE we\n      // replace the DOM. Any Control that subscribed to element state\n      // (via element.addSyncListener) or held DOM listeners / observers\n      // stashed disposers on itself via BaseControl.addDisposer. Calling\n      // destroy() here is the single teardown point — without it,\n      // subscriptions would outlive the Control instance and leak across\n      // sidebar rebuilds. Guarded so plain controls without destroy pass\n      // through untouched (back-compat).\n      var prevControls = this._activeControlList || [];\n      var _iterator6 = _createForOfIteratorHelper(prevControls),\n        _step6;\n      try {\n        for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {\n          var ctrl = _step6.value;\n          if (ctrl && typeof ctrl.destroy === 'function') {\n            try {\n              ctrl.destroy();\n            } catch (err) {\n              // eslint-disable-next-line no-console\n              console.error('[bjs:builder] control destroy threw:', err);\n            }\n          }\n        }\n      } catch (err) {\n        _iterator6.e(err);\n      } finally {\n        _iterator6.f();\n      }\n      this._activeControlList = [];\n\n      // Settings panel shell — breadcrumb, element header (name + action\n      // icons), then the control list. 2026-04-17 refinement:\n      //  - `.bjs-settings-header` is the canonical panel-header primitive:\n      //    bold element name left + icon-button toolbar right +\n      //    1 px border-bottom, 16 px inset (matches the section\n      //    header treatment).\n      //  - Action icons are `.bjs-icon-btn` (32 px square) grouped in a\n      //    subtle `.bjs-settings-actions` pill. No more Bootstrap\n      //    `.btn-light .p-1 .d-flex`.\n      //  - Dropped the dedicated \"CONFIGURATIONS\" section header —\n      //    user flagged it as redundant noise 2026-04-17. The element\n      //    header above is the only divider needed before the control list.\n      container.innerHTML = \"\\n            <div class=\\\"settings-container styles-box shadow-sm rounded-0 bg-white\\\">\\n                <div class=\\\"settings-breadcrumb\\\" style=\\\"width:100%;overflow-x:auto;\\\">\\n                    <span data-control=\\\"breadcrumb\\\" class=\\\"d-flex align-items-center\\\"></span>\\n                </div>\\n                <div class=\\\"bjs-settings-header\\\">\\n                    <h4 class=\\\"bjs-settings-header-title\\\">\".concat(element.getName(), \"</h4>\\n                    <div data-control=\\\"actions\\\" class=\\\"bjs-settings-actions\\\"></div>\\n                </div>\\n                <div data-control=\\\"settings-controls-container\\\"></div>\\n            </div>\\n        \");\n      var currentElement = element.container;\n      var breadcrumbContent = container.querySelector('[data-control=\"breadcrumb\"]');\n      var _loop = function _loop() {\n          breadcrumbItem = document.createElement('a');\n          breadcrumbItem.setAttribute('class', 'd-flex align-items-center py-2 px-2 settings-breadcrumb-item text-nowrap');\n          breadcrumbItem.setAttribute('href', 'javascript:;');\n          breadcrumbItem.innerHTML = currentElement.getName() + '<span class=\"material-symbols-rounded settings-breadcrumb-arrow\" style=\"margin-right:-17px\">arrow_right</span>';\n          if (currentElement.getClassName() === 'PageElement') {\n            breadcrumbItem.innerHTML = \"<span class=\\\"material-symbols-rounded\\\">home</span>\";\n          }\n\n          // prepend breadcrumbItem to breadcrumbContent\n          breadcrumbContent.prepend(breadcrumbItem);\n\n          // click event\n          var i = currentElement; // capture the current value of currentElement\n\n          breadcrumbItem.addEventListener('click', function () {\n            _this7.selectElement(i);\n          });\n          currentElement = currentElement.container;\n        },\n        breadcrumbItem;\n      while (currentElement) {\n        _loop();\n      }\n\n      //\n      var controls = element.getControls();\n      // Host injection — controls are emitted lazily on selection (NOT\n      // adopted by `_adopt()` which only walks elements + overlays).\n      // Assign `host = this` here so each control can reach the bus,\n      // pin-set, recent-color LRU, active-control slot, etc., without\n      // any global reach-in.\n      var _iterator7 = _createForOfIteratorHelper(controls),\n        _step7;\n      try {\n        for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {\n          var c = _step7.value;\n          if (c) c.host = this;\n        }\n        // Track the new control list so the NEXT renderElementControls call\n        // can tear them down via destroy() — Phase 1.8 SA I14.\n      } catch (err) {\n        _iterator7.e(err);\n      } finally {\n        _iterator7.f();\n      }\n      this._activeControlList = controls.slice();\n      // (No \"CONFIGURATIONS\" divider — removed 2026-04-17; the element\n      // header above is the only panel-level heading needed.)\n\n      // render element controls\n      var controlsContainer = container.querySelector('[data-control=\"settings-controls-container\"]');\n      controls.forEach(function (control) {\n        var controlObj = control.domNode;\n        controlsContainer.appendChild(controlObj);\n\n        //\n        if (control.afterRender) {\n          control.afterRender();\n        }\n      });\n\n      // 2026-04-18 panel parent-merge: for content elements (anything whose\n      // container is a CellElement or GridElement), append the parent-chain\n      // sections at the bottom of the panel as collapsed `<details>`. Each\n      // section renders the parent's full control list so the author can\n      // edit cell / grid settings without leaving the current selection.\n      //\n      // Rules:\n      //  - Only content-inside-container situations. If the selected element\n      //    IS a Cell or Grid, don't merge (it's already at the target\n      //    scope).\n      //  - Walk at most 2 levels up (typical: Block → Cell → Grid). Stop\n      //    before hitting PageElement.\n      //  - Collapsed by default — keeps the panel compact; authors expand\n      //    when they need the section.\n      //  - Section labels carry a \"(parent)\" qualifier so control labels\n      //    reading like \"Padding\" or \"Background\" aren't confused with\n      //    this-element-level controls of the same name.\n      this._renderParentSections(element, controlsContainer);\n\n      // Render head actions — select-parent / copy / delete / unselect.\n      // Uses `.bjs-icon-btn` (32 px square) so the toolbar feels clicky\n      // instead of the prior cramped `.btn-light .p-1`.\n      element.getActions().forEach(function (action) {\n        var actionButton = document.createElement('button');\n        actionButton.className = 'element-action-item bjs-icon-btn';\n        actionButton.type = 'button';\n        actionButton.setAttribute('data-tooltip', action.label);\n        actionButton.setAttribute('aria-label', action.label);\n        actionButton.innerHTML = \"<span class=\\\"material-symbols-rounded\\\">\".concat(action.icon, \"</span>\");\n        container.querySelector('[data-control=\"actions\"]').appendChild(actionButton);\n        actionButton.addEventListener('click', function () {\n          return action.run();\n        });\n      });\n    }\n  }, {\n    key: \"_renderParentSections\",\n    value: function _renderParentSections(element, controlsContainer) {\n      var _this8 = this;\n      if (!element || !element.container) return;\n      var selfClass = element.getClassName && element.getClassName();\n      if (selfClass === 'CellElement' || selfClass === 'GridElement' || selfClass === 'PageElement') return;\n      var parents = [];\n      var cur = element.container;\n      var depth = 0;\n      while (cur && cur.getClassName && cur.getClassName() !== 'PageElement' && depth < 2) {\n        parents.push(cur);\n        cur = cur.container;\n        depth++;\n      }\n      if (!parents.length) return;\n      parents.forEach(function (parent, idx) {\n        var klass = parent.getClassName();\n        var label = parent.getName ? parent.getName() : klass;\n        // Nested: outer wraps inner so CELL sits above GRID when the chain\n        // is `Block inside Cell inside Grid`. We also render them in the\n        // order they appear in the container chain (direct parent first).\n        var details = document.createElement('details');\n        details.className = 'bjs-panel-parent-section';\n        details.setAttribute('data-parent-class', klass);\n        details.open = false;\n        var summary = document.createElement('summary');\n        summary.className = 'bjs-panel-parent-summary';\n        summary.innerHTML = \"\\n                <span class=\\\"material-symbols-rounded bjs-panel-parent-icon\\\" aria-hidden=\\\"true\\\">\".concat(klass === 'CellElement' ? 'view_column' : klass === 'GridElement' ? 'grid_view' : 'dashboard', \"</span>\\n                <span class=\\\"bjs-panel-parent-label\\\">\").concat(label.toUpperCase(), \" <small class=\\\"bjs-panel-parent-qualifier\\\">(\").concat(idx === 0 ? 'parent' : 'grandparent', \")</small></span>\\n                <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-panel-parent-select\\\" data-parent-select data-tooltip=\\\"Select this \").concat(label, \"\\\" aria-label=\\\"Select this \").concat(label, \"\\\">\\n                    <span class=\\\"material-symbols-rounded\\\">arrow_forward</span>\\n                </button>\\n                <span class=\\\"material-symbols-rounded bjs-panel-parent-chevron\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n            \");\n        details.appendChild(summary);\n        var body = document.createElement('div');\n        body.className = 'bjs-panel-parent-body';\n        details.appendChild(body);\n\n        // Render the parent's own controls into the section body. We\n        // intentionally re-invoke getControls() so the parent constructs\n        // fresh control instances with its own state + callbacks —\n        // editing here mutates the parent and re-renders canvas.\n        try {\n          var parentControls = parent.getControls();\n          // Host injection — same as the primary getControls() path.\n          var _iterator8 = _createForOfIteratorHelper(parentControls),\n            _step8;\n          try {\n            for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {\n              var c = _step8.value;\n              if (c) c.host = _this8;\n            }\n          } catch (err) {\n            _iterator8.e(err);\n          } finally {\n            _iterator8.f();\n          }\n          parentControls.forEach(function (c) {\n            if (c && c.domNode) body.appendChild(c.domNode);\n            if (c && c.afterRender) c.afterRender();\n          });\n        } catch (err) {\n          console.warn(\"[parent-merge] failed to render \".concat(klass, \" controls:\"), err);\n          body.innerHTML = \"<div class=\\\"bjs-panel-parent-error\\\">Could not render \".concat(label, \" settings: \").concat(err.message, \"</div>\");\n        }\n\n        // Wire the \"select this parent\" jump button.\n        var selectBtn = summary.querySelector('[data-parent-select]');\n        if (selectBtn) {\n          selectBtn.addEventListener('click', function (ev) {\n            ev.preventDefault();\n            ev.stopPropagation();\n            _this8.selectElement(parent);\n          });\n        }\n        controlsContainer.appendChild(details);\n      });\n    }\n\n    /**\n     * Builder-mode helper CSS. Returned as a raw string so `_injectIframeHelpers`\n     * can wrap it in a single <style data-helper-id=\"debug-css\"> node that\n     * survives PageElement.render() head replacement. See `_injectIframeHelpers`\n     * for the re-injection contract — this method has no side effects.\n     */\n  }, {\n    key: \"_getDebugCss\",\n    value: function _getDebugCss() {\n      return \"\\n            /* Holed-box primitive \\u2014 minimal iframe-local copy of just\\n               the classes the focus-dim spotlight needs. Main builder.css\\n               lives in the parent document; iframe needs its own copy\\n               because the spotlight mounts into iframe body. --blur is\\n               NOT mirrored here: focus-dim went blur-less to sidestep\\n               the Chrome/Safari backdrop-filter \\xD7 clip-path compositing\\n               quirk (filtered snapshot leaks into the hole area \\u2014 user\\n               report \\\"dim blur lu\\xF4n c\\u1EA3 element \\u0111ang ch\\u1ECDn\\\"). Dim is\\n               black-alpha which reads as neutral gray on any canvas. */\\n            .bjs-holed-box {\\n                position: absolute;\\n                inset: 0;\\n                pointer-events: none;\\n            }\\n            .bjs-holed-box--dim {\\n                background-color: rgba(0, 0, 0, 0.42);\\n            }\\n\\n            /* Focus-dim spot transition \\u2014 single holed-box element, so\\n               only one selector to target. */\\n            .bjs-focus-dim-spot {\\n                transition: opacity 0.18s ease;\\n            }\\n            @media (prefers-reduced-motion: reduce) {\\n                .bjs-focus-dim-spot { transition: none; }\\n            }\\n\\n            [builder-element] {\\n                cursor: pointer;\\n                position: relative;\\n            }\\n\\n            [builder-element]::before {\\n                font-size: 10px!important;\\n            }\\n                \\n            .builder-mode-design [builder-element=\\\"PageElement\\\"] {\\n                display: flex;\\n                flex-direction: column;\\n                gap: 10px;\\n                padding: 30px;\\n                background-color: #f0f0f0;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element]::before {\\n                font-family: monospace;\\n                font-size: 90%;\\n                position: absolute;\\n                top: 0;\\n                right: 0;\\n                font-weight: bold;\\n                color: #333;\\n                border: solid 1px #ddd;\\n                padding: 2px 5px;\\n                border-top: none;\\n                border-right: none;\\n\\n                pointer-events: none;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"PageElement\\\"]::before {\\n                content: \\\"PageElement\\\";\\n                pointer-events: none;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"BlockElement\\\"] {\\n                display: flex;\\n                flex-direction: column;\\n                gap: 10px;\\n                padding: 15px;\\n                background-color: #e0e0e0;\\n                border: 1px solid #ccc;\\n                margin-bottom: 10px;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"BlockElement\\\"]::before {\\n                content: \\\"BlockElement\\\";\\n                border-color: #ccc;\\n\\n                pointer-events: none;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"H1Element\\\"] {\\n                padding: 10px;\\n                background-color: #cfdce4;\\n                border: 1px solid #bbb;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"H1Element\\\"]::before {\\n                content: \\\"H1Element\\\";\\n                border-color: #bbb;\\n                font-size: initial;\\n\\n                pointer-events: none;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"PElement\\\"] {\\n                padding: 10px;\\n                background-color: #cfdce4;\\n                border: 1px solid #bbb;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"PElement\\\"]::before {\\n                content: \\\"PElement\\\";\\n                border-color: #bbb;\\n\\n                pointer-events: none;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"MenuElement\\\"] {\\n                padding: 10px;\\n                background-color: #cfdce4;\\n                border: 1px solid #bbb;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"MenuElement\\\"]::before {\\n                content: \\\"MenuElement\\\";\\n                border-color: #bbb;\\n\\n                pointer-events: none;\\n            }\\n            .builder-mode-design [builder-element=\\\"GridElement\\\"] {\\n                gap: 10px;\\n                padding: 10px;\\n                background-color: #ccc;\\n                border: 1px solid #aaa;\\n                margin: 10px 0;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"GridElement\\\"]::before {\\n                content: \\\"GridElement\\\";\\n                border-color: #bbb;\\n\\n                pointer-events: none;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"CellElement\\\"] {\\n                padding: 10px;\\n                background-color: #e0e0e0;\\n                border: 1px solid #aaa;\\n                margin: 10px 0;\\n                position: relative;\\n            }\\n\\n            .builder-mode-design [builder-element=\\\"CellElement\\\"]::before {\\n                content: \\\"CellElement\\\";\\n                border-color: #ccc;\\n\\n                pointer-events: none;\\n            }\\n\\n            [builder-element=\\\"BlockElement\\\"] {\\n                position: relative;\\n            }\\n\\n            /* inside iframe's document */\\n            ::-webkit-scrollbar {\\n                width: 7px;\\n                height: 7px;\\n            }\\n\\n            ::-webkit-scrollbar-thumb {\\n                background: rgba(0, 0, 0, 0.3);\\n                border-radius: 4px;\\n            }\\n\\n            ::-webkit-scrollbar-track {\\n                background: transparent;\\n            }\\n\\n            [contenteditable] {\\n                outline: none!important;\\n                -webkit-focus-ring-color: transparent;\\n            }\\n\\n            [contenteditable]:focus, [contenteditable]:focus-visible {\\n                outline: none!important;\\n                border-color: transparent!important;\\n                box-shadow: none!important;\\n                -webkit-focus-ring-color: transparent;\\n            }\\n\\n            /* Kill default browser focus outline on every focusable element in design iframe */\\n            *:focus, *:focus-visible, *:focus-within {\\n                outline: none!important;\\n                -webkit-focus-ring-color: transparent;\\n            }\\n\\n            input, select, textarea, button {\\n                pointer-events: none;\\n            }\\n            input:focus, select:focus, textarea:focus, button:focus,\\n            input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible {\\n                outline: none!important;\\n                box-shadow: none!important;\\n                border-color: inherit!important;\\n            }\\n\\n            /* PLAN_UNDO_REDO W7.3 \\u2014 history apply suppression.\\n             * HistoryManager._apply toggles .bjs-history-applying on\\n             * <body> around the render pass. Disables ALL transitions\\n             * and animations iframe-wide so undo/redo snaps instantly\\n             * to the target state \\u2014 no block fade-in cascade, no shake,\\n             * no jank. Standard batch-update pattern. 2x rAF in\\n             * HistoryManager._apply keeps the class on through layout\\n             * plus paint \\u2014 post-apply interactions resume with full\\n             * motion. */\\n            body.bjs-history-applying,\\n            body.bjs-history-applying *,\\n            body.bjs-history-applying *::before,\\n            body.bjs-history-applying *::after {\\n                transition: none !important;\\n                animation: none !important;\\n                animation-duration: 0s !important;\\n                animation-delay: 0s !important;\\n            }\\n        \";\n    }\n  }, {\n    key: \"validateKeysUsage\",\n    value: function validateKeysUsage(html, keys, failedCallback) {\n      // Scan every identifier inside each <% ... %> block, not just the first\n      // token after <%. Templates may legitimately access a required key from\n      // inside a nested expression — e.g. `<% if (blocks && blocks.length) {\n      // blocks.forEach(...) %>` — where the leading token is `if`, not the key\n      // itself. Grabbing only the first word produced false-positive\n      // \"DESIGN ERROR: Template does not use required key: blocks\" warnings.\n      var blockRegex = /<%[=\\-]?([\\s\\S]*?)%>/g;\n      var idRegex = /[A-Za-z_][\\w]*/g;\n      var usedKeys = new Set();\n      var blockMatch;\n      while ((blockMatch = blockRegex.exec(html)) !== null) {\n        var body = blockMatch[1];\n        var idMatch = void 0;\n        while ((idMatch = idRegex.exec(body)) !== null) {\n          usedKeys.add(idMatch[0]);\n        }\n      }\n      var unusedKeys = keys.filter(function (k) {\n        return !usedKeys.has(k);\n      });\n      if (unusedKeys.length > 0) {\n        if (typeof failedCallback === 'function') {\n          failedCallback(unusedKeys);\n        } else {\n          _BuilderjsPopup_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].alert({\n            title: _I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.unused_ejs_keys_title', 'Unused EJS keys'),\n            message: \"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].t('errors.unused_ejs_keys_msg', 'The following template keys were not used during render:'), \" \").concat(unusedKeys.join(', ')),\n            kind: 'warn'\n          });\n          throw new Error(\"Unused EJS keys: \".concat(unusedKeys.join(', ')));\n        }\n      }\n    }\n  }, {\n    key: \"renderTemplate\",\n    value: function renderTemplate(template) {\n      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      var html = this.getTemplate(template);\n\n      // EJS render — elements resolve their own URLs via transferMediaAbsUrl()\n      // before passing to templates, so no post-processing needed here.\n      html = ejs.render(html, options);\n      return html;\n    }\n\n    /**\n     * Convert a relative asset path to an absolute URL using themeMediaUrl.\n     *\n     * Relative paths stored in template JSON (e.g. \"assets/profile_image/avatar.png\")\n     * become absolute for the browser (e.g. \"https://app.example.com/p/templates/000abc/assets/profile_image/avatar.png\").\n     *\n     * Already-absolute URLs (http://, https://), root-relative (/path), anchors (#),\n     * template tags ([[tag]], {tag}), and data URIs (data:image/...) are returned as-is.\n     *\n     * Inverse operation: getHtmlWithRelativeLinks() strips themeMediaUrl back out for saving.\n     *\n     * @param {string} url - The URL to resolve (may be relative or absolute).\n     * @returns {string} Absolute URL if input was relative, otherwise unchanged.\n     */\n  }, {\n    key: \"transferMediaAbsUrl\",\n    value: function transferMediaAbsUrl(url) {\n      if (!/^https?:\\/\\//i.test(url) && !url.startsWith('/') && !url.startsWith('#') && !url.startsWith('/javascript:;') && !url.startsWith('[[') && !url.startsWith('[') && !url.startsWith('{') && !url.startsWith('data:image')) {\n        return this.themeMediaUrl + '/' + url;\n      } else {\n        return url;\n      }\n    }\n  }, {\n    key: \"browseMedia\",\n    value: function browseMedia(onSelectCallback) {\n      this.fileManager.browseFile(onSelectCallback);\n    }\n  }, {\n    key: \"closeBrowseMedia\",\n    value: function closeBrowseMedia() {\n      var modal = document.getElementById('filemanagerModal');\n      if (modal) {\n        var bootstrapModal = bootstrap.Modal.getInstance(modal);\n        if (bootstrapModal) {\n          bootstrapModal.hide();\n        }\n      }\n      modal.remove();\n    }\n\n    /**\n     * Register a custom element class so JSON documents containing\n     * `{ \"name\": \"<typeName>\", … }` can parse + render via the canvas pipeline.\n     *\n     * AIBuilder Wave 1 — CD-1 (2026-05-04). Replaces the previously frozen\n     * `ELEMENT_REGISTRY` plain object with a mutable `Map`. Host apps (e.g. the\n     * AI Builder WordPress plugin) call this BEFORE `builder.load()` to add\n     * host-specific element types (T4 — see AIBuilder DESIGN.md §3) without\n     * forking BuilderJS. Existing JSON samples continue to render byte-identical\n     * (N16) — this method only adds capability, never removes.\n     *\n     * Re-registering an existing name is allowed (replaces) so a plugin can\n     * override a stock element (e.g. provide its own HeadingElement variant);\n     * the responsibility for the resulting compatibility lies with the host.\n     *\n     * @param {string} name JSON `name` field used in saved templates (e.g. `\"WPNavMenuElement\"`).\n     * @param {Function} klass Element class. Must expose `static parse(data)` returning an instance.\n     * @throws {Error} when `name` is not a non-empty string or `klass.parse` is not callable.\n     *\n     * @example\n     *   class WPNavMenuElement extends BaseElement {\n     *     static parse(data) { … }\n     *     render() { … }\n     *   }\n     *   Builder.registerElement('WPNavMenuElement', WPNavMenuElement);\n     *   await builder.load(json, themeTemplates, themeConfig, themeMediaUrl);\n     */\n    /**\n     * Frozen enum of canonical event names emitted on `builder.events` AND\n     * expected by host apps subscribing for save / dirty / element-graph\n     * concerns. Use these constants instead of string literals so a typo\n     * surfaces at parse-time and renames are tractable.\n     *\n     * AIBuilder Wave 4 — CD-3 (2026-05-05). See `docs/core/USAGE.md`\n     * \"Event bus (CD-3)\" for the full table including payload shapes,\n     * debounce config, and host-vs-engine emitter ownership.\n     *\n     * Adding a new event = update this enum + the canonical-events table +\n     * R-bjs-docs in one commit.\n     */\n  }, {\n    key: \"getRenderedBlocks\",\n    value:\n    /**\n     * Return the rendered body inner HTML of the canvas — no `<html>`, no\n     * `<head>`, no `<body>` wrap. Stripped of editor-only artefacts identically\n     * to `getHtml()` (no `data-control=\"builder-helper\"` nodes, no\n     * `[contenteditable]`/`[inline-edit]` attrs, no editor-only `overflow:hidden`\n     * on `<html>`). Theme media URLs are converted back to relative paths\n     * matching `getHtmlWithRelativeLinks()` so the saved cache is portable\n     * across domains / templates.\n     *\n     * AIBuilder Wave 1 — CD-1c (2026-05-04). Added so host apps can cache the\n     * canvas-rendered blocks without owning the surrounding `<html>` shell —\n     * the WordPress plugin wraps this body inner via 3 PHP page templates\n     * (theme-default / canvas-only / fullwidth) so the same cache serves all\n     * three modes. See AIBuilder DESIGN.md §5.\n     *\n     * @returns {string} Body inner HTML, sanitized of editor-only attributes,\n     *   with relative theme asset paths.\n     */\n    function getRenderedBlocks() {\n      // Clone the document — same invariant as getHtml. Pre-2026-05-20 this\n      // mutated the live iframe DOM directly (stripping builder-helper\n      // styles + inline-edit attrs in place); that was an unrelated\n      // dormant bug because PageElement.render() runs\n      // `_injectIframeHelpers` afterwards and re-injects the autosize\n      // override, so users never saw the half-second of broken layout.\n      // Switching to clone-then-clean kills that race AND lets us route\n      // through the shared `_sanitiseForExport` so HARD RULE T11 (no\n      // block tags inside inline-edit hosts) is enforced for THIS export\n      // path too — saved HTML round-trip parity with `getHtml()`.\n      var htmlDoc = this.iframe.contentDocument.documentElement.cloneNode(true);\n      this._sanitiseForExport(htmlDoc);\n\n      // Body-inner — query the CLONE's body (not the live iframe).\n      var body = htmlDoc.querySelector('body');\n      if (!body) return '';\n      var inner = body.innerHTML;\n\n      // Match getHtmlWithRelativeLinks() — strip themeMediaUrl prefix so the\n      // saved cache is portable across domains / template installs.\n      if (this.themeMediaUrl) {\n        inner = inner.split(this.themeMediaUrl + '/').join('');\n      }\n      return inner;\n    }\n  }], [{\n    key: \"registerElement\",\n    value: function registerElement(name, klass) {\n      if (typeof name !== 'string' || !name) {\n        throw new Error('Builder.registerElement: name must be a non-empty string');\n      }\n      if (!klass || typeof klass.parse !== 'function') {\n        throw new Error(\"Builder.registerElement(\\\"\".concat(name, \"\\\"): klass.parse(data) must be a function\"));\n      }\n      var constructorName = klass.name || name;\n      _ElementFactory_js__WEBPACK_IMPORTED_MODULE_17__.ELEMENT_REGISTRY.set(name, constructorName);\n      // Mirror onto window so ElementFactory.getElementClass() can resolve it\n      // — same lookup path stock elements use.\n      if (typeof window !== 'undefined') {\n        window[constructorName] = klass;\n      }\n    }\n  }]);\n}();\n_defineProperty(Builder, \"EVENTS\", Object.freeze({\n  DOCUMENT_CHANGED: 'document:changed',\n  DOCUMENT_SAVED: 'document:saved',\n  ELEMENT_ADDED: 'element:added',\n  ELEMENT_REMOVED: 'element:removed',\n  // W6.A.A.4 — fires on every `setMode(mode)` call with `{from, to}`.\n  // Cookbook chrome presets subscribe to keep header pills in sync.\n  // Originally paired with `theme:changed` in the W6 plan; that one\n  // was deferred because Builder.js has no `setTheme()` API yet —\n  // theme switching today is page-reload, so there is no caller to\n  // emit from. Will land alongside a future setTheme method (likely\n  // when a no-reload theme-swap cookbook variant ships).\n  MODE_CHANGED: 'mode:changed'\n}));\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Builder);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/Builder.js?");

/***/ }),

/***/ "./src/includes/BuilderJsonStructureValidator.js":
/*!*******************************************************!*\
  !*** ./src/includes/BuilderJsonStructureValidator.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar BuilderJsonStructureValidator = /*#__PURE__*/function () {\n  function BuilderJsonStructureValidator() {\n    _classCallCheck(this, BuilderJsonStructureValidator);\n    this.pageElements = new Set(['PageElement']);\n    this.blockElements = new Set(['BlockElement']);\n    this.gridElements = new Set(['GridElement', 'PricingCardsElement']);\n    this.cellElements = new Set(['CellElement', 'PricingCardElement', 'FormContainerCell']);\n    this.supportedLeafElements = new Set(['HeadingElement', 'H1Element', 'H2Element', 'H3Element', 'H4Element', 'H5Element', 'PElement', 'LabelElement', 'LinkElement', 'AlertElement', 'ImageElement', 'VideoElement', 'YoutubeElement', 'SocialIconsElement', 'FieldElement', 'TextInputElement', 'SelectElement', 'RadioElement', 'CheckboxElement', 'CheckoutElement', 'CheckoutSimpleElement', 'ListElement', 'MenuElement', 'RSSElement', 'ButtonElement', 'SubmitButtonElement', 'DividerElement', 'HTMLElement']);\n    this.requiredAttributes = {\n      HeadingElement: ['text', 'type'],\n      H1Element: ['text'],\n      H2Element: ['text'],\n      H3Element: ['text'],\n      H4Element: ['text'],\n      H5Element: ['text'],\n      PElement: ['text'],\n      LabelElement: ['text'],\n      LinkElement: ['text', 'url'],\n      AlertElement: ['text'],\n      ImageElement: ['src'],\n      VideoElement: ['src'],\n      YoutubeElement: ['url'],\n      SocialIconsElement: ['items'],\n      FieldElement: [],\n      TextInputElement: [],\n      SelectElement: ['items'],\n      RadioElement: ['items'],\n      CheckboxElement: ['items'],\n      CheckoutElement: [],\n      CheckoutSimpleElement: [],\n      ListElement: ['items'],\n      MenuElement: ['items'],\n      RSSElement: [],\n      ButtonElement: ['text', 'url'],\n      SubmitButtonElement: ['text'],\n      DividerElement: [],\n      HTMLElement: ['html'],\n      PageElement: ['blocks'],\n      BlockElement: ['elements'],\n      GridElement: ['cells'],\n      PricingCardsElement: ['cells'],\n      CellElement: ['blocks'],\n      PricingCardElement: ['blocks'],\n      FormContainerCell: ['blocks']\n    };\n  }\n  return _createClass(BuilderJsonStructureValidator, [{\n    key: \"validate\",\n    value: function validate(data) {\n      var _this = this;\n      if (!data || _typeof(data) !== 'object' || Array.isArray(data)) {\n        throw new Error('Builder JSON root must be an object.');\n      }\n      this.assertNodeShape(data, 'root');\n      if (!this.pageElements.has(data.name)) {\n        throw new Error('Builder JSON root must be a PageElement or supported page subclass.');\n      }\n      this.assertArray(data.blocks, 'root.blocks');\n      data.blocks.forEach(function (block, index) {\n        return _this.assertPageBlock(block, \"root.blocks.\".concat(index));\n      });\n    }\n  }, {\n    key: \"assertPageBlock\",\n    value: function assertPageBlock(node, path) {\n      var _this2 = this;\n      this.assertNodeShape(node, path);\n      if (!this.blockElements.has(node.name)) {\n        throw new Error(\"\".concat(path, \" must be a BlockElement or supported block subclass.\"));\n      }\n      this.assertRequiredAttributes(node, path);\n      this.assertArray(node.elements, \"\".concat(path, \".elements\"));\n      node.elements.forEach(function (element, index) {\n        return _this2.assertBlockChild(element, \"\".concat(path, \".elements.\").concat(index));\n      });\n    }\n  }, {\n    key: \"assertBlockChild\",\n    value: function assertBlockChild(node, path) {\n      this.assertNodeShape(node, path);\n      if (this.pageElements.has(node.name)) {\n        throw new Error(\"\".concat(path, \" cannot use PageElement inside BlockElement.elements.\"));\n      }\n      if (this.cellElements.has(node.name)) {\n        throw new Error(\"\".concat(path, \" cannot use CellElement inside BlockElement.elements.\"));\n      }\n      if (this.gridElements.has(node.name)) {\n        this.assertGrid(node, path);\n        return;\n      }\n      if (this.blockElements.has(node.name)) {\n        throw new Error(\"\".concat(path, \" cannot use block-like elements inside BlockElement.elements.\"));\n      }\n      if (!this.supportedLeafElements.has(node.name)) {\n        throw new Error(\"\".concat(path, \" uses unsupported element `\").concat(node.name, \"`.\"));\n      }\n      this.assertRequiredAttributes(node, path);\n    }\n  }, {\n    key: \"assertGrid\",\n    value: function assertGrid(node, path) {\n      var _this3 = this;\n      this.assertRequiredAttributes(node, path);\n      this.assertArray(node.cells, \"\".concat(path, \".cells\"));\n      node.cells.forEach(function (cell, index) {\n        return _this3.assertCell(cell, \"\".concat(path, \".cells.\").concat(index));\n      });\n    }\n  }, {\n    key: \"assertCell\",\n    value: function assertCell(node, path) {\n      var _this4 = this;\n      this.assertNodeShape(node, path);\n      if (!this.cellElements.has(node.name)) {\n        throw new Error(\"\".concat(path, \" must be a CellElement.\"));\n      }\n      this.assertRequiredAttributes(node, path);\n      this.assertArray(node.blocks, \"\".concat(path, \".blocks\"));\n      node.blocks.forEach(function (block, index) {\n        return _this4.assertPageBlock(block, \"\".concat(path, \".blocks.\").concat(index));\n      });\n    }\n  }, {\n    key: \"assertNodeShape\",\n    value: function assertNodeShape(node, path) {\n      if (!node || _typeof(node) !== 'object' || Array.isArray(node)) {\n        throw new Error(\"\".concat(path, \" must be an object.\"));\n      }\n      if (typeof node.name !== 'string' || node.name.trim() === '') {\n        throw new Error(\"\".concat(path, \".name is required.\"));\n      }\n      if (typeof node.template !== 'string' || node.template.trim() === '') {\n        throw new Error(\"\".concat(path, \".template is required.\"));\n      }\n      if (!Object.prototype.hasOwnProperty.call(node, 'formats')) {\n        throw new Error(\"\".concat(path, \".formats is required.\"));\n      }\n\n      // if (!node.formats || typeof node.formats !== 'object' || Array.isArray(node.formats)) {\n      //     throw new Error(`${path}.formats must be an object.`);\n      // }\n    }\n  }, {\n    key: \"assertRequiredAttributes\",\n    value: function assertRequiredAttributes(node, path) {\n      var required = this.requiredAttributes[node.name] || [];\n      required.forEach(function (attribute) {\n        if (!Object.prototype.hasOwnProperty.call(node, attribute)) {\n          throw new Error(\"\".concat(path, \".\").concat(attribute, \" is required for \").concat(node.name, \".\"));\n        }\n      });\n    }\n  }, {\n    key: \"assertArray\",\n    value: function assertArray(value, path) {\n      if (!Array.isArray(value)) {\n        throw new Error(\"\".concat(path, \" must be an array.\"));\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BuilderJsonStructureValidator);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BuilderJsonStructureValidator.js?");

/***/ }),

/***/ "./src/includes/BuilderjsPopup.js":
/*!****************************************!*\
  !*** ./src/includes/BuilderjsPopup.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * BuilderjsPopup — themed replacement for native window.alert / confirm / prompt\n *\n * Why: native dialogs look ugly, can't be styled to match the builder theme,\n * block the browser event loop, and don't respect dark mode. BuilderjsPopup\n * is a pure-DOM, Promise-based, keyboard-accessible modal that matches the\n * rest of the `.bjs-*` design system.\n *\n * Public API — static helpers cover 95% of use cases:\n *\n *   await BuilderjsPopup.alert({\n *     title:   'Template not found',\n *     message: 'The \"xyz\" template could not be located.',\n *     kind:    'error',          // info | warn | error | success\n *   });\n *\n *   const ok = await BuilderjsPopup.confirm({\n *     title:        'Delete block?',\n *     message:      'This cannot be undone.',\n *     okLabel:      'Delete',\n *     cancelLabel:  'Keep',\n *     destructive:  true,        // red OK button\n *   });\n *\n *   const url = await BuilderjsPopup.prompt({\n *     title:       'Image link URL',\n *     label:       'URL',\n *     value:       'https://…',\n *     placeholder: 'https://example.com',\n *     validate:    (v) => /^https?:\\/\\//.test(v) || 'URL must start with http(s)://',\n *   });\n *   if (url === null) return;    // user cancelled\n *\n * Semantics match native:\n *   - alert   → Promise<void>                (resolves on OK or Esc)\n *   - confirm → Promise<boolean>             (true = OK; false = Cancel/Esc)\n *   - prompt  → Promise<string | null>       (string = OK; null = Cancel/Esc)\n *\n * Advanced (instance) API — use directly for custom forms (multi-field,\n * conditional UI, etc.). Not currently consumed in the builder; static\n * helpers cover the existing native-dialog callsites.\n *\n *   const popup = new BuilderjsPopup({ title, bodyRenderer: (container) => {...} });\n *   const result = await popup.open();   // resolves when popup.close(value) is called\n *\n * Accessibility:\n *   - role=\"dialog\" + aria-modal=\"true\" + aria-labelledby + aria-describedby\n *   - Focus trap (Tab cycles within popup; Shift+Tab reverses)\n *   - Focus restoration (returns to previously-focused element on close)\n *   - Esc cancels; Enter confirms (or submits when input is focused)\n *\n * Styling: see /* Builderjs Popup *\\/ section in src/builder.css. Uses the\n * same `.bjs-*` design tokens as the rest of the builder — light + dark\n * mode inherit automatically.\n *\n * Stacking:\n *   - z-index: 10000 (above Canvas Overlay System which sits at 1000)\n *   - Mounts in parent `document.body`; safe when builder is in an iframe.\n */\n\nvar FOCUSABLE = ['a[href]', 'button:not([disabled])', 'input:not([disabled]):not([type=\"hidden\"])', 'select:not([disabled])', 'textarea:not([disabled])', '[tabindex]:not([tabindex=\"-1\"])'].join(',');\n\n// Icon glyphs (material-symbols-rounded — already loaded by builder)\nvar ICONS = {\n  info: 'info',\n  warn: 'warning',\n  error: 'error',\n  success: 'check_circle'\n};\nvar BuilderjsPopup = /*#__PURE__*/function () {\n  function BuilderjsPopup() {\n    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n    _classCallCheck(this, BuilderjsPopup);\n    this.options = Object.assign({\n      title: '',\n      message: '',\n      kind: 'info',\n      okLabel: 'OK',\n      cancelLabel: 'Cancel',\n      showCancel: false,\n      destructive: false,\n      bodyRenderer: null // optional custom body renderer\n    }, options);\n    this._resolve = null;\n    this._previousFocus = null;\n    this._rootNode = null;\n    this._onKeyDown = this._onKeyDown.bind(this);\n  }\n\n  // ─── Static helpers ─────────────────────────────────────────────────────\n  return _createClass(BuilderjsPopup, [{\n    key: \"open\",\n    value:\n    // ─── Instance lifecycle ──────────────────────────────────────────────────\n\n    function open() {\n      var _this = this;\n      return new Promise(function (resolve) {\n        _this._resolve = resolve;\n        _this._previousFocus = document.activeElement;\n        _this._mount();\n        // Force reflow before adding .is-open so CSS transition runs\n        /* eslint-disable-next-line no-unused-expressions */\n        _this._rootNode.offsetWidth;\n        _this._rootNode.classList.add('is-open');\n        _this._focusInitial();\n        document.addEventListener('keydown', _this._onKeyDown, true);\n      });\n    }\n\n    /**\n     * Close the popup. Resolves the open() promise with `{ ok, value }` so\n     * callers never have to synchronize through static state.\n     *   - ok === true  : user clicked OK (or pressed Enter on alert)\n     *   - ok === false : user clicked Cancel, pressed Esc (when cancelable),\n     *                    or clicked the backdrop (when cancelable)\n     *   - value        : current input value (prompt only); undefined otherwise\n     *\n     * If `okOverride` is passed, it replaces the computed ok flag — used by\n     * Esc/backdrop paths to force `false` even when no Cancel button is shown.\n     */\n  }, {\n    key: \"close\",\n    value: function close(okOverride) {\n      if (!this._rootNode) return;\n      var ok = typeof okOverride === 'boolean' ? okOverride : true;\n      var value = this._ctx && typeof this._ctx.getValue === 'function' ? this._ctx.getValue() : undefined;\n      document.removeEventListener('keydown', this._onKeyDown, true);\n      this._rootNode.classList.remove('is-open');\n\n      // Wait for close animation then detach\n      var node = this._rootNode;\n      setTimeout(function () {\n        if (node && node.parentNode) node.parentNode.removeChild(node);\n      }, 220);\n      this._rootNode = null;\n\n      // Restore focus\n      if (this._previousFocus && typeof this._previousFocus.focus === 'function') {\n        try {\n          this._previousFocus.focus();\n        } catch (_) {/* no-op */}\n      }\n      if (this._resolve) {\n        var r = this._resolve;\n        this._resolve = null;\n        r({\n          ok: ok,\n          value: value\n        });\n      }\n    }\n\n    // ─── Internal ────────────────────────────────────────────────────────────\n  }, {\n    key: \"_mount\",\n    value: function _mount() {\n      var _this2 = this;\n      var popupId = 'bjs-popup-' + Math.random().toString(36).slice(2, 9);\n      var titleId = popupId + '-title';\n      var descId = popupId + '-desc';\n      var inputId = popupId + '-input';\n      this._ctx = {\n        inputId: inputId,\n        getValue: null,\n        autoFocus: null,\n        validateSubmit: null\n      };\n\n      // Backdrop (click-outside to cancel unless alert)\n      var backdrop = document.createElement('div');\n      backdrop.className = 'bjs-popup-backdrop';\n      backdrop.setAttribute('aria-hidden', 'true');\n\n      // Popup card\n      var popup = document.createElement('div');\n      popup.className = 'bjs-popup';\n      popup.setAttribute('role', 'dialog');\n      popup.setAttribute('aria-modal', 'true');\n      popup.setAttribute('aria-labelledby', titleId);\n      if (this.options.message) popup.setAttribute('aria-describedby', descId);\n      popup.tabIndex = -1;\n\n      // Header (icon + title)\n      var header = document.createElement('div');\n      header.className = 'bjs-popup-header';\n      var icon = document.createElement('span');\n      icon.className = 'bjs-popup-icon bjs-popup-icon--' + (this.options.kind || 'info');\n      icon.innerHTML = '<span class=\"material-symbols-rounded\" aria-hidden=\"true\">' + (ICONS[this.options.kind] || ICONS.info) + '</span>';\n      header.appendChild(icon);\n      var title = document.createElement('div');\n      title.className = 'bjs-popup-title';\n      title.id = titleId;\n      title.textContent = this.options.title || '';\n      header.appendChild(title);\n      popup.appendChild(header);\n\n      // Body\n      var body = document.createElement('div');\n      body.className = 'bjs-popup-body';\n      if (this.options.message) {\n        var message = document.createElement('p');\n        message.className = 'bjs-popup-message';\n        message.id = descId;\n        message.textContent = this.options.message;\n        body.appendChild(message);\n      }\n      if (typeof this.options.bodyRenderer === 'function') {\n        this.options.bodyRenderer(body, this._ctx);\n      }\n      popup.appendChild(body);\n\n      // Footer (buttons)\n      var footer = document.createElement('div');\n      footer.className = 'bjs-popup-footer';\n      if (this.options.showCancel) {\n        var cancelBtn = document.createElement('button');\n        cancelBtn.type = 'button';\n        cancelBtn.className = 'bjs-popup-btn bjs-popup-btn--secondary';\n        cancelBtn.textContent = this.options.cancelLabel || 'Cancel';\n        cancelBtn.addEventListener('click', function () {\n          return _this2._cancel();\n        });\n        footer.appendChild(cancelBtn);\n      }\n      var okBtn = document.createElement('button');\n      okBtn.type = 'button';\n      okBtn.className = 'bjs-popup-btn ' + (this.options.destructive ? 'bjs-popup-btn--destructive' : 'bjs-popup-btn--primary');\n      okBtn.textContent = this.options.okLabel || 'OK';\n      okBtn.addEventListener('click', function () {\n        return _this2._submitOk();\n      });\n      footer.appendChild(okBtn);\n      this._okBtn = okBtn;\n      popup.appendChild(footer);\n      backdrop.appendChild(popup);\n\n      // Backdrop click: cancel for prompt/confirm; alert resolves as OK\n      // (there's no Cancel button to signal otherwise, and clicking\n      // outside a pure alert is a dismissal — matches the native behavior\n      // where alert returns regardless of which key dismisses it).\n      backdrop.addEventListener('click', function (e) {\n        if (e.target !== backdrop) return; // don't close when clicking the card\n        if (_this2.options.showCancel) _this2._cancel();else _this2.close(true);\n      });\n      document.body.appendChild(backdrop);\n      this._rootNode = backdrop;\n    }\n  }, {\n    key: \"_submitOk\",\n    value: function _submitOk() {\n      if (this._ctx && typeof this._ctx.validateSubmit === 'function') {\n        if (!this._ctx.validateSubmit()) return; // validation blocked\n      }\n      this.close(true);\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      this.close(false);\n    }\n  }, {\n    key: \"_focusInitial\",\n    value: function _focusInitial() {\n      var target = this._ctx && this._ctx.autoFocus || this._okBtn;\n      if (target && typeof target.focus === 'function') {\n        try {\n          target.focus();\n          if (target.tagName === 'INPUT') target.select();\n        } catch (_) {/* no-op */}\n      }\n    }\n  }, {\n    key: \"_onKeyDown\",\n    value: function _onKeyDown(e) {\n      if (!this._rootNode) return;\n      if (e.key === 'Escape') {\n        e.preventDefault();\n        // Cancelable popup: Esc = Cancel. Alert-only: Esc = OK (dismiss,\n        // matches native alert where any dismissal key \"accepts\" the\n        // message — there's no cancel signal to send).\n        if (this.options.showCancel) this._cancel();else this.close(true);\n        return;\n      }\n      if (e.key === 'Enter') {\n        // Enter in a <textarea> stays a newline; Enter elsewhere submits.\n        if (e.target && e.target.tagName === 'TEXTAREA') return;\n        e.preventDefault();\n        this._submitOk();\n        return;\n      }\n      if (e.key === 'Tab') {\n        this._trapFocus(e);\n      }\n    }\n  }, {\n    key: \"_trapFocus\",\n    value: function _trapFocus(e) {\n      var focusables = Array.from(this._rootNode.querySelectorAll(FOCUSABLE)).filter(function (el) {\n        return el.offsetParent !== null;\n      });\n      if (focusables.length === 0) return;\n      var first = focusables[0];\n      var last = focusables[focusables.length - 1];\n      if (e.shiftKey && document.activeElement === first) {\n        e.preventDefault();\n        last.focus();\n      } else if (!e.shiftKey && document.activeElement === last) {\n        e.preventDefault();\n        first.focus();\n      }\n    }\n  }], [{\n    key: \"alert\",\n    value: function alert() {\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      return new BuilderjsPopup(Object.assign({\n        showCancel: false\n      }, opts)).open().then(function () {\n        return undefined;\n      });\n    }\n  }, {\n    key: \"confirm\",\n    value: function confirm() {\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      return new BuilderjsPopup(Object.assign({\n        showCancel: true\n      }, opts)).open().then(function (result) {\n        return !!(result && result.ok);\n      });\n    }\n\n    /** Prompt for text input. Returns the submitted value (string), or null\n     *  when the user cancels or dismisses via Esc. Empty string is a valid\n     *  submission (NOT treated as cancel — matches the native prompt when\n     *  the user clears the field and clicks OK). */\n  }, {\n    key: \"prompt\",\n    value: function prompt() {\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      var title = opts.title,\n        message = opts.message,\n        label = opts.label,\n        _opts$value = opts.value,\n        value = _opts$value === void 0 ? '' : _opts$value,\n        _opts$placeholder = opts.placeholder,\n        placeholder = _opts$placeholder === void 0 ? '' : _opts$placeholder,\n        okLabel = opts.okLabel,\n        cancelLabel = opts.cancelLabel,\n        validate = opts.validate;\n      return new BuilderjsPopup({\n        title: title,\n        message: message,\n        okLabel: okLabel,\n        cancelLabel: cancelLabel,\n        showCancel: true,\n        bodyRenderer: function bodyRenderer(container, ctx) {\n          if (label) {\n            var labelEl = document.createElement('label');\n            labelEl.className = 'bjs-popup-input-label';\n            labelEl.textContent = label;\n            labelEl.setAttribute('for', ctx.inputId);\n            container.appendChild(labelEl);\n          }\n          var input = document.createElement('input');\n          input.type = 'text';\n          input.id = ctx.inputId;\n          input.className = 'bjs-popup-input';\n          input.value = value != null ? String(value) : '';\n          input.placeholder = placeholder || '';\n          input.autocomplete = 'off';\n          input.spellcheck = false;\n          container.appendChild(input);\n          var errorEl = document.createElement('div');\n          errorEl.className = 'bjs-popup-error-message';\n          errorEl.setAttribute('role', 'alert');\n          errorEl.style.display = 'none';\n          container.appendChild(errorEl);\n          ctx.getValue = function () {\n            return input.value;\n          };\n          ctx.autoFocus = input;\n          ctx.validateSubmit = function () {\n            if (typeof validate !== 'function') return true;\n            var result = validate(input.value);\n            if (result === true || result === undefined) {\n              input.classList.remove('bjs-popup-input--error');\n              errorEl.style.display = 'none';\n              return true;\n            }\n            input.classList.add('bjs-popup-input--error');\n            errorEl.textContent = typeof result === 'string' ? result : 'Invalid value';\n            errorEl.style.display = '';\n            input.focus();\n            return false;\n          };\n        }\n      }).open().then(function (result) {\n        return result && result.ok ? result.value : null;\n      });\n    }\n  }]);\n}(); // Make the class accessible to non-module contexts (tests, host apps)\nif (typeof window !== 'undefined') {\n  window.BuilderjsPopup = BuilderjsPopup;\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BuilderjsPopup);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/BuilderjsPopup.js?");

/***/ }),

/***/ "./src/includes/ButtonElement.js":
/*!***************************************!*\
  !*** ./src/includes/ButtonElement.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\n/* harmony import */ var _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./InnerPaddingControl.js */ \"./src/includes/InnerPaddingControl.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./SegmentedTextControl.js */ \"./src/includes/SegmentedTextControl.js\");\n/* harmony import */ var _StylePickerControl_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./StylePickerControl.js */ \"./src/includes/StylePickerControl.js\");\n/* harmony import */ var _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _overlays_ButtonActionsOverlay_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./overlays/ButtonActionsOverlay.js */ \"./src/includes/overlays/ButtonActionsOverlay.js\");\n/* harmony import */ var _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./overlays/LinkPopoverOverlay.js */ \"./src/includes/overlays/LinkPopoverOverlay.js\");\n/* harmony import */ var _overlays_ButtonPresetPickerOverlay_js__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./overlays/ButtonPresetPickerOverlay.js */ \"./src/includes/overlays/ButtonPresetPickerOverlay.js\");\n/* harmony import */ var _overlays_ButtonSettingsPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./overlays/ButtonSettingsPopoverOverlay.js */ \"./src/includes/overlays/ButtonSettingsPopoverOverlay.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * Formatter keys emitted via `toStyleStringAll(...)` — kept in sync with\n * `Button.template.html`. applyFormatStyles() patches ONLY these on the\n * existing <a> so the click target, contenteditable cursor, and any\n * in-flight navigation state are preserved across format tweaks.\n *\n * 2026-04-19: `box_shadow` joined the list to back the new Shadow scale\n * control (page-only, but emitted via inline style — Outlook safely\n * strips it on render so flat fallback degrades cleanly).\n */\nvar CSS_KEYS = ['font_family', 'font_weight', 'font_size', 'text_color', 'link_color', 'text_align', 'line_height', 'letter_spacing', 'text_direction', 'paragraph_spacing', 'background_color', 'background_image', 'background_position', 'background_size', 'background_repeat', 'padding_top', 'padding_right', 'padding_bottom', 'padding_left', 'border_top_style', 'border_top_width', 'border_top_color', 'border_right_style', 'border_right_width', 'border_right_color', 'border_bottom_style', 'border_bottom_width', 'border_bottom_color', 'border_left_style', 'border_left_width', 'border_left_color', 'border_radius', 'box_shadow', 'width', 'max_width', 'min_width'];\nvar ButtonElement = /*#__PURE__*/function (_BaseElement) {\n  function ButtonElement(template, text) {\n    var _this;\n    var url = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '#';\n    _classCallCheck(this, ButtonElement);\n    _this = _callSuper(this, ButtonElement);\n    _this.template = template;\n    _this.text = text;\n    // Link semantics — kept as top-level properties (not formatter\n    // entries). Target/rel/title/download are attribute-level, not\n    // visual styles.\n    _this.url = url || '';\n    _this.target = '';\n    _this.rel = '';\n    _this.title = '';\n    _this.download = '';\n    // W4.3 — a11y override. Set via LinkConfigControl; rendered as\n    // `aria-label` on the `<a>` inside the button template.\n    _this.ariaLabel = '';\n\n    // Style preset identity + orthogonal modifier axes (2026-04-19).\n    // Default = `solid-ink` LG centered — replaces the older blue-pill\n    // default (#0d6efd, padding 6/12) which user feedback flagged as\n    // \"ugly\". Defaults are picked so a fresh widget drag delivers a\n    // confident, ready-to-publish button (no first-time tuning needed).\n    // Saved data with explicit values overrides defaults via parse().\n    _this.preset_id = 'solid-ink';\n    _this.size_key = 'lg';\n    _this.shadow_key = 'none';\n    _this.hover_effect = 'none';\n    _this.icon = null;\n    _this.icon_position = 'none';\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['text'];\n    // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n    _this.registerInlineEdit('text');\n\n    // Defaults below mirror PRESETS['solid-ink'] + SIZE_SCALE.lg so a\n    // new ButtonElement boots into the \"solid ink, large\" look even\n    // before the picker overlay has a chance to apply the preset\n    // (the constructor runs sync, applyPreset needs a mounted DOM).\n    // Keep these in sync with buttonPresets.js solid-ink + SIZE_SCALE.lg.\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_19__[\"default\"]({\n      align: 'center',\n      font_family: \"inherit\",\n      font_weight: \"500\",\n      font_size: \"16px\",\n      text_color: \"#ffffff\",\n      link_color: \"#ffffff\",\n      paragraph_spacing: null,\n      text_align: 'center',\n      line_height: \"1.5\",\n      letter_spacing: null,\n      text_direction: \"ltr\",\n      background_color: \"#111827\",\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      padding_top: 12,\n      padding_right: 28,\n      padding_bottom: 12,\n      padding_left: 28,\n      border_top_style: \"solid\",\n      border_top_width: \"1px\",\n      border_top_color: \"#111827\",\n      border_right_style: \"solid\",\n      border_right_width: \"1px\",\n      border_right_color: \"#111827\",\n      border_bottom_style: \"solid\",\n      border_bottom_width: \"1px\",\n      border_bottom_color: \"#111827\",\n      border_left_width: \"1px\",\n      border_left_style: \"solid\",\n      border_left_color: \"#111827\",\n      border_radius: \"6px\",\n      box_shadow: '',\n      width: null,\n      max_width: null,\n      min_width: null\n    });\n    return _this;\n  }\n  _inherits(ButtonElement, _BaseElement);\n  return _createClass(ButtonElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.button');\n    }\n\n    /**\n     * Canvas overlays (Phase 1.7 + Style Picker upgrade 2026-04-19):\n     *   - ButtonActionsOverlay (FloatingActionBarOverlay, trigger 'select')\n     *     — 3-pill toolbar anchored top-right of the button: \"Edit text\"\n     *       / \"Link\" / \"Style\" — the Style pill enters 'style-picker'\n     *       edit mode which mounts ButtonPresetPickerOverlay below.\n     *   - LinkPopoverOverlay (AnchoredPopoverOverlay, trigger 'edit',\n     *     mode 'link-popover') — compact URL editor.\n     *   - ButtonPresetPickerOverlay (AnchoredPopoverOverlay, trigger\n     *     'edit', mode 'style-picker') — anchored 9-tab preset picker.\n     *     Anchor reads from `_lastActionAnchorRect` so it works for both\n     *     entry points: action-bar palette pill AND sidebar Change btn.\n     *\n     * See docs/core/OVERLAY.md §7.5 + §7.7 + docs/BUTTON_UPGRADE_PLAN.md.\n     */\n  }, {\n    key: \"getOverlays\",\n    value: function getOverlays() {\n      var _this2 = this;\n      var anchorTo = function anchorTo() {\n        return _this2._lastActionAnchorRect || null;\n      };\n      return [new _overlays_ButtonActionsOverlay_js__WEBPACK_IMPORTED_MODULE_20__[\"default\"](this), new _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__[\"default\"](this, {\n        anchorTo: anchorTo,\n        side: 'right',\n        width: 380\n      }), new _overlays_ButtonSettingsPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_23__[\"default\"](this), new _overlays_ButtonPresetPickerOverlay_js__WEBPACK_IMPORTED_MODULE_22__[\"default\"](this)];\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        url: this.url || '#',\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        icon: this.icon,\n        iconPosition: this.icon_position,\n        hoverEffect: this.hover_effect\n      });\n\n      // Inline-edit wiring auto-fires from BaseElement.afterRender (W0.2b).\n      this.applyButtonExtras();\n    }\n\n    /**\n     * Format-only update (structure-preserving). Patches the <a>'s inline\n     * style + outer wrapper text-align in place. No innerHTML swap →\n     * contenteditable cursor + DOM identity survive every tweak.\n     *\n     * Fires `notifySyncListeners()` at the end so sidebar surfaces (Style\n     * summary thumb, dual-view link control, future preview tiles) re-read\n     * the live formatter state after any color / border / padding tweak\n     * — not just preset / size / shadow / hover changes that go through\n     * apply*() helpers.\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var a = this.domNode.querySelector('a');\n      var wrapper = this.domNode.firstElementChild;\n      if (!a || !wrapper) {\n        this.render();\n        return;\n      }\n      wrapper.style.textAlign = this.formatter.getFormat('align', 'center');\n      var hasWidth = !!this.formatter.getFormat('width');\n      var display = hasWidth ? \"display: block; \".concat(this.formatter.getFormat('align') === 'center' ? 'margin-left: auto; margin-right: auto;' : '') : 'display: inline-block;';\n      var styleBase = this.formatter.toStyleStringAll(CSS_KEYS);\n      a.setAttribute('style', \"\".concat(styleBase, \" \").concat(display, \" text-decoration: none;\"));\n      this.notifySyncListeners();\n    }\n\n    /**\n     * Patches the icon slot + hover-effect data attribute on the existing\n     * <a> in place. Called from render() AND from any preset / icon /\n     * hover_effect mutation path so the structural extras stay current\n     * without a full innerHTML swap (preserves contenteditable caret).\n     */\n  }, {\n    key: \"applyButtonExtras\",\n    value: function applyButtonExtras() {\n      var _this3 = this;\n      if (!this.domNode) return;\n      var a = this.domNode.querySelector('a');\n      if (!a) return;\n\n      // Hover effect attribute — CSS rules in builder.css act on this\n      if (this.hover_effect && this.hover_effect !== 'none') {\n        a.setAttribute('data-bjs-hover-fx', this.hover_effect);\n      } else {\n        a.removeAttribute('data-bjs-hover-fx');\n      }\n\n      // Icon slot patch\n      var existingLeft = a.querySelector(':scope > .bjs-btn-icon--left');\n      var existingRight = a.querySelector(':scope > .bjs-btn-icon--right');\n      var existingOnly = a.querySelector(':scope > .bjs-btn-icon--only');\n      var textNode = a.querySelector(':scope > [inline-edit=\"text\"]');\n\n      // Wipe any existing icon spans before re-adding (idempotent)\n      if (existingLeft) existingLeft.remove();\n      if (existingRight) existingRight.remove();\n      if (existingOnly) existingOnly.remove();\n      var wantsIcon = !!this.icon && this.icon_position && this.icon_position !== 'none';\n      if (!wantsIcon) {\n        if (textNode) textNode.style.display = '';\n        return;\n      }\n\n      // Inline SVG — theme iframes don't load the Material Symbols font,\n      // and exported HTML (especially email) is even less reliable. SVG\n      // renders deterministically everywhere. Unknown names fall back to\n      // a letter-in-a-circle glyph (InlineIcons.render's built-in\n      // fallback) so a typo doesn't produce an empty span.\n      //\n      // Spacing — apply margin INLINE (not via CSS class) because:\n      //   1. The canvas iframe loads the THEME stylesheet, not the\n      //      builder.css that carries `.bjs-btn-icon--left { margin-* }`.\n      //   2. Exported email HTML is stripped of external stylesheets\n      //      entirely — only inline styles survive.\n      // Inline margin is the only approach that renders identically\n      // across builder canvas, preview iframe, and exported email.\n      var iconSpan = function iconSpan(cls, side) {\n        var s = document.createElement('span');\n        s.className = \"bjs-btn-icon \".concat(cls);\n        s.setAttribute('aria-hidden', 'true');\n        s.style.display = 'inline-flex';\n        s.style.alignItems = 'center';\n        s.style.justifyContent = 'center';\n        s.style.verticalAlign = 'middle';\n        s.style.lineHeight = '1';\n        if (side === 'left') s.style.marginRight = '8px';\n        if (side === 'right') s.style.marginLeft = '8px';\n        s.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_24__[\"default\"].render(_this3.icon, {\n          size: 18,\n          color: 'currentColor'\n        });\n        return s;\n      };\n      if (this.icon_position === 'only') {\n        if (textNode) textNode.style.display = 'none';\n        var ic = iconSpan('bjs-btn-icon--only', 'only');\n        a.insertBefore(ic, a.firstChild);\n      } else if (this.icon_position === 'left') {\n        if (textNode) textNode.style.display = '';\n        var _ic = iconSpan('bjs-btn-icon--left', 'left');\n        a.insertBefore(_ic, a.firstChild);\n      } else if (this.icon_position === 'right') {\n        if (textNode) textNode.style.display = '';\n        var _ic2 = iconSpan('bjs-btn-icon--right', 'right');\n        a.appendChild(_ic2);\n      }\n    }\n\n    /**\n     * Apply a named preset by id. Mutates formatter (full snapshot\n     * overwrite — preset is the new identity), keeps user's current size\n     * (preset is a LOOK, size is an axis), then re-runs\n     * applyFormatStyles + applyButtonExtras + applySize.\n     *\n     * Side-effects (in addition to formatter rewrite):\n     *   - preset_id      ← presetId\n     *   - icon           ← preset.icon       (preset owns icon identity)\n     *   - icon_position  ← preset.iconPosition\n     *\n     * Size / shadow / hover_effect persist across preset switches because\n     * they're orthogonal modifier axes — switching look shouldn't lose\n     * the user's \"I want a large button with a glow\" intent.\n     */\n  }, {\n    key: \"applyPreset\",\n    value: function applyPreset(presetId) {\n      var preset = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.findPreset)(presetId);\n      if (!preset) return;\n      this.preset_id = presetId;\n      this.icon = preset.icon || null;\n      this.icon_position = preset.iconPosition || 'none';\n      // Overwrite formatter with preset's snapshot (full-overwrite —\n      // partial would leak previous preset's color into the new one)\n      if (preset.formats && this.formatter) {\n        var desiredKeys = Object.keys(preset.formats);\n        // Reset any CSS_KEYS the preset doesn't own to their pre-set\n        // values from its DEFAULT_MD skeleton — handled because\n        // every preset includes the full skeleton. So we just merge:\n        for (var _i = 0, _desiredKeys = desiredKeys; _i < _desiredKeys.length; _i++) {\n          var k = _desiredKeys[_i];\n          if (k in this.formatter.formats) {\n            this.formatter.formats[k] = preset.formats[k];\n          }\n        }\n      }\n      // Re-apply current size on top of preset\n      this._applySizeToFormatter(this.size_key || 'md');\n      // Re-apply current shadow override on top of preset (shadow is\n      // an axis: user wanted SHADOW=lg → keep it after switching look)\n      this._applyShadowToFormatter(this.shadow_key || 'none', preset);\n      this.applyFormatStyles();\n      this.applyButtonExtras();\n      this.notifySyncListeners();\n    }\n\n    /**\n     * Switch size axis. Patches padding + font-size only. Keeps preset\n     * identity (color/border/radius/shadow). Idempotent — re-running with\n     * same key is a no-op.\n     */\n  }, {\n    key: \"applySize\",\n    value: function applySize(sizeKey) {\n      if (!_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SIZE_KEYS.includes(sizeKey)) return;\n      this.size_key = sizeKey;\n      this._applySizeToFormatter(sizeKey);\n      this.applyFormatStyles();\n      this.notifySyncListeners();\n    }\n  }, {\n    key: \"_applySizeToFormatter\",\n    value: function _applySizeToFormatter(sizeKey) {\n      var scale = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SIZE_SCALE[sizeKey];\n      if (!scale || !this.formatter) return;\n      for (var _i2 = 0, _Object$entries = Object.entries(scale); _i2 < _Object$entries.length; _i2++) {\n        var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),\n          k = _Object$entries$_i[0],\n          v = _Object$entries$_i[1];\n        if (k in this.formatter.formats) this.formatter.formats[k] = v;\n      }\n    }\n\n    /**\n     * Switch shadow axis. The 'none' value clears box_shadow (so the\n     * preset's intrinsic shadow returns); other values OVERRIDE the\n     * preset's shadow (user's per-element shadow choice wins).\n     */\n  }, {\n    key: \"applyShadow\",\n    value: function applyShadow(shadowKey) {\n      if (!_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SHADOW_KEYS.includes(shadowKey)) return;\n      this.shadow_key = shadowKey;\n      var preset = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.findPreset)(this.preset_id);\n      this._applyShadowToFormatter(shadowKey, preset);\n      this.applyFormatStyles();\n      this.notifySyncListeners();\n    }\n  }, {\n    key: \"_applyShadowToFormatter\",\n    value: function _applyShadowToFormatter(shadowKey) {\n      var preset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n      if (!this.formatter) return;\n      if (shadowKey === 'none') {\n        // Restore preset's intrinsic shadow (or empty)\n        var intrinsic = preset && preset.formats && preset.formats.box_shadow || '';\n        this.formatter.formats.box_shadow = intrinsic;\n      } else {\n        this.formatter.formats.box_shadow = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SHADOW_SCALE[shadowKey] || '';\n      }\n    }\n\n    /**\n     * Switch hover-effect axis. Hover effect lives as a data attribute\n     * (`data-bjs-hover-fx`) — actual :hover CSS rules in builder.css\n     * key off it. No formatter mutation needed.\n     */\n  }, {\n    key: \"applyHoverEffect\",\n    value: function applyHoverEffect(key) {\n      if (!_buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.HOVER_EFFECT_KEYS.includes(key)) return;\n      this.hover_effect = key;\n      this.applyButtonExtras();\n      this.notifySyncListeners();\n    }\n\n    /**\n     * Set or clear the icon. `name` null = remove icon (also resets\n     * icon_position to 'none'). `position` ignored when name null.\n     */\n  }, {\n    key: \"applyIcon\",\n    value: function applyIcon(name) {\n      var position = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'left';\n      if (!name) {\n        this.icon = null;\n        this.icon_position = 'none';\n      } else {\n        this.icon = name;\n        this.icon_position = ['left', 'right', 'only', 'none'].includes(position) ? position : 'left';\n      }\n      this.applyButtonExtras();\n      this.notifySyncListeners();\n    }\n  }, {\n    key: \"applyIconPosition\",\n    value: function applyIconPosition(position) {\n      if (!['left', 'right', 'only', 'none'].includes(position)) return;\n      this.icon_position = position;\n      this.applyButtonExtras();\n      this.notifySyncListeners();\n    }\n\n    /**\n     * Width axis — auto / 50% / full. Translates to formatter.width.\n     */\n  }, {\n    key: \"applyWidth\",\n    value: function applyWidth(key) {\n      if (!this.formatter) return;\n      if (key === 'auto') this.formatter.formats.width = null;else if (key === 'half') this.formatter.formats.width = '50%';else if (key === 'full') this.formatter.formats.width = '100%';\n      this.applyFormatStyles();\n      this.notifySyncListeners();\n    }\n  }, {\n    key: \"_currentWidthKey\",\n    value: function _currentWidthKey() {\n      var w = this.formatter && this.formatter.getFormat('width');\n      if (!w) return 'auto';\n      if (String(w).trim() === '50%') return 'half';\n      if (String(w).trim() === '100%') return 'full';\n      return 'auto';\n    }\n\n    /**\n     * Radius axis — sharp / sm / md / lg / pill. Maps to border_radius.\n     */\n  }, {\n    key: \"applyRadiusKey\",\n    value: function applyRadiusKey(key) {\n      if (!this.formatter) return;\n      var map = {\n        sharp: '0px',\n        sm: '4px',\n        md: '8px',\n        lg: '16px',\n        pill: '999px'\n      };\n      if (!(key in map)) return;\n      this.formatter.formats.border_radius = map[key];\n      this.applyFormatStyles();\n      this.notifySyncListeners();\n    }\n  }, {\n    key: \"_currentRadiusKey\",\n    value: function _currentRadiusKey() {\n      var r = String(this.formatter && this.formatter.getFormat('border_radius') || '').trim();\n      if (r === '0px' || r === '0') return 'sharp';\n      if (r === '4px') return 'sm';\n      if (r === '8px') return 'md';\n      if (r === '16px') return 'lg';\n      if (r === '999px' || r === '9999px') return 'pill';\n      return null; // custom — none of the chips active, slider in Advanced shows current\n    }\n\n    /**\n     * Link-attrs update (also structure-preserving). Updates href/target/\n     * rel/title/download on the existing <a> — does NOT touch style.\n     */\n  }, {\n    key: \"applyLinkAttrs\",\n    value: function applyLinkAttrs() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var a = this.domNode.querySelector('a');\n      if (!a) {\n        this.render();\n        return;\n      }\n      a.setAttribute('href', this.url || '#');\n      if (this.target) a.setAttribute('target', this.target);else a.removeAttribute('target');\n      if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n      if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n      if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n      if (this.ariaLabel) a.setAttribute('aria-label', this.ariaLabel);else a.removeAttribute('aria-label');\n      this.notifySyncListeners();\n    }\n\n    /**\n     * LinkConfigControl factory — see Phase 1.7 / Lesson 39.\n     */\n  }, {\n    key: \"buildLinkControl\",\n    value: function buildLinkControl() {\n      var _this4 = this;\n      return new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link'), {\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        ariaLabel: this.ariaLabel\n      }, {\n        setLink: function setLink(_ref) {\n          var url = _ref.url,\n            target = _ref.target,\n            rel = _ref.rel,\n            title = _ref.title,\n            download = _ref.download,\n            ariaLabel = _ref.ariaLabel;\n          _this4.url = url || '';\n          _this4.target = target || '';\n          _this4.rel = rel || '';\n          _this4.title = title || '';\n          _this4.download = download || '';\n          _this4.ariaLabel = ariaLabel || '';\n          _this4.applyLinkAttrs();\n        }\n      }, {\n        subscribe: function subscribe(fn) {\n          return _this4.addSyncListener('LinkConfigControl:' + Math.random().toString(36).slice(2, 7), fn);\n        },\n        readState: function readState() {\n          return {\n            url: _this4.url,\n            target: _this4.target,\n            rel: _this4.rel,\n            title: _this4.title,\n            download: _this4.download,\n            ariaLabel: _this4.ariaLabel\n          };\n        }\n      });\n    }\n\n    /**\n     * IconPicker factory — shared by sidebar + ButtonSettingsPopoverOverlay.\n     * Wires a sync listener so programmatic icon changes (preset apply,\n     * popover mutation) visibly update every live instance without each\n     * call-site having to renderElementControls from scratch.\n     */\n  }, {\n    key: \"_buildIconPicker\",\n    value: function _buildIconPicker() {\n      var _this5 = this;\n      var picker = new _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_18__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon.label', 'Icon'), this.icon || '', {\n        setValue: function setValue(name) {\n          return _this5.applyIcon(name || null, _this5.icon_position && _this5.icon_position !== 'none' ? _this5.icon_position : 'left');\n        }\n      });\n      // Silent sync — only patches the trigger glyph + label; does not\n      // re-invoke the callback (which would loop back into applyIcon).\n      var dispose = this.addSyncListener('ButtonIconPicker:' + Math.random().toString(36).slice(2, 7), function () {\n        var next = _this5.icon || '';\n        if (picker.value !== next) {\n          picker.value = next;\n          picker.isCustomOpen = picker._detectCustom(next);\n          if (typeof picker._refreshTrigger === 'function') picker._refreshTrigger();\n        }\n      });\n      var prevDestroy = typeof picker.destroy === 'function' ? picker.destroy.bind(picker) : null;\n      picker.destroy = function () {\n        try {\n          dispose && dispose();\n        } catch (_) {/* no-op */}\n        if (prevDestroy) {\n          try {\n            prevDestroy();\n          } catch (_) {/* no-op */}\n        }\n      };\n      return picker;\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(ButtonElement, \"getData\", this, 3)([])), {}, {\n        text: this.text,\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        ariaLabel: this.ariaLabel,\n        preset_id: this.preset_id,\n        size_key: this.size_key,\n        shadow_key: this.shadow_key,\n        hover_effect: this.hover_effect,\n        icon: this.icon,\n        icon_position: this.icon_position\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value:\n    /**\n     * getControls — 2026-04-19 reorganized into 4 sections matching the\n     * sidebar showcase + design preview:\n     *\n     *   STYLE SETTINGS  → StylePickerControl (compound) + Size + Radius\n     *   EFFECTS         → Shadow + HoverEffect (page-only — banner badge)\n     *   ICON            → IconPicker + IconPosition\n     *   LAYOUT          → Width\n     *   ADVANCED        → text / link / colors / border / padding / font /\n     *                     spacing — every legacy power-user knob lives here\n     *\n     * SectionLabelControl renders divider rows between groups.\n     */\n    function getControls() {\n      var _this6 = this,\n        _this$host;\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          _this6.formatter.setFormat(key, value);\n          _this6.applyFormatStyles();\n        };\n      };\n      // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n      var busOpts = function busOpts(key) {\n        var _this6$host;\n        return {\n          bus: (_this6$host = _this6.host) === null || _this6$host === void 0 ? void 0 : _this6$host.events,\n          elementUid: _this6.id,\n          formatterKey: key\n        };\n      };\n      var sizeOpts = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SIZE_KEYS.map(function (k) {\n        return {\n          value: k,\n          label: k.toUpperCase(),\n          tooltip: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.size.' + k, k.toUpperCase())\n        };\n      });\n      var shadowOpts = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.SHADOW_KEYS.map(function (k) {\n        return {\n          value: k,\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.shadow.' + k, k === 'inner' ? 'Inner' : k.toUpperCase())\n        };\n      });\n      var hoverOpts = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_25__.HOVER_EFFECT_KEYS.map(function (k) {\n        return {\n          value: k,\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.hover.' + k, k.charAt(0).toUpperCase() + k.slice(1))\n        };\n      });\n      var radiusOpts = [{\n        value: 'sharp',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.sharp', 'Sharp')\n      }, {\n        value: 'sm',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.sm', 'SM')\n      }, {\n        value: 'md',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.md', 'MD')\n      }, {\n        value: 'lg',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.lg', 'LG')\n      }, {\n        value: 'pill',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.pill', 'Pill')\n      }];\n      var iconPosOpts = [{\n        value: 'left',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.left', 'Left')\n      }, {\n        value: 'right',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.right', 'Right')\n      }, {\n        value: 'only',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.only', 'Only')\n      }, {\n        value: 'none',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.none', 'None')\n      }];\n      var widthOpts = [{\n        value: 'auto',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.auto', 'Auto')\n      }, {\n        value: 'half',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.half', '50%')\n      }, {\n        value: 'full',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.full', 'Full')\n      }];\n      var controls = [\n      // ═══ STYLE SETTINGS ═══\n      new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.style', 'Style Settings'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.style_desc', 'Preset look, size, shape & modifiers.')), new _StylePickerControl_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.size.label', 'Size'), this.size_key || 'md', function (v) {\n        return _this6.applySize(v);\n      }, sizeOpts, {\n        element: this,\n        readValue: function readValue() {\n          return _this6.size_key || 'md';\n        }\n      }), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.radius.label', 'Radius'), this._currentRadiusKey() || 'md', function (v) {\n        return _this6.applyRadiusKey(v);\n      }, radiusOpts, {\n        element: this,\n        readValue: function readValue() {\n          return _this6._currentRadiusKey() || 'md';\n        }\n      }),\n      // ═══ EFFECTS (page-only) ═══\n      new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.effects', 'Effects'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.effects_desc', 'Depth and micro-interactions. Page mode only.')), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.shadow.label', 'Shadow'), this.shadow_key || 'none', function (v) {\n        return _this6.applyShadow(v);\n      }, shadowOpts, {\n        element: this,\n        readValue: function readValue() {\n          return _this6.shadow_key || 'none';\n        }\n      }), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.hover.label', 'Hover effect'), this.hover_effect || 'none', function (v) {\n        return _this6.applyHoverEffect(v);\n      }, hoverOpts, {\n        element: this,\n        readValue: function readValue() {\n          return _this6.hover_effect || 'none';\n        }\n      }),\n      // ═══ ICON ═══\n      new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.icon', 'Icon'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.icon_desc', 'Optional pictogram beside, before, or instead of the label.')), this._buildIconPicker(), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.icon_pos.label', 'Position'), this.icon_position || 'none', function (v) {\n        return _this6.applyIconPosition(v);\n      }, iconPosOpts, {\n        element: this,\n        readValue: function readValue() {\n          return _this6.icon_position || 'none';\n        }\n      }),\n      // ═══ LAYOUT ═══\n      new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.layout', 'Layout'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.layout_desc', 'Width within the block row.')), new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.width.label', 'Width'), this._currentWidthKey(), function (v) {\n        return _this6.applyWidth(v);\n      }, widthOpts, {\n        element: this,\n        readValue: function readValue() {\n          return _this6._currentWidthKey();\n        }\n      }),\n      // ═══ ADVANCED — every legacy power-user control ═══\n      new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.advanced', 'Advanced'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('button.section.advanced_desc', 'Color, border, padding, font, spacing overrides.')),\n      // Text — inline-edit on canvas is the primary path; this control\n      // is a panel-side fallback. Text change = content mutation,\n      // patch <a> innerHTML directly to preserve identity.\n      new _TextControl_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text'), this.text, {\n        setText: function setText(text) {\n          _this6.text = text;\n          var a = _this6.domNode && _this6.domNode.querySelector('a');\n          var tn = a && a.querySelector('[inline-edit=\"text\"]');\n          if (tn) tn.innerHTML = text;else _this6.render();\n        }\n      }), this.buildLinkControl(), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n        setValue: setFmt('align')\n      }, ['left', 'center', 'right']), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: setFmt('text_color')\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: setFmt('link_color')\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n        setValue: setFmt('text_align')\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: setFmt('paragraph_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: setFmt('line_height')\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: setFmt('letter_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: setFmt('text_direction')\n      }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this6.formatter.setFormat('background_color', values.color);\n          _this6.formatter.setFormat('background_image', values.image);\n          _this6.formatter.setFormat('background_position', values.position);\n          _this6.formatter.setFormat('background_size', values.size);\n          _this6.formatter.setFormat('background_repeat', values.repeat);\n          _this6.applyFormatStyles();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this6.formatter.setFormat('border_top_style', border_top_style);\n          _this6.formatter.setFormat('border_top_width', border_top_width);\n          _this6.formatter.setFormat('border_top_color', border_top_color);\n          _this6.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this6.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this6.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this6.formatter.setFormat('border_left_style', border_left_style);\n          _this6.formatter.setFormat('border_left_width', border_left_width);\n          _this6.formatter.setFormat('border_left_color', border_left_color);\n          _this6.formatter.setFormat('border_right_style', border_right_style);\n          _this6.formatter.setFormat('border_right_width', border_right_width);\n          _this6.formatter.setFormat('border_right_color', border_right_color);\n          _this6.applyFormatStyles();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this6.formatter.setFormat('border_radius', v);\n          _this6.applyFormatStyles();\n        }\n      }), new _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.button_padding'), {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      }, {\n        setValues: function setValues(values) {\n          _this6.formatter.setFormat('padding_top', values.top);\n          _this6.formatter.setFormat('padding_right', values.right);\n          _this6.formatter.setFormat('padding_bottom', values.bottom);\n          _this6.formatter.setFormat('padding_left', values.left);\n          _this6.applyFormatStyles();\n        }\n      })];\n      return controls;\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new ButtonElement(data.template, data.text, data.url);\n      e.target = data.target || '';\n      e.rel = data.rel || '';\n      e.title = data.title || '';\n      e.download = data.download || '';\n      e.ariaLabel = data.ariaLabel || '';\n      // New optional fields — back-compat: missing keys leave defaults\n      if ('preset_id' in data) e.preset_id = data.preset_id || null;\n      if ('size_key' in data) e.size_key = data.size_key || 'md';\n      if ('shadow_key' in data) e.shadow_key = data.shadow_key || 'none';\n      if ('hover_effect' in data) e.hover_effect = data.hover_effect || 'none';\n      if ('icon' in data) e.icon = data.icon || null;\n      if ('icon_position' in data) e.icon_position = data.icon_position || 'none';\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ButtonElement.js?");

/***/ }),

/***/ "./src/includes/ButtonWidget.js":
/*!**************************************!*\
  !*** ./src/includes/ButtonWidget.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar ButtonWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ButtonWidget() {\n    var _this;\n    _classCallCheck(this, ButtonWidget);\n    _this = _callSuper(this, ButtonWidget); // Call the parent class constructor\n\n    // Add a ButtonElement to the widget\n    var button = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Button', 'Click Me');\n\n    // Append the new element to the block\n    _this.block.appendElements([button]);\n    return _this;\n  }\n  _inherits(ButtonWidget, _BaseWidget);\n  return _createClass(ButtonWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.button');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'smart_button';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ButtonWidget.js?");

/***/ }),

/***/ "./src/includes/CellElement.js":
/*!*************************************!*\
  !*** ./src/includes/CellElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\n/* harmony import */ var _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar CellElement = /*#__PURE__*/function (_BaseElement) {\n  function CellElement(template) {\n    var _this;\n    _classCallCheck(this, CellElement);\n    _this = _callSuper(this, CellElement);\n    _this.template = template;\n    _this.blocks = [];\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = [\"blocks\"];\n    _this.Auto = {\n      heightAuto: false,\n      widthAuto: false\n    };\n\n    // Formatter\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"]({\n      width: \"auto\",\n      // display and flex\n      display: null,\n      flex_direction: null,\n      flex: null,\n      gap: null,\n      // background\n      background_color: null,\n      background_image: null,\n      background_position: null,\n      background_size: null,\n      background_repeat: null,\n      background_blend_mode: null,\n      opacity: null,\n      filter: null,\n      // border\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      // border radius\n      border_radius: null,\n      // box shadow\n      box_shadow: null,\n      // padding\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      // margin\n      margin_top: null,\n      margin_right: null,\n      margin_bottom: null,\n      margin_left: null,\n      // size\n      height: null,\n      max_width: null,\n      max_height: null,\n      min_width: null,\n      min_height: null,\n      // additional layout properties\n      justify_content: null,\n      align_items: null\n    });\n    return _this;\n  }\n  _inherits(CellElement, _BaseElement);\n  return _createClass(CellElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.cell');\n    }\n\n    // 2026-04-19 — Cell is hoverable + selectable on canvas. Click on the\n    // cell's padding (anywhere NOT inside an inner block) selects the cell;\n    // top-element rule still gives inner blocks priority for clicks on\n    // their own DOM. See docs/core/OVERLAY.md §7.3 (updated). Same precedent as\n    // PricingCardElement.isHoverable() — selecting the container is a\n    // first-class user intent now that Grid resize/insert affordances live\n    // in the cell-selection overlay set.\n  }, {\n    key: \"isHoverable\",\n    value: function isHoverable() {\n      return true;\n    }\n  }, {\n    key: \"isDroppable\",\n    value: function isDroppable() {\n      return true;\n    }\n\n    // Cell composes its parent Grid's overlays into its own overlay set —\n    // same pattern as getControls() concat(this.container.getControls()).\n    // When the user selects a cell on canvas, the Grid's GridStructureOverlay\n    // + GridColumnResizeOverlay × (n-1) + GridInsertColumnOverlay × (n+1)\n    // all mount, giving full grid editing affordances without forcing the\n    // user to navigate up to the Grid via breadcrumb. Cell itself contributes\n    // no overlays of its own (today) — composition delegates entirely.\n    // Defensive: container may not yet exist for orphaned cells in widget-\n    // construction code paths.\n  }, {\n    key: \"getOverlays\",\n    value: function getOverlays() {\n      var overlays = [];\n\n      // PLAN_EFFECT W3.5 — padding visualiser (trigger 'select'). Always\n      // emit; the overlay self-disposes in afterMount() when host's\n      // usePaddingVisualizer flag is off. Why: getOverlays() runs during\n      // parse — `this.host` is null then, so a flag check here would\n      // always skip. The flag gate moved to PaddingVisualizerOverlay\n      // (commit 4 + 6 of host-injection refactor).\n      overlays.push(new _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](this));\n      if (this.container && typeof this.container.getOverlays === 'function') {\n        overlays.push.apply(overlays, _toConsumableArray(this.container.getOverlays()));\n      }\n      return overlays;\n    }\n\n    /** Host-injection recursion hook — returns this cell's blocks so\n     *  Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n     *  Injection\" lesson. */\n  }, {\n    key: \"getChildren\",\n    value: function getChildren() {\n      return this.blocks || [];\n    }\n\n    /**\n     * In-place style patch — fast path that avoids Cell.render().\n     *\n     * Cell.render() is heavier than Block.render() — it clears child DOMs\n     * and re-appends them, which causes any block-level overlay's\n     * ResizeObserver to see a transient size-0 tick as blocks are\n     * disconnected then re-attached. Keystroke-rate padding changes\n     * AND drag-rate column resize both trigger applyFormatStyles many\n     * times per second; render() each tick produces visible flicker on\n     * the CHILD overlays (NO-FLICKER, SA I9).\n     *\n     * Patches the inline `style` attribute in place by stripping the\n     * declarations this method owns (padding-*, flex) and re-emitting\n     * fresh ones from the formatter. Everything else in the style string\n     * — height, background, border, etc. — is left untouched.\n     *\n     * **CONTRACT:** must cover EVERY declaration the Cell template emits\n     * from formatter values that callers mutate at hot-path rates. Today\n     * that's padding (PaddingMarginControl stepper) + flex (driven by\n     * `width`, mutated by GridColumnResizeOverlay drag). Adding more\n     * hot-path mutations means extending this method — partial coverage\n     * is a silent-failure trap (the formatter changes but the DOM doesn't\n     * update because the fallback `render()` branch in callers never runs\n     * once `applyFormatStyles` exists).\n     *\n     * Width / flex math MUST stay in sync with Cell.template.html — both\n     * read the same `formatter.width` shape (auto / fill / \"N%\" / \"Npx\"\n     * / bare number). The shared helper is `_computeFlexStyle()` below.\n     *\n     * Falls back to render() when domNode is absent (orphaned cell or\n     * pre-initial-render call).\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n\n      // Strip padding-* AND flex declarations. We rebuild both from\n      // formatter state below. min-width is left untouched: the template\n      // emits `min-width: 0` next to flex (always 0, value-agnostic), and\n      // user-set min_width via toStyleStringAll comes later in the string\n      // and would be lost if we stripped it. The fresh `flex: ...; min-\n      // width: 0;` we re-emit is harmless when concatenated after an\n      // existing `min-width: 0` (same value, no cascade conflict).\n      var stripped = (this.domNode.getAttribute('style') || '').replace(/(?:^|;)\\s*padding(?:-top|-right|-bottom|-left)?\\s*:[^;]*;?/gi, ';').replace(/(?:^|;)\\s*flex\\s*:[^;]*;?/gi, ';').replace(/;{2,}/g, ';').replace(/^[;\\s]+|[;\\s]+$/g, '').trim();\n      var f = this.formatter;\n      var padRules = ['top', 'right', 'bottom', 'left'].map(function (side) {\n        var v = f.getFormat(\"padding_\".concat(side));\n        if (v === null || v === undefined || v === '') return '';\n        var val = typeof v === 'number' || /^-?\\d+(\\.\\d+)?$/.test(String(v)) ? \"\".concat(v, \"px\") : v;\n        return \"padding-\".concat(side, \": \").concat(val, \";\");\n      }).filter(Boolean).join(' ');\n      var flexRule = this._computeFlexStyle();\n      var parts = [stripped, flexRule, padRules].filter(Boolean);\n      this.domNode.setAttribute('style', parts.join('; ').trim());\n    }\n\n    /**\n     * Compute the `flex: ...; min-width: 0;` declaration (or empty string\n     * for content-sized cells) from the formatter's `width` value.\n     *\n     * **MUST stay in sync with Cell.template.html width branch.** Both\n     * code paths consume the same `formatter.width` shape — auto / fill /\n     * \"N%\" / \"Npx|em|rem|vw|vh|ch|ex\" / bare number. Any change to one\n     * MUST be mirrored in the other. The template runs at full-render\n     * time; this helper runs at applyFormatStyles fast-path time. Two\n     * call sites, one truth.\n     */\n  }, {\n    key: \"_computeFlexStyle\",\n    value: function _computeFlexStyle() {\n      var width = this.formatter.getFormat('width', 'auto');\n      if (width === 'auto' || width === null || width === undefined || width === '') {\n        return '';\n      }\n      if (width === 'fill') {\n        return 'flex: 1 1 0; min-width: 0;';\n      }\n      var str = String(width).trim();\n      if (/%$/.test(str)) {\n        var pct = parseFloat(str);\n        if (!isNaN(pct) && pct > 0) {\n          var gap = this.container && typeof this.container.cell_gap === 'number' ? this.container.cell_gap : 0;\n          var count = this.container && Array.isArray(this.container.cells) ? this.container.cells.length : 1;\n          if (gap > 0 && count > 1) {\n            var gapShare = gap * (count - 1) / count;\n            return \"flex: 0 0 calc(\".concat(pct, \"% - \").concat(gapShare, \"px); min-width: 0;\");\n          }\n          return \"flex: 0 0 \".concat(pct, \"%; min-width: 0;\");\n        }\n        return 'flex: 1 1 0; min-width: 0;';\n      }\n      if (/(px|em|rem|vw|vh|ch|ex)$/i.test(str)) {\n        return \"flex: 0 0 \".concat(str, \"; min-width: 0;\");\n      }\n      var numWidth = parseFloat(str);\n      if (!isNaN(numWidth) && numWidth > 0) {\n        return \"flex: \".concat(numWidth, \" 1 0; min-width: 0;\");\n      }\n      return 'flex: 1 1 0; min-width: 0;';\n    }\n  }, {\n    key: \"canDropInside\",\n    value: function canDropInside() {\n      // ─────────────────────────────────────────────────────────────────\n      // RULE: drop-inside is allowed on a CellElement ONLY when it's empty.\n      // ─────────────────────────────────────────────────────────────────\n      //\n      // Same rule as PageElement.canDropInside() — see that method for the\n      // full rationale. Short version:\n      //\n      //   • Empty cell  → drop-inside is allowed (whole cell highlights, the\n      //                   block becomes the first child of the cell).\n      //   • Non-empty cell → drop-inside is DISABLED. The user must hover an\n      //                   existing block inside the cell and drop above/below\n      //                   it. This makes the landing position unambiguous and\n      //                   prevents the \"whole cell lights up but the block\n      //                   silently lands at the bottom\" UX bug.\n      //\n      // Cells are special because they live inside a GridElement and the user\n      // already has a hard time telling cells apart from the grid. A\n      // misleading highlight here is even worse than on the page. The rule\n      // must stay symmetrical with PageElement so the two containers behave\n      // identically from the user's point of view.\n      //\n      // Regression tests: e2e/drop-inside-empty-only.spec.js\n      return this.blocks.length === 0;\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      var _this2 = this;\n      // reset domNode\n      while (this.domNode.firstChild) {\n        this.domNode.removeChild(this.domNode.firstChild);\n      }\n\n      // Thread parent-grid context into the template so the percent-width branch can\n      // subtract the proportional share of `gap` from each cell's `flex-basis`. Without\n      // this, two 50%-cells inside a Grid with `cell_gap: 20` overflow the canvas by\n      // 20px (2×50% + 20px > 100%). With it, flex-basis becomes `calc(50% - 10px)`\n      // so the cells share the gap evenly and the total lands at exactly 100%.\n      var parentGap = this.container && typeof this.container.cell_gap === \"number\" ? this.container.cell_gap : 0;\n      var parentCellCount = this.container && Array.isArray(this.container.cells) ? this.container.cells.length : 1;\n\n      // 2026-04-18 refactor — drop the block-anchor text-placeholder pattern\n      // for the same reason as GridElement: a failed-replacement leaves the\n      // raw block ID (\"_xxxxxxxxx\") visible on canvas. Render the cell\n      // wrapper EMPTY, then DOM-append each block's domNode directly.\n      // formatter auto-merged (W0.2c)\n      var html = this.renderTemplate({\n        blocks: [],\n        vertical_align: this.vertical_align,\n        cell_gap: parentGap,\n        cell_count: parentCellCount\n      });\n      var temp = document.createElement(\"div\");\n      temp.innerHTML = html;\n      var parsedDiv = temp.firstElementChild;\n      var _iterator = _createForOfIteratorHelper(parsedDiv.attributes),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var attr = _step.value;\n          this.domNode.setAttribute(attr.name, attr.value);\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n      this.domNode.innerHTML = parsedDiv.innerHTML;\n      this.blocks.forEach(function (block) {\n        var blockDom = block.render();\n        _this2.domNode.appendChild(blockDom);\n        _this2.host.uiManager.addElement(block);\n      });\n\n      // empty cell — delegate visual to renderEmptyPlaceholder() so subclasses\n      // (e.g. FormContainerCell) can override the placeholder without copying\n      // the whole _doRender() method.\n      if (this.blocks.length == 0) {\n        this.domNode.innerHTML = this.renderEmptyPlaceholder();\n      }\n    }\n\n    // Override point for subclasses. Default = \"empty gallery\" SVG icon on\n    // a subtle dashed background — signals \"drop blocks here\" in generic\n    // cells. Subclasses that want a domain-specific empty state (form,\n    // pricing, etc.) override this to change only the visual.\n  }, {\n    key: \"renderEmptyPlaceholder\",\n    value: function renderEmptyPlaceholder() {\n      return \"\\n            <div style=\\\"display: flex;\\n                align-items: center;\\n                justify-content: center;\\n                height: 100%;\\n                min-height: 100px;\\n                background-color: rgba(34,83,159,0.05);\\n                border: dashed 1px rgba(120, 130, 150, 0.5);\\n                \\\">\\n                <svg style=\\\"width: 100px;\\n                    display: inline-block;\\n                    margin: auto;\\n                    opacity: 1;\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"48px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"48px\\\" fill=\\\"#808080\\\"><path d=\\\"M345-285q-24 0-42-18t-18-42v-435q0-24 18-42t42-18h435q24 0 42 18t18 42v435q0 24-18 42t-42 18H345Zm0-60h435v-435H345v435ZM149.82-615q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Z\\\"/></svg>\\n\\n            </div>\\n        \";\n    }\n  }, {\n    key: \"appendBlock\",\n    value: function appendBlock(block) {\n      // private\n      // set container\n      block.container = this;\n\n      // Host injection — adopt before insert. No-op when this cell isn't\n      // yet adopted; the outer `_adopt` walk reaches it via getChildren().\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(block);\n      }\n      this.blocks.push(block);\n      // Surgical DOM mount when this cell is live. Parse-path callers\n      // (CellElement.parse + parent's parse cascade) run BEFORE the\n      // owning Page renders, so domNode is null → no-op. The full\n      // _doRender path mounts everything after parse.\n      this._mountChildBlockDom(block, {\n        append: true\n      });\n    }\n  }, {\n    key: \"addBlockAfter\",\n    value: function addBlockAfter(newBlock, referenceBlock) {\n      // set container\n      newBlock.container = this;\n      var index = this.blocks.indexOf(referenceBlock);\n      if (index === -1) {\n        throw new Error(\"Reference block not found\");\n      }\n      this.blocks.splice(index + 1, 0, newBlock);\n      this._mountChildBlockDom(newBlock, {\n        afterDomNode: referenceBlock.domNode\n      });\n    }\n  }, {\n    key: \"addBlockBefore\",\n    value: function addBlockBefore(newBlock, referenceBlock) {\n      // set container\n      newBlock.container = this;\n      var index = this.blocks.indexOf(referenceBlock);\n      if (index === -1) {\n        throw new Error(\"Reference block not found\");\n      }\n      this.blocks.splice(index, 0, newBlock);\n      this._mountChildBlockDom(newBlock, {\n        beforeDomNode: referenceBlock.domNode\n      });\n    }\n\n    /**\n     * Surgical mount + empty-placeholder swap. Same contract as\n     * PageElement._mountBlockDom but scoped to the Cell's child wrapper.\n     * Pre-fix the host called `cell.render()` after every add/remove,\n     * which churned every sibling block; see BlockElement.removeElement\n     * + PageElement.removeElement notes for the cascade-bug rationale.\n     */\n  }, {\n    key: \"_mountChildBlockDom\",\n    value: function _mountChildBlockDom(block, position) {\n      if (!this.domNode) return;\n      // Strip any inline empty-state placeholder before the first real\n      // mount. The placeholder lives directly inside `this.domNode`.\n      if (this.blocks.length === 1) {\n        this.domNode.innerHTML = \"\"; // wipe placeholder\n      }\n      var rendered = block.render();\n      if (position && position.afterDomNode && position.afterDomNode.parentNode === this.domNode) {\n        this.domNode.insertBefore(rendered, position.afterDomNode.nextSibling);\n      } else if (position && position.beforeDomNode && position.beforeDomNode.parentNode === this.domNode) {\n        this.domNode.insertBefore(rendered, position.beforeDomNode);\n      } else {\n        this.domNode.appendChild(rendered);\n      }\n      if (this.host && this.host.uiManager) {\n        this.host.uiManager.addElement(block);\n      }\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(CellElement, \"getData\", this, 3)([])), {}, {\n        blocks: this.blocks.map(function (block) {\n          return block.getData();\n        }),\n        vertical_align: this.vertical_align\n      });\n    }\n  }, {\n    key: \"removeElement\",\n    value: function removeElement(element) {\n      var idx = this.blocks.indexOf(element);\n      if (idx === -1) return;\n      this.blocks.splice(idx, 1);\n      if (element.domNode && element.domNode.parentNode) {\n        element.domNode.remove();\n      }\n\n      // Empty-state — drop the inline placeholder. Reuses the same\n      // markup that _doRender emits when blocks.length === 0.\n      if (this.blocks.length === 0 && this.domNode) {\n        this.domNode.innerHTML = this.renderEmptyPlaceholder();\n      }\n    }\n  }, {\n    key: \"isAutoFormat\",\n    value: function isAutoFormat(key) {\n      var value = this.formatter.getFormat(key);\n      return value === null || value === undefined || value === '' || value === 'auto';\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this3 = this;\n      var cellControls = [\n      // BackgroundControl renders its own CELL BACKGROUND header — no\n      // extra SectionLabelControl needed here (would duplicate).\n      new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_background'), {\n        color: this.formatter.getFormat('background_color', '#ffffff'),\n        image: this.formatter.getFormat('background_image', ''),\n        position: this.formatter.getFormat('background_position', 'center'),\n        size: this.formatter.getFormat('background_size', '100'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n        blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n        opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n        filter: this.formatter.getFormat('filter', '')\n      }, {\n        setBackground: function setBackground(values) {\n          _this3.formatter.setFormat('background_color', values.color);\n          _this3.formatter.setFormat('background_image', values.image);\n          _this3.formatter.setFormat('background_position', values.position);\n          _this3.formatter.setFormat('background_size', values.size);\n          _this3.formatter.setFormat('background_repeat', values.repeat);\n          _this3.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n          _this3.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n          _this3.formatter.setFormat('filter', values.filter || null);\n          _this3.render();\n        }\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_border'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this3.formatter.setFormat('border_top_style', border_top_style);\n          _this3.formatter.setFormat('border_top_width', border_top_width);\n          _this3.formatter.setFormat('border_top_color', border_top_color);\n          _this3.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this3.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this3.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this3.formatter.setFormat('border_left_style', border_left_style);\n          _this3.formatter.setFormat('border_left_width', border_left_width);\n          _this3.formatter.setFormat('border_left_color', border_left_color);\n          _this3.formatter.setFormat('border_right_style', border_right_style);\n          _this3.formatter.setFormat('border_right_width', border_right_width);\n          _this3.formatter.setFormat('border_right_color', border_right_color);\n          _this3.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(value) {\n          _this3.formatter.setFormat('border_radius', value);\n          _this3.render();\n        }\n      }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_padding'), {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      }, {\n        setValues: function setValues(values) {\n          _this3.formatter.setFormat('padding_top', values.top);\n          _this3.formatter.setFormat('padding_right', values.right);\n          _this3.formatter.setFormat('padding_bottom', values.bottom);\n          _this3.formatter.setFormat('padding_left', values.left);\n          // PLAN_EFFECT W3.5 — in-place patch; keeps child block\n          // overlays anchored without the render() strip+re-append\n          // cycle that caused flicker.\n          _this3.applyFormatStyles();\n        }\n      },\n      // Host-injection — PaddingMarginControl reads bus + pinSet\n      // directly off `this.host` set by Builder.renderElementControls.\n      // No prop-drilling needed.\n      {\n        elementUid: this.id\n      }), new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_height'), this.formatter.getFormat('height', 'auto'), {\n        units: ['px', '%', 'em', 'rem', 'vh', 'auto'],\n        onChange: function onChange(value) {\n          _this3.formatter.setFormat('height', value === null ? null : value);\n          _this3.render();\n        }\n      }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.display'), this.formatter.getFormat('display') || '', [{\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n        value: ''\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.block'),\n        value: 'block'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.flex'),\n        value: 'flex'\n      }], function (value) {\n        _this3.formatter.setFormat('display', value || null);\n        _this3.render();\n      }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.direction'), this.formatter.getFormat('flex_direction') || '', [{\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n        value: ''\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.row'),\n        value: 'row'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.column'),\n        value: 'column'\n      }], function (value) {\n        _this3.formatter.setFormat('flex_direction', value || null);\n        _this3.render();\n      }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.justify'), this.formatter.getFormat('justify_content') || '', [{\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n        value: ''\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.start'),\n        value: 'flex-start'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.center'),\n        value: 'center'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.end'),\n        value: 'flex-end'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.space_between'),\n        value: 'space-between'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.space_around'),\n        value: 'space-around'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.space_evenly'),\n        value: 'space-evenly'\n      }], function (value) {\n        _this3.formatter.setFormat('justify_content', value || null);\n        _this3.render();\n      }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.align_items'), this.formatter.getFormat('align_items') || '', [{\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.default'),\n        value: ''\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.stretch'),\n        value: 'stretch'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.start'),\n        value: 'flex-start'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.center'),\n        value: 'center'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.end'),\n        value: 'flex-end'\n      }], function (value) {\n        _this3.formatter.setFormat('align_items', value || null);\n        _this3.render();\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.content_gap'), this.formatter.getFormat('gap', 0), {\n        setValue: function setValue(value) {\n          _this3.formatter.setFormat('gap', value);\n          _this3.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 400,\n        suffix: 'px',\n        allowZero: true\n      }),\n      // Explicit separator before the inherited Grid-level controls so\n      // users notice the transition from \"this cell\" to \"the whole grid\".\n      new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.parent_grid'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.parent_grid_desc'))];\n      var gridControls = this.container.getControls();\n      return cellControls.concat(gridControls);\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var cell = new this(data.template);\n      var blocks = Array.isArray(data.blocks) ? data.blocks : [];\n      blocks.forEach(function (blockData) {\n        var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"].createElement(blockData);\n        block.container = cell;\n        cell.appendBlock(block);\n      });\n      cell.vertical_align = data.vertical_align || \"top\";\n      return this.parseFormats(cell, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CellElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CellElement.js?");

/***/ }),

/***/ "./src/includes/CheckboxControl.js":
/*!*****************************************!*\
  !*** ./src/includes/CheckboxControl.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * CheckboxControl — labeled boolean toggle.\n *\n * 2026-04-18 (Phase 2.24) rewrite — drops `.builder-checkbox-modern`\n * + `.toggle-label` legacy pair and Bootstrap utility classes. Uses\n * the shared `.bjs-toggle` primitive.\n */\nvar CheckboxControl = /*#__PURE__*/function () {\n  function CheckboxControl(label, description, value, callback) {\n    _classCallCheck(this, CheckboxControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.description = description;\n    this.value = value;\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-checkbox-control');\n    this.render();\n  }\n  return _createClass(CheckboxControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row bjs-checkbox-control-row\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"checkbox_\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label>\\n                    \").concat(this.description ? \"<span class=\\\"bjs-control-description\\\">\".concat(this.description, \"</span>\") : '', \"\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <label class=\\\"bjs-toggle\\\">\\n                        <input id=\\\"checkbox_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" \").concat(this.value ? 'checked' : '', \">\\n                        <span class=\\\"bjs-toggle-track\\\"></span>\\n                        <span class=\\\"bjs-toggle-thumb\\\"></span>\\n                    </label>\\n                </div>\\n            </div>\\n        \");\n      var checkbox = this.domNode.querySelector(\"#checkbox_\".concat(this.id));\n      checkbox.addEventListener('change', function (e) {\n        _this.value = e.target.checked;\n        if (typeof _this.callback === 'function') _this.callback(_this.value);\n      });\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      var checkbox = this.domNode.querySelector(\"#checkbox_\".concat(this.id));\n      if (checkbox) {\n        checkbox.checked = this.value;\n        if (typeof this.callback === 'function') this.callback(this.value);\n      }\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckboxControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckboxControl.js?");

/***/ }),

/***/ "./src/includes/CheckboxElement.js":
/*!*****************************************!*\
  !*** ./src/includes/CheckboxElement.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectControl.js */ \"./src/includes/SelectControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckboxElement = /*#__PURE__*/function (_BaseElement) {\n  function CheckboxElement(template) {\n    var _this;\n    var inputName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n    var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];\n    _classCallCheck(this, CheckboxElement);\n    _this = _callSuper(this, CheckboxElement);\n    _this.template = template;\n    _this.inputName = inputName;\n    _this.items = _this.normalizeItems(items);\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['items'];\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({});\n    return _this;\n  }\n  _inherits(CheckboxElement, _BaseElement);\n  return _createClass(CheckboxElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.checkbox');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        items: this.items,\n        inputName: this.inputName\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(CheckboxElement, \"getData\", this, 3)([])), {}, {\n        inputName: this.inputName,\n        items: this.items\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [new _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.checkbox_options'), this.items.map(function (item) {\n        return {\n          label: item.label,\n          value: item.value\n        };\n      }), {\n        setItems: function setItems(items) {\n          _this2.items = _this2.normalizeItems(items);\n          _this2.render();\n        },\n        setName: function setName(name) {\n          _this2.inputName = name;\n          _this2.render();\n        }\n      }, this.inputName)];\n    }\n  }, {\n    key: \"normalizeItems\",\n    value: function normalizeItems(items) {\n      return (Array.isArray(items) ? items : []).map(function (item, index) {\n        var _item$label, _item$value;\n        return {\n          label: (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : \"Option \".concat(index + 1),\n          value: (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : \"option_\".concat(index + 1)\n        };\n      });\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.inputName || \"\", data.items || []), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckboxElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckboxElement.js?");

/***/ }),

/***/ "./src/includes/CheckboxWidget.js":
/*!****************************************!*\
  !*** ./src/includes/CheckboxWidget.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _CheckboxElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./CheckboxElement.js */ \"./src/includes/CheckboxElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar CheckboxWidget = /*#__PURE__*/function (_BaseWidget) {\n  function CheckboxWidget() {\n    var _this;\n    _classCallCheck(this, CheckboxWidget);\n    _this = _callSuper(this, CheckboxWidget);\n    _this.block.appendElements([new _CheckboxElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Checkbox', 'interests', [{\n      label: 'Product updates',\n      value: 'product_updates'\n    }, {\n      label: 'Events',\n      value: 'events'\n    }, {\n      label: 'Promotions',\n      value: 'promotions'\n    }])]);\n    return _this;\n  }\n  _inherits(CheckboxWidget, _BaseWidget);\n  return _createClass(CheckboxWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.checkbox');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'check_box';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckboxWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckboxWidget.js?");

/***/ }),

/***/ "./src/includes/CheckoutControl.js":
/*!*****************************************!*\
  !*** ./src/includes/CheckoutControl.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar CheckoutControl = /*#__PURE__*/function () {\n  function CheckoutControl() {\n    var values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n    var callbacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, CheckoutControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.values = values;\n    this.callbacks = callbacks;\n\n    // Create the main container element. Initial render is deferred\n    // to afterRender() so this.host is available — Builder assigns\n    // host AFTER getControls() returns and BEFORE afterRender().\n    this.domNode = document.createElement(\"div\");\n  }\n\n  /** Builder hook — fires after host injection + DOM mount. Safe entry\n   *  point for the first render that depends on `this.host`. */\n  return _createClass(CheckoutControl, [{\n    key: \"afterRender\",\n    value: function afterRender() {\n      this.render();\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      this.domNode.innerHTML = this.host.renderTemplate('CheckoutControl', {\n        id: this.id,\n        values: this.values\n      });\n      this.attachEvents();\n    }\n  }, {\n    key: \"attachEvents\",\n    value: function attachEvents() {\n      var _this = this;\n      var inputs = this.domNode.querySelectorAll('[data-path]');\n      inputs.forEach(function (input) {\n        var update = function update() {\n          var path = input.getAttribute('data-path');\n          var value = input.type === 'checkbox' ? input.checked : input.value;\n          _this.setValue(path, value);\n\n          /* Color chip: reflect picked value on the parent .bjs-checkout-color-chip\n             via --bjs-color-current so the preview updates live during the native\n             color picker session, before the element re-renders. */\n          if (input.type === 'color') {\n            var chip = input.closest('.bjs-checkout-color-chip');\n            if (chip) chip.style.setProperty('--bjs-color-current', value);\n          }\n        };\n        input.addEventListener('input', update);\n        input.addEventListener('change', update);\n      });\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(path, value) {\n      this.setValueByPath(this.values, path, value);\n      if (this.callbacks && typeof this.callbacks.update === 'function') {\n        this.callbacks.update(path, value, this.values);\n      }\n    }\n  }, {\n    key: \"setValueByPath\",\n    value: function setValueByPath(obj, path, value) {\n      if (!path) {\n        return;\n      }\n      var segments = path.split('.');\n      var cursor = obj;\n      segments.forEach(function (segment, index) {\n        if (index === segments.length - 1) {\n          cursor[segment] = value;\n        } else {\n          if (!cursor[segment] || _typeof(cursor[segment]) !== 'object') {\n            cursor[segment] = {};\n          }\n          cursor = cursor[segment];\n        }\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutControl.js?");

/***/ }),

/***/ "./src/includes/CheckoutElement.js":
/*!*****************************************!*\
  !*** ./src/includes/CheckoutElement.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _CheckoutControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./CheckoutControl.js */ \"./src/includes/CheckoutControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutElement = /*#__PURE__*/function (_BaseElement) {\n  function CheckoutElement(template, action, method) {\n    var _this;\n    _classCallCheck(this, CheckoutElement);\n    _this = _callSuper(this, CheckoutElement);\n    _this.template = template;\n    _this.action = action || '';\n    _this.method = method || '';\n    _this.domNode = null;\n\n    // text + label values that drive the checkout template\n    _this.values = _this.getDefaultValues();\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = [];\n\n    // W0.2b — no inline-edit registrations (CheckoutElement renders a\n    // multi-section form, not a single editable text). The base class\n    // _wireInlineEdit() short-circuits cleanly when the registry is empty.\n\n    // Formatter - Bootstrap button default styles\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      // \n    });\n    return _this;\n  }\n  _inherits(CheckoutElement, _BaseElement);\n  return _createClass(CheckoutElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.checkout');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c). W0.2b: legacy applyInlineEdit()\n      // removed; the new framework (auto-fired _wireInlineEdit from\n      // afterRender) is a no-op when the registry is empty.\n      this.domNode.innerHTML = this.renderTemplate({\n        action: this.action,\n        method: this.method,\n        values: this.values\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(CheckoutElement, \"getData\", this, 3)([])), {}, {\n        action: this.action,\n        method: this.method,\n        values: this.values\n      });\n    }\n  }, {\n    key: \"getDefaultValues\",\n    value: function getDefaultValues() {\n      return {\n        ui: {\n          previewLabel: 'Checkout Preview',\n          modeLabel: 'Guest Checkout'\n        },\n        headerTitle: 'Checkout Form',\n        buttonTexts: {\n          guestSubmit: 'Complete Order',\n          saved: 'Rush My Order!',\n          upgrade: 'Update My Order!',\n          submitting: 'Submitting...'\n        },\n        headlines: {\n          contact: 'CONTACT INFORMATION',\n          billing: 'BILLING INFORMATION',\n          payment: 'PAYMENT INFORMATION',\n          privacy: 'We Never Share Your Information With Anyone'\n        },\n        contactLabels: {\n          firstName: 'First Name',\n          lastName: 'Last Name',\n          email: 'Email',\n          phone: 'Phone Number',\n          address: 'Address',\n          apartment: 'Apartment, building, floor',\n          apartmentOptional: '(optional)',\n          country: 'Country',\n          state: 'State',\n          city: 'City',\n          postal: 'Postal Code'\n        },\n        defaults: {\n          country: 'Vietnam',\n          state: 'An Giang'\n        },\n        paymentSummary: {\n          title: 'Summary',\n          cta: 'For more details, fill the form'\n        }\n      };\n    }\n  }, {\n    key: \"mergeDeep\",\n    value: function mergeDeep(target, source) {\n      var _this2 = this;\n      var output = target || {};\n      if (_typeof(target) !== 'object' || target === null) {\n        return source;\n      }\n      if (_typeof(source) !== 'object' || source === null) {\n        return target;\n      }\n      Object.keys(source).forEach(function (key) {\n        if (Array.isArray(source[key])) {\n          output[key] = source[key].slice();\n        } else if (_typeof(source[key]) === 'object') {\n          output[key] = _this2.mergeDeep(target[key] || {}, source[key]);\n        } else {\n          output[key] = source[key];\n        }\n      });\n      return output;\n    }\n  }, {\n    key: \"setValueByPath\",\n    value: function setValueByPath(obj, path, value) {\n      if (!path) {\n        return;\n      }\n      var segments = path.split('.');\n      var current = obj;\n      segments.forEach(function (segment, index) {\n        if (index === segments.length - 1) {\n          current[segment] = value;\n        } else {\n          if (!current[segment] || _typeof(current[segment]) !== 'object') {\n            current[segment] = {};\n          }\n          current = current[segment];\n        }\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this3 = this;\n      return [\n      // TextControl\n      new TextControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.action_url'),\n      // value\n      this.action,\n      // callback\n      {\n        // set name\n        setText: function setText(action) {\n          _this3.action = action;\n          _this3.render();\n        }\n      }),\n      // TextControl\n      new TextControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.method'),\n      // value\n      this.method,\n      // callback\n      {\n        // set name\n        setText: function setText(method) {\n          _this3.method = method;\n          _this3.render();\n        }\n      }), new _CheckoutControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this.values, {\n        update: function update(path, value) {\n          _this3.setValueByPath(_this3.values, path, value);\n          _this3.render();\n        }\n      })\n\n      // new AlignControl(\n      //     'Alignment',\n      //     this.formatter.getFormat('align'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('align', value);\n      //             this.render();\n      //         }\n      //     },\n      //     ['left', 'center', 'right']\n      // ),\n\n      // new FontFamilyControl(\n      //     'Font Family',\n      //     this.formatter.getFormat('font_family'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('font_family', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new FontWeightControl(\n      //     'Font Weight',\n      //     this.formatter.getFormat('font_weight'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('font_weight', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new NumberControl(\n      //     'Font Size',\n      //     this.formatter.getFormat('font_size'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('font_size', value);\n      //             this.render();\n      //         }\n      //     },\n      //     {\n      //         defaultValue: 16,\n      //         minValue: 8,\n      //         maxValue: 72,\n      //         suffix: 'px',\n      //         allowZero: false\n      //     }\n      // ),\n\n      // new ColorPickerControl(\n      //     'Text Color',\n      //     this.formatter.getFormat('text_color'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('text_color', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new ColorPickerControl(\n      //     'Link Color',\n      //     this.formatter.getFormat('link_color'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('link_color', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new AlignControl(\n      //     'Text alignment',\n      //     this.formatter.getFormat('text_align'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('text_align', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new NumberControl(\n      //     'Paragraph Spacing',\n      //     this.formatter.getFormat('paragraph_spacing'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('paragraph_spacing', value);\n      //             this.render();\n      //         }\n      //     },\n      //     {\n      //         defaultValue: 0,\n      //         minValue: 0,\n      //         maxValue: 50,\n      //         suffix: 'px',\n      //         allowZero: true\n      //     }\n      // ),\n\n      // new LineHeightControl(\n      //     'Line Height',\n      //     this.formatter.getFormat('line_height'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('line_height', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new NumberControl(\n      //     'Letter Spacing',\n      //     this.formatter.getFormat('letter_spacing'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('letter_spacing', value);\n      //             this.render();\n      //         }\n      //     },\n      //     {\n      //         defaultValue: 0,\n      //         minValue: -5,\n      //         maxValue: 10,\n      //         step: 0.1,\n      //         suffix: 'px',\n      //         allowZero: true,\n      //         allowNegative: true\n      //     }\n      // ),\n      // new TextDirectionControl(\n      //     'Text Direction',\n      //     this.formatter.getFormat('text_direction'),\n      //     {\n      //         setValue: (value) => {\n      //             this.formatter.setFormat('text_direction', value);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new BackgroundControl(\n      //     // label\n      //     'Background Settings',\n      //     // values\n      //     {\n      //         color: this.formatter.getFormat('background_color'),\n      //         image: this.formatter.getFormat('background_image'),\n      //         position: this.formatter.getFormat('background_position'),\n      //         size: this.formatter.getFormat('background_size').toString().replace('%', ''),\n      //         toRepeat: this.formatter.getFormat('background_repeat') === 'repeat'\n      //     },\n      //     // callback\n      //     {\n      //         setBackground: (values) => {\n      //             this.formatter.setFormat('background_color', values.color);\n      //             this.formatter.setFormat('background_image', values.image);\n      //             this.formatter.setFormat('background_position', values.position);\n      //             this.formatter.setFormat('background_size', parseInt(values.size, 10) || 100);\n      //             this.formatter.setFormat('background_repeat', values.toRepeat ? 'repeat' : 'no-repeat');\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new BorderControl(\n      //     'Border Settings',\n\n      //     {\n      //         border_top_style: this.formatter.getFormat('border_top_style'),\n      //         border_top_width: this.formatter.getFormat('border_top_width'),\n      //         border_top_color: this.formatter.getFormat('border_top_color'),\n      //         border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n      //         border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n      //         border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n      //         border_left_style: this.formatter.getFormat('border_left_style'),\n      //         border_left_width: this.formatter.getFormat('border_left_width'),\n      //         border_left_color: this.formatter.getFormat('border_left_color'),\n      //         border_right_style: this.formatter.getFormat('border_right_style'),\n      //         border_right_width: this.formatter.getFormat('border_right_width'),\n      //         border_right_color: this.formatter.getFormat('border_right_color'),\n      //     },\n\n      //     {\n      //         setBorder: (\n      //             border_top_style, border_top_width, border_top_color,\n      //             border_bottom_style, border_bottom_width, border_bottom_color,\n      //             border_left_style, border_left_width, border_left_color,\n      //             border_right_style, border_right_width, border_right_color\n      //         ) => {\n      //             this.formatter.setFormat('border_top_style', border_top_style);\n      //             this.formatter.setFormat('border_top_width', border_top_width);\n      //             this.formatter.setFormat('border_top_color', border_top_color);\n\n      //             this.formatter.setFormat('border_bottom_style', border_bottom_style);\n      //             this.formatter.setFormat('border_bottom_width', border_bottom_width);\n      //             this.formatter.setFormat('border_bottom_color', border_bottom_color);\n\n      //             this.formatter.setFormat('border_left_style', border_left_style);\n      //             this.formatter.setFormat('border_left_width', border_left_width);\n      //             this.formatter.setFormat('border_left_color', border_left_color);\n\n      //             this.formatter.setFormat('border_right_style', border_right_style);\n      //             this.formatter.setFormat('border_right_width', border_right_width);\n      //             this.formatter.setFormat('border_right_color', border_right_color);\n\n      //             // re-render\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new BorderRadiusControl(\n      //     'Radius',\n      //     this.formatter.getFormat('border_radius'),\n      //     {\n      //         setRadius: (v) => {\n      //             this.formatter.setFormat('border_radius', v);\n      //             this.render();\n      //         }\n      //     }\n      // ),\n\n      // new PaddingMarginControl(\n      //     // label\n      //     'Padding',\n      //     // value\n      //     {\n      //         top: this.formatter.getFormat('padding_top'),\n      //         right: this.formatter.getFormat('padding_right'),\n      //         bottom: this.formatter.getFormat('padding_bottom'),\n      //         left: this.formatter.getFormat('padding_left'),\n      //     },\n      //     // callback\n      //     {\n      //         setValues: (values) => {\n      //             this.formatter.setFormat('padding_top', values.top);\n      //             this.formatter.setFormat('padding_right', values.right);\n      //             this.formatter.setFormat('padding_bottom', values.bottom);\n      //             this.formatter.setFormat('padding_left', values.left);\n\n      //             this.render();\n      //         }\n      //     }\n      // ),\n      ];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new this(data.template, data.action, data.method);\n      // merge stored values with defaults to keep compatibility\n      if (data.values) {\n        e.values = e.mergeDeep(e.getDefaultValues(), data.values);\n      }\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutElement.js?");

/***/ }),

/***/ "./src/includes/CheckoutSimpleControl.js":
/*!***********************************************!*\
  !*** ./src/includes/CheckoutSimpleControl.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar CheckoutSimpleControl = /*#__PURE__*/function () {\n  function CheckoutSimpleControl() {\n    var values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n    var callbacks = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, CheckoutSimpleControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.values = values;\n    this.callbacks = callbacks;\n\n    // Create the main container element. Initial render is deferred\n    // to afterRender() so this.host is available — Builder assigns\n    // host AFTER getControls() returns and BEFORE afterRender().\n    this.domNode = document.createElement(\"div\");\n  }\n\n  /** Builder hook — fires after host injection + DOM mount. Safe entry\n   *  point for the first render that depends on `this.host`. */\n  return _createClass(CheckoutSimpleControl, [{\n    key: \"afterRender\",\n    value: function afterRender() {\n      this.render();\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      this.domNode.innerHTML = this.host.renderTemplate('CheckoutSimpleControl', {\n        id: this.id,\n        values: this.values\n      });\n      this.attachEvents();\n    }\n  }, {\n    key: \"attachEvents\",\n    value: function attachEvents() {\n      var _this = this;\n      var inputs = this.domNode.querySelectorAll('[data-path]');\n      inputs.forEach(function (input) {\n        var update = function update() {\n          var path = input.getAttribute('data-path');\n          var value = input.type === 'checkbox' ? input.checked : input.value;\n          _this.setValue(path, value);\n        };\n        input.addEventListener('input', update);\n        input.addEventListener('change', update);\n      });\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(path, value) {\n      this.setValueByPath(this.values, path, value);\n      if (this.callbacks && typeof this.callbacks.update === 'function') {\n        this.callbacks.update(path, value, this.values);\n      }\n    }\n  }, {\n    key: \"setValueByPath\",\n    value: function setValueByPath(obj, path, value) {\n      if (!path) {\n        return;\n      }\n      var segments = path.split('.');\n      var cursor = obj;\n      segments.forEach(function (segment, index) {\n        if (index === segments.length - 1) {\n          cursor[segment] = value;\n        } else {\n          if (!cursor[segment] || _typeof(cursor[segment]) !== 'object') {\n            cursor[segment] = {};\n          }\n          cursor = cursor[segment];\n        }\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutSimpleControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutSimpleControl.js?");

/***/ }),

/***/ "./src/includes/CheckoutSimpleElement.js":
/*!***********************************************!*\
  !*** ./src/includes/CheckoutSimpleElement.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./CheckoutSimpleControl.js */ \"./src/includes/CheckoutSimpleControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutSimpleElement = /*#__PURE__*/function (_BaseElement) {\n  function CheckoutSimpleElement(template) {\n    var _this;\n    _classCallCheck(this, CheckoutSimpleElement);\n    _this = _callSuper(this, CheckoutSimpleElement);\n    _this.template = template;\n    _this.domNode = null;\n\n    // text + label values that drive the checkout template\n    _this.values = _this.getDefaultValues();\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = [];\n\n    // W0.2b — no inline-edit registrations (CheckoutSimpleElement renders\n    // a multi-section form, not a single editable text). The base class\n    // _wireInlineEdit() short-circuits cleanly when the registry is empty.\n    // The `inlineEditableAttributes()` accessor below still works via the\n    // `inlineEditParams` computed getter on BaseElement (returns [] here).\n\n    // Formatter - Bootstrap button default styles\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      // text styles\n      font_family: \"inherit\",\n      font_weight: \"400\",\n      font_size: \"16px\",\n      text_color: \"#ffffff\",\n      link_color: \"#ffffff\",\n      paragraph_spacing: null,\n      text_align: 'center',\n      // left, center, right,\n      line_height: \"1.5\",\n      letter_spacing: null,\n      text_direction: \"ltr\",\n      // ltr, rtl\n\n      // background - Bootstrap primary button\n      background_color: \"#0d6efd\",\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      // spacing - Bootstrap button padding\n      padding_top: 6,\n      padding_right: 12,\n      padding_bottom: 6,\n      padding_left: 12,\n      // border - Bootstrap button border\n      border_top_style: \"solid\",\n      border_top_width: \"1px\",\n      border_top_color: \"#0d6efd\",\n      border_right_style: \"solid\",\n      border_right_width: \"1px\",\n      border_right_color: \"#0d6efd\",\n      border_bottom_style: \"solid\",\n      border_bottom_width: \"1px\",\n      border_bottom_color: \"#0d6efd\",\n      border_left_width: \"1px\",\n      border_left_style: \"solid\",\n      border_left_color: \"#0d6efd\",\n      // border radius - Bootstrap button radius\n      border_radius: \"0.375rem\",\n      // sizing\n      width: null,\n      max_width: null,\n      min_width: null\n    });\n    return _this;\n  }\n  _inherits(CheckoutSimpleElement, _BaseElement);\n  return _createClass(CheckoutSimpleElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.checkout_simple');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c). W0.2b: legacy applyInlineEdit()\n      // removed; the new framework (auto-fired _wireInlineEdit from\n      // afterRender) is a no-op when the registry is empty.\n      this.domNode.innerHTML = this.renderTemplate({\n        values: this.values\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(CheckoutSimpleElement, \"getData\", this, 3)([])), {}, {\n        values: this.values\n      });\n    }\n  }, {\n    key: \"getDefaultValues\",\n    value: function getDefaultValues() {\n      return {\n        ui: {\n          previewLabel: 'Simple Checkout Preview',\n          modeLabel: 'Contact Information'\n        },\n        headerTitle: 'Quick Checkout',\n        buttonTexts: {\n          submit: 'Submit Order',\n          submitting: 'Submitting...'\n        },\n        headlines: {\n          contact: 'CONTACT INFORMATION',\n          privacy: 'We Never Share Your Information With Anyone'\n        },\n        contactLabels: {\n          firstName: 'First Name',\n          lastName: 'Last Name',\n          email: 'Email',\n          phone: 'Phone Number'\n        }\n      };\n    }\n  }, {\n    key: \"mergeDeep\",\n    value: function mergeDeep(target, source) {\n      var _this2 = this;\n      var output = target || {};\n      if (_typeof(target) !== 'object' || target === null) {\n        return source;\n      }\n      if (_typeof(source) !== 'object' || source === null) {\n        return target;\n      }\n      Object.keys(source).forEach(function (key) {\n        if (Array.isArray(source[key])) {\n          output[key] = source[key].slice();\n        } else if (_typeof(source[key]) === 'object') {\n          output[key] = _this2.mergeDeep(target[key] || {}, source[key]);\n        } else {\n          output[key] = source[key];\n        }\n      });\n      return output;\n    }\n  }, {\n    key: \"setValueByPath\",\n    value: function setValueByPath(obj, path, value) {\n      if (!path) {\n        return;\n      }\n      var segments = path.split('.');\n      var current = obj;\n      segments.forEach(function (segment, index) {\n        if (index === segments.length - 1) {\n          current[segment] = value;\n        } else {\n          if (!current[segment] || _typeof(current[segment]) !== 'object') {\n            current[segment] = {};\n          }\n          current = current[segment];\n        }\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this3 = this;\n      return [new _CheckoutSimpleControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](this.values, {\n        update: function update(path, value) {\n          _this3.setValueByPath(_this3.values, path, value);\n          _this3.render();\n        }\n      })];\n    }\n  }, {\n    key: \"inlineEditableAttributes\",\n    value: function inlineEditableAttributes() {\n      return this.inlineEditParams;\n    }\n  }, {\n    key: \"getFormats\",\n    value: function getFormats() {\n      return this.formatter.getFormats();\n    }\n\n    // W0.2c: legacy 2-arg `renderTemplate(templateName, data)` override removed.\n    // BaseElement.renderTemplate(vars) now handles everything correctly.\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new this(data.template);\n      if (data.values) {\n        e.values = e.mergeDeep(e.getDefaultValues(), data.values);\n      }\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutSimpleElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutSimpleElement.js?");

/***/ }),

/***/ "./src/includes/CheckoutSimpleWidget.js":
/*!**********************************************!*\
  !*** ./src/includes/CheckoutSimpleWidget.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CheckoutSimpleElement.js */ \"./src/includes/CheckoutSimpleElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutSimpleWidget = /*#__PURE__*/function (_BaseWidget) {\n  function CheckoutSimpleWidget() {\n    var _this;\n    _classCallCheck(this, CheckoutSimpleWidget);\n    _this = _callSuper(this, CheckoutSimpleWidget); // Call the parent class constructor\n\n    // Add a CheckoutSimpleElement to the widget\n    var checkout = new _CheckoutSimpleElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('CheckoutSimple');\n\n    // Append the new element to the block\n    _this.block.appendElements([checkout]);\n    return _this;\n  }\n  _inherits(CheckoutSimpleWidget, _BaseWidget);\n  return _createClass(CheckoutSimpleWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.checkout_simple');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'badge';\n    }\n  }, {\n    key: \"getElements\",\n    value: function getElements() {\n      // Return the elements\n      return this.elements;\n    }\n  }, {\n    key: \"renderElements\",\n    value: function renderElements() {\n      // Clone all elements and return the cloned ones\n      return this.elements.map(function (element) {\n        var data = element.getData();\n        return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n      });\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutSimpleWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutSimpleWidget.js?");

/***/ }),

/***/ "./src/includes/CheckoutWidget.js":
/*!****************************************!*\
  !*** ./src/includes/CheckoutWidget.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CheckoutElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CheckoutElement.js */ \"./src/includes/CheckoutElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar CheckoutWidget = /*#__PURE__*/function (_BaseWidget) {\n  function CheckoutWidget() {\n    var _this;\n    _classCallCheck(this, CheckoutWidget);\n    _this = _callSuper(this, CheckoutWidget); // Call the parent class constructor\n\n    // Add a CheckoutElement to the widget\n    var checkout = new _CheckoutElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Checkout');\n\n    // Append the new element to the block\n    _this.block.appendElements([checkout]);\n    return _this;\n  }\n  _inherits(CheckoutWidget, _BaseWidget);\n  return _createClass(CheckoutWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.checkout');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'payment';\n    }\n  }, {\n    key: \"getElements\",\n    value: function getElements() {\n      // Return the elements\n      return this.elements;\n    }\n  }, {\n    key: \"renderElements\",\n    value: function renderElements() {\n      // Clone all elements and return the cloned ones\n      return this.elements.map(function (element) {\n        var data = element.getData();\n        return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n      });\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CheckoutWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CheckoutWidget.js?");

/***/ }),

/***/ "./src/includes/ColorPickerControl.js":
/*!********************************************!*\
  !*** ./src/includes/ColorPickerControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ui/ColorPalettePicker.js */ \"./src/includes/ui/ColorPalettePicker.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n/**\n * ColorPickerControl — labeled color + hex pair.\n *\n * 2026-04-18 (Phase 2.13) rewrite: drops Bootstrap `.form-control` + inline\n * `<style>` injection, replaces with the `.bjs-color-input` primitive for\n * the swatch and `.bjs-text-input` for the hex field. Null state shows the\n * transparent checkerboard pattern baked into `.bjs-color-swatch`.\n *\n * 2026-04-21 (TEXT_INLINE_PLAN W1.2+): swatch click no longer opens the\n * native browser color picker. It opens a floating popover hosting the\n * shared `ColorPalettePicker` primitive (same Google-style 60-swatch UX\n * used by the canvas inline toolbar's Text Color / Highlight popovers —\n * see `src/includes/overlays/TextColorPopoverOverlay.js`). The native\n * `<input type=\"color\">` is kept ONLY as the \"Custom\" row inside the\n * popover. Single-popover invariant enforced via a module-scoped\n * singleton — clicking a different swatch elsewhere in the sidebar\n * dismisses the previous popover automatically.\n *\n * Hex input parses 3- and 6-digit hex; invalid input reverts to the last\n * known value on blur. Empty input clears to null (`color.not_set` label).\n */\n\nvar POPOVER_Z_INDEX = 1001; // above sidebar panels / overlays\nvar RECENT_MAX = 10;\n\n// Module-scoped singleton — enforces the \"one open sidebar color popover\n// at a time\" invariant across every ColorPickerControl instance. Swapping\n// is cheaper than dismiss+reopen (no flicker); the previous popover is\n// closed synchronously when a new one opens.\nvar _activeSidebarPopover = null;\nvar ColorPickerControl = /*#__PURE__*/function () {\n  function ColorPickerControl(label, color, callback) {\n    _classCallCheck(this, ColorPickerControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.color = color;\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-color-picker-control');\n    this._popover = null;\n    this.render();\n  }\n  return _createClass(ColorPickerControl, [{\n    key: \"render\",\n    value: function render() {\n      var swatchColor = this.color || '#000000';\n      var hexLabel = this.color || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n      var isUnset = !this.color;\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"\".concat(this.id, \"_hex\\\"><span>\").concat(this.label, \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-color-input\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-color-swatch\\\"\\n                            id=\\\"\").concat(this.id, \"_swatch\\\"\\n                            aria-label=\\\"\").concat(this.label, \"\\\"\\n                            aria-haspopup=\\\"dialog\\\"\\n                            aria-expanded=\\\"false\\\">\\n                            <span class=\\\"bjs-color-preview\\\" data-role=\\\"swatch-preview\\\"\\n                                style=\\\"--bjs-color-current: \").concat(isUnset ? 'transparent' : swatchColor, \";\\\"></span>\\n                        </button>\\n                        <input id=\\\"\").concat(this.id, \"_hex\\\" type=\\\"text\\\"\\n                            class=\\\"bjs-color-hex\\\"\\n                            value=\\\"\").concat(hexLabel, \"\\\"\\n                            aria-label=\\\"\").concat(this.label, \" hex value\\\"\\n                            autocomplete=\\\"off\\\" spellcheck=\\\"false\\\">\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n      this.swatchBtn = this.domNode.querySelector(\"#\".concat(this.id, \"_swatch\"));\n      this.hexInput = this.domNode.querySelector(\"#\".concat(this.id, \"_hex\"));\n      this.swatchPreview = this.domNode.querySelector('[data-role=\"swatch-preview\"]');\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      this.swatchBtn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this._togglePopover();\n      });\n\n      // Placeholder UX: clear \"not set\" label on focus so user can type.\n      this.hexInput.addEventListener('focus', function (e) {\n        if (e.target.value === _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set')) e.target.value = '';\n      });\n\n      // Empty on blur → clear to null.\n      this.hexInput.addEventListener('blur', function (e) {\n        if (e.target.value.trim() === '') {\n          e.target.value = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n          _this._notify(null);\n        }\n      });\n      this.hexInput.addEventListener('change', function (e) {\n        var v = e.target.value.trim();\n        if (v === '' || v === _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set')) {\n          _this.hexInput.value = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n          _this._notify(null);\n          return;\n        }\n        if (!v.startsWith('#')) v = '#' + v;\n        if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) {\n          _this.hexInput.value = v;\n          _this._notify(v);\n        } else {\n          // Invalid → revert to last known good.\n          _this.hexInput.value = _this.color || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n        }\n      });\n    }\n  }, {\n    key: \"_notify\",\n    value: function _notify(val) {\n      this.color = val;\n      // Update swatch preview — null → transparent checkerboard shows.\n      if (this.swatchPreview) {\n        this.swatchPreview.style.setProperty('--bjs-color-current', val || 'transparent');\n      }\n      if (typeof this.callback === 'function') {\n        this.callback(val);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(val);\n      } else if (this.callback && typeof this.callback.setColor === 'function') {\n        this.callback.setColor(val);\n      }\n    }\n\n    /* ── popover lifecycle ─────────────────────────────────────────── */\n  }, {\n    key: \"_togglePopover\",\n    value: function _togglePopover() {\n      if (_activeSidebarPopover && _activeSidebarPopover.owner === this) {\n        // Second click on same swatch → close.\n        this._closePopover();\n        return;\n      }\n      // Different control's popover open → swap (close previous first).\n      if (_activeSidebarPopover) {\n        try {\n          _activeSidebarPopover.close();\n        } catch (_) {}\n        _activeSidebarPopover = null;\n      }\n      this._openPopover();\n    }\n  }, {\n    key: \"_openPopover\",\n    value: function _openPopover() {\n      var _this2 = this;\n      try {\n        var popover = this._buildPopover();\n        document.body.appendChild(popover.domNode);\n        popover.positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n          anchor: function anchor() {\n            return _this2.swatchBtn.getBoundingClientRect();\n          },\n          target: popover.domNode,\n          offset: 8,\n          collisionPadding: 12,\n          preferredSide: 'below',\n          flip: true\n        });\n        this._registerDismissListeners(popover);\n        this._popover = popover;\n        _activeSidebarPopover = {\n          owner: this,\n          close: function close() {\n            return _this2._closePopover();\n          }\n        };\n        this.swatchBtn.setAttribute('aria-expanded', 'true');\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:color-picker-control] popover open failed:', err);\n        this._closePopover();\n      }\n    }\n  }, {\n    key: \"_closePopover\",\n    value: function _closePopover() {\n      var pop = this._popover;\n      if (!pop) return;\n      this._unregisterDismissListeners(pop);\n      if (pop.positionHandle) {\n        try {\n          pop.positionHandle.dispose();\n        } catch (_) {}\n      }\n      if (pop.domNode && pop.domNode.parentNode) {\n        try {\n          pop.domNode.parentNode.removeChild(pop.domNode);\n        } catch (_) {}\n      }\n      this._popover = null;\n      if (_activeSidebarPopover && _activeSidebarPopover.owner === this) {\n        _activeSidebarPopover = null;\n      }\n      if (this.swatchBtn) this.swatchBtn.setAttribute('aria-expanded', 'false');\n    }\n  }, {\n    key: \"_buildPopover\",\n    value: function _buildPopover() {\n      var _this3 = this;\n      var domNode = document.createElement('div');\n      // Reuse the canvas popover's chrome class — same visual shell,\n      // same tokens, same dark-mode rules. Adding a data-surface marker\n      // so tests / styles can target the sidebar variant when needed.\n      domNode.className = 'bjs-ovl bjs-ovl-color-popover';\n      domNode.setAttribute('role', 'dialog');\n      domNode.setAttribute('aria-label', this.label);\n      domNode.setAttribute('data-surface', 'sidebar');\n      domNode.style.zIndex = String(POPOVER_Z_INDEX);\n\n      // Preserve focus on interactive children — prevent the mousedown\n      // on the popover body from stealing focus from the hex input / etc.\n      domNode.addEventListener('mousedown', function (e) {\n        if (e.target && e.target.closest('input, textarea, select, button[data-role=\"eyedropper\"], button[data-role=\"swatch\"], button[data-role=\"reset\"]')) return;\n        e.preventDefault();\n      });\n      var picker = new _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n        value: this.color,\n        recent: this._getRecentColors(),\n        title: this.label,\n        onPick: function onPick(hex) {\n          if (hex === null) {\n            _this3._handleReset();\n            return;\n          }\n          _this3._handlePick(hex);\n        },\n        onReset: function onReset() {\n          return _this3._handleReset();\n        }\n      });\n      domNode.appendChild(picker.domNode);\n      return {\n        domNode: domNode,\n        picker: picker,\n        positionHandle: null\n      };\n    }\n  }, {\n    key: \"_handlePick\",\n    value: function _handlePick(hex) {\n      this._pushRecent(hex);\n      this._applyValue(hex);\n      this._closePopover();\n    }\n  }, {\n    key: \"_handleReset\",\n    value: function _handleReset() {\n      this._applyValue(null);\n      this._closePopover();\n    }\n  }, {\n    key: \"_applyValue\",\n    value: function _applyValue(val) {\n      this.color = val;\n      if (this.hexInput) {\n        this.hexInput.value = val || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n      }\n      if (this.swatchPreview) {\n        this.swatchPreview.style.setProperty('--bjs-color-current', val || 'transparent');\n      }\n      if (typeof this.callback === 'function') {\n        this.callback(val);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(val);\n      } else if (this.callback && typeof this.callback.setColor === 'function') {\n        this.callback.setColor(val);\n      }\n    }\n\n    /* ── recent LRU (sidebar-wide bucket) ─────────────────────────── */\n  }, {\n    key: \"_getRecentColors\",\n    value: function _getRecentColors() {\n      // Host-injection — `this.host` is set by Builder.renderElementControls\n      // when this control is emitted by an element's getControls(). Each\n      // Builder owns its own LRU bucket so two on-page builders don't\n      // share recent colors.\n      var host = this.host;\n      if (!host) return [];\n      var arr = Array.isArray(host._recentElementColors) ? host._recentElementColors : [];\n      return arr.slice();\n    }\n  }, {\n    key: \"_pushRecent\",\n    value: function _pushRecent(hex) {\n      var host = this.host;\n      if (!host || !hex) return;\n      var arr = Array.isArray(host._recentElementColors) ? host._recentElementColors.slice() : [];\n      var idx = arr.findIndex(function (c) {\n        return c.toLowerCase() === hex.toLowerCase();\n      });\n      if (idx >= 0) arr.splice(idx, 1);\n      arr.unshift(hex);\n      if (arr.length > RECENT_MAX) arr = arr.slice(0, RECENT_MAX);\n      host._recentElementColors = arr;\n    }\n\n    /* ── dismiss ──────────────────────────────────────────────────── */\n  }, {\n    key: \"_registerDismissListeners\",\n    value: function _registerDismissListeners(popover) {\n      var _this4 = this;\n      popover.onDocKey = function (e) {\n        if (e.key === 'Escape') {\n          e.stopPropagation();\n          _this4._closePopover();\n        }\n      };\n      document.addEventListener('keydown', popover.onDocKey, true);\n      popover.onDocMouseDown = function (e) {\n        if (!_this4._popover) return;\n        var t = e.target;\n        if (_this4._popover.domNode.contains(t)) return;\n        if (_this4.swatchBtn && _this4.swatchBtn.contains(t)) return;\n        _this4._closePopover();\n      };\n      setTimeout(function () {\n        if (_this4._popover === popover) {\n          document.addEventListener('mousedown', popover.onDocMouseDown, true);\n        }\n      }, 0);\n    }\n  }, {\n    key: \"_unregisterDismissListeners\",\n    value: function _unregisterDismissListeners(popover) {\n      if (popover.onDocKey) {\n        document.removeEventListener('keydown', popover.onDocKey, true);\n        popover.onDocKey = null;\n      }\n      if (popover.onDocMouseDown) {\n        document.removeEventListener('mousedown', popover.onDocMouseDown, true);\n        popover.onDocMouseDown = null;\n      }\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.color = newValue;\n      if (!this.hexInput) return;\n      if (newValue === null || newValue === undefined) {\n        this.hexInput.value = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color.not_set');\n        if (this.swatchPreview) this.swatchPreview.style.setProperty('--bjs-color-current', 'transparent');\n      } else {\n        this.hexInput.value = newValue;\n        if (this.swatchPreview) this.swatchPreview.style.setProperty('--bjs-color-current', newValue);\n      }\n      if (this._popover && this._popover.picker) {\n        try {\n          this._popover.picker.setValue(newValue);\n        } catch (_) {}\n      }\n      if (typeof this.callback === 'function') this.callback(this.color);else if (this.callback && typeof this.callback.setValue === 'function') this.callback.setValue(this.color);else if (this.callback && typeof this.callback.setColor === 'function') this.callback.setColor(this.color);\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.color;\n    }\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._popover) this._closePopover();\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ColorPickerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ColorPickerControl.js?");

/***/ }),

/***/ "./src/includes/CustomRangeControl.js":
/*!********************************************!*\
  !*** ./src/includes/CustomRangeControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar CustomRangeControl = /*#__PURE__*/function () {\n  function CustomRangeControl(label, min, max, unit, isAuto, callback) {\n    var value = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : '';\n    _classCallCheck(this, CustomRangeControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.min = min; // Minimum value for the range\n    this.max = max; // Maximum value for the range\n    this.unit = unit; // Unit of measurement (e.g., px, em)\n    this.isAuto = isAuto; // Flag to indicate if the range is auto-adjusting\n    this.callback = callback; // Callback function to handle input changes\n\n    if (value === '' || value === 'auto') {\n      this.value = 48;\n    } else {\n      this.value = parseInt(value, 10);\n    }\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n    this.setupEventListeners(); // Set up event listeners\n  }\n  return _createClass(CustomRangeControl, [{\n    key: \"render\",\n    value: function render() {\n      this.domNode.innerHTML = \"\\n    <div class=\\\"py-2 px-3\\\">\\n      <div class=\\\"d-flex justify-content-between mb-2 align-items-center\\\">\\n        <h4 class=\\\"form-label fw-semibold mb-0\\\">\".concat(this.label, \"</h4>\\n        <div class=\\\"d-flex align-items-center gap-2 ms-3\\\">\\n          <span class=\\\"form-label mb-0\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.fixed'), \"</span>\\n          <div class=\\\"ms-auto\\\">\\n            <input type=\\\"checkbox\\\" class=\\\"builder-checkbox-modern\\\" id=\\\"toggle_\").concat(this.id, \"\\\" \").concat(this.isAuto ? 'checked' : '', \" />\\n            <label class=\\\"toggle-label\\\" for=\\\"toggle_\").concat(this.id, \"\\\"></label>\\n          </div>\\n          <span class=\\\"form-label mb-0\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.auto'), \"</span>\\n        </div>\\n      </div>\\n      <div class=\\\"d-flex justify-content-between align-items-center mb-0 pe-1 me-3\\\">\\n        <p class=\\\"mb-0 me-2\\\">\").concat(this.min).concat(this.unit, \"</p>\\n        <p class=\\\"mb-0 pe-2 me-4\\\">\").concat(this.max).concat(this.unit, \"</p>\\n      </div>\\n      <div class=\\\"d-flex\\\">\\n        <div class=\\\"flex-grow-1\\\">\\n          <input type=\\\"range\\\" min=\\\"\").concat(this.min, \"\\\" max=\\\"\").concat(this.max, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-range slider w-100\\\" id=\\\"\").concat(this.id, \"_slider\\\" \").concat(this.isAuto ? 'disabled' : '', \">\\n        </div>\\n        <div style=\\\"min-width: 50px; text-align: right;\\\">\\n          <label for=\\\"\").concat(this.id, \"_slider\\\" class=\\\"form-label ms-2 mb-0\\\">\").concat(this.isAuto ? 'auto' : this.value + this.unit, \"</label>\\n        </div>\\n      </div>\\n    </div>\");\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var isAuto = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.isAuto;\n      this.value = newValue;\n      this.isAuto = isAuto;\n      this.render();\n      this.setupEventListeners();\n      if (this.callback && typeof this.callback.setValue === \"function\") {\n        this.callback.setValue(this.value, this.isAuto);\n      }\n    }\n  }, {\n    key: \"setupEventListeners\",\n    value: function setupEventListeners() {\n      var _this = this;\n      var rangeInput = this.domNode.querySelector(\"input[type=\\\"range\\\"]\");\n      var valueLabel = this.domNode.querySelector(\"label[for=\\\"\".concat(this.id, \"_slider\\\"]\"));\n      var autoSwitch = this.domNode.querySelector(\"#toggle_\".concat(this.id));\n\n      // Debounce variables\n      var debounceTimeout = null;\n      var debounceDelay = 50; // milliseconds\n\n      if (rangeInput) {\n        rangeInput.addEventListener(\"input\", function (event) {\n          _this.value = event.target.value;\n          if (valueLabel && !_this.isAuto) {\n            valueLabel.textContent = \"\".concat(_this.value).concat(_this.unit);\n          }\n\n          // Debounce the callback\n          if (debounceTimeout) clearTimeout(debounceTimeout);\n          debounceTimeout = setTimeout(function () {\n            if (_this.callback && typeof _this.callback.setValue === \"function\") {\n              _this.callback.setValue(_this.value, _this.isAuto);\n            }\n          }, debounceDelay);\n        });\n      }\n      if (autoSwitch) {\n        autoSwitch.addEventListener(\"change\", function (event) {\n          _this.isAuto = event.target.checked;\n          _this.render();\n          _this.setupEventListeners();\n          if (_this.callback && typeof _this.callback.setValue === \"function\") {\n            _this.callback.setValue(_this.value, _this.isAuto);\n          }\n        });\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CustomRangeControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/CustomRangeControl.js?");

/***/ }),

/***/ "./src/includes/DimensionControl.js":
/*!******************************************!*\
  !*** ./src/includes/DimensionControl.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n// Per-unit slider range + help text.\n// Range chosen for \"80% of real use cases\" for both email (600px-ish) AND\n// full-width web pages (up to ~1200px / Bootstrap XL). Number input accepts\n// any value beyond the slider max — slider clamps visually, value persists.\nvar UNIT_CONFIG = {\n  px: {\n    min: 0,\n    max: 1200,\n    step: 1,\n    helpKey: 'dimension.help_px',\n    defaultValue: 300\n  },\n  '%': {\n    min: 0,\n    max: 100,\n    step: 1,\n    helpKey: 'dimension.help_pct',\n    defaultValue: 100\n  },\n  em: {\n    min: 0,\n    max: 20,\n    step: 0.1,\n    helpKey: 'dimension.help_em',\n    defaultValue: 1\n  },\n  rem: {\n    min: 0,\n    max: 20,\n    step: 0.1,\n    helpKey: 'dimension.help_rem',\n    defaultValue: 1\n  },\n  vw: {\n    min: 0,\n    max: 100,\n    step: 1,\n    helpKey: 'dimension.help_vw',\n    defaultValue: 50\n  },\n  vh: {\n    min: 0,\n    max: 100,\n    step: 1,\n    helpKey: 'dimension.help_vh',\n    defaultValue: 50\n  },\n  // `fill` — value-less unit meaning \"grow to absorb remaining row space\".\n  // Used for the classic `[\"auto\", \"fill\"]` image+text layout. Slider is\n  // disabled (no numeric value); serializes as `\"fill\"` (no number prefix).\n  fill: {\n    helpKey: 'dimension.help_fill'\n  },\n  auto: {\n    helpKey: 'dimension.help_auto'\n  }\n};\n\n// Quick-size presets per unit, shown in the dropdown menu under \"Quick size\".\n// Values cover typical web + email ranges (email column ≈ 600, page full ≈ 1200).\nvar PRESETS = {\n  px: [{\n    labelKey: 'dimension.preset_sm',\n    value: 160\n  }, {\n    labelKey: 'dimension.preset_md',\n    value: 400\n  }, {\n    labelKey: 'dimension.preset_lg',\n    value: 800\n  }, {\n    labelKey: 'dimension.preset_full',\n    value: 1200\n  }],\n  '%': [{\n    label: '25%',\n    value: 25\n  }, {\n    label: '50%',\n    value: 50\n  }, {\n    label: '75%',\n    value: 75\n  }, {\n    label: '100%',\n    value: 100\n  }]\n};\nvar DimensionControl = /*#__PURE__*/function (_BaseControl) {\n  /**\n   * @param {string}   label         Display label (already translated)\n   * @param {*}        initialOrValue One of:\n   *                   - primitive: \"300px\" | \"50%\" | \"auto\" | null | number (legacy form)\n   *                   - capability-token form (preferred):\n   *                     { initial, subscribe, readState }\n   *                       - `initial`   — same shape as the primitive form\n   *                       - `subscribe` — `(fn) => disposer` capability that\n   *                         fires `fn()` whenever element state changes\n   *                         (per SA I13 R3). When present, the control\n   *                         registers a disposer + calls `syncFromExternal()`\n   *                         on every notify.\n   *                       - `readState` — `() => freshValue` returning the\n   *                         current primitive form for this key (e.g.\n   *                         `() => element.formatter.getFormat('width')`).\n   *                         Required for observer-aware mode; without it\n   *                         the control can't re-read state on notify.\n   * @param {object}   options\n   * @param {string[]} options.units Subset of ['px','%','em','rem','vw','vh','auto']\n   * @param {function} options.onChange Receives serialized: \"300px\" | \"50%\" | \"auto\" | null\n   *\n   * Embeddable in any DOM container — the `domNode` property is the root.\n   * Multiple instances can coexist on the same element key (sidebar +\n   * popup overlay, etc.); both subscribe and stay in sync.\n   */\n  function DimensionControl(label, initialOrValue) {\n    var _this;\n    var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n    _classCallCheck(this, DimensionControl);\n    _this = _callSuper(this, DimensionControl);\n    _this.id = '_dim_' + Math.random().toString(36).substr(2, 9);\n    _this.label = label;\n    _this.units = options.units && options.units.length ? options.units : ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'];\n    _this.onChange = typeof options.onChange === 'function' ? options.onChange : function () {};\n\n    // Detect capability-token form vs legacy primitive form.\n    var initial = initialOrValue;\n    _this._readState = null;\n    if (initialOrValue && _typeof(initialOrValue) === 'object' && (typeof initialOrValue.subscribe === 'function' || 'initial' in initialOrValue || typeof initialOrValue.readState === 'function')) {\n      initial = initialOrValue.initial;\n      if (typeof initialOrValue.readState === 'function') {\n        _this._readState = initialOrValue.readState;\n      }\n      if (typeof initialOrValue.subscribe === 'function') {\n        // Subscribe via capability token (SA I13 R3). Disposer auto-runs\n        // in BaseControl.destroy() when sidebar rebuilds OR when popup\n        // overlay tears down (popup must call control.destroy()).\n        _this.addDisposer(initialOrValue.subscribe(function () {\n          return _this.syncFromExternal();\n        }));\n      }\n    }\n    var parsed = _this._parse(initial);\n    _this.value = parsed.value;\n    _this.unit = parsed.unit;\n    _this._menuOpen = false;\n    _this._outsideClickHandler = null;\n    _this.domNode = document.createElement('div');\n    _this.domNode.classList.add('dimension-control');\n    _this.render();\n    _this._bindEvents();\n    return _this;\n  }\n\n  /** Re-read state from `readState()` (supplied via capability token) and\n   *  patch DOM in place. Skips inputs that currently hold focus so user's\n   *  in-flight typing isn't clobbered (per SA I13 R4).\n   *\n   *  Listener idempotence (per SA I13 R7) — every element.render() fires\n   *  this. We early-out cheaply when value+unit haven't changed. */\n  _inherits(DimensionControl, _BaseControl);\n  return _createClass(DimensionControl, [{\n    key: \"syncFromExternal\",\n    value: function syncFromExternal() {\n      if (!this._readState) return; // observer mode requires readState\n      if (this._destroyed) return; // disposer should have unsubscribed\n      if (!this.domNode) return; // DOM gone — sidebar rebuilt or section destroyed\n      var next = this._parse(this._readState());\n      if (next.value === this.value && next.unit === this.unit) return;\n      var unitChanged = next.unit !== this.unit;\n      this.value = next.value;\n      this.unit = next.unit;\n      if (unitChanged) {\n        // Unit change rewrites slider min/max/step + unit-button label +\n        // input disabled state. Cheapest correct path is _renderAndRebind\n        // (innerHTML + re-bind) since structure differs across units. The\n        // sidebar instance lives in a steady-state container; rebuild here\n        // doesn't trigger any sidebar-rebuild side effects.\n        this._renderAndRebind();\n        return;\n      }\n\n      // Same-unit value change — surgical patch to preserve focus/selection.\n      var slider = this.domNode.querySelector('.dim-slider');\n      var valueInput = this.domNode.querySelector('.dim-value');\n      var sliderVal = this.value === null || isNaN(this.value) ? 0 : this.value;\n      if (slider && document.activeElement !== slider) {\n        slider.value = String(sliderVal);\n        var cfg = this._config();\n        var pct = cfg && cfg.max !== cfg.min ? (sliderVal - cfg.min) / (cfg.max - cfg.min) * 100 : 0;\n        slider.style.setProperty('--pct', pct + '%');\n      }\n      if (valueInput && document.activeElement !== valueInput) {\n        valueInput.value = this.value === null || isNaN(this.value) ? '' : String(this.value);\n      }\n    }\n  }, {\n    key: \"_parse\",\n    value: function _parse(input) {\n      var fallbackUnit = this.units.includes('px') ? 'px' : this.units[0];\n      // Default unit for bare (unitless) numbers: prefer `%` when the caller\n      // supports it. Historical reason: CellElement + GridElement storing bare\n      // numbers like `50` meant-to-be \"50%\" — falling back to `px` showed\n      // \"50 px\" in the panel and surprised authors (user report 2026-04-18).\n      // Width-shaped DimensionControl instances include `%` in their unit set\n      // → bare numbers now show as `%`. Fixed-dimension instances without `%`\n      // (e.g. px-only) keep the legacy `px` fallback.\n      var bareFallback = this.units.includes('%') ? '%' : this.units.includes('px') ? 'px' : this.units[0];\n      if (input === null || input === undefined || input === '') {\n        return {\n          value: null,\n          unit: fallbackUnit\n        };\n      }\n      if (input === 'auto') {\n        return {\n          value: null,\n          unit: this.units.includes('auto') ? 'auto' : fallbackUnit\n        };\n      }\n      if (input === 'fill') {\n        return {\n          value: null,\n          unit: this.units.includes('fill') ? 'fill' : fallbackUnit\n        };\n      }\n      if (typeof input === 'number') {\n        return {\n          value: isNaN(input) ? null : input,\n          unit: bareFallback\n        };\n      }\n      if (typeof input === 'string') {\n        var m = input.trim().match(/^(-?[\\d.]+)\\s*(px|%|em|rem|vw|vh)?$/i);\n        if (m) {\n          var num = parseFloat(m[1]);\n          var explicitUnit = m[2] ? m[2].toLowerCase() : null;\n          var unit = explicitUnit || bareFallback;\n          return {\n            value: isNaN(num) ? null : num,\n            unit: this.units.includes(unit) ? unit : fallbackUnit\n          };\n        }\n      }\n      return {\n        value: null,\n        unit: fallbackUnit\n      };\n    }\n  }, {\n    key: \"_serialize\",\n    value: function _serialize() {\n      if (this.unit === 'auto') return 'auto';\n      if (this.unit === 'fill') return 'fill';\n      if (this.value === null || isNaN(this.value)) return null;\n      var num = Number.isInteger(this.value) ? this.value : parseFloat(this.value.toFixed(2));\n      return \"\".concat(num).concat(this.unit);\n    }\n  }, {\n    key: \"_emit\",\n    value: function _emit() {\n      this.onChange(this._serialize());\n    }\n  }, {\n    key: \"_config\",\n    value: function _config() {\n      return UNIT_CONFIG[this.unit] || UNIT_CONFIG.px;\n    }\n  }, {\n    key: \"_t\",\n    value: function _t(key, fallback) {\n      try {\n        var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n        return v && v !== key ? v : fallback;\n      } catch (_e) {\n        return fallback;\n      }\n    }\n\n    /** Reset value to unset. Unit is preserved — placeholder \"auto\" appears\n     *  in the input to signal \"no size applied\" without changing user's pick. */\n  }, {\n    key: \"clear\",\n    value: function clear() {\n      this.value = null;\n      this._closeMenu();\n      this.render();\n      this._bindEvents();\n      this._emit();\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var isAuto = this.unit === 'auto';\n      var isFill = this.unit === 'fill';\n      // `auto` + `fill` are both value-less units — slider/input are disabled\n      // and a placeholder communicates the meaning.\n      var isValueless = isAuto || isFill;\n      var cfg = this._config();\n      var presets = isValueless ? [] : PRESETS[this.unit] || [];\n      var hasValue = !isValueless && this.value !== null && !isNaN(this.value);\n      var placeholderText = isFill ? this._t('dimension.placeholder_fill', 'fill') : this._t('dimension.placeholder', 'auto');\n      var sliderVal = hasValue ? this.value : cfg.min || 0;\n      var pct = !isValueless && cfg.max !== cfg.min ? (sliderVal - cfg.min) / (cfg.max - cfg.min) * 100 : 0;\n      this.domNode.innerHTML = \"\\n      <div class=\\\"dim-row\\\">\\n        <label class=\\\"dim-label\\\" for=\\\"\".concat(this.id, \"_slider\\\">\").concat(this.label, \"</label>\\n        <div class=\\\"dim-slider-wrap\\\">\\n          <input type=\\\"range\\\" class=\\\"dim-slider\\\" id=\\\"\").concat(this.id, \"_slider\\\"\\n            min=\\\"\").concat(isValueless ? 0 : cfg.min, \"\\\"\\n            max=\\\"\").concat(isValueless ? 100 : cfg.max, \"\\\"\\n            step=\\\"\").concat(isValueless ? 1 : cfg.step, \"\\\"\\n            value=\\\"\").concat(sliderVal, \"\\\"\\n            style=\\\"--pct: \").concat(pct, \"%\\\"\\n            \").concat(isValueless ? 'disabled' : '', \">\\n        </div>\\n        <input type=\\\"number\\\" class=\\\"dim-value\\\"\\n          value=\\\"\").concat(isValueless ? '' : hasValue ? this.value : '', \"\\\"\\n          placeholder=\\\"\").concat(placeholderText, \"\\\"\\n          step=\\\"\").concat(cfg.step || 1, \"\\\"\\n          min=\\\"0\\\"\\n          \").concat(isValueless ? 'disabled' : '', \">\\n        <button type=\\\"button\\\" class=\\\"dim-menu-btn\\\" aria-haspopup=\\\"true\\\" aria-expanded=\\\"\").concat(this._menuOpen, \"\\\">\\n          <span class=\\\"dim-menu-btn-unit\\\">\").concat(this.unit, \"</span>\\n          <span class=\\\"dim-menu-btn-caret\\\" aria-hidden=\\\"true\\\">\\u25BE</span>\\n        </button>\\n      </div>\\n    \");\n    }\n\n    /** Build the popover menu element (portaled to document.body on open). */\n  }, {\n    key: \"_buildMenu\",\n    value: function _buildMenu() {\n      var _this2 = this;\n      var isValueless = this.unit === 'auto' || this.unit === 'fill';\n      var presets = isValueless ? [] : PRESETS[this.unit] || [];\n      var hasValue = !isValueless && this.value !== null && !isNaN(this.value);\n      var menuUnits = this.units.map(function (u) {\n        var isActive = u === _this2.unit;\n        return \"<button type=\\\"button\\\" class=\\\"dim-menu-item \".concat(isActive ? 'is-active' : '', \"\\\" data-kind=\\\"unit\\\" data-value=\\\"\").concat(u, \"\\\" role=\\\"menuitemradio\\\" aria-checked=\\\"\").concat(isActive, \"\\\">\").concat(u, \"</button>\");\n      }).join('');\n      var menuPresets = presets.map(function (p) {\n        var label = p.label || _this2._t(p.labelKey, p.labelKey.split('.').pop());\n        return \"<button type=\\\"button\\\" class=\\\"dim-menu-item dim-menu-item--preset\\\" data-kind=\\\"preset\\\" data-value=\\\"\".concat(p.value, \"\\\" role=\\\"menuitem\\\"><span>\").concat(label, \"</span><span class=\\\"dim-menu-item-value\\\">\").concat(p.value).concat(_this2.unit, \"</span></button>\");\n      }).join('');\n      var menu = document.createElement('div');\n      menu.className = 'dim-menu dim-menu--portal is-open';\n      menu.setAttribute('role', 'menu');\n      menu.innerHTML = \"\\n      <div class=\\\"dim-menu-section\\\">\\n        <div class=\\\"dim-menu-heading\\\">\".concat(this._t('dimension.menu_unit', 'Unit'), \"</div>\\n        <div class=\\\"dim-menu-grid\\\">\").concat(menuUnits, \"</div>\\n      </div>\\n      \").concat(menuPresets ? \"\\n        <div class=\\\"dim-menu-section\\\">\\n          <div class=\\\"dim-menu-heading\\\">\".concat(this._t('dimension.menu_quick', 'Quick size'), \"</div>\\n          <div class=\\\"dim-menu-list\\\">\").concat(menuPresets, \"</div>\\n        </div>\\n      \") : '', \"\\n      \").concat(hasValue ? \"\\n        <div class=\\\"dim-menu-section dim-menu-section--foot\\\">\\n          <button type=\\\"button\\\" class=\\\"dim-menu-item dim-menu-item--clear\\\" data-kind=\\\"clear\\\" role=\\\"menuitem\\\">\\n            <span>\".concat(this._t('dimension.clear', 'Clear value'), \"</span>\\n          </button>\\n        </div>\\n      \") : '', \"\\n    \");\n      return menu;\n    }\n  }, {\n    key: \"_renderAndRebind\",\n    value: function _renderAndRebind() {\n      this._closeMenu();\n      this.render();\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this3 = this;\n      var slider = this.domNode.querySelector('.dim-slider');\n      var valueInput = this.domNode.querySelector('.dim-value');\n      var menuBtn = this.domNode.querySelector('.dim-menu-btn');\n\n      // Update the CSS --pct custom property so the track fill matches current value.\n      var updateFill = function updateFill() {\n        if (!slider) return;\n        var cfg = _this3._config();\n        var raw = parseFloat(slider.value);\n        var pct = cfg.max !== cfg.min ? (raw - cfg.min) / (cfg.max - cfg.min) * 100 : 0;\n        slider.style.setProperty('--pct', pct + '%');\n      };\n      if (slider) {\n        var t = null;\n        slider.addEventListener('input', function (e) {\n          var _this3$value;\n          var v = parseFloat(e.target.value);\n          _this3.value = isNaN(v) ? null : v;\n          if (valueInput) valueInput.value = (_this3$value = _this3.value) !== null && _this3$value !== void 0 ? _this3$value : '';\n          updateFill();\n          if (t) clearTimeout(t);\n          t = setTimeout(function () {\n            return _this3._emit();\n          }, 50);\n        });\n      }\n      if (valueInput) {\n        var _t2 = null;\n        valueInput.addEventListener('input', function (e) {\n          var raw = e.target.value.trim();\n          _this3.value = raw === '' ? null : Math.max(0, parseFloat(raw) || 0);\n          var cfg = _this3._config();\n          if (slider && _this3.value !== null) {\n            var _cfg$min, _cfg$max;\n            slider.value = Math.min(Math.max(_this3.value, (_cfg$min = cfg.min) !== null && _cfg$min !== void 0 ? _cfg$min : 0), (_cfg$max = cfg.max) !== null && _cfg$max !== void 0 ? _cfg$max : 1200);\n          }\n          updateFill();\n          if (_t2) clearTimeout(_t2);\n          _t2 = setTimeout(function () {\n            return _this3._emit();\n          }, 150);\n        });\n      }\n      if (menuBtn) {\n        menuBtn.addEventListener('click', function (e) {\n          e.stopPropagation();\n          _this3._toggleMenu();\n        });\n      }\n    }\n  }, {\n    key: \"_toggleMenu\",\n    value: function _toggleMenu() {\n      if (this._menuOpen) this._closeMenu();else this._openMenu();\n    }\n\n    /**\n     * Portal the menu to document.body with position:fixed so it escapes any\n     * `overflow: hidden/auto` ancestors (the settings panel scrolls, which used\n     * to clip the menu before this fix).\n     */\n  }, {\n    key: \"_openMenu\",\n    value: function _openMenu() {\n      var _this4 = this;\n      if (this._menuOpen) return;\n      this._menuOpen = true;\n      var btn = this.domNode.querySelector('.dim-menu-btn');\n      if (!btn) return;\n      btn.setAttribute('aria-expanded', 'true');\n\n      // Build a fresh menu each open — keeps the \"Clear\" footer in sync with\n      // the current hasValue state without needing a separate update pass.\n      var menu = this._buildMenu();\n      document.body.appendChild(menu);\n      this._portalMenu = menu;\n      this._positionMenu();\n      menu.addEventListener('click', this._onMenuClick = function (e) {\n        var item = e.target.closest('.dim-menu-item');\n        if (!item) return;\n        var kind = item.dataset.kind;\n        if (kind === 'unit') {\n          _this4._switchUnit(item.dataset.value);\n          _this4._closeMenu();\n        } else if (kind === 'preset') {\n          _this4.value = parseFloat(item.dataset.value);\n          _this4._closeMenu();\n          _this4.render();\n          _this4._bindEvents();\n          _this4._emit();\n        } else if (kind === 'clear') {\n          _this4.clear();\n        }\n      });\n\n      // Close on outside click\n      this._onOutsideDown = function (e) {\n        if (menu.contains(e.target)) return;\n        if (btn.contains(e.target)) return;\n        _this4._closeMenu();\n      };\n      // Close on scroll / resize (menu position goes stale)\n      this._onReflow = function () {\n        return _this4._closeMenu();\n      };\n      setTimeout(function () {\n        document.addEventListener('mousedown', _this4._onOutsideDown, true);\n        window.addEventListener('scroll', _this4._onReflow, true);\n        window.addEventListener('resize', _this4._onReflow, true);\n      }, 0);\n    }\n  }, {\n    key: \"_positionMenu\",\n    value: function _positionMenu() {\n      if (!this._portalMenu) return;\n      var btn = this.domNode.querySelector('.dim-menu-btn');\n      if (!btn) return;\n      var rect = btn.getBoundingClientRect();\n      // Measure menu after insertion so we can flip up if no room below.\n      var menu = this._portalMenu;\n      menu.style.visibility = 'hidden';\n      menu.style.left = '0px';\n      menu.style.top = '0px';\n      var mw = menu.offsetWidth;\n      var mh = menu.offsetHeight;\n      var vw = window.innerWidth;\n      var vh = window.innerHeight;\n      var left = rect.right - mw; // right-align to button\n      if (left < 8) left = 8; // keep on-screen\n      if (left + mw > vw - 8) left = vw - mw - 8;\n      var top = rect.bottom + 4;\n      if (top + mh > vh - 8) {\n        // Flip above the button\n        top = rect.top - mh - 4;\n        if (top < 8) top = 8;\n      }\n      menu.style.left = \"\".concat(Math.round(left), \"px\");\n      menu.style.top = \"\".concat(Math.round(top), \"px\");\n      menu.style.visibility = 'visible';\n    }\n  }, {\n    key: \"_closeMenu\",\n    value: function _closeMenu() {\n      this._menuOpen = false;\n      var btn = this.domNode.querySelector('.dim-menu-btn');\n      if (btn) btn.setAttribute('aria-expanded', 'false');\n      if (this._portalMenu) {\n        if (this._onMenuClick) this._portalMenu.removeEventListener('click', this._onMenuClick);\n        this._portalMenu.remove();\n        this._portalMenu = null;\n      }\n      if (this._onOutsideDown) {\n        document.removeEventListener('mousedown', this._onOutsideDown, true);\n        this._onOutsideDown = null;\n      }\n      if (this._onReflow) {\n        window.removeEventListener('scroll', this._onReflow, true);\n        window.removeEventListener('resize', this._onReflow, true);\n        this._onReflow = null;\n      }\n    }\n  }, {\n    key: \"_switchUnit\",\n    value: function _switchUnit(newUnit) {\n      var prev = this.unit;\n      this.unit = newUnit;\n      if (newUnit === 'auto' || newUnit === 'fill') {\n        this.value = null;\n      } else if (prev === 'auto' || prev === 'fill' || this.value === null || isNaN(this.value)) {\n        var _UNIT_CONFIG$newUnit$;\n        this.value = (_UNIT_CONFIG$newUnit$ = UNIT_CONFIG[newUnit].defaultValue) !== null && _UNIT_CONFIG$newUnit$ !== void 0 ? _UNIT_CONFIG$newUnit$ : UNIT_CONFIG[newUnit].min;\n      } else {\n        var cfg = UNIT_CONFIG[newUnit];\n        this.value = Math.max(cfg.min, Math.min(this.value, cfg.max));\n      }\n      this.render();\n      this._bindEvents();\n      this._emit();\n    }\n  }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DimensionControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DimensionControl.js?");

/***/ }),

/***/ "./src/includes/DividerElement.js":
/*!****************************************!*\
  !*** ./src/includes/DividerElement.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./DividerStyleControl.js */ \"./src/includes/DividerStyleControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\nvar DividerElement = /*#__PURE__*/function (_BaseElement) {\n  function DividerElement(template) {\n    var _this;\n    _classCallCheck(this, DividerElement);\n    _this = _callSuper(this, DividerElement); // Call the parent class constructor\n    _this.template = template;\n    _this.domNode = null;\n\n    // Formatter\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      background_color: '#333333',\n      height: 2,\n      // structured style (solid|dashed|dotted|double|none) for border-top render\n      divider_style: 'solid',\n      // padding\n      padding_top: 10,\n      padding_right: null,\n      padding_bottom: 10,\n      padding_left: null\n    });\n    return _this;\n  }\n  _inherits(DividerElement, _BaseElement);\n  return _createClass(DividerElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.divider');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({});\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread({}, _superPropGet(DividerElement, \"getData\", this, 3)([]));\n    }\n  }, {\n    key: \"isAutoFormat\",\n    value: function isAutoFormat(key) {\n      return this.formatter.getFormat(key) === \"auto\";\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), this.formatter.getFormat('height'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('height', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 1,\n        minValue: 0,\n        maxValue: 500,\n        suffix: 'px',\n        allowZero: false\n      }),\n      // W3.8b — PaddingMarginControl removed. Padding is a\n      // container-only concern (Block/Cell/Page).\n      // Divider style control (solid / dashed / dotted / double / none)\n      new _DividerStyleControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.divider_style'), this.formatter.getFormat('divider_style', 'solid'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('divider_style', value);\n          _this2.render();\n        }\n      }, ['solid', 'dashed', 'dotted', 'double']),\n      // Divider colour — the template renders `background_color` as the\n      // border-top colour for every divider_style. Without this control\n      // users can't edit a colour set by the template (missing-control\n      // bug surfaced by InternationalWomensDay sample, 2026-04-16).\n      new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.color'), this.formatter.getFormat('background_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('background_color', value);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DividerElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DividerElement.js?");

/***/ }),

/***/ "./src/includes/DividerStyleControl.js":
/*!*********************************************!*\
  !*** ./src/includes/DividerStyleControl.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar DividerStyleControl = /*#__PURE__*/function () {\n  function DividerStyleControl(label, value, callback) {\n    var possibleValues = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ['solid', 'dashed', 'dotted', 'double'];\n    _classCallCheck(this, DividerStyleControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n    var iconMap = {\n      solid: 'horizontal_rule',\n      dashed: 'unknown_med',\n      dotted: 'more_horiz',\n      \"double\": 'equal'\n    };\n    this.options = possibleValues.map(function (val) {\n      return {\n        icon: iconMap[val] || 'horizontal_rule',\n        value: val\n      };\n    });\n    this.domNode = document.createElement(\"div\");\n    this.render();\n  }\n  return _createClass(DividerStyleControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var buttons = this.options.map(function (option) {\n        var isActive = _this.value === option.value;\n        return \"\\n        <button type=\\\"button\\\"\\n                class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n                role=\\\"radio\\\"\\n                aria-checked=\\\"\").concat(isActive, \"\\\"\\n                data-value=\\\"\").concat(option.value, \"\\\"\\n                data-tooltip=\\\"\").concat(option.value, \"\\\"\\n                aria-label=\\\"\").concat(option.value, \"\\\"\\n                tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n          <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(option.icon, \"</span>\\n        </button>\\n      \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"width: 180px;\\\">\\n            \").concat(buttons, \"\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      var group = this.domNode.querySelector('.bjs-segmented');\n      if (!group) return;\n      group.addEventListener('click', function (e) {\n        var btn = e.target.closest('.bjs-segmented-btn');\n        if (!btn || !group.contains(btn)) return;\n        _this2._selectValue(btn.dataset.value, {\n          focus: true\n        });\n      });\n      group.addEventListener('keydown', function (e) {\n        if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n        e.preventDefault();\n        var buttons = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n        var currentIndex = buttons.findIndex(function (b) {\n          return b.classList.contains('is-active');\n        });\n        var nextIndex = currentIndex;\n        if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n          nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n        } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n          nextIndex = (currentIndex + 1) % buttons.length;\n        } else if (e.key === 'Home') {\n          nextIndex = 0;\n        } else if (e.key === 'End') {\n          nextIndex = buttons.length - 1;\n        }\n        var nextBtn = buttons[nextIndex];\n        if (nextBtn) _this2._selectValue(nextBtn.dataset.value, {\n          focus: true\n        });\n      });\n    }\n  }, {\n    key: \"_selectValue\",\n    value: function _selectValue(value) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$focus = _ref.focus,\n        focus = _ref$focus === void 0 ? false : _ref$focus;\n      if (value === this.value) return;\n      this.value = value;\n      this._updateActiveState();\n      if (focus) {\n        var active = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n        if (active) active.focus();\n      }\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n  }, {\n    key: \"_updateActiveState\",\n    value: function _updateActiveState() {\n      var _this3 = this;\n      this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var isActive = btn.dataset.value === _this3.value;\n        btn.classList.toggle('is-active', isActive);\n        btn.setAttribute('aria-checked', String(isActive));\n        btn.setAttribute('tabindex', isActive ? '0' : '-1');\n      });\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      if (newValue === this.value) return;\n      this.value = newValue;\n      this._updateActiveState();\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DividerStyleControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DividerStyleControl.js?");

/***/ }),

/***/ "./src/includes/DividerWidget.js":
/*!***************************************!*\
  !*** ./src/includes/DividerWidget.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _DividerElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./DividerElement.js */ \"./src/includes/DividerElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar DividerWidget = /*#__PURE__*/function (_BaseWidget) {\n  function DividerWidget() {\n    var _this;\n    _classCallCheck(this, DividerWidget);\n    _this = _callSuper(this, DividerWidget); // Call the parent class constructor\n\n    // New element for Divider\n    var divider = new _DividerElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Divider');\n\n    // Append the new element to the block\n    _this.block.appendElements([divider]);\n    return _this;\n  }\n  _inherits(DividerWidget, _BaseWidget);\n  return _createClass(DividerWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.divider');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'border_horizontal';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DividerWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DividerWidget.js?");

/***/ }),

/***/ "./src/includes/DropdownControl.js":
/*!*****************************************!*\
  !*** ./src/includes/DropdownControl.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * DropdownControl — labeled value picker emitting `.bjs-select` primitive\n * (see builder.css §9 + ui-showcase #9).\n *\n * 2026-04-18 audit (§2.11): migrated from `.form-select` + hardcoded 140×32\n * inline styles + `builder-select-container` pad wrapper to `.bjs-control-\n * row` + `.bjs-select` (token-driven, dark-mode safe, consistent with the\n * rest of the panel). Consumers: CellElement (×4: display, flex-direction,\n * justify, align-items), PageElement. Both auto-upgrade — signature kept.\n *\n * Failure-state audit: options are validated against the provided `options`\n * array; if the incoming `value` doesn't match, the control still renders\n * the first option but surfaces a `.bjs-link-error` row with the stale\n * value so the user knows a legacy setting was migrated.\n */\nvar DropdownControl = /*#__PURE__*/function () {\n  /**\n   * @param {string}   label\n   * @param {string}   value        Current value\n   * @param {Array<{label: string, value: string}>} options\n   * @param {function} callback     Receives the new value string on change\n   */\n  function DropdownControl(label, value, options, callback) {\n    var _this = this;\n    _classCallCheck(this, DropdownControl);\n    this.id = '_ddl_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.options = Array.isArray(options) ? options : [];\n    this.callback = callback;\n    this.invalidValue = this.value !== null && this.value !== undefined && this.value !== '' && !this.options.some(function (o) {\n      return String(o.value) === String(_this.value);\n    }) ? this.value : null;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('dropdown-control');\n    this.render();\n    this._bindEvents();\n  }\n  return _createClass(DropdownControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this2 = this;\n      var optsHtml = this.options.map(function (opt) {\n        var selected = String(_this2.value) === String(opt.value) ? ' selected' : '';\n        return \"<option value=\\\"\".concat(opt.value, \"\\\"\").concat(selected, \">\").concat(opt.label, \"</option>\");\n      }).join('');\n      var errorLine = this.invalidValue ? \"<span class=\\\"bjs-link-error\\\" role=\\\"status\\\">Unknown value \\\"\".concat(String(this.invalidValue).replace(/\"/g, '&quot;'), \"\\\" \\u2014 migrated to default.</span>\") : '';\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\">\\n          <span>\".concat(this.label, \"</span>\\n        </div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-select\\\">\\n            <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\">\").concat(optsHtml, \"</select>\\n            <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n          </div>\\n        </div>\\n      </div>\\n      \").concat(errorLine, \"\\n    \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this3 = this;\n      var sel = this.domNode.querySelector(\"#\".concat(this.id));\n      if (!sel) return;\n      sel.addEventListener('change', function (e) {\n        _this3.value = e.target.value;\n        var hadError = !!_this3.invalidValue;\n        _this3.invalidValue = null;\n        if (hadError) {\n          _this3.render();\n          _this3._bindEvents();\n        }\n        if (typeof _this3.callback === 'function') _this3.callback(_this3.value);\n      });\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      var sel = this.domNode.querySelector(\"#\".concat(this.id));\n      if (sel) sel.value = newValue;\n      if (typeof this.callback === 'function') this.callback(this.value);\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DropdownControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/DropdownControl.js?");

/***/ }),

/***/ "./src/includes/ElementFactory.js":
/*!****************************************!*\
  !*** ./src/includes/ElementFactory.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   ELEMENT_REGISTRY: () => (/* binding */ ELEMENT_REGISTRY),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n// Element registry. Mutable `Map` (post-CD-1, AIBuilder Wave 1 / 2026-05-04) so\n// host apps can register new element types via `Builder.registerElement(name, klass)`\n// without forking BuilderJS. Key = JSON `name` (used in saved templates); value =\n// constructor name on `window`. The constructor itself is resolved at lookup time\n// so subclasses can replace a prior registration. Stock elements are seeded below;\n// custom registrations append to the same Map.\n//\n// See `docs/core/USAGE.md` → \"Registering custom elements (CD-1)\" and\n// `docs/core/ELEMENT_DEFINITION.md` → \"Registering a new Element class (CD-1)\".\nvar ELEMENT_REGISTRY = new Map([['AlertElement', 'AlertElement'], ['BlockElement', 'BlockElement'], ['ButtonElement', 'ButtonElement'], ['CheckboxElement', 'CheckboxElement'], ['CellElement', 'CellElement'], ['CheckoutElement', 'CheckoutElement'], ['CheckoutSimpleElement', 'CheckoutSimpleElement'], ['DividerElement', 'DividerElement'], ['FieldElement', 'FieldElement'], ['FormContainerCell', 'FormContainerCell'], ['GridElement', 'GridElement'], ['H1Element', 'H1Element'], ['H2Element', 'H2Element'], ['H3Element', 'H3Element'], ['H4Element', 'H4Element'], ['H5Element', 'H5Element'], ['HeadingElement', 'HeadingElement'], ['HTMLElement', 'HTMLElement'], ['ImageElement', 'ImageElement'], ['LabelElement', 'LabelElement'], ['LinkElement', 'LinkElement'], ['ListElement', 'ListElement'], ['MenuElement', 'MenuElement'], ['PElement', 'PElement'], ['PageElement', 'PageElement'], ['PricingCardsElement', 'PricingCardsElement'], ['PricingCardElement', 'PricingCardElement'], ['RadioElement', 'RadioElement'], ['RSSElement', 'RSSElement'], ['SelectElement', 'SelectElement'], ['SocialIconsElement', 'SocialIconsElement'], ['SubmitButtonElement', 'SubmitButtonElement'], ['TermsOfServiceElement', 'TermsOfServiceElement'], ['TextInputElement', 'TextInputElement'], ['VideoElement', 'VideoElement'], ['YoutubeElement', 'YoutubeElement']]);\nvar ElementFactory = /*#__PURE__*/function () {\n  function ElementFactory() {\n    _classCallCheck(this, ElementFactory);\n  }\n  return _createClass(ElementFactory, null, [{\n    key: \"getElementClass\",\n    value: function getElementClass(name) {\n      var constructorName = ELEMENT_REGISTRY.get(name);\n      if (!constructorName) {\n        throw new Error(\"Unknown element name: \".concat(name));\n      }\n      var elementClass = window[constructorName];\n      if (!elementClass || typeof elementClass.parse !== 'function') {\n        throw new Error(\"ElementFactory registry entry \\\"\".concat(constructorName, \"\\\" is not available at runtime.\"));\n      }\n      return elementClass;\n    }\n  }, {\n    key: \"createElement\",\n    value: function createElement(data) {\n      if (!data || _typeof(data) !== 'object') {\n        throw new Error('ElementFactory.createElement requires a data object.');\n      }\n      var elementClass = ElementFactory.getElementClass(data.name);\n      return elementClass.parse(data);\n    }\n  }]);\n}();\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ElementFactory);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ElementFactory.js?");

/***/ }),

/***/ "./src/includes/EventEmitter.js":
/*!**************************************!*\
  !*** ./src/includes/EventEmitter.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * EventEmitter — generic pub/sub primitive used by every Builder instance via\n * `builder.events`. Started life as `CanvasHighlightBus` (W0.1 control↔overlay\n * signalling); generalised in CD-3 (AIBuilder Wave 4) so host apps can drive\n * autosave, dirty-state tickers, and any other change-driven UX off the same\n * bus the History system + region-focus system already publish on.\n *\n * Design choices:\n *   - Map<event, Set<fn>>: fast add/remove, stable iteration order.\n *   - `on()` returns a disposer so subscribers can match the Phase 1.8\n *     Control-disposer pattern (BaseControl.addDisposer).\n *   - Listener throws caught via BJS.error so one bad subscriber cannot break\n *     the dispatch loop — same guarantee as BaseElement.notifySyncListeners\n *     (SA I15).\n *   - Iterate over a snapshot (Array.from) so a listener that unsubscribes\n *     itself during dispatch does not skip its sibling.\n *   - Per-event debounce config (CD-3): pass `{ debounce: { 'foo': 120 } }` to\n *     the constructor; emits to those events coalesce timers, with the LAST\n *     payload winning. `flushPending(name)` synchronously fires any pending\n *     debounced emit for that name (host calls this in Cmd-S handlers so the\n *     pending autosave's debounce doesn't race the manual save's PUT).\n *\n * Canonical events — see `docs/core/USAGE.md` \"Event bus (CD-3)\" for the\n * authoritative table. Adding a new event = update Builder.EVENTS + the\n * canonical-events table + R-bjs-docs in one commit. Drift = bug (RULE E).\n */\nvar EventEmitter = /*#__PURE__*/function () {\n  /**\n   * @param {Object} [options]\n   * @param {Object<string, number>} [options.debounce]  event-name → debounce ms.\n   */\n  function EventEmitter() {\n    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n    _classCallCheck(this, EventEmitter);\n    this._listeners = new Map();\n    this._debounce = new Map();\n    this._pending = new Map(); // name → { timerId, payload }\n\n    var debounceCfg = options && options.debounce || {};\n    for (var _i = 0, _Object$entries = Object.entries(debounceCfg); _i < _Object$entries.length; _i++) {\n      var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n        event = _Object$entries$_i[0],\n        ms = _Object$entries$_i[1];\n      if (typeof ms === 'number' && ms > 0) {\n        this._debounce.set(event, ms);\n      }\n    }\n  }\n\n  /**\n   * Subscribe to an event. Returns a disposer function — call it to\n   * unsubscribe. Safe to call the disposer multiple times.\n   */\n  return _createClass(EventEmitter, [{\n    key: \"on\",\n    value: function on(event, fn) {\n      var _this = this;\n      if (typeof event !== 'string' || !event) {\n        throw new Error('EventEmitter.on: event must be a non-empty string');\n      }\n      if (typeof fn !== 'function') {\n        throw new Error('EventEmitter.on: fn must be a function');\n      }\n      var set = this._listeners.get(event);\n      if (!set) {\n        set = new Set();\n        this._listeners.set(event, set);\n      }\n      set.add(fn);\n      return function () {\n        return _this.off(event, fn);\n      };\n    }\n\n    /** Explicit unsubscribe. Idempotent. */\n  }, {\n    key: \"off\",\n    value: function off(event, fn) {\n      var set = this._listeners.get(event);\n      if (!set) return;\n      set[\"delete\"](fn);\n      if (set.size === 0) this._listeners[\"delete\"](event);\n    }\n\n    /**\n     * Dispatch an event. If the event has a configured debounce window, the\n     * call coalesces — only the LAST payload within the window fires when the\n     * timer expires. Otherwise dispatch is synchronous.\n     */\n  }, {\n    key: \"emit\",\n    value: function emit(event, payload) {\n      if (this._debounce.has(event)) {\n        this._scheduleDebounced(event, payload);\n        return;\n      }\n      this._dispatch(event, payload);\n    }\n\n    /**\n     * Synchronously fire any pending debounced emit for `event` and cancel\n     * the timer. No-op if nothing is pending. Use case: a host whose UX needs\n     * a deterministic \"no debounce in flight after this returns\" guarantee\n     * (e.g. Cmd-S consuming the pending document:changed before issuing PUT).\n     */\n  }, {\n    key: \"flushPending\",\n    value: function flushPending(event) {\n      var pending = this._pending.get(event);\n      if (!pending) return;\n      clearTimeout(pending.timerId);\n      this._pending[\"delete\"](event);\n      this._dispatch(event, pending.payload);\n    }\n\n    /** Cancel pending debounced emits + drop every listener. Tests + teardown. */\n  }, {\n    key: \"clear\",\n    value: function clear() {\n      var _iterator = _createForOfIteratorHelper(this._pending.values()),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var timerId = _step.value.timerId;\n          clearTimeout(timerId);\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n      this._pending.clear();\n      this._listeners.clear();\n    }\n\n    /** Debug / test helper — how many listeners for `event`. */\n  }, {\n    key: \"listenerCount\",\n    value: function listenerCount(event) {\n      var set = this._listeners.get(event);\n      return set ? set.size : 0;\n    }\n\n    /** Debug / test helper — true when a debounced emit is queued for `event`. */\n  }, {\n    key: \"hasPending\",\n    value: function hasPending(event) {\n      return this._pending.has(event);\n    }\n  }, {\n    key: \"_scheduleDebounced\",\n    value: function _scheduleDebounced(event, payload) {\n      var _this2 = this;\n      var ms = this._debounce.get(event);\n      var existing = this._pending.get(event);\n      if (existing) clearTimeout(existing.timerId);\n      var timerId = setTimeout(function () {\n        _this2._pending[\"delete\"](event);\n        _this2._dispatch(event, payload);\n      }, ms);\n      this._pending.set(event, {\n        timerId: timerId,\n        payload: payload\n      });\n    }\n  }, {\n    key: \"_dispatch\",\n    value: function _dispatch(event, payload) {\n      var set = this._listeners.get(event);\n      if (!set || set.size === 0) return;\n      for (var _i2 = 0, _Array$from = Array.from(set); _i2 < _Array$from.length; _i2++) {\n        var fn = _Array$from[_i2];\n        try {\n          fn(payload);\n        } catch (err) {\n          _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error(\"event-bus:listener \\\"\".concat(event, \"\\\"\"), err);\n        }\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EventEmitter);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/EventEmitter.js?");

/***/ }),

/***/ "./src/includes/FieldConfigControl.js":
/*!********************************************!*\
  !*** ./src/includes/FieldConfigControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * FieldConfigControl — flat panel for FieldElement.\n *\n * Bundles every field-shaping knob (visibility of label + content of label,\n * placeholder, default value, required flag + indicator + custom messages)\n * into one panel. No panel chrome — rows align with sibling sidebar\n * primitives at the natural sidebar inset.\n *\n * Conditional UI (`_syncConditionalRows`):\n *   • field-label row     — hidden when `showLabel === false`\n *   • placeholder row     — hidden for `date|datetime|checkbox|radio`\n *                           (those input types don't render a placeholder)\n *   • required toggle     — disabled when `requiredEditable === false`\n *   • locked-hint banner  — visible only when `requiredEditable === false &&\n *                           requiredEditableHint` is non-empty\n *   • indicator picker    — hidden when `!showLabel || !required`\n *   • msg-required row    — hidden when `required === false`\n *   • msg-email row       — visible only when `fieldType === 'email'`\n *\n * Toggle visibility via `is-hidden` class — DO NOT remove rows from DOM,\n * so values survive a `fieldType` / `showLabel` / `required` round-trip.\n *\n * Callback contract:\n *   callback.setValues({ fieldLabel?, fieldPlaceholder?, fieldValue?,\n *                        required?, errorMessage?, emailErrorMessage?,\n *                        showLabel?, requiredIndicator? })\n *   The element merges + re-renders; only present keys are applied.\n *   `requiredEditable` / `requiredEditableHint` are host-provided\n *   read-only flags — the panel never emits them back.\n */\nvar FieldConfigControl = /*#__PURE__*/function () {\n  function FieldConfigControl(label, value, callback) {\n    _classCallCheck(this, FieldConfigControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = {\n      fieldType: value && typeof value.fieldType === 'string' ? value.fieldType : 'text',\n      fieldLabel: value && value.fieldLabel != null ? String(value.fieldLabel) : '',\n      fieldPlaceholder: value && value.fieldPlaceholder != null ? String(value.fieldPlaceholder) : '',\n      fieldValue: value && value.fieldValue != null ? String(value.fieldValue) : '',\n      required: !!(value && value.required),\n      errorMessage: value && typeof value.errorMessage === 'string' ? value.errorMessage : '',\n      emailErrorMessage: value && typeof value.emailErrorMessage === 'string' ? value.emailErrorMessage : '',\n      showLabel: value && value.showLabel === undefined ? true : !!(value && value.showLabel),\n      requiredIndicator: value && typeof value.requiredIndicator === 'string' ? value.requiredIndicator : '',\n      requiredEditable: value && value.requiredEditable === undefined ? true : !!(value && value.requiredEditable),\n      requiredEditableHint: value && typeof value.requiredEditableHint === 'string' ? value.requiredEditableHint : '',\n      requiredEditableHintActionText: value && typeof value.requiredEditableHintActionText === 'string' ? value.requiredEditableHintActionText : '',\n      requiredEditableHintActionUrl: value && typeof value.requiredEditableHintActionUrl === 'string' ? value.requiredEditableHintActionUrl : ''\n    };\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-field-config-control');\n\n    // Per-input debounce handles. Distinct timers so a fast typist\n    // alternating between fields doesn't cancel each other's commits.\n    this._labelDebounce = null;\n    this._placeholderDebounce = null;\n    this._valueDebounce = null;\n    this._errorDebounce = null;\n    this._emailErrorDebounce = null;\n    this._indicatorDebounce = null;\n    this.render();\n  }\n  return _createClass(FieldConfigControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this$value$fieldLabe, _this$value$fieldPlac, _this$value$fieldValu, _this$value$requiredI, _this$value$errorMess, _this$value$emailErro;\n      var escapeAttr = function escapeAttr(s) {\n        return String(s == null ? '' : s).replace(/\"/g, '&quot;');\n      };\n      var escapeText = function escapeText(s) {\n        return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n      };\n\n      // Indicator preset chips. Labels come from i18n; the `text` preset's\n      // chip label IS the i18n string (so the chip reads \"required\" /\n      // \"bắt buộc\" depending on locale).\n      var presets = FieldConfigControl.INDICATOR_PRESETS;\n      var presetButtons = presets.map(function (p) {\n        var labelKey = \"controls.field_required_indicator_preset_\".concat(p.id);\n        return \"\\n                <button type=\\\"button\\\"\\n                        class=\\\"bjs-segmented-btn\\\"\\n                        data-preset=\\\"\".concat(escapeAttr(p.id), \"\\\"\\n                        role=\\\"radio\\\"\\n                        aria-checked=\\\"false\\\"\\n                        tabindex=\\\"-1\\\">\\n                    \").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey)), \"\\n                </button>\\n            \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__head\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label><span>\".concat(escapeText(this.label), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_settings_help')), \"</span>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-row bjs-field-config-control__show-label-row\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_show_label_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_show_label')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_show_label_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <label class=\\\"bjs-toggle\\\">\\n                        <input id=\\\"field_show_label_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" />\\n                        <span class=\\\"bjs-toggle-track\\\"><span class=\\\"bjs-toggle-thumb\\\"></span></span>\\n                    </label>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__label-row\\\" data-row=\\\"field-label\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_label_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_label')), \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"field_label_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__placeholder-row\\\" data-row=\\\"placeholder\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_placeholder_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.placeholder')), \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"field_placeholder_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__default-row\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_default_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_default')), \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"field_default_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-row bjs-field-config-control__required-row\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_required_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <label class=\\\"bjs-toggle\\\">\\n                        <input id=\\\"field_required_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" />\\n                        <span class=\\\"bjs-toggle-track\\\"><span class=\\\"bjs-toggle-thumb\\\"></span></span>\\n                    </label>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-info-banner bjs-field-config-control__locked-hint\\\" data-row=\\\"required-locked-hint\\\" role=\\\"note\\\">\\n                <span class=\\\"bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\\u24D8</span>\\n                <span class=\\\"bjs-info-banner-text\\\" data-slot=\\\"locked-hint-text\\\"></span>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__indicator-row\\\" data-row=\\\"required-indicator\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-segmented bjs-field-config-control__indicator-presets\\\" data-group=\\\"indicator-preset\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator')), \"\\\">\\n                        \").concat(presetButtons, \"\\n                    </div>\\n                    <input id=\\\"field_indicator_\").concat(this.id, \"\\\"\\n                           type=\\\"text\\\"\\n                           class=\\\"bjs-text-input bjs-field-config-control__indicator-input\\\"\\n                           data-row=\\\"indicator-custom\\\"\\n                           placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_custom_placeholder')), \"\\\" />\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__msg-required-row\\\" data-row=\\\"msg-required\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_msg_required_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_required')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_required_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"field_msg_required_\").concat(this.id, \"\\\"\\n                           type=\\\"text\\\"\\n                           class=\\\"bjs-text-input\\\"\\n                           placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_required_placeholder')), \"\\\" />\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-field-config-control__msg-email-row\\\" data-row=\\\"msg-email\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"field_msg_email_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_email')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_email_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"field_msg_email_\").concat(this.id, \"\\\"\\n                           type=\\\"text\\\"\\n                           class=\\\"bjs-text-input\\\"\\n                           placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_msg_email_placeholder')), \"\\\" />\\n                </div>\\n            </div>\\n\\n            <p class=\\\"bjs-field-config-control__hint\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_inline_hint')), \"</p>\\n        \");\n\n      // Hydrate inputs from current value\n      this._showLabelInput().checked = !!this.value.showLabel;\n      this._labelInput().value = (_this$value$fieldLabe = this.value.fieldLabel) !== null && _this$value$fieldLabe !== void 0 ? _this$value$fieldLabe : '';\n      this._placeholderInput().value = (_this$value$fieldPlac = this.value.fieldPlaceholder) !== null && _this$value$fieldPlac !== void 0 ? _this$value$fieldPlac : '';\n      this._defaultInput().value = (_this$value$fieldValu = this.value.fieldValue) !== null && _this$value$fieldValu !== void 0 ? _this$value$fieldValu : '';\n      this._requiredInput().checked = !!this.value.required;\n      this._requiredInput().disabled = !this.value.requiredEditable;\n      // Match the ui-showcase disabled-toggle convention: the host\n      // `<label class=\"bjs-toggle\">` carries the visual disabled state via\n      // an `is-disabled` modifier (CSS dims opacity + blocks pointer events).\n      var requiredToggleLabel = this._requiredInput().closest('.bjs-toggle');\n      if (requiredToggleLabel) requiredToggleLabel.classList.toggle('is-disabled', !this.value.requiredEditable);\n      this._indicatorInput().value = (_this$value$requiredI = this.value.requiredIndicator) !== null && _this$value$requiredI !== void 0 ? _this$value$requiredI : '';\n      this._errorInput().value = (_this$value$errorMess = this.value.errorMessage) !== null && _this$value$errorMess !== void 0 ? _this$value$errorMess : '';\n      this._emailErrorInput().value = (_this$value$emailErro = this.value.emailErrorMessage) !== null && _this$value$emailErro !== void 0 ? _this$value$emailErro : '';\n\n      // Locked-hint text + optional CTA link. Library never invents copy —\n      // both the hint text AND the link text/url come from the host.\n      // HTML-escape both, then compose the markup safely (no innerHTML\n      // injection of host strings; we only inject the host strings into\n      // text content / href via escape helpers).\n      var hintSlot = this.domNode.querySelector('[data-slot=\"locked-hint-text\"]');\n      if (hintSlot) {\n        var hintHtml = escapeText(this.value.requiredEditableHint || '');\n        var actionText = this.value.requiredEditableHintActionText;\n        var actionUrl = this.value.requiredEditableHintActionUrl;\n        if (actionText && actionUrl) {\n          hintSlot.innerHTML = hintHtml + ' <a href=\"' + escapeAttr(actionUrl) + '\"' + ' target=\"_blank\" rel=\"noopener noreferrer\"' + ' class=\"bjs-field-config-control__locked-hint-link\">' + escapeText(actionText) + '</a>';\n        } else {\n          hintSlot.textContent = this.value.requiredEditableHint || '';\n        }\n      }\n      this._syncIndicatorActive();\n      this._syncConditionalRows();\n      this._bindEvents();\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      // Show-label toggle — instant commit.\n      this._showLabelInput().addEventListener('change', function (e) {\n        _this.value.showLabel = !!e.target.checked;\n        _this._syncConditionalRows();\n        _this._emit({\n          showLabel: _this.value.showLabel\n        });\n      });\n\n      // Field-label input — debounced 200ms.\n      this._labelInput().addEventListener('input', function () {\n        if (_this._labelDebounce) clearTimeout(_this._labelDebounce);\n        _this._labelDebounce = setTimeout(function () {\n          _this.value.fieldLabel = _this._labelInput().value;\n          _this._emit({\n            fieldLabel: _this.value.fieldLabel\n          });\n        }, 200);\n      });\n\n      // Placeholder input — debounced 200ms.\n      this._placeholderInput().addEventListener('input', function () {\n        if (_this._placeholderDebounce) clearTimeout(_this._placeholderDebounce);\n        _this._placeholderDebounce = setTimeout(function () {\n          _this.value.fieldPlaceholder = _this._placeholderInput().value;\n          _this._emit({\n            fieldPlaceholder: _this.value.fieldPlaceholder\n          });\n        }, 200);\n      });\n\n      // Default-value input — debounced 200ms.\n      this._defaultInput().addEventListener('input', function () {\n        if (_this._valueDebounce) clearTimeout(_this._valueDebounce);\n        _this._valueDebounce = setTimeout(function () {\n          _this.value.fieldValue = _this._defaultInput().value;\n          _this._emit({\n            fieldValue: _this.value.fieldValue\n          });\n        }, 200);\n      });\n\n      // Required toggle — instant commit. Disabled state respects the\n      // `requiredEditable` host flag; the disabled attr blocks the change\n      // event already, but we double-guard so a programmatic .click()\n      // doesn't sneak past.\n      this._requiredInput().addEventListener('change', function (e) {\n        if (!_this.value.requiredEditable) {\n          e.target.checked = !!_this.value.required; // snap back\n          return;\n        }\n        _this.value.required = !!e.target.checked;\n        _this._syncConditionalRows();\n        _this._emit({\n          required: _this.value.required\n        });\n      });\n\n      // Indicator preset chips\n      var presetGroup = this.domNode.querySelector('.bjs-segmented[data-group=\"indicator-preset\"]');\n      if (presetGroup) {\n        presetGroup.addEventListener('click', function (e) {\n          var btn = e.target.closest('.bjs-segmented-btn');\n          if (!btn || !presetGroup.contains(btn)) return;\n          _this._applyIndicatorPreset(btn.dataset.preset);\n        });\n      }\n\n      // Indicator custom-text input — debounced 200ms. Free-typing\n      // immediately switches the active chip to \"Custom\" via _syncIndicatorActive.\n      this._indicatorInput().addEventListener('input', function () {\n        if (_this._indicatorDebounce) clearTimeout(_this._indicatorDebounce);\n        _this._indicatorDebounce = setTimeout(function () {\n          _this.value.requiredIndicator = _this._indicatorInput().value;\n          _this._syncIndicatorActive();\n          _this._emit({\n            requiredIndicator: _this.value.requiredIndicator\n          });\n        }, 200);\n      });\n\n      // Required-message input — debounced 200ms.\n      this._errorInput().addEventListener('input', function () {\n        if (_this._errorDebounce) clearTimeout(_this._errorDebounce);\n        _this._errorDebounce = setTimeout(function () {\n          _this.value.errorMessage = _this._errorInput().value;\n          _this._emit({\n            errorMessage: _this.value.errorMessage\n          });\n        }, 200);\n      });\n\n      // Email-format-message input — debounced 200ms.\n      this._emailErrorInput().addEventListener('input', function () {\n        if (_this._emailErrorDebounce) clearTimeout(_this._emailErrorDebounce);\n        _this._emailErrorDebounce = setTimeout(function () {\n          _this.value.emailErrorMessage = _this._emailErrorInput().value;\n          _this._emit({\n            emailErrorMessage: _this.value.emailErrorMessage\n          });\n        }, 200);\n      });\n    }\n  }, {\n    key: \"_applyIndicatorPreset\",\n    value: function _applyIndicatorPreset(presetId) {\n      var nextValue = this.value.requiredIndicator;\n      if (presetId === 'none') nextValue = '';else if (presetId === 'star') nextValue = '★';else if (presetId === 'asterisk') nextValue = '*';else if (presetId === 'text') nextValue = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_preset_text_value');else if (presetId === 'custom') {\n        // \"Custom\" doesn't change the value — focuses the input so the\n        // author can free-type. If the current value matches another\n        // preset, clear it so \"Custom\" reads as a fresh slate.\n        var matchedPreset = this._matchPresetId(this.value.requiredIndicator);\n        if (matchedPreset && matchedPreset !== 'custom') {\n          nextValue = '';\n        }\n        this.value.requiredIndicator = nextValue;\n        this._indicatorInput().value = nextValue;\n        this._indicatorInput().focus();\n        this._syncIndicatorActive('custom');\n        this._emit({\n          requiredIndicator: nextValue\n        });\n        return;\n      }\n      this.value.requiredIndicator = nextValue;\n      this._indicatorInput().value = nextValue;\n      this._syncIndicatorActive(presetId);\n      this._emit({\n        requiredIndicator: nextValue\n      });\n    }\n  }, {\n    key: \"_matchPresetId\",\n    value: function _matchPresetId(value) {\n      if (value === '') return 'none';\n      if (value === '★') return 'star';\n      if (value === '*') return 'asterisk';\n      if (value === _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_preset_text_value')) return 'text';\n      return null; // free text — Custom\n    }\n  }, {\n    key: \"_syncIndicatorActive\",\n    value: function _syncIndicatorActive() {\n      var forcedId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n      var group = this.domNode.querySelector('.bjs-segmented[data-group=\"indicator-preset\"]');\n      if (!group) return;\n      var matchId = forcedId || this._matchPresetId(this.value.requiredIndicator) || 'custom';\n      group.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var isActive = btn.dataset.preset === matchId;\n        btn.classList.toggle('is-active', isActive);\n        btn.setAttribute('aria-checked', isActive ? 'true' : 'false');\n        btn.setAttribute('tabindex', isActive ? '0' : '-1');\n      });\n\n      // Custom-input visibility — only show when \"Custom\" preset is active.\n      // Selecting any other preset (None/★/*/(required)) hides the input\n      // since the value is already set by the preset literal.\n      var customInput = this._indicatorInput();\n      if (customInput) customInput.classList.toggle('is-hidden', matchId !== 'custom');\n    }\n  }, {\n    key: \"_syncConditionalRows\",\n    value: function _syncConditionalRows() {\n      // field-label row — only when label is shown\n      var labelRow = this.domNode.querySelector('[data-row=\"field-label\"]');\n      if (labelRow) labelRow.classList.toggle('is-hidden', !this.value.showLabel);\n\n      // placeholder row — only for input types that render a placeholder\n      var placeholderRow = this.domNode.querySelector('[data-row=\"placeholder\"]');\n      if (placeholderRow) {\n        var noPlaceholder = FieldConfigControl.PLACEHOLDER_DISABLED_TYPES.includes(this.value.fieldType);\n        placeholderRow.classList.toggle('is-hidden', noPlaceholder);\n      }\n\n      // locked-hint banner — only when locked AND host supplied a hint\n      var lockedHint = this.domNode.querySelector('[data-row=\"required-locked-hint\"]');\n      if (lockedHint) {\n        var showLockedHint = !this.value.requiredEditable && !!this.value.requiredEditableHint;\n        lockedHint.classList.toggle('is-hidden', !showLockedHint);\n      }\n\n      // indicator picker — only when the label IS visible AND required IS on\n      var indicatorRow = this.domNode.querySelector('[data-row=\"required-indicator\"]');\n      if (indicatorRow) {\n        var hide = !this.value.showLabel || !this.value.required;\n        indicatorRow.classList.toggle('is-hidden', hide);\n      }\n\n      // msg-required row — only when required is on\n      var msgRequiredRow = this.domNode.querySelector('[data-row=\"msg-required\"]');\n      if (msgRequiredRow) msgRequiredRow.classList.toggle('is-hidden', !this.value.required);\n\n      // msg-email row — only for email type\n      var msgEmailRow = this.domNode.querySelector('[data-row=\"msg-email\"]');\n      if (msgEmailRow) msgEmailRow.classList.toggle('is-hidden', this.value.fieldType !== 'email');\n    }\n  }, {\n    key: \"_emit\",\n    value: function _emit(patch) {\n      if (this.callback && typeof this.callback.setValues === 'function') {\n        this.callback.setValues(patch);\n      }\n    }\n  }, {\n    key: \"_showLabelInput\",\n    value: function _showLabelInput() {\n      return this.domNode.querySelector(\"#field_show_label_\".concat(this.id));\n    }\n  }, {\n    key: \"_labelInput\",\n    value: function _labelInput() {\n      return this.domNode.querySelector(\"#field_label_\".concat(this.id));\n    }\n  }, {\n    key: \"_placeholderInput\",\n    value: function _placeholderInput() {\n      return this.domNode.querySelector(\"#field_placeholder_\".concat(this.id));\n    }\n  }, {\n    key: \"_defaultInput\",\n    value: function _defaultInput() {\n      return this.domNode.querySelector(\"#field_default_\".concat(this.id));\n    }\n  }, {\n    key: \"_requiredInput\",\n    value: function _requiredInput() {\n      return this.domNode.querySelector(\"#field_required_\".concat(this.id));\n    }\n  }, {\n    key: \"_indicatorInput\",\n    value: function _indicatorInput() {\n      return this.domNode.querySelector(\"#field_indicator_\".concat(this.id));\n    }\n  }, {\n    key: \"_errorInput\",\n    value: function _errorInput() {\n      return this.domNode.querySelector(\"#field_msg_required_\".concat(this.id));\n    }\n  }, {\n    key: \"_emailErrorInput\",\n    value: function _emailErrorInput() {\n      return this.domNode.querySelector(\"#field_msg_email_\".concat(this.id));\n    }\n  }]);\n}();\n/** Field types that don't render a placeholder attribute on their input. */\n_defineProperty(FieldConfigControl, \"PLACEHOLDER_DISABLED_TYPES\", ['date', 'datetime', 'checkbox', 'radio']);\n/** Required-indicator presets. `id` is just for chip-active detection;\n *  `value` is the literal that gets written into `requiredIndicator`.\n *  The `text` preset reads its literal from i18n at apply-time so the\n *  user's locale-aware \"required\" word lands in the saved JSON. */\n_defineProperty(FieldConfigControl, \"INDICATOR_PRESETS\", [{\n  id: 'none',\n  value: ''\n}, {\n  id: 'star',\n  value: '★'\n}, {\n  id: 'asterisk',\n  value: '*'\n}, {\n  id: 'text',\n  value: null\n},\n// resolved at apply-time via i18n\n{\n  id: 'custom',\n  value: null\n} // free-text — see _applyIndicatorPreset\n]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FieldConfigControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FieldConfigControl.js?");

/***/ }),

/***/ "./src/includes/FieldElement.js":
/*!**************************************!*\
  !*** ./src/includes/FieldElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./FieldConfigControl.js */ \"./src/includes/FieldConfigControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n/**\n * FieldElement — generic input/select/textarea/checkbox/radio renderer for\n * subscriber-list custom fields.\n *\n * Validation contract (paired with the visitor-side jQuery validate gate):\n *   • `required` (bool) — emits the HTML5 `required` attribute on the input\n *     so the client-side gate fires before the AJAX submit. The server-side\n *     gate (e.g. the host's list-subscribe endpoint) is the safety net.\n *   • `errorMessage` (string) — overrides the default required-field message\n *     via `data-msg-required=\"…\"`. Empty falls through to the locale default.\n *   • `emailErrorMessage` (string) — only for `fieldType === 'email'`.\n *     Emits `data-msg-email=\"…\"` so format-mismatch text is independent of\n *     the required-empty text.\n *\n * Label / required UX (Phase 5):\n *   • `showLabel` (bool, default true) — when false, the `<label>` is omitted\n *     entirely from the rendered HTML. The required indicator (which lives\n *     inside the label) is also suppressed.\n *   • `requiredIndicator` (string, default '') — literal text/glyph rendered\n *     next to the label when `required && showLabel`. Empty = no indicator.\n *     Examples: `*`, `★`, `required`, `(required)`. Library renders raw —\n *     callers control content.\n *   • `requiredEditable` (bool, default true) — when false, the\n *     FieldConfigControl's required toggle renders as `disabled` and the\n *     accompanying hint replaces the toggle's edit affordance. Lets a host\n *     (whose list-field schema is the source of truth) prevent the\n *     in-builder author from desyncing the flag.\n *   • `requiredEditableHint` (string, default '') — caption shown beneath\n *     the disabled toggle. Caller passes locale-aware copy; library never\n *     defaults a string here (zero hardcoded strings — keeps BuilderJS\n *     standalone).\n *   • `requiredEditableHintActionText` + `requiredEditableHintActionUrl`\n *     (strings, default '') — optional CTA link appended to the locked\n *     hint. Both must be set for the link to render. The library\n *     URL-escapes the URL into the `href` attribute and HTML-escapes the\n *     text content; standalone callers passing empty values get plain\n *     hint text with no link.\n *\n * Inline edit: `fieldLabel` is registered with the BaseElement inline-edit\n * framework — fixes the latent Guard A bug where the template stamped the\n * marker but the element never registered it.\n */\nvar FieldElement = /*#__PURE__*/function (_BaseElement) {\n  function FieldElement(template, fieldType, fieldName, fieldValue, fieldLabel, fieldPlaceholder, fieldOptions) {\n    var _this;\n    var required = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;\n    var errorMessage = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : '';\n    var emailErrorMessage = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : '';\n    var showLabel = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : true;\n    var requiredIndicator = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : '';\n    var requiredIndicatorColor = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : '#9b1c2e';\n    var requiredEditable = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : true;\n    var requiredEditableHint = arguments.length > 14 && arguments[14] !== undefined ? arguments[14] : '';\n    var requiredEditableHintActionText = arguments.length > 15 && arguments[15] !== undefined ? arguments[15] : '';\n    var requiredEditableHintActionUrl = arguments.length > 16 && arguments[16] !== undefined ? arguments[16] : '';\n    _classCallCheck(this, FieldElement);\n    _this = _callSuper(this, FieldElement);\n    _this.template = template;\n    _this.fieldType = fieldType;\n    _this.fieldName = fieldName;\n    _this.fieldValue = fieldValue;\n    _this.fieldLabel = fieldLabel;\n    _this.fieldPlaceholder = fieldPlaceholder;\n    _this.fieldOptions = fieldOptions;\n    _this.required = !!required;\n    _this.errorMessage = typeof errorMessage === 'string' ? errorMessage : '';\n    _this.emailErrorMessage = typeof emailErrorMessage === 'string' ? emailErrorMessage : '';\n    _this.showLabel = showLabel === undefined ? true : !!showLabel;\n    _this.requiredIndicator = typeof requiredIndicator === 'string' ? requiredIndicator : '';\n    _this.requiredIndicatorColor = typeof requiredIndicatorColor === 'string' && requiredIndicatorColor ? requiredIndicatorColor : '#9b1c2e';\n    _this.requiredEditable = requiredEditable === undefined ? true : !!requiredEditable;\n    _this.requiredEditableHint = typeof requiredEditableHint === 'string' ? requiredEditableHint : '';\n    _this.requiredEditableHintActionText = typeof requiredEditableHintActionText === 'string' ? requiredEditableHintActionText : '';\n    _this.requiredEditableHintActionUrl = typeof requiredEditableHintActionUrl === 'string' ? requiredEditableHintActionUrl : '';\n    _this.domNode = null;\n\n    // Guard V — every key the template MUST receive. The new optional\n    // keys (`required` / `errorMessage` / `emailErrorMessage` /\n    // `showLabel` / `requiredIndicator`) are NOT listed here so legacy\n    // themes that don't reference them keep parsing.\n    _this.requiredTemplateKeys = ['fieldType', 'fieldName', 'fieldValue', 'fieldLabel', 'fieldPlaceholder', 'fieldOptions'];\n\n    // Inline edit on the field label. MUST run AFTER `this.fieldLabel = …`\n    // (Guard C: the property must exist on `this` at registration time).\n    _this.registerInlineEdit('fieldLabel');\n    return _this;\n  }\n\n  // Webpack mangling guard — registry + JSON `name` field must be stable.\n  _inherits(FieldElement, _BaseElement);\n  return _createClass(FieldElement, [{\n    key: \"getClassName\",\n    value: function getClassName() {\n      return 'FieldElement';\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      this.domNode.innerHTML = this.renderTemplate({\n        fieldType: this.fieldType,\n        fieldName: this.fieldName,\n        fieldValue: this.fieldValue,\n        fieldLabel: this.fieldLabel,\n        fieldPlaceholder: this.fieldPlaceholder,\n        fieldOptions: this.fieldOptions,\n        required: this.required,\n        errorMessage: this.errorMessage,\n        emailErrorMessage: this.emailErrorMessage,\n        showLabel: this.showLabel,\n        requiredIndicator: this.requiredIndicator,\n        requiredIndicatorColor: this.requiredIndicatorColor\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      var _this$fieldOptions;\n      return _objectSpread(_objectSpread({}, _superPropGet(FieldElement, \"getData\", this, 3)([])), {}, {\n        fieldType: this.fieldType,\n        fieldName: this.fieldName,\n        fieldValue: this.fieldValue,\n        fieldLabel: this.fieldLabel,\n        fieldPlaceholder: this.fieldPlaceholder,\n        fieldOptions: (_this$fieldOptions = this.fieldOptions) !== null && _this$fieldOptions !== void 0 ? _this$fieldOptions : [],\n        required: !!this.required,\n        errorMessage: this.errorMessage || '',\n        emailErrorMessage: this.emailErrorMessage || '',\n        showLabel: !!this.showLabel,\n        requiredIndicator: this.requiredIndicator || '',\n        requiredIndicatorColor: this.requiredIndicatorColor || '#9b1c2e'\n        // requiredEditable + requiredEditableHint are PROVENANCE flags —\n        // the host re-passes them on every construction (they describe\n        // \"is this field's required-flag locked by an external schema?\").\n        // Persisting them in the saved JSON would let stale lock-state\n        // outlive the host's source of truth. So they're intentionally\n        // omitted from getData() / parse().\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      var controls = [];\n      controls.push(new _FieldConfigControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_settings'), {\n        fieldType: this.fieldType,\n        fieldLabel: this.fieldLabel,\n        fieldPlaceholder: this.fieldPlaceholder,\n        fieldValue: this.fieldValue,\n        required: this.required,\n        errorMessage: this.errorMessage,\n        emailErrorMessage: this.emailErrorMessage,\n        showLabel: this.showLabel,\n        requiredIndicator: this.requiredIndicator,\n        requiredIndicatorColor: this.requiredIndicatorColor,\n        requiredEditable: this.requiredEditable,\n        requiredEditableHint: this.requiredEditableHint,\n        requiredEditableHintActionText: this.requiredEditableHintActionText,\n        requiredEditableHintActionUrl: this.requiredEditableHintActionUrl\n      }, {\n        setValues: function setValues(patch) {\n          if ('fieldLabel' in patch) _this2.fieldLabel = patch.fieldLabel;\n          if ('fieldPlaceholder' in patch) _this2.fieldPlaceholder = patch.fieldPlaceholder;\n          if ('fieldValue' in patch) _this2.fieldValue = patch.fieldValue;\n          if ('required' in patch) _this2.required = !!patch.required;\n          if ('errorMessage' in patch) _this2.errorMessage = patch.errorMessage || '';\n          if ('emailErrorMessage' in patch) _this2.emailErrorMessage = patch.emailErrorMessage || '';\n          if ('showLabel' in patch) _this2.showLabel = !!patch.showLabel;\n          if ('requiredIndicator' in patch) _this2.requiredIndicator = patch.requiredIndicator || '';\n          if ('requiredIndicatorColor' in patch) _this2.requiredIndicatorColor = patch.requiredIndicatorColor || '#9b1c2e';\n          _this2.render();\n        }\n      }));\n\n      // Indicator-color picker — only meaningful when the field is\n      // required, an indicator literal is set, AND the label is shown.\n      // Built from the canonical `ColorPickerControl` primitive (same\n      // panel chrome / popover UX as every other colour control in the\n      // sidebar) instead of inventing a one-off picker. Sits as a sibling\n      // control below the FieldConfigControl panel.\n      if (this.required && this.requiredIndicator && this.showLabel) {\n        controls.push(new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.field_required_indicator_color'), this.requiredIndicatorColor, {\n          setValue: function setValue(color) {\n            _this2.requiredIndicatorColor = color || '#9b1c2e';\n            _this2.render();\n          }\n        }));\n      }\n      return controls;\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      // Backwards-compat: legacy JSON pre-Phase-1 has no `required` /\n      // `errorMessage` / `emailErrorMessage`; pre-Phase-5 has no\n      // `showLabel` / `requiredIndicator`. Defaults preserve the\n      // pre-feature visual: required gate off, label visible, no indicator.\n      return new this(data.template, data.fieldType, data.fieldName, data.fieldValue, data.fieldLabel, data.fieldPlaceholder, data.fieldOptions, data.required !== undefined ? !!data.required : false, typeof data.errorMessage === 'string' ? data.errorMessage : '', typeof data.emailErrorMessage === 'string' ? data.emailErrorMessage : '', data.showLabel !== undefined ? !!data.showLabel : true, typeof data.requiredIndicator === 'string' ? data.requiredIndicator : '', typeof data.requiredIndicatorColor === 'string' && data.requiredIndicatorColor ? data.requiredIndicatorColor : '#9b1c2e'\n      // requiredEditable / requiredEditableHint NOT read from data —\n      // they're host-provided (see getData() comment).\n      );\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FieldElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FieldElement.js?");

/***/ }),

/***/ "./src/includes/FontFamilyControl.js":
/*!*******************************************!*\
  !*** ./src/includes/FontFamilyControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * FontFamilyControl — sidebar + popover font-family picker.\n *\n * 2026-04-24 (W3.1) — optional 4th-arg `options = { bus, elementUid,\n * formatterKey }` adds bus subscribe/emit so this control dual-mounts\n * across sidebar AND the canvas FontPopoverOverlay. When the popover\n * writes a new font-family via `element.formatter.setFormat + emit\n * formatter:change`, every sidebar instance with matching elementUid +\n * formatterKey (and foreign `source`) silently mirrors the change —\n * UI flips, callback does NOT refire. Zero regression for legacy\n * 3-arg callers.\n */\nvar FontFamilyControl = /*#__PURE__*/function () {\n  function FontFamilyControl(label, font_family, callback) {\n    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, FontFamilyControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.font_family = font_family || \"\";\n    this.callback = callback;\n    this._options = {\n      bus: options.bus || null,\n      elementUid: options.elementUid || null,\n      formatterKey: options.formatterKey || null\n    };\n    this._busOff = null;\n    this._busSource = 'font-family-control:' + this.id;\n    this.domNode = document.createElement(\"div\");\n    this.render();\n    this._attachBusSubscription();\n  }\n  return _createClass(FontFamilyControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var fontList = [{\n        name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font.system_inherit'),\n        value: \"inherit\"\n      }, {\n        name: \"Arial\",\n        value: \"Arial, Helvetica, sans-serif\"\n      }, {\n        name: \"Verdana\",\n        value: \"Verdana, Geneva, sans-serif\"\n      }, {\n        name: \"Times New Roman\",\n        value: '\"Times New Roman\", Times, serif'\n      }, {\n        name: \"Georgia\",\n        value: 'Georgia, \"Times New Roman\", serif'\n      }, {\n        name: \"Courier New\",\n        value: '\"Courier New\", Courier, monospace'\n      }, {\n        name: \"Trebuchet MS\",\n        value: '\"Trebuchet MS\", Helvetica, sans-serif'\n      }, {\n        name: \"Tahoma\",\n        value: \"Tahoma, Geneva, sans-serif\"\n      }, {\n        name: \"Impact\",\n        value: \"Impact, Charcoal, sans-serif\"\n      }, {\n        name: \"Inter\",\n        value: '\"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif'\n      }, {\n        name: \"Roboto\",\n        value: '\"Roboto\", Arial, sans-serif'\n      }];\n      var optionsHtml = [\"<option value=\\\"\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font.not_set'), \"</option>\")].concat(_toConsumableArray(fontList.map(function (font) {\n        var selected = String(_this.font_family) === String(font.value) ? ' selected' : '';\n        var escapedValue = font.value.replace(/\"/g, '&quot;');\n        var escapedStyle = font.value.replace(/\"/g, '&quot;');\n        return \"<option value=\\\"\".concat(escapedValue, \"\\\" style=\\\"font-family: \").concat(escapedStyle, \";\\\"\").concat(selected, \">\").concat(font.name, \"</option>\");\n      }))).join('');\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-select\\\">\\n            <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" name=\\\"font-family\\\">\").concat(optionsHtml, \"</select>\\n            <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this.selectEl = this.domNode.querySelector('select');\n      this.selectEl.addEventListener('change', function (e) {\n        var val = e.target.value;\n        _this.font_family = val;\n        _this._fireCallback(val);\n        _this._emitBus();\n      });\n    }\n  }, {\n    key: \"_fireCallback\",\n    value: function _fireCallback(val) {\n      if (typeof this.callback === 'function') {\n        this.callback(val);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(val);\n      } else if (this.callback && typeof this.callback.setFontFamily === 'function') {\n        this.callback.setFontFamily(val);\n      }\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$silent = _ref.silent,\n        silent = _ref$silent === void 0 ? false : _ref$silent;\n      this.font_family = newValue || \"\";\n      if (this.selectEl) this.selectEl.value = this.font_family;\n      if (silent) return;\n      this._fireCallback(this.font_family);\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.font_family;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    /** Control teardown — drops bus subscription. Called by\n     *  `Builder.renderElementControls` (SA I14) on sidebar rebuild. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._busOff) {\n        this._busOff();\n        this._busOff = null;\n      }\n    }\n  }, {\n    key: \"_attachBusSubscription\",\n    value: function _attachBusSubscription() {\n      var _this2 = this;\n      var _this$_options = this._options,\n        bus = _this$_options.bus,\n        elementUid = _this$_options.elementUid,\n        formatterKey = _this$_options.formatterKey;\n      if (!bus || !elementUid || !formatterKey) return;\n      if (typeof bus.on !== 'function') return;\n      this._busOff = bus.on('formatter:change', function (payload) {\n        if (!payload) return;\n        if (payload.elementUid !== elementUid) return;\n        if (payload.key !== formatterKey) return;\n        if (payload.source === _this2._busSource) return;\n        _this2.setValue(payload.value, {\n          silent: true\n        });\n      });\n    }\n  }, {\n    key: \"_emitBus\",\n    value: function _emitBus() {\n      var _this$_options2 = this._options,\n        bus = _this$_options2.bus,\n        elementUid = _this$_options2.elementUid,\n        formatterKey = _this$_options2.formatterKey;\n      if (!bus || !elementUid || !formatterKey) return;\n      if (typeof bus.emit !== 'function') return;\n      bus.emit('formatter:change', {\n        elementUid: elementUid,\n        key: formatterKey,\n        value: this.font_family,\n        source: this._busSource\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontFamilyControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FontFamilyControl.js?");

/***/ }),

/***/ "./src/includes/FontSizeControl.js":
/*!*****************************************!*\
  !*** ./src/includes/FontSizeControl.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar FontSizeControl = /*#__PURE__*/function () {\n  function FontSizeControl(label, value, callback) {\n    _classCallCheck(this, FontSizeControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.value = value === null || value === undefined ? 16 : value; // Default to 16 if null\n    this.callback = callback; // Callback function to handle input changes\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n  }\n  return _createClass(FontSizeControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n      <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3\\\">\").concat(this.label, \"</label>\\n\\n\\n      <div class=\\\"input-group flex-nowrap w-25 \\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"min-width:140px; height: 32px;\\\">\\n        <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"reduction\\\" type=\\\"button\\\">-</button>\\n        <input id=\\\"\").concat(this.id, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control text-center\\\" style=\\\"font-size: 0.875em;\\\" readonly>\\n        <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"increment\\\" type=\\\"button\\\">+</button>\\n      </div>\\n    </div>\");\n      var decrease = this.domNode.querySelector('[role=\"reduction\"]');\n      var increase = this.domNode.querySelector('[role=\"increment\"]');\n      var input = this.domNode.querySelector(\"#\".concat(this.id));\n      var changeValue = function changeValue(delta) {\n        var numeric = parseInt(_this.value, 10) || 0;\n        numeric = Math.max(1, numeric + delta);\n        _this.setValue(numeric);\n      };\n      if (decrease) {\n        decrease.addEventListener('click', function (e) {\n          e.preventDefault();\n          changeValue(-1);\n        });\n      }\n      if (increase) {\n        increase.addEventListener('click', function (e) {\n          e.preventDefault();\n          changeValue(1);\n        });\n      }\n\n      // allow direct programmatic update keeping UI in sync\n      this._inputNode = input;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue === null || newValue === undefined ? 16 : newValue;\n      var input = this.domNode.querySelector('input');\n      if (input) {\n        input.value = this.value;\n      }\n\n      // Support both function and object with setValue\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontSizeControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FontSizeControl.js?");

/***/ }),

/***/ "./src/includes/FontWeightControl.js":
/*!*******************************************!*\
  !*** ./src/includes/FontWeightControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * FontWeightControl — sidebar + popover font-weight picker.\n *\n * 2026-04-24 (W3.1) — optional 4th-arg `options = { bus, elementUid,\n * formatterKey }` enables dual-mount bus sync. Same pattern as\n * AlignControl (W1.1b) / FontFamilyControl.\n */\nvar FontWeightControl = /*#__PURE__*/function () {\n  function FontWeightControl(label, font_weight, callback) {\n    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, FontWeightControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.font_weight = font_weight === null || font_weight === undefined ? '' : String(font_weight);\n    this.callback = callback;\n    this._options = {\n      bus: options.bus || null,\n      elementUid: options.elementUid || null,\n      formatterKey: options.formatterKey || null\n    };\n    this._busOff = null;\n    this._busSource = 'font-weight-control:' + this.id;\n    this.domNode = document.createElement('div');\n    this.render();\n    this._attachBusSubscription();\n  }\n  return _createClass(FontWeightControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var weightList = ['normal', 'bold', 'lighter', 'bolder', '100', '200', '300', '400', '500', '600', '700', '800', '900'];\n      var optionsHtml = [\"<option value=\\\"\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_weight.not_set'), \"</option>\")].concat(_toConsumableArray(weightList.map(function (weight) {\n        var selected = String(_this.font_weight) === String(weight) ? ' selected' : '';\n        return \"<option value=\\\"\".concat(weight, \"\\\" style=\\\"font-weight: \").concat(weight, \";\\\"\").concat(selected, \">\").concat(weight, \"</option>\");\n      }))).join('');\n      this.domNode.innerHTML = \"\\n          <div class=\\\"bjs-control-row\\\">\\n            <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n            <div class=\\\"bjs-control-input\\\">\\n              <div class=\\\"bjs-select\\\">\\n                <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" name=\\\"font-weight\\\">\").concat(optionsHtml, \"</select>\\n                <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n              </div>\\n            </div>\\n          </div>\\n        \");\n      this.selectEl = this.domNode.querySelector('select');\n      this.selectEl.addEventListener('change', function (e) {\n        var val = e.target.value === '' ? null : e.target.value;\n        _this.font_weight = val === null ? '' : val;\n        _this._fireCallback(val);\n        _this._emitBus();\n      });\n    }\n  }, {\n    key: \"_fireCallback\",\n    value: function _fireCallback(val) {\n      if (typeof this.callback === 'function') {\n        this.callback(val);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(val);\n      } else if (this.callback && typeof this.callback.setFontWeight === 'function') {\n        this.callback.setFontWeight(val);\n      }\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$silent = _ref.silent,\n        silent = _ref$silent === void 0 ? false : _ref$silent;\n      this.font_weight = newValue === null || newValue === undefined ? '' : String(newValue);\n      if (this.selectEl) this.selectEl.value = this.font_weight;\n      if (silent) return;\n      this._fireCallback(newValue);\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.font_weight === '' ? null : this.font_weight;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._busOff) {\n        this._busOff();\n        this._busOff = null;\n      }\n    }\n  }, {\n    key: \"_attachBusSubscription\",\n    value: function _attachBusSubscription() {\n      var _this2 = this;\n      var _this$_options = this._options,\n        bus = _this$_options.bus,\n        elementUid = _this$_options.elementUid,\n        formatterKey = _this$_options.formatterKey;\n      if (!bus || !elementUid || !formatterKey) return;\n      if (typeof bus.on !== 'function') return;\n      this._busOff = bus.on('formatter:change', function (payload) {\n        if (!payload) return;\n        if (payload.elementUid !== elementUid) return;\n        if (payload.key !== formatterKey) return;\n        if (payload.source === _this2._busSource) return;\n        _this2.setValue(payload.value, {\n          silent: true\n        });\n      });\n    }\n  }, {\n    key: \"_emitBus\",\n    value: function _emitBus() {\n      var _this$_options2 = this._options,\n        bus = _this$_options2.bus,\n        elementUid = _this$_options2.elementUid,\n        formatterKey = _this$_options2.formatterKey;\n      if (!bus || !elementUid || !formatterKey) return;\n      if (typeof bus.emit !== 'function') return;\n      bus.emit('formatter:change', {\n        elementUid: elementUid,\n        key: formatterKey,\n        value: this.getValue(),\n        source: this._busSource\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontWeightControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FontWeightControl.js?");

/***/ }),

/***/ "./src/includes/FormContainerCell.js":
/*!*******************************************!*\
  !*** ./src/includes/FormContainerCell.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n/**\n * FormContainerCell — a Cell that IS the form area.\n *\n * Differs from a plain CellElement in three ways:\n *   1. Template \"FormContainerCell\" renders children wrapped in\n *      <form action={action} method={method}>…</form>. This is the single\n *      <form> tag on the page — PageElement.template has moved to \"default\"\n *      so there is no longer a top-level form wrapper. Scope of the form\n *      element matches the area the user edits as \"form\", and no nested\n *      <form> tags can appear in the DOM.\n *   2. Overrides renderEmptyPlaceholder() with a dashed call-to-action\n *      that hints at the sidebar's \"Load list defaults\" button. This is\n *      the only cell type whose empty state guides users to a specific\n *      action instead of showing a generic \"drop blocks\" placeholder.\n *   3. Carries action + method fields directly (form POST target). Pre-\n *      cleanup these used to live on a separate FormBlockElement marker\n *      block; that legacy class was retired 2026-04-20 and all bundled\n *      samples migrated to the FormContainerCell shape.\n */\nvar FormContainerCell = /*#__PURE__*/function (_CellElement) {\n  function FormContainerCell(template, action, method) {\n    var _this;\n    _classCallCheck(this, FormContainerCell);\n    _this = _callSuper(this, FormContainerCell, [template]);\n    _this.action = action || '';\n    _this.method = method || '';\n    return _this;\n  }\n\n  // Explicit override — BaseElement.getClassName() uses `this.constructor.name`,\n  // which webpack may mangle or reset in some builds. Hard-coding the class\n  // name here guarantees getData() always writes `name: \"FormContainerCell\"`\n  // and render() always tags the domNode as `builder-element=\"FormContainerCell\"`.\n  _inherits(FormContainerCell, _CellElement);\n  return _createClass(FormContainerCell, [{\n    key: \"getClassName\",\n    value: function getClassName() {\n      return 'FormContainerCell';\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.name');\n    }\n\n    // Override the generic \"empty gallery\" SVG with a form-specific hint.\n    // Styles are inline + icon is inline SVG so the placeholder renders\n    // correctly inside the builder iframe — external class-based CSS and\n    // icon-font URLs don't necessarily load in every theme's page template.\n    // The SVG depicts three stacked form-input bars (clear domain signal for\n    // \"this is where form fields go\", not the generic lock icon).\n  }, {\n    key: \"renderEmptyPlaceholder\",\n    value: function renderEmptyPlaceholder() {\n      var title = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.empty_title');\n      var hint = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.empty_hint');\n      // No inner border — the outer builder-helper ornament already draws\n      // the dashed frame. Stacking two dashed borders looked noisy. Colour\n      // palette is neutral grey / white (was blue) to match the greyed-out\n      // \"FORM AREA\" pill + avoid colour-clashing with primary-blue themes.\n      return \"\\n            <div builder-no-select style=\\\"\\n                display: flex;\\n                flex-direction: column;\\n                align-items: center;\\n                justify-content: center;\\n                gap: 10px;\\n                min-height: 160px;\\n                padding: 28px 20px;\\n                margin: 0;\\n                border-radius: 10px;\\n                background: #fafafa;\\n                color: #6b7280;\\n                font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\\n                text-align: center;\\n                user-select: none;\\n                pointer-events: none;\\n            \\\">\\n                <svg width=\\\"44\\\" height=\\\"32\\\" viewBox=\\\"0 0 44 32\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" style=\\\"opacity: 0.9;\\\">\\n                    <rect x=\\\"1\\\" y=\\\"1\\\" width=\\\"42\\\" height=\\\"8\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\" stroke-width=\\\"1.25\\\"/>\\n                    <rect x=\\\"5\\\" y=\\\"4.5\\\" width=\\\"14\\\" height=\\\"1.25\\\" rx=\\\"0.625\\\" fill=\\\"#9ca3af\\\"/>\\n                    <rect x=\\\"1\\\" y=\\\"13\\\" width=\\\"42\\\" height=\\\"8\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\" stroke-width=\\\"1.25\\\"/>\\n                    <rect x=\\\"5\\\" y=\\\"16.5\\\" width=\\\"22\\\" height=\\\"1.25\\\" rx=\\\"0.625\\\" fill=\\\"#9ca3af\\\"/>\\n                    <rect x=\\\"1\\\" y=\\\"25\\\" width=\\\"14\\\" height=\\\"5\\\" rx=\\\"1.5\\\" fill=\\\"#4b5563\\\"/>\\n                </svg>\\n                <div style=\\\"font-size: 14px; font-weight: 600; color: #1f2937; line-height: 1.3;\\\">\".concat(title, \"</div>\\n                <div style=\\\"font-size: 12px; color: #6b7280; line-height: 1.5; max-width: 260px;\\\">\").concat(hint, \"</div>\\n            </div>\\n        \");\n    }\n\n    // Wrap child blocks in a real <form action method> so the exported HTML\n    // has proper form semantics. CellElement.render() appends blocks as direct\n    // children of domNode (a <div>); we relocate them into a <form> wrapper\n    // without re-rendering, so event listeners + selection state stay intact.\n    //\n    // Also attaches the persistent \"Form Area\" ornament (dashed outline +\n    // floating label) so authors always know where the form lives, whether\n    // the FCC is empty or populated. The ornament is stripped from exported\n    // HTML via the `data-control=\"builder-helper\"` filter in Builder.getHtml().\n  }, {\n    key: \"render\",\n    value: function render() {\n      var domNode = _superPropGet(FormContainerCell, \"render\", this, 3)([]);\n      if (this.blocks.length > 0) {\n        // Only wrap when we haven't already — super.render clears domNode\n        // every call, so this is mostly defensive.\n        var first = domNode.firstElementChild;\n        if (!(first && first.tagName === 'FORM' && first.dataset.formContainerWrapper === '1')) {\n          var form = document.createElement('form');\n          form.setAttribute('action', this.action || '');\n          form.setAttribute('method', this.method || 'post');\n          form.dataset.formContainerWrapper = '1';\n          while (domNode.firstChild) form.appendChild(domNode.firstChild);\n          domNode.appendChild(form);\n        }\n      }\n      this._attachBuilderOrnaments(domNode);\n      return domNode;\n    }\n\n    // Always-visible \"Form Area\" decoration inside the builder canvas.\n    // - outline (not border — no box-model impact, no layout shift)\n    // - floating pill label top-left corner\n    // Both elements are tagged `data-control=\"builder-helper\"` so\n    // Builder.getHtml() strips them before export. Authors see the anchor,\n    // end-users see clean HTML.\n  }, {\n    key: \"_attachBuilderOrnaments\",\n    value: function _attachBuilderOrnaments(domNode) {\n      // Position context for absolute children. Only style we touch on the\n      // cell itself — has to stay so the builder-helper overlay anchors to\n      // it. Browsers treat `position: relative` with no offset as a no-op\n      // visually, so exported HTML renders the cell identically.\n      if (domNode.style.position !== 'relative') domNode.style.position = 'relative';\n\n      // Strip any legacy inline outline from a prior build — previous\n      // implementations leaked `outline` directly onto domNode which then\n      // appeared in the exported HTML that end-users see.\n      domNode.style.outline = '';\n      domNode.style.outlineOffset = '';\n      domNode.style.paddingTop = '';\n\n      // One shot of builder-only decoration: a single overlay element\n      // carries the dashed border + the \"FORM AREA\" pill. Tagged with\n      // data-control=\"builder-helper\" so Builder.getHtml() strips it\n      // entirely from exported HTML. End-users see a clean form.\n      var stale = domNode.querySelector('[data-form-area-helper]');\n      if (stale) stale.remove();\n\n      // Generous 14px outset so the outline sits clearly OUTSIDE field\n      // labels — previously 4px which crossed through \"Email\", \"First\n      // name\", etc. on typical form themes. The builder canvas has room\n      // around each cell; the wider frame makes the \"this is the form\n      // area\" grouping unambiguous.\n      var helper = document.createElement('div');\n      helper.setAttribute('data-control', 'builder-helper');\n      helper.setAttribute('data-form-area-helper', '1');\n      helper.setAttribute('builder-no-select', '');\n      helper.style.cssText = ['position: absolute', 'top: -14px', 'left: -14px', 'right: -14px', 'bottom: -14px', 'border: 1.5px dashed rgba(55, 65, 81, 0.28)', 'border-radius: 10px', 'pointer-events: none', 'z-index: 0'].join('; ') + ';';\n      var label = document.createElement('div');\n      label.setAttribute('data-form-area-label', '1');\n      // Pill height ≈ 18px (3px padding × 2 + 10px font-size + line-box).\n      // Placing top at -9px (relative to helper, whose top IS the dashed\n      // line) centres the pill ON the border — the line cuts through the\n      // pill's vertical middle like a classic <fieldset>/<legend>. Reads\n      // as \"this label names the outlined area\" at a glance.\n      label.style.cssText = ['position: absolute', 'top: -9px', 'left: 10px', 'padding: 3px 10px', 'background: #1f2937', 'color: #fff', 'font-size: 10px', 'font-weight: 700', 'letter-spacing: 0.5px', 'text-transform: uppercase', 'border-radius: 999px', 'box-shadow: 0 1px 3px rgba(17, 24, 39, 0.25)', \"font-family: Inter, -apple-system, 'Segoe UI', Roboto, sans-serif\", 'pointer-events: none', 'user-select: none', 'white-space: nowrap'].join('; ') + ';';\n      label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('form_container.name');\n      helper.appendChild(label);\n      domNode.appendChild(helper);\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      // Serialise the same block-holding shape as CellElement, plus the\n      // form-specific action/method so the next load restores the POST\n      // target exactly as the user left it.\n      var base = _superPropGet(FormContainerCell, \"getData\", this, 3)([]);\n      base.action = this.action;\n      base.method = this.method;\n      return base;\n    }\n  }, {\n    key: \"getControls\",\n    value:\n    // Same control set as CellElement plus two TextControls for the form\n    // endpoint. The Settings panel surfaces action/method when the user\n    // selects the form area — matching how other containers expose their\n    // config.\n    function getControls() {\n      var _this2 = this;\n      return [new _TextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.action_url'), this.action, {\n        setText: function setText(action) {\n          _this2.action = action;\n          _this2.render();\n        }\n      }), new _TextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.method'), this.method, {\n        setText: function setText(method) {\n          _this2.method = method;\n          _this2.render();\n        }\n      })].concat(_toConsumableArray(_superPropGet(FormContainerCell, \"getControls\", this, 3)([])));\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var cell = new this(data.template, data.action, data.method);\n      var blocks = Array.isArray(data.blocks) ? data.blocks : [];\n      blocks.forEach(function (blockData) {\n        var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(blockData);\n        block.container = cell;\n        cell.appendBlock(block);\n      });\n      cell.formatter.parseFormats(data.formats || {});\n      cell.vertical_align = data.vertical_align || 'top';\n      return cell;\n    }\n  }]);\n}(_CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FormContainerCell);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/FormContainerCell.js?");

/***/ }),

/***/ "./src/includes/Formatter.js":
/*!***********************************!*\
  !*** ./src/includes/Formatter.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction normalizeBackgroundAssetUrl(value, host) {\n  if (typeof value !== 'string') {\n    return value;\n  }\n  var normalizedValue = value.trim();\n  var cssUrlMatch = normalizedValue.match(/^url\\((.*)\\)$/i);\n  if (cssUrlMatch) {\n    normalizedValue = cssUrlMatch[1].trim();\n  }\n  normalizedValue = normalizedValue.replace(/^['\"]|['\"]$/g, '');\n  if (!normalizedValue || !host) {\n    return normalizedValue;\n  }\n  if (typeof host.transferMediaAbsUrl === 'function') {\n    return host.transferMediaAbsUrl(normalizedValue);\n  }\n  return normalizedValue;\n}\nvar Formatter = /*#__PURE__*/function () {\n  // host-injection: owner-Element passes itself so background_image\n  // url-resolution can route through host.transferMediaAbsUrl per\n  // instance instead of the bare-`builder` global. Pre-existing\n  // single-arg callers still work — host stays null and the URL is\n  // returned verbatim (legacy behavior).\n  function Formatter(formats) {\n    var host = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n    _classCallCheck(this, Formatter);\n    this.formats = formats || {};\n    this.host = host;\n  }\n\n  /** Late host injection — called by the owning element after host is\n   *  set on it (BaseElement._setFormatterHost helper). Lets us keep\n   *  the constructor signature back-compat for callers that don't\n   *  thread host through. */\n  return _createClass(Formatter, [{\n    key: \"_setHost\",\n    value: function _setHost(host) {\n      this.host = host;\n    }\n  }, {\n    key: \"isKeyValid\",\n    value: function isKeyValid(key) {\n      return this.formats[key] !== undefined;\n    }\n  }, {\n    key: \"validateKey\",\n    value: function validateKey(key) {\n      if (this.isKeyValid(key) === false) {\n        throw new Error(\"Formatter: key \\\"\".concat(key, \"\\\" is not valid.\"));\n      }\n    }\n  }, {\n    key: \"getFormat\",\n    value: function getFormat(key) {\n      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n      if (!this.formats || _typeof(this.formats) !== 'object') return defaultValue;\n      if (typeof this.formats[key] === 'undefined' || this.formats[key] === null) {\n        return defaultValue;\n      }\n      return this.formats[key];\n    }\n  }, {\n    key: \"setFormat\",\n    value: function setFormat(key, value) {\n      // validate key\n      this.validateKey(key);\n      this.formats[key] = value;\n    }\n  }, {\n    key: \"toStyleString\",\n    value: function toStyleString(key) {\n      var value = this.getFormat(key);\n      if (value === null || value === undefined || value === '') {\n        return '';\n      }\n\n      // Convert camelCase to kebab-case\n      var kebabKey = key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase().replace(/_/g, '-');\n\n      // Properties that should never be treated as numeric (always strings)\n      var stringOnlyProperties = ['font-family', 'text-align', 'direction', 'background-image', 'background-position', 'background-repeat', 'background-blend-mode', 'background-attachment', 'mix-blend-mode', 'filter', 'border-style', 'border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style', 'display', 'flex-direction', 'justify-content', 'align-items', 'color', 'background-color', 'border-color', 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color', 'text-decoration', 'white-space', 'box-shadow'];\n\n      // Add 'px' for numeric values except for certain CSS properties\n      var cssNumberProperties = ['opacity', 'z-index', 'flex-grow', 'flex-shrink', 'order', 'zoom', 'width', 'height', 'top', 'right', 'bottom', 'left', 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'border-width', 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', 'border-radius', 'letter-spacing', 'word-spacing', 'text-indent', 'outline-width', 'gap', 'column-gap', 'row-gap', 'grid-gap', 'max-width', 'max-height', 'min-width', 'min-height', 'flex-basis', 'font-size', 'letter-spacing', 'text-indent'];\n\n      // Unitless CSS properties — numbers passed through as-is (no px).\n      // opacity accepts 0..1, z-index/order accept integers, flex-* accept floats, zoom accepts factor.\n      var unitlessNumberProperties = ['opacity', 'z-index', 'flex-grow', 'flex-shrink', 'order', 'zoom'];\n      if (unitlessNumberProperties.includes(kebabKey)) {\n        if (typeof value === 'number') {\n          value = \"\".concat(value, \" !important\");\n        } else if (typeof value === 'string') {\n          var trimmed = value.trim();\n          if (trimmed !== '' && !isNaN(trimmed)) value = \"\".concat(trimmed, \" !important\");\n        }\n      } else if (!stringOnlyProperties.includes(kebabKey) && cssNumberProperties.includes(kebabKey)) {\n        // Dimensional properties: preserve any pre-attached unit, otherwise append px.\n        // Accepted forms:\n        //   300          (number)     -> \"300px !important\"   (legacy)\n        //   \"300\"        (numeric str)-> \"300px !important\"   (legacy)\n        //   \"300px\"      (with unit)  -> \"300px !important\"\n        //   \"50%\"        (percent)    -> \"50% !important\"\n        //   \"1.5em\"      (em/rem/...) -> \"1.5em !important\"\n        //   \"auto\"       (keyword)    -> \"auto\"               (no !important — lets\n        //                                                      children override)\n        //   \"inherit\"/\"initial\"/\"unset\"/\"revert\" -> bare keyword, no !important\n        var cssKeywords = ['auto', 'inherit', 'initial', 'unset', 'revert', 'fit-content', 'max-content', 'min-content'];\n        var hasUnitRegex = /^-?[\\d.]+(px|%|em|rem|vw|vh|ch|ex|cm|mm|in|pt|pc|fr)$/i;\n        if (typeof value === 'number') {\n          value = \"\".concat(value, \"px !important\");\n        } else if (typeof value === 'string') {\n          var _trimmed = value.trim();\n          if (cssKeywords.includes(_trimmed.toLowerCase())) {\n            value = _trimmed;\n          } else if (hasUnitRegex.test(_trimmed)) {\n            value = \"\".concat(_trimmed, \" !important\");\n          } else if (!isNaN(_trimmed) && _trimmed !== '') {\n            // numeric string with no unit — legacy — assume px\n            value = \"\".concat(_trimmed, \"px !important\");\n          }\n          // else: pass through raw string (e.g. \"calc(100% - 20px)\")\n        }\n      }\n\n      // special handling for background_image\n      // Supports 3 input forms:\n      //   1. Plain URL          → wrap in url(...)\n      //   2. Gradient string    → pass through (linear-gradient / radial-gradient / conic-gradient)\n      //   3. Composite string   → already contains url(...) or gradient + url → pass through\n      // (3) lets BackgroundControl stack \"gradient, url(image)\" into a single background-image value.\n      if (key === 'background_image') {\n        var raw = typeof value === 'string' ? value.trim() : '';\n        var hasGradient = /^(linear|radial|conic)-gradient\\s*\\(/i.test(raw);\n        var hasUrlFunc = /\\burl\\s*\\(/i.test(raw);\n        if (hasGradient || hasUrlFunc) {\n          value = raw;\n        } else {\n          value = \"url(\".concat(normalizeBackgroundAssetUrl(value, this.host), \")\");\n        }\n      }\n\n      // translate specific keys\n      if (key === 'text_direction') {\n        kebabKey = 'direction';\n      }\n      if (key === 'paragraph_spacing') {\n        kebabKey = 'margin-bottom';\n      }\n      if (key === 'text_color') {\n        kebabKey = 'color';\n      }\n\n      // Normalize double-quotes to single-quotes in CSS values so the\n      // emitted string is safe to drop into a double-quoted HTML attribute\n      // (e.g. `style=\"...\"`). CSS treats '\"' and \"'\" identically for\n      // string tokens like `font-family: \"Work Sans\"`. Without this,\n      // font-family names with double-quotes break the style attribute\n      // parser and every format after it silently fails to apply.\n      if (typeof value === 'string' && value.indexOf('\"') !== -1) {\n        value = value.replace(/\"/g, \"'\");\n      }\n      return \"\".concat(kebabKey, \": \").concat(value, \"; \");\n    }\n  }, {\n    key: \"toStyleStringAll\",\n    value: function toStyleStringAll() {\n      var filters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n      var styleString = '';\n      for (var _i = 0, _Object$entries = Object.entries(this.formats); _i < _Object$entries.length; _i++) {\n        var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n          key = _Object$entries$_i[0],\n          value = _Object$entries$_i[1];\n        if (value !== null && value !== undefined && value !== '' && (filters === null || filters.includes(key))) {\n          styleString += this.toStyleString(key);\n        }\n      }\n      return styleString.trim();\n    }\n  }, {\n    key: \"getFormats\",\n    value: function getFormats() {\n      // filter formats return only those with non-null/undefined/empty values\n      var filteredFormats = {};\n      for (var _i2 = 0, _Object$entries2 = Object.entries(this.formats); _i2 < _Object$entries2.length; _i2++) {\n        var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),\n          key = _Object$entries2$_i[0],\n          value = _Object$entries2$_i[1];\n        if (value !== null && value !== undefined && value !== '') {\n          filteredFormats[key] = value;\n        }\n      }\n      return filteredFormats;\n    }\n  }, {\n    key: \"parseFormats\",\n    value: function parseFormats(formats) {\n      // Defensive: if formats is not an object, ignore it.\n      if (!formats || _typeof(formats) !== 'object') return;\n      for (var _i3 = 0, _Object$entries3 = Object.entries(formats); _i3 < _Object$entries3.length; _i3++) {\n        var _Object$entries3$_i = _slicedToArray(_Object$entries3[_i3], 2),\n          key = _Object$entries3$_i[0],\n          value = _Object$entries3$_i[1];\n        if (this.isKeyValid(key)) {\n          this.setFormat(key, value);\n        }\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Formatter);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/Formatter.js?");

/***/ }),

/***/ "./src/includes/GridControl.js":
/*!*************************************!*\
  !*** ./src/includes/GridControl.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * GridControl — horizontal visual cell editor for a Grid element's cells.\n *\n * Renders `.bjs-cell-manager` (see builder.css §17 + docs/core/UI.md). Cards sit\n * in a flex row with widths proportional to their configured `width` format\n * so the control mirrors the canvas layout — WYSIWYG. Quick-apply layout\n * presets above the strip cover 90%+ of real grids (1 / 1·1 / 1·1·1 / 1·2 /\n * 2·1 / 1·2·1).\n *\n * Phase-3 W6.1 (2026-04-18) adds four \"pro\" affordances on top of the\n * baseline Phase-2 editor:\n *\n *   1. **Drag-reorder.** Pointer-based drag on the card handle (non-functional\n *      in Phase-2) reorders cells. A vertical drop indicator tracks the\n *      target slot; release commits via `callbacks.moveCell(from, to)`.\n *   2. **Bulk-select.** Shift-click extends selection from the primary cell;\n *      Cmd/Ctrl-click toggles individual cells. A bulk toolbar surfaces\n *      when ≥2 cells are selected and exposes a single-shot Delete.\n *   3. **Snap-ratios.** Thin resizer grips between adjacent cards adjust both\n *      neighbor widths simultaneously. During drag, magnetic snap to 1/4,\n *      1/3, 1/2, 2/3, 3/4 of the combined (left+right) span — the same\n *      ratios designers build around. Ratio tooltip hovers above the grip.\n *   4. **Pixel ruler.** A subtle tick strip above the cards shows 10% minor /\n *      25% major marks. During resize the active-ratio markers light up so\n *      the author sees what percentage they're committing.\n *\n * Structure-preserving: when a caller only changes a cell's width, the\n * controller patches the existing card's `style.flex` via\n * `applyCardWidths()` — no full innerHTML rebuild. Full `render()` only\n * happens on cell count changes (add/remove/preset).\n */\n\n// One-click layout presets. `widths` is the format stored per cell.\n// Bare numbers mean grow-share (flex: N 1 0) — preferred for responsive.\nvar LAYOUT_PRESETS = [{\n  id: '1',\n  widths: ['auto'],\n  titleKey: 'grid.preset_1col'\n}, {\n  id: '1-1',\n  widths: [1, 1],\n  titleKey: 'grid.preset_1_1'\n}, {\n  id: '1-1-1',\n  widths: [1, 1, 1],\n  titleKey: 'grid.preset_1_1_1'\n}, {\n  id: '1-2',\n  widths: [1, 2],\n  titleKey: 'grid.preset_1_2'\n}, {\n  id: '2-1',\n  widths: [2, 1],\n  titleKey: 'grid.preset_2_1'\n}, {\n  id: '1-2-1',\n  widths: [1, 2, 1],\n  titleKey: 'grid.preset_1_2_1'\n}];\n\n// Magnetic snap points for resize drag, expressed as fractions of the combined\n// (left + right) cell span. Chosen to match the canonical design ratios every\n// preset above covers, so a user dragging into \"50/50\" gets help landing\n// exactly there. Ratios are symmetric — 0.25 on the left ≡ 0.75 on the right.\nvar SNAP_RATIOS = [{\n  v: 0.25,\n  label: '1 : 3'\n}, {\n  v: 1 / 3,\n  label: '1 : 2'\n}, {\n  v: 0.5,\n  label: '1 : 1'\n}, {\n  v: 2 / 3,\n  label: '2 : 1'\n}, {\n  v: 0.75,\n  label: '3 : 1'\n}];\nvar SNAP_TOLERANCE = 0.025; // ± percentage-of-combined at which snap engages\n\n// Pixel-ruler ticks. Major at 25% intervals, minor at 10% intervals. Both sets\n// are drawn; CSS differentiates thickness + label visibility.\nvar RULER_MINOR = [10, 20, 30, 40, 60, 70, 80, 90];\nvar RULER_MAJOR = [0, 25, 50, 75, 100];\nvar GridControl = /*#__PURE__*/function () {\n  /**\n   * @param {string}   label         Translated title (\"Cells\")\n   * @param {object}   values\n   * @param {function} values.getItemCount\n   * @param {function} [values.getCellWidths]        Returns ['50%', 'auto', ...] — for preset detection + card layout\n   * @param {function} [values.getSelectedIndex]     Returns 0-based index of selected cell, or -1\n   * @param {object}   callbacks\n   * @param {function} callbacks.addCell\n   * @param {function} callbacks.addCellAt\n   * @param {function} callbacks.removeCell\n   * @param {function} [callbacks.selectCell]        Optional: called when user clicks a card\n   * @param {function} [callbacks.applyPreset]       Optional: called with preset.widths array\n   * @param {function} [callbacks.moveCell]          Reorder: (from, to) — move source to slot\n   * @param {function} [callbacks.resizeCellPair]    Resize: (leftIdx, leftPct, rightPct)\n   * @param {function} [callbacks.removeCells]       Bulk-remove: indices[] (descending order)\n   * @param {function} [callbacks.rebalanceProportional]\n   * @param {function} [callbacks.equalize]\n   */\n  function GridControl(label, values, callbacks) {\n    _classCallCheck(this, GridControl);\n    this.label = label;\n    this.getItemCount = values.getItemCount;\n    this.getCellWidths = values.getCellWidths || function () {\n      return [];\n    };\n    this.getSelectedIndex = values.getSelectedIndex || function () {\n      return -1;\n    };\n    this.callback = callbacks;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-cell-manager');\n\n    // Pro state (Phase-3 W6.1)\n    this._dragState = null;\n    this._resizeState = null;\n    this._multiSelected = new Set();\n    this.render();\n  }\n  return _createClass(GridControl, [{\n    key: \"_t\",\n    value: function _t(key, fallback) {\n      try {\n        var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n        return v && v !== key ? v : fallback;\n      } catch (_e) {\n        return fallback;\n      }\n    }\n\n    /** Infer a card's flex-style from its width format. Mirrors the math in\n     *  Cell.template.html so the panel visually matches canvas. */\n  }, {\n    key: \"_cardFlexStyle\",\n    value: function _cardFlexStyle(width) {\n      if (width === 'auto' || width === null || width === '' || width === undefined) {\n        return 'flex: 1 1 0;';\n      }\n      var str = String(width).trim();\n      if (/%$/.test(str)) {\n        var pct = parseFloat(str);\n        if (!isNaN(pct) && pct > 0) return \"flex: 0 0 \".concat(pct, \"%;\");\n        return 'flex: 1 1 0;';\n      }\n      if (/(px|em|rem|vw|vh|ch|ex)$/i.test(str)) {\n        return \"flex: 0 0 \".concat(str, \";\");\n      }\n      var num = parseFloat(str);\n      if (!isNaN(num) && num > 0) return \"flex: \".concat(num, \" 1 0;\");\n      return 'flex: 1 1 0;';\n    }\n\n    /** Format a width for display on the card. */\n  }, {\n    key: \"_widthLabel\",\n    value: function _widthLabel(width) {\n      if (width === 'auto' || width === null || width === '' || width === undefined) {\n        return 'auto';\n      }\n      var str = String(width).trim();\n      if (/%$/.test(str) || /(px|em|rem|vw|vh|ch|ex)$/i.test(str)) return str;\n      var num = parseFloat(str);\n      if (!isNaN(num) && num > 0) return \"\".concat(num);\n      return 'auto';\n    }\n\n    /** Identify which preset (if any) the current widths match — used to\n     *  highlight the active preset tile. Bare-number proportions are compared\n     *  via normalised ratios; explicit % cells map only to presets that use\n     *  the same values. */\n  }, {\n    key: \"_activePresetId\",\n    value: function _activePresetId() {\n      var widths = this.getCellWidths();\n      if (!Array.isArray(widths) || widths.length === 0) return null;\n\n      // One-column\n      if (widths.length === 1) {\n        var w = widths[0];\n        if (w === 'auto' || w === null || w === undefined || w === '') return '1';\n        return null;\n      }\n\n      // Multi-cell presets: check bare-number ratios\n      var nums = widths.map(function (w) {\n        if (typeof w === 'number') return w;\n        var str = String(w).trim();\n        if (/%$/.test(str)) return parseFloat(str);\n        var n = parseFloat(str);\n        return isNaN(n) ? null : n;\n      });\n      if (nums.some(function (n) {\n        return n === null;\n      })) return null;\n      var _loop = function _loop() {\n          var preset = _LAYOUT_PRESETS[_i];\n          if (preset.widths.length !== widths.length) return 0; // continue\n          var pNums = preset.widths.map(function (w) {\n            return typeof w === 'number' ? w : 100 / preset.widths.length;\n          });\n          // Normalise both to sum=1 and compare element-wise with tolerance.\n          var sum = nums.reduce(function (a, b) {\n            return a + b;\n          }, 0);\n          var pSum = pNums.reduce(function (a, b) {\n            return a + b;\n          }, 0);\n          if (sum === 0 || pSum === 0) return 0; // continue\n          var nNorm = nums.map(function (n) {\n            return n / sum;\n          });\n          var pNorm = pNums.map(function (n) {\n            return n / pSum;\n          });\n          var match = nNorm.every(function (v, i) {\n            return Math.abs(v - pNorm[i]) < 0.01;\n          });\n          if (match) return {\n            v: preset.id\n          };\n        },\n        _ret;\n      for (var _i = 0, _LAYOUT_PRESETS = LAYOUT_PRESETS; _i < _LAYOUT_PRESETS.length; _i++) {\n        _ret = _loop();\n        if (_ret === 0) continue;\n        if (_ret) return _ret.v;\n      }\n      return null;\n    }\n  }, {\n    key: \"_renderPresets\",\n    value: function _renderPresets() {\n      var _this = this;\n      var activeId = this._activePresetId();\n      var html = LAYOUT_PRESETS.map(function (preset) {\n        var active = preset.id === activeId ? ' is-active' : '';\n        var pNums = preset.widths.map(function (w) {\n          return typeof w === 'number' ? w : 1;\n        });\n        var segs = pNums.map(function (n) {\n          return \"<span class=\\\"bjs-cell-manager-preset-seg\\\" style=\\\"flex: \".concat(n, \";\\\"></span>\");\n        }).join('');\n        var title = _this._t(preset.titleKey, preset.id.replace(/-/g, ' / ')) || preset.id;\n        return \"<button type=\\\"button\\\" class=\\\"bjs-cell-manager-preset\".concat(active, \"\\\" data-preset=\\\"\").concat(preset.id, \"\\\" data-tooltip=\\\"\").concat(title, \"\\\" aria-label=\\\"\").concat(title, \"\\\"><span class=\\\"bjs-cell-manager-preset-icon\\\">\").concat(segs, \"</span></button>\");\n      }).join('');\n      return \"<div class=\\\"bjs-cell-manager-presets\\\" role=\\\"toolbar\\\" aria-label=\\\"\".concat(this._t('grid.layout_presets', 'Layout presets'), \"\\\">\").concat(html, \"</div>\");\n    }\n\n    /** Ruler strip above the cards — tick marks at 10% minor / 25% major.\n     *  Ticks are percent-positioned so the ruler stays aligned with the strip\n     *  regardless of panel width. The active-ratio helpers (`is-active` class\n     *  applied during resize drag) are handled by _updateRulerSnap. */\n  }, {\n    key: \"_renderRuler\",\n    value: function _renderRuler() {\n      var label = this._t('grid.ruler', 'Row ruler');\n      var majors = RULER_MAJOR.map(function (v) {\n        return \"<span class=\\\"bjs-cell-manager-ruler-tick bjs-cell-manager-ruler-tick--major\\\" data-ruler=\\\"\".concat(v, \"\\\" style=\\\"left: \").concat(v, \"%;\\\"><span class=\\\"bjs-cell-manager-ruler-label\\\">\").concat(v === 0 || v === 100 ? '' : v + '%', \"</span></span>\");\n      }).join('');\n      var minors = RULER_MINOR.map(function (v) {\n        return \"<span class=\\\"bjs-cell-manager-ruler-tick bjs-cell-manager-ruler-tick--minor\\\" data-ruler=\\\"\".concat(v, \"\\\" style=\\\"left: \").concat(v, \"%;\\\"></span>\");\n      }).join('');\n      return \"<div class=\\\"bjs-cell-manager-ruler\\\" role=\\\"presentation\\\" aria-label=\\\"\".concat(label, \"\\\"><div class=\\\"bjs-cell-manager-ruler-track\\\">\").concat(majors).concat(minors, \"</div></div>\");\n    }\n  }, {\n    key: \"_renderCard\",\n    value: function _renderCard(index, total, width, isSelected) {\n      var flex = this._cardFlexStyle(width);\n      var label = this._widthLabel(width);\n      var removable = total > 1;\n      var sel = isSelected ? ' is-selected' : '';\n      var multi = this._multiSelected.has(index) ? ' is-multi-selected' : '';\n      var selAttr = isSelected ? 'aria-selected=\"true\"' : '';\n      var removeDisabled = removable ? '' : 'data-removable=\"false\"';\n      var handleTitle = this._t('grid.drag_cell', 'Drag to reorder');\n      return \"\\n      <article class=\\\"bjs-cell-card\".concat(sel).concat(multi, \"\\\" role=\\\"option\\\" \").concat(selAttr, \" \").concat(removeDisabled, \" data-cell-index=\\\"\").concat(index, \"\\\" style=\\\"\").concat(flex, \"\\\">\\n        <header class=\\\"bjs-cell-card-head\\\">\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-card-handle\\\" aria-label=\\\"\").concat(handleTitle, \"\\\" data-tooltip=\\\"\").concat(handleTitle, \"\\\" tabindex=\\\"0\\\">\\n            <span class=\\\"material-symbols-rounded\\\">drag_indicator</span>\\n          </button>\\n          <span class=\\\"bjs-cell-card-index\\\">#\").concat(index + 1, \"</span>\\n        </header>\\n        <div class=\\\"bjs-cell-card-body\\\">\\n          <span>\\n            <span class=\\\"bjs-cell-card-width\\\">\").concat(label, \"</span>\\n          </span>\\n        </div>\\n        <footer class=\\\"bjs-cell-card-foot\\\">\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-card-remove\\\" data-control=\\\"remove-cell\\\" data-index=\\\"\").concat(index, \"\\\" aria-label=\\\"\").concat(this._t('grid.remove_cell', 'Remove cell'), \" \").concat(index + 1, \"\\\">\\n            <span class=\\\"material-symbols-rounded\\\">delete</span>\\n          </button>\\n        </footer>\\n      </article>\\n    \");\n    }\n  }, {\n    key: \"_renderSlots\",\n    value: function _renderSlots(count) {\n      /* Initial `left:` values are a reasonable first paint placeholder — the\n         real position is written in px by `_positionSlots()` after the cards\n         measure. Slot N+1 edge slots (0% / 100%) would land at the strip's\n         outer edges here, but `_positionSlots()` overrides every slot. */\n      var out = [];\n      for (var i = 0; i <= count; i++) {\n        var pct = i / count * 100;\n        out.push(\"\\n        <div class=\\\"bjs-cell-manager-slot\\\" data-slot-index=\\\"\".concat(i, \"\\\" style=\\\"left: \").concat(pct, \"%;\\\">\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-slot-btn\\\" data-control=\\\"add-cell-at\\\" data-index=\\\"\").concat(i, \"\\\" aria-label=\\\"\").concat(this._t('grid.insert_cell_at', 'Insert cell at'), \" \").concat(i + 1, \"\\\">\\n            <span class=\\\"material-symbols-rounded\\\">add</span>\\n          </button>\\n        </div>\\n      \"));\n      }\n      return out.join('');\n    }\n\n    /** Resizer grips — narrow vertical grips in the gap between adjacent cards.\n     *  Each grip targets the pair (i, i+1) and lets the user drag to rebalance\n     *  their widths without leaving the panel. Only rendered when BOTH cells in\n     *  the pair are percent-based (bare / auto pairs fall back to the numeric\n     *  DimensionControl below — we can't do math without a numeric %).  */\n  }, {\n    key: \"_renderResizers\",\n    value: function _renderResizers(count) {\n      if (count < 2) return '';\n      var widths = this.getCellWidths();\n      var out = [];\n      for (var i = 0; i < count - 1; i++) {\n        var wL = widths[i];\n        var wR = widths[i + 1];\n        var bothPct = this._asPct(wL) !== null && this._asPct(wR) !== null;\n        if (!bothPct) continue;\n        var label = this._t('grid.resize_between', 'Resize cell');\n        out.push(\"\\n        <div class=\\\"bjs-cell-manager-resizer\\\" data-resizer-left=\\\"\".concat(i, \"\\\" data-resizer-right=\\\"\").concat(i + 1, \"\\\">\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-resizer-grip\\\" aria-label=\\\"\").concat(label, \" \").concat(i + 1, \"/\").concat(i + 2, \"\\\" data-tooltip=\\\"\").concat(label, \" \").concat(i + 1, \"/\").concat(i + 2, \"\\\" tabindex=\\\"-1\\\">\\n            <span class=\\\"material-symbols-rounded\\\">drag_indicator</span>\\n          </button>\\n          <div class=\\\"bjs-cell-manager-resizer-tip\\\" role=\\\"status\\\" aria-hidden=\\\"true\\\"><span class=\\\"bjs-cell-manager-resizer-tip-value\\\"></span></div>\\n        </div>\\n      \"));\n      }\n      return out.join('');\n    }\n\n    /** Return a numeric percent for a width format that's a %, or null. */\n  }, {\n    key: \"_asPct\",\n    value: function _asPct(w) {\n      if (typeof w === 'string' && /%$/.test(w.trim())) {\n        var n = parseFloat(w);\n        return isNaN(n) ? null : n;\n      }\n      return null;\n    }\n\n    /** Position the resizer grips on the real gap midpoints between card pairs.\n     *  Similar math to _positionSlots but only for inner gaps (not outer edges)\n     *  and only for pairs we actually rendered (bothPct). Accepts the list of\n     *  rendered grip DOM elements in order and matches them to their card pair\n     *  via data-resizer-left. */\n  }, {\n    key: \"_positionResizers\",\n    value: function _positionResizers() {\n      if (!this.domNode) return;\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (!strip) return;\n      var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n      var grips = Array.from(strip.querySelectorAll(':scope > .bjs-cell-manager-resizer'));\n      if (!cards.length || !grips.length) return;\n      var stripRect = strip.getBoundingClientRect();\n      if (stripRect.width === 0) return;\n      grips.forEach(function (grip) {\n        var i = parseInt(grip.getAttribute('data-resizer-left'), 10);\n        if (isNaN(i) || !cards[i] || !cards[i + 1]) return;\n        var prev = cards[i].getBoundingClientRect();\n        var next = cards[i + 1].getBoundingClientRect();\n        var xPx = (prev.right - stripRect.left + (next.left - stripRect.left)) / 2;\n        grip.style.left = \"\".concat(xPx, \"px\");\n      });\n    }\n\n    /**\n     * Re-position every `+` insert slot at the actual gap midpoint between\n     * cards (in px, not percentages). Cells can have arbitrary widths\n     * (%, px, bare-number flex-grow, `auto`) so the equal-fraction placement\n     * that `_renderSlots` emits on first paint is wrong for any non-uniform\n     * row. We measure rendered card boundaries instead — the single source of\n     * truth that reflects whatever the browser's flex solver actually did.\n     */\n  }, {\n    key: \"_positionSlots\",\n    value: function _positionSlots() {\n      if (!this.domNode) return;\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (!strip) return;\n      var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n      var slots = Array.from(strip.querySelectorAll(':scope > .bjs-cell-manager-slot'));\n      if (!cards.length || slots.length !== cards.length + 1) return;\n      var stripRect = strip.getBoundingClientRect();\n      if (stripRect.width === 0) return; /* panel hidden — skip */\n\n      slots.forEach(function (slot, i) {\n        var xPx;\n        if (i === 0) {\n          /* Leftmost edge slot — midpoint between strip edge and card 0 left */\n          var card = cards[0];\n          var left = card.getBoundingClientRect().left - stripRect.left;\n          xPx = left / 2;\n        } else if (i === cards.length) {\n          /* Rightmost edge slot — midpoint between last card right and strip edge */\n          var _card = cards[cards.length - 1];\n          var right = _card.getBoundingClientRect().right - stripRect.left;\n          xPx = (right + stripRect.width) / 2;\n        } else {\n          /* Between cards — midpoint of the gap */\n          var prev = cards[i - 1].getBoundingClientRect();\n          var next = cards[i].getBoundingClientRect();\n          xPx = (prev.right - stripRect.left + (next.left - stripRect.left)) / 2;\n        }\n        slot.style.left = \"\".concat(xPx, \"px\");\n      });\n      this._positionResizers();\n    }\n\n    /**\n     * Watch the strip for size changes (panel resize, cell width edits,\n     * add / remove cell) and reposition slots when layout shifts. One observer\n     * per control instance, torn down + recreated on each render().\n     */\n  }, {\n    key: \"_observeStripResize\",\n    value: function _observeStripResize() {\n      var _this2 = this;\n      if (this._resizeObserver) {\n        try {\n          this._resizeObserver.disconnect();\n        } catch (_e) {}\n        this._resizeObserver = null;\n      }\n      if (typeof ResizeObserver === 'undefined' || !this.domNode) return;\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (!strip) return;\n      this._resizeObserver = new ResizeObserver(function () {\n        return _this2._positionSlots();\n      });\n      this._resizeObserver.observe(strip);\n      /* Also observe each card — a `width: 33.33%` → `width: 50%` edit via the\n         DimensionControl below changes a card's flex without changing strip's\n         own bounding box, and ResizeObserver on strip alone may miss it. */\n      strip.querySelectorAll(':scope > .bjs-cell-card').forEach(function (c) {\n        return _this2._resizeObserver.observe(c);\n      });\n    }\n\n    /** Compute percentage-sum when every cell is a percent — otherwise null.\n     *  Used to decide whether the \"row overflow\" rebalance banner should show\n     *  (only makes sense when the row IS an all-% row). Mixed rows with\n     *  `fill`/`auto`/`px` don't have a meaningful \"sum\" and never show the\n     *  banner. */\n  }, {\n    key: \"_percentSum\",\n    value: function _percentSum() {\n      var widths = this.getCellWidths();\n      if (!widths.length) return null;\n      var allPct = widths.every(function (w) {\n        return typeof w === 'string' && /%$/.test(String(w).trim());\n      });\n      if (!allPct) return null;\n      var sum = widths.reduce(function (acc, w) {\n        return acc + (parseFloat(w) || 0);\n      }, 0);\n      return Math.round(sum * 100) / 100;\n    }\n  }, {\n    key: \"_renderRebalanceAlert\",\n    value: function _renderRebalanceAlert() {\n      var sum = this._percentSum();\n      // Tolerance: rounding residue from the migration can leave sums at\n      // 99.99 or 100.01. Only surface the banner when > 1% off.\n      if (sum === null || Math.abs(sum - 100) <= 1) return '';\n      var over = sum > 100;\n      var msg = over ? this._t('grid.alert_overflow', \"Cells sum to \".concat(sum, \"% \\u2014 row will overflow. Rebalance to fit, or equalize?\")) : this._t('grid.alert_underfill', \"Cells sum to \".concat(sum, \"% \\u2014 row has \").concat(Math.round(100 - sum), \"% empty space. Rebalance to fill, or equalize?\"));\n      return \"\\n      <div class=\\\"bjs-cell-manager-alert\\\" role=\\\"status\\\" data-sum=\\\"\".concat(sum, \"\\\" data-state=\\\"\").concat(over ? 'overflow' : 'underfill', \"\\\">\\n        <span class=\\\"bjs-cell-manager-alert-icon material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(over ? 'warning' : 'info', \"</span>\\n        <span class=\\\"bjs-cell-manager-alert-body\\\">\").concat(msg.replace(/\\n/g, ' '), \"</span>\\n        <span class=\\\"bjs-cell-manager-alert-actions\\\">\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-alert-btn\\\" data-control=\\\"alert-rebalance\\\" data-tooltip=\\\"\").concat(this._t('grid.alert_rebalance_title', 'Scale existing widths proportionally so the row sums to 100%'), \"\\\">\").concat(this._t('grid.alert_rebalance', 'Rebalance'), \"</button>\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-alert-btn\\\" data-control=\\\"alert-equalize\\\" data-tooltip=\\\"\").concat(this._t('grid.alert_equalize_title', 'Set every cell to 100 / N percent'), \"\\\">\").concat(this._t('grid.alert_equalize', 'Equalize'), \"</button>\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-alert-btn bjs-cell-manager-alert-dismiss\\\" data-control=\\\"alert-dismiss\\\" aria-label=\\\"\").concat(this._t('grid.alert_dismiss', 'Dismiss'), \"\\\" data-tooltip=\\\"\").concat(this._t('grid.alert_dismiss', 'Dismiss'), \"\\\">\\n            <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">close</span>\\n          </button>\\n        </span>\\n      </div>\\n    \");\n    }\n\n    /** Bulk-action toolbar (Phase-3 W6.1). Surfaces only when ≥1 cell is in the\n     *  multi-select set (a Shift/Cmd-click extension beyond the primary\n     *  selection). Cells marked via `.is-multi-selected`. */\n  }, {\n    key: \"_renderBulkBar\",\n    value: function _renderBulkBar() {\n      var n = this._multiSelected.size;\n      if (n < 1) return '';\n      var label = this._t('grid.bulk_selected', '{n} selected').replace('{n}', String(n));\n      var delLabel = this._t('grid.bulk_delete', 'Delete');\n      var clearLabel = this._t('grid.bulk_clear', 'Clear');\n      return \"\\n      <div class=\\\"bjs-cell-manager-bulk\\\" role=\\\"status\\\" data-count=\\\"\".concat(n, \"\\\">\\n        <span class=\\\"bjs-cell-manager-bulk-count\\\">\").concat(label, \"</span>\\n        <span class=\\\"bjs-cell-manager-bulk-actions\\\">\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-bulk-btn\\\" data-control=\\\"bulk-delete\\\">\\n            <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">delete</span>\\n            <span>\").concat(delLabel, \"</span>\\n          </button>\\n          <button type=\\\"button\\\" class=\\\"bjs-cell-manager-bulk-btn bjs-cell-manager-bulk-btn--ghost\\\" data-control=\\\"bulk-clear\\\">\").concat(clearLabel, \"</button>\\n        </span>\\n      </div>\\n    \");\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this3 = this;\n      var total = this.getItemCount();\n      var widths = this.getCellWidths();\n      var selected = this.getSelectedIndex();\n      var safeWidths = Array.from({\n        length: total\n      }, function (_, i) {\n        return widths[i];\n      });\n\n      // Prune stale multi-select indices (cells removed since the set was built)\n      if (this._multiSelected.size) {\n        this._multiSelected = new Set(Array.from(this._multiSelected).filter(function (i) {\n          return i < total && i >= 0;\n        }));\n      }\n      var cards = safeWidths.map(function (w, i) {\n        return _this3._renderCard(i, total, w, i === selected);\n      }).join('');\n      var slots = total > 0 ? this._renderSlots(total) : '';\n      var resizers = total > 1 ? this._renderResizers(total) : '';\n      var alert = this._dismissed ? '' : this._renderRebalanceAlert();\n      var bulk = this._renderBulkBar();\n      this.domNode.innerHTML = \"\\n      <header class=\\\"bjs-cell-manager-header\\\">\\n        <div class=\\\"bjs-cell-manager-title\\\">\\n          <span>\".concat(this.label, \"</span>\\n          <span class=\\\"bjs-cell-manager-count\\\" aria-label=\\\"\").concat(total, \" \").concat(total === 1 ? 'cell' : 'cells', \"\\\">\").concat(total, \"</span>\\n        </div>\\n        <button type=\\\"button\\\" class=\\\"bjs-cell-manager-add\\\" data-control=\\\"add-cell\\\">\\n          <span class=\\\"material-symbols-rounded\\\">add</span>\\n          <span>\").concat(this._t('grid.add_cell', 'Add cell'), \"</span>\\n        </button>\\n      </header>\\n\\n      \").concat(this._renderPresets(), \"\\n\\n      \").concat(total > 0 ? this._renderRuler() : '', \"\\n\\n      <div class=\\\"bjs-cell-manager-strip\\\" role=\\\"listbox\\\" aria-multiselectable=\\\"true\\\" aria-label=\\\"\").concat(this._t('grid.cells', 'Cells'), \"\\\" style=\\\"--bjs-cell-manager-gap: 8px;\\\">\\n        \").concat(cards, \"\\n        \").concat(resizers, \"\\n        \").concat(slots, \"\\n      </div>\\n\\n      \").concat(bulk, \"\\n\\n      \").concat(alert, \"\\n\\n      <div class=\\\"bjs-cell-manager-hint\\\">\\n        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">lightbulb</span>\\n        <span>\").concat(this._t('grid.manager_hint', 'Card widths mirror the live grid layout. Click a card to edit its width below.'), \"</span>\\n      </div>\\n    \");\n      this._bindEvents();\n\n      /* After innerHTML lands, measure card rects and position insert slots\n         at the actual gap midpoints. Double-rAF — cards need one frame for\n         layout, then slots can read the resolved getBoundingClientRect. */\n      requestAnimationFrame(function () {\n        requestAnimationFrame(function () {\n          _this3._positionSlots();\n          _this3._observeStripResize();\n        });\n      });\n    }\n\n    /** Structure-preserving update: only patches `style.flex` + width label on\n     *  existing cards (no innerHTML swap). Used when CELL WIDTHS section\n     *  emits a width change — keeps focus + avoids flicker. */\n  }, {\n    key: \"applyCardWidths\",\n    value: function applyCardWidths() {\n      var _this4 = this;\n      var widths = this.getCellWidths();\n      var cards = this.domNode.querySelectorAll('.bjs-cell-card');\n      cards.forEach(function (card, i) {\n        var w = widths[i];\n        card.style.cssText = _this4._cardFlexStyle(w);\n        var label = card.querySelector('.bjs-cell-card-width');\n        if (label) label.textContent = _this4._widthLabel(w);\n      });\n      // Preset highlight may change\n      this._refreshPresetActive();\n      /* Widths changed → cards re-flex → slot gap positions drift. Re-measure. */\n      requestAnimationFrame(function () {\n        return _this4._positionSlots();\n      });\n    }\n\n    /** Update `is-selected` state without a full re-render. */\n  }, {\n    key: \"applySelection\",\n    value: function applySelection() {\n      var selected = this.getSelectedIndex();\n      this.domNode.querySelectorAll('.bjs-cell-card').forEach(function (card, i) {\n        card.classList.toggle('is-selected', i === selected);\n        if (i === selected) card.setAttribute('aria-selected', 'true');else card.removeAttribute('aria-selected');\n      });\n    }\n  }, {\n    key: \"_refreshPresetActive\",\n    value: function _refreshPresetActive() {\n      var activeId = this._activePresetId();\n      this.domNode.querySelectorAll('.bjs-cell-manager-preset').forEach(function (btn) {\n        btn.classList.toggle('is-active', btn.getAttribute('data-preset') === activeId);\n      });\n    }\n  }, {\n    key: \"_refreshMultiSelectClasses\",\n    value: function _refreshMultiSelectClasses() {\n      var _this5 = this;\n      this.domNode.querySelectorAll('.bjs-cell-card').forEach(function (card, i) {\n        card.classList.toggle('is-multi-selected', _this5._multiSelected.has(i));\n      });\n      /* Toggle the bulk bar via full re-render of that block only. Cheap — the\n         bulk bar DOM is ~3 elements, and multi-select state is infrequent. */\n      var host = this.domNode.querySelector('.bjs-cell-manager-bulk');\n      var fresh = this._renderBulkBar();\n      if (host && fresh) {\n        host.outerHTML = fresh;\n        this._bindBulkEvents();\n      } else if (host && !fresh) {\n        host.remove();\n      } else if (!host && fresh) {\n        var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n        if (strip) strip.insertAdjacentHTML('afterend', fresh);\n        this._bindBulkEvents();\n      }\n    }\n  }, {\n    key: \"_bindBulkEvents\",\n    value: function _bindBulkEvents() {\n      var _this6 = this;\n      var del = this.domNode.querySelector('[data-control=\"bulk-delete\"]');\n      var clear = this.domNode.querySelector('[data-control=\"bulk-clear\"]');\n      if (del) {\n        del.addEventListener('click', function () {\n          return _this6._bulkDelete();\n        });\n      }\n      if (clear) {\n        clear.addEventListener('click', function () {\n          _this6._multiSelected.clear();\n          _this6._refreshMultiSelectClasses();\n        });\n      }\n    }\n  }, {\n    key: \"_bulkDelete\",\n    value: function _bulkDelete() {\n      var _this7 = this;\n      var total = this.getItemCount();\n      if (total <= 1) return; // never delete the last cell\n      // Include the primary selection in the bulk set (so Shift-select + Delete\n      // behaves the way users expect — \"these + my current one\").\n      var primary = this.getSelectedIndex();\n      var set = new Set(this._multiSelected);\n      if (primary >= 0) set.add(primary);\n      // Never delete ALL cells — leave at least one standing.\n      if (set.size >= total) {\n        // Drop the highest index so the surviving cell is \"cell #1\".\n        var sorted = Array.from(set).sort(function (a, b) {\n          return b - a;\n        });\n        set[\"delete\"](sorted[0]);\n      }\n      if (!set.size) return;\n      var descending = Array.from(set).sort(function (a, b) {\n        return b - a;\n      });\n      this._multiSelected.clear();\n      if (this.callback && typeof this.callback.removeCells === 'function') {\n        this.callback.removeCells(descending);\n      } else if (this.callback && typeof this.callback.removeCell === 'function') {\n        descending.forEach(function (i) {\n          return _this7.callback.removeCell(i);\n        });\n      }\n      this.render();\n    }\n\n    /** Pointer-based drag-reorder on a card handle. Uses PointerCaptureRegistry\n     *  so lost-pointer cleanup happens automatically if the panel is torn down\n     *  mid-drag. A drop indicator line follows the pointer and snaps to the\n     *  nearest gap midpoint (between cards or at the outer edge).\n     */\n  }, {\n    key: \"_startHandleDrag\",\n    value: function _startHandleDrag(handle, card, ev) {\n      var _this8 = this;\n      if (ev.button !== undefined && ev.button !== 0) return;\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (!strip) return;\n      var sourceIdx = parseInt(card.getAttribute('data-cell-index'), 10);\n      if (isNaN(sourceIdx)) return;\n      ev.preventDefault();\n      ev.stopPropagation();\n\n      // Create drop indicator lazily — once per drag.\n      var indicator = strip.querySelector('.bjs-cell-manager-drop-indicator');\n      if (!indicator) {\n        indicator = document.createElement('div');\n        indicator.className = 'bjs-cell-manager-drop-indicator';\n        strip.appendChild(indicator);\n      }\n      indicator.classList.add('is-visible');\n      card.classList.add('is-dragging');\n      strip.classList.add('is-dragging');\n      _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].acquire(handle, ev.pointerId);\n      var onMove = function onMove(e) {\n        var slot = _this8._hitTestDropSlot(e.clientX);\n        _this8._dragState.dropSlot = slot;\n        _this8._paintDropIndicator(indicator, slot);\n      };\n      var onUp = function onUp() {\n        var dest = _this8._dragState ? _this8._dragState.dropSlot : null;\n        _this8._endHandleDrag(handle, card, indicator);\n        if (dest !== null && _this8.callback && typeof _this8.callback.moveCell === 'function') {\n          _this8.callback.moveCell(sourceIdx, dest);\n        }\n        // Re-render the panel so card indices + preset highlight reflect the\n        // new order. Use the existing render path so ResizeObserver + slot\n        // positioning re-attach cleanly.\n        _this8.render();\n      };\n      var onCancel = function onCancel() {\n        return _this8._endHandleDrag(handle, card, indicator);\n      };\n      this._dragState = {\n        sourceIdx: sourceIdx,\n        pointerId: ev.pointerId,\n        dropSlot: null,\n        handle: handle,\n        onMove: onMove,\n        onUp: onUp,\n        onCancel: onCancel\n      };\n      handle.addEventListener('pointermove', onMove);\n      handle.addEventListener('pointerup', onUp);\n      handle.addEventListener('pointercancel', onCancel);\n      handle.addEventListener('lostpointercapture', onCancel);\n\n      // First paint — show the indicator at the drag source so the UI confirms\n      // the interaction started. hitTest may return null if pointer is inside\n      // the source card itself (no valid move), which _paintDropIndicator\n      // handles by hiding the indicator.\n      var slot0 = this._hitTestDropSlot(ev.clientX);\n      this._dragState.dropSlot = slot0;\n      this._paintDropIndicator(indicator, slot0);\n    }\n  }, {\n    key: \"_endHandleDrag\",\n    value: function _endHandleDrag(handle, card, indicator) {\n      var st = this._dragState;\n      this._dragState = null;\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (strip) strip.classList.remove('is-dragging');\n      if (card) card.classList.remove('is-dragging');\n      if (indicator) indicator.classList.remove('is-visible');\n      if (st) {\n        try {\n          handle.removeEventListener('pointermove', st.onMove);\n        } catch (_e) {}\n        try {\n          handle.removeEventListener('pointerup', st.onUp);\n        } catch (_e) {}\n        try {\n          handle.removeEventListener('pointercancel', st.onCancel);\n        } catch (_e) {}\n        try {\n          handle.removeEventListener('lostpointercapture', st.onCancel);\n        } catch (_e) {}\n        try {\n          _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].release(handle, st.pointerId);\n        } catch (_e) {}\n      }\n    }\n\n    /** Given a pointer X (clientX), find the nearest drop slot (0..N). Returns\n     *  null when the pointer is over the source card itself OR the immediately\n     *  adjacent slots — those are no-op moves (the cell stays where it is). */\n  }, {\n    key: \"_hitTestDropSlot\",\n    value: function _hitTestDropSlot(clientX) {\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (!strip) return null;\n      var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n      if (!cards.length) return null;\n      var stripRect = strip.getBoundingClientRect();\n      var relX = clientX - stripRect.left;\n\n      // Build gap-midpoint candidates: slot 0 at left edge, slot N at right edge,\n      // slot i (0<i<N) between card[i-1] and card[i].\n      var midpoints = [];\n      midpoints.push(cards[0].getBoundingClientRect().left - stripRect.left - 8);\n      for (var i = 1; i < cards.length; i++) {\n        var a = cards[i - 1].getBoundingClientRect().right - stripRect.left;\n        var b = cards[i].getBoundingClientRect().left - stripRect.left;\n        midpoints.push((a + b) / 2);\n      }\n      midpoints.push(cards[cards.length - 1].getBoundingClientRect().right - stripRect.left + 8);\n      var bestI = 0;\n      var bestDist = Infinity;\n      midpoints.forEach(function (x, i) {\n        var d = Math.abs(x - relX);\n        if (d < bestDist) {\n          bestDist = d;\n          bestI = i;\n        }\n      });\n\n      // Reject no-op slots (source and source+1 both resolve back to same cell).\n      var src = this._dragState ? this._dragState.sourceIdx : -1;\n      if (src === bestI || src + 1 === bestI) return null;\n      return bestI;\n    }\n  }, {\n    key: \"_paintDropIndicator\",\n    value: function _paintDropIndicator(indicator, slot) {\n      if (!indicator) return;\n      if (slot === null || slot === undefined) {\n        indicator.classList.remove('is-visible');\n        return;\n      }\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (!strip) return;\n      var cards = Array.from(strip.querySelectorAll(':scope > .bjs-cell-card'));\n      var stripRect = strip.getBoundingClientRect();\n      var xPx;\n      if (slot === 0) {\n        xPx = Math.max(0, cards[0].getBoundingClientRect().left - stripRect.left - 4);\n      } else if (slot >= cards.length) {\n        xPx = Math.min(stripRect.width, cards[cards.length - 1].getBoundingClientRect().right - stripRect.left + 4);\n      } else {\n        var a = cards[slot - 1].getBoundingClientRect().right - stripRect.left;\n        var b = cards[slot].getBoundingClientRect().left - stripRect.left;\n        xPx = (a + b) / 2;\n      }\n      indicator.style.left = \"\".concat(xPx, \"px\");\n      indicator.classList.add('is-visible');\n    }\n\n    /** Pointer-based resize between two adjacent cells. Computes new left/right\n     *  percent of their combined span as the pointer moves; snap magnets engage\n     *  near the canonical ratios (see SNAP_RATIOS). Preview-only until pointerup\n     *  — final widths are committed in a single `resizeCellPair` call so the\n     *  rebalance banner doesn't flicker. */\n  }, {\n    key: \"_startResizeDrag\",\n    value: function _startResizeDrag(grip, ev) {\n      var _this9 = this;\n      if (ev.button !== undefined && ev.button !== 0) return;\n      var leftIdx = parseInt(grip.parentElement.getAttribute('data-resizer-left'), 10);\n      if (isNaN(leftIdx)) return;\n      var widths = this.getCellWidths();\n      var lPct = this._asPct(widths[leftIdx]);\n      var rPct = this._asPct(widths[leftIdx + 1]);\n      if (lPct === null || rPct === null) return;\n      ev.preventDefault();\n      ev.stopPropagation();\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      var combined = lPct + rPct; // the \"budget\" for this pair\n\n      var leftCard = strip.querySelectorAll(':scope > .bjs-cell-card')[leftIdx];\n      var rightCard = strip.querySelectorAll(':scope > .bjs-cell-card')[leftIdx + 1];\n      var leftRect = leftCard.getBoundingClientRect();\n      var rightRect = rightCard.getBoundingClientRect();\n      var pxLeft = leftRect.left;\n      var pxRight = rightRect.right;\n      var pxSpan = pxRight - pxLeft;\n      this._resizeState = {\n        grip: grip,\n        pointerId: ev.pointerId,\n        leftIdx: leftIdx,\n        startL: lPct,\n        startR: rPct,\n        combined: combined,\n        pxLeft: pxLeft,\n        pxSpan: pxSpan,\n        currL: lPct,\n        currR: rPct\n      };\n      strip.parentElement.classList.add('is-resizing');\n      this.domNode.classList.add('is-measuring');\n      grip.parentElement.classList.add('is-dragging');\n      _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].acquire(grip, ev.pointerId);\n      var onMove = function onMove(e) {\n        return _this9._applyResizePreview(e.clientX);\n      };\n      var onUp = function onUp() {\n        return _this9._finishResize(false);\n      };\n      var onCancel = function onCancel() {\n        return _this9._finishResize(true);\n      };\n      this._resizeState.onMove = onMove;\n      this._resizeState.onUp = onUp;\n      this._resizeState.onCancel = onCancel;\n      grip.addEventListener('pointermove', onMove);\n      grip.addEventListener('pointerup', onUp);\n      grip.addEventListener('pointercancel', onCancel);\n      grip.addEventListener('lostpointercapture', onCancel);\n    }\n\n    /** Update card DOM + tooltip during resize drag. Does NOT call setFormat —\n     *  that fires on pointerup so undo stack stays single-entry per drag. */\n  }, {\n    key: \"_applyResizePreview\",\n    value: function _applyResizePreview(clientX) {\n      var st = this._resizeState;\n      if (!st) return;\n      var rel = Math.max(0, Math.min(st.pxSpan, clientX - st.pxLeft));\n      var ratio = rel / st.pxSpan; // 0..1 — fraction of combined given to LEFT cell\n\n      // Snap check — if ratio is within tolerance of a canonical snap, lock it.\n      var snapLabel = null;\n      for (var _i2 = 0, _SNAP_RATIOS = SNAP_RATIOS; _i2 < _SNAP_RATIOS.length; _i2++) {\n        var s = _SNAP_RATIOS[_i2];\n        if (Math.abs(ratio - s.v) <= SNAP_TOLERANCE) {\n          ratio = s.v;\n          snapLabel = s.label;\n          break;\n        }\n      }\n      var l = Math.max(1, Math.min(99, ratio * st.combined));\n      var r = Math.max(1, st.combined - l);\n      st.currL = l;\n      st.currR = r;\n      st.snapLabel = snapLabel;\n\n      // Paint neighbors' flex in place (no full re-render).\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      var leftCard = strip.querySelectorAll(':scope > .bjs-cell-card')[st.leftIdx];\n      var rightCard = strip.querySelectorAll(':scope > .bjs-cell-card')[st.leftIdx + 1];\n      if (leftCard) {\n        leftCard.style.cssText = \"flex: 0 0 \".concat(l, \"%;\");\n        var lbl = leftCard.querySelector('.bjs-cell-card-width');\n        if (lbl) lbl.textContent = \"\".concat(Math.round(l * 100) / 100, \"%\");\n      }\n      if (rightCard) {\n        rightCard.style.cssText = \"flex: 0 0 \".concat(r, \"%;\");\n        var _lbl = rightCard.querySelector('.bjs-cell-card-width');\n        if (_lbl) _lbl.textContent = \"\".concat(Math.round(r * 100) / 100, \"%\");\n      }\n\n      // Tooltip\n      var tip = st.grip.parentElement.querySelector('.bjs-cell-manager-resizer-tip');\n      if (tip) {\n        var val = tip.querySelector('.bjs-cell-manager-resizer-tip-value');\n        if (val) val.innerHTML = snapLabel ? \"<strong>\".concat(snapLabel, \"</strong> <span class=\\\"bjs-cell-manager-resizer-tip-pct\\\">\").concat(Math.round(l), \"% / \").concat(Math.round(r), \"%</span>\") : \"\".concat(Math.round(l * 100) / 100, \"% / \").concat(Math.round(r * 100) / 100, \"%\");\n        tip.classList.add('is-visible');\n        tip.classList.toggle('is-snapped', !!snapLabel);\n      }\n\n      // Ruler active-tick highlight — light up the major ticks nearest the\n      // preview value so the author sees alignment opportunities.\n      this._updateRulerSnap(l);\n\n      // Slot positions + sibling resizers depend on flex widths → re-measure.\n      this._positionSlots();\n    }\n  }, {\n    key: \"_updateRulerSnap\",\n    value: function _updateRulerSnap(leftPct) {\n      if (!this.domNode) return;\n      var ticks = this.domNode.querySelectorAll('.bjs-cell-manager-ruler-tick');\n      ticks.forEach(function (t) {\n        var v = parseFloat(t.getAttribute('data-ruler'));\n        t.classList.toggle('is-active', !isNaN(v) && Math.abs(v - leftPct) < 2);\n      });\n    }\n  }, {\n    key: \"_finishResize\",\n    value: function _finishResize(cancelled) {\n      var st = this._resizeState;\n      this._resizeState = null;\n      if (!st) return;\n      var grip = st.grip;\n      var resizerEl = grip.parentElement;\n      var strip = this.domNode.querySelector('.bjs-cell-manager-strip');\n      if (strip && strip.parentElement) strip.parentElement.classList.remove('is-resizing');\n      this.domNode.classList.remove('is-measuring');\n      if (resizerEl) resizerEl.classList.remove('is-dragging');\n      var tip = resizerEl ? resizerEl.querySelector('.bjs-cell-manager-resizer-tip') : null;\n      if (tip) {\n        tip.classList.remove('is-visible');\n        tip.classList.remove('is-snapped');\n      }\n      try {\n        grip.removeEventListener('pointermove', st.onMove);\n      } catch (_e) {}\n      try {\n        grip.removeEventListener('pointerup', st.onUp);\n      } catch (_e) {}\n      try {\n        grip.removeEventListener('pointercancel', st.onCancel);\n      } catch (_e) {}\n      try {\n        grip.removeEventListener('lostpointercapture', st.onCancel);\n      } catch (_e) {}\n      try {\n        _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].release(grip, st.pointerId);\n      } catch (_e) {}\n\n      // Clear ruler snap highlight.\n      this.domNode.querySelectorAll('.bjs-cell-manager-ruler-tick.is-active').forEach(function (t) {\n        return t.classList.remove('is-active');\n      });\n      if (cancelled) {\n        // Restore starting widths via callback — NOT just CSS — so the underlying\n        // formatter doesn't drift. Cheaper than a full render().\n        if (this.callback && typeof this.callback.resizeCellPair === 'function') {\n          this.callback.resizeCellPair(st.leftIdx, st.startL, st.startR);\n        }\n        this.applyCardWidths();\n        return;\n      }\n\n      // Commit final widths via callback — single formatter tick.\n      if (this.callback && typeof this.callback.resizeCellPair === 'function') {\n        this.callback.resizeCellPair(st.leftIdx, st.currL, st.currR);\n      }\n      this._dismissed = false;\n      this.applyCardWidths();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this10 = this;\n      // GridElement now does incremental DOM updates (no full re-render on\n      // add/remove), so the settings panel is NOT torn down. Our panel\n      // repaint can therefore be synchronous — reflects the latest cell\n      // count immediately.\n      //\n      // Add cell (end)\n      this.domNode.querySelectorAll('[data-control=\"add-cell\"]').forEach(function (btn) {\n        btn.addEventListener('click', function () {\n          if (_this10.callback && typeof _this10.callback.addCell === 'function') {\n            _this10.callback.addCell();\n            _this10.render();\n          }\n        });\n      });\n\n      // Add at specific index (inline insert slots)\n      this.domNode.querySelectorAll('[data-control=\"add-cell-at\"]').forEach(function (btn) {\n        btn.addEventListener('click', function () {\n          var idx = parseInt(btn.getAttribute('data-index'), 10);\n          if (_this10.callback && typeof _this10.callback.addCellAt === 'function') {\n            _this10.callback.addCellAt(idx);\n            _this10.render();\n          }\n        });\n      });\n\n      // Remove cell\n      this.domNode.querySelectorAll('[data-control=\"remove-cell\"]').forEach(function (btn) {\n        btn.addEventListener('click', function (e) {\n          e.stopPropagation(); // don't also trigger card selection\n          var idx = parseInt(btn.getAttribute('data-index'), 10);\n          if (_this10.callback && typeof _this10.callback.removeCell === 'function') {\n            _this10.callback.removeCell(idx);\n            _this10.render();\n          }\n        });\n      });\n\n      // Card click — primary select OR bulk toggle (Shift/Cmd)\n      this.domNode.querySelectorAll('.bjs-cell-card').forEach(function (card) {\n        card.addEventListener('click', function (e) {\n          var idx = parseInt(card.getAttribute('data-cell-index'), 10);\n          if (isNaN(idx)) return;\n\n          // Ignore clicks that landed on a button child (those already handled\n          // their own event); click on handle also bails — handle is a drag\n          // affordance, not a select affordance.\n          if (e.target.closest('.bjs-cell-card-remove, .bjs-cell-card-handle')) return;\n          if (e.shiftKey) {\n            // Range select from primary selection to clicked idx\n            var primary = _this10.getSelectedIndex();\n            if (primary >= 0 && primary !== idx) {\n              var _ref = primary < idx ? [primary, idx] : [idx, primary],\n                _ref2 = _slicedToArray(_ref, 2),\n                lo = _ref2[0],\n                hi = _ref2[1];\n              for (var i = lo; i <= hi; i++) if (i !== primary) _this10._multiSelected.add(i);\n            } else {\n              _this10._multiSelected.add(idx);\n            }\n            _this10._refreshMultiSelectClasses();\n            return;\n          }\n          if (e.ctrlKey || e.metaKey) {\n            if (_this10._multiSelected.has(idx)) _this10._multiSelected[\"delete\"](idx);else _this10._multiSelected.add(idx);\n            _this10._refreshMultiSelectClasses();\n            return;\n          }\n\n          // Plain click → primary select + clear multi-selection\n          if (_this10._multiSelected.size) {\n            _this10._multiSelected.clear();\n            _this10._refreshMultiSelectClasses();\n          }\n          if (_this10.callback && typeof _this10.callback.selectCell === 'function') {\n            _this10.callback.selectCell(idx);\n          }\n        });\n      });\n\n      // Drag handle — pointer-based drag-reorder (Phase-3 W6.1)\n      this.domNode.querySelectorAll('.bjs-cell-card-handle').forEach(function (handle) {\n        var card = handle.closest('.bjs-cell-card');\n        if (!card) return;\n        // Block the browser's native drag on the icon span inside the handle —\n        // we use pointer events, not HTML5 DnD.\n        handle.addEventListener('dragstart', function (e) {\n          return e.preventDefault();\n        });\n        handle.addEventListener('pointerdown', function (e) {\n          return _this10._startHandleDrag(handle, card, e);\n        });\n        // Keyboard reorder — ArrowLeft / ArrowRight while the handle has focus\n        // moves the cell one slot in the chosen direction. Accessibility parity\n        // with pointer drag.\n        handle.addEventListener('keydown', function (e) {\n          if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n          var idx = parseInt(card.getAttribute('data-cell-index'), 10);\n          if (isNaN(idx)) return;\n          var total = _this10.getItemCount();\n          var target = e.key === 'ArrowLeft' ? idx - 1 : idx + 2; // slot semantics\n          if (target < 0 || target > total) return;\n          if (!_this10.callback || typeof _this10.callback.moveCell !== 'function') return;\n          e.preventDefault();\n          _this10.callback.moveCell(idx, target);\n          _this10.render();\n          // Re-focus the handle on the new card so the user can keep arrowing.\n          requestAnimationFrame(function () {\n            var newIdx = e.key === 'ArrowLeft' ? idx - 1 : idx + 1;\n            var newCard = _this10.domNode.querySelector(\".bjs-cell-card[data-cell-index=\\\"\".concat(newIdx, \"\\\"] .bjs-cell-card-handle\"));\n            if (newCard && typeof newCard.focus === 'function') newCard.focus();\n          });\n        });\n      });\n\n      // Layout presets\n      this.domNode.querySelectorAll('.bjs-cell-manager-preset').forEach(function (btn) {\n        btn.addEventListener('click', function () {\n          var id = btn.getAttribute('data-preset');\n          var preset = LAYOUT_PRESETS.find(function (p) {\n            return p.id === id;\n          });\n          if (!preset) return;\n          if (_this10.callback && typeof _this10.callback.applyPreset === 'function') {\n            // A fresh preset resets the \"user has dismissed the alert\" flag —\n            // the banner should appear again if the new preset over/under-fills.\n            _this10._dismissed = false;\n            _this10._multiSelected.clear();\n            _this10.callback.applyPreset(preset.widths.slice());\n            _this10.render();\n          }\n        });\n      });\n\n      // Rebalance alert actions (only present when the row sums != 100%).\n      var alertRebalance = this.domNode.querySelector('[data-control=\"alert-rebalance\"]');\n      if (alertRebalance) {\n        alertRebalance.addEventListener('click', function () {\n          if (_this10.callback && typeof _this10.callback.rebalanceProportional === 'function') {\n            _this10.callback.rebalanceProportional();\n            _this10._dismissed = false;\n            _this10.render();\n          }\n        });\n      }\n      var alertEqualize = this.domNode.querySelector('[data-control=\"alert-equalize\"]');\n      if (alertEqualize) {\n        alertEqualize.addEventListener('click', function () {\n          if (_this10.callback && typeof _this10.callback.equalize === 'function') {\n            _this10.callback.equalize();\n            _this10._dismissed = false;\n            _this10.render();\n          }\n        });\n      }\n      var alertDismiss = this.domNode.querySelector('[data-control=\"alert-dismiss\"]');\n      if (alertDismiss) {\n        alertDismiss.addEventListener('click', function () {\n          _this10._dismissed = true;\n          _this10.render();\n        });\n      }\n\n      // Resizer grips — pointer-based snap-resize (Phase-3 W6.1)\n      this.domNode.querySelectorAll('.bjs-cell-manager-resizer-grip').forEach(function (grip) {\n        grip.addEventListener('dragstart', function (e) {\n          return e.preventDefault();\n        });\n        grip.addEventListener('pointerdown', function (e) {\n          return _this10._startResizeDrag(grip, e);\n        });\n      });\n      this._bindBulkEvents();\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/GridControl.js?");

/***/ }),

/***/ "./src/includes/GridElement.js":
/*!*************************************!*\
  !*** ./src/includes/GridElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _GridControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./GridControl.js */ \"./src/includes/GridControl.js\");\n/* harmony import */ var _RangeControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _overlays_GridStructureOverlay_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./overlays/GridStructureOverlay.js */ \"./src/includes/overlays/GridStructureOverlay.js\");\n/* harmony import */ var _overlays_GridColumnResizeOverlay_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./overlays/GridColumnResizeOverlay.js */ \"./src/includes/overlays/GridColumnResizeOverlay.js\");\n/* harmony import */ var _overlays_GridInsertColumnOverlay_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./overlays/GridInsertColumnOverlay.js */ \"./src/includes/overlays/GridInsertColumnOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar GridElement = /*#__PURE__*/function (_BaseElement) {\n  function GridElement(template) {\n    var _this;\n    _classCallCheck(this, GridElement);\n    _this = _callSuper(this, GridElement);\n    _this.template = template;\n    _this.cells = [];\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['cells'];\n    _this.cell_gap = 0;\n\n    // `align_items` controls cell HEIGHT (stretch = equal, others = auto\n    // with vertical positioning). Default 'stretch' matches Webflow /\n    // Figma / Tailwind / CSS flex default — coloring a cell background\n    // fills the cell edge-to-edge without leaving a gap under shorter\n    // content. Existing samples with staggered heights can opt into\n    // 'flex-start' via the Cell Alignment control.\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"]({\n      background_color: null,\n      background_image: null,\n      background_position: null,\n      background_size: null,\n      background_repeat: null,\n      background_blend_mode: null,\n      opacity: null,\n      filter: null,\n      align_items: 'stretch'\n    });\n    return _this;\n  }\n  _inherits(GridElement, _BaseElement);\n  return _createClass(GridElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return 'Grid';\n    }\n  }, {\n    key: \"isHoverable\",\n    value: function isHoverable() {\n      return false;\n    }\n\n    /**\n     * Canvas overlays:\n     *   - GridStructureOverlay (Phase 1.3) — dashed cell boundaries\n     *   - n-1 × GridColumnResizeOverlay (Phase 1.3) — drag separators\n     *   - n+1 × GridInsertColumnOverlay (Phase 1.5) — \"+\" insert buttons,\n     *     one before cell 0, then one after each cell\n     *\n     * Total instances for n cells: 1 + (n-1) + (n+1) = 2n+1.\n     *\n     * Trigger: 'select' (isHoverable() === false — SA invariant I7).\n     * Mount path: user selects grid via breadcrumb or GridControl card.\n     * See docs/core/OVERLAY.md §7.1 + docs/archived/OVERLAY_PLAN.md §3.4 + §3.6.\n     */\n  }, {\n    key: \"getOverlays\",\n    value: function getOverlays() {\n      var overlays = [new _overlays_GridStructureOverlay_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](this)];\n      var n = Array.isArray(this.cells) ? this.cells.length : 0;\n      for (var i = 0; i < n - 1; i++) {\n        overlays.push(new _overlays_GridColumnResizeOverlay_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](this, {\n          boundaryIndex: i\n        }));\n      }\n      // Insert buttons: one per insertion boundary. Skip when grid is\n      // empty (no boundaries yet — addCell flow is via the sidebar\n      // GridControl in that state).\n      if (n > 0) {\n        for (var _i = 0; _i <= n; _i++) {\n          overlays.push(new _overlays_GridInsertColumnOverlay_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](this, {\n            insertAt: _i,\n            boundary: _i === 0 ? 'before' : 'after'\n          }));\n        }\n      }\n      return overlays;\n    }\n\n    /** Host-injection recursion hook — returns this grid's cells so\n     *  Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n     *  Injection\" lesson. */\n  }, {\n    key: \"getChildren\",\n    value: function getChildren() {\n      return this.cells || [];\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      var _this2 = this;\n      while (this.domNode.firstChild) {\n        this.domNode.removeChild(this.domNode.firstChild);\n      }\n\n      // 2026-04-18 refactor — drop the cell-anchor text-placeholder pattern.\n      // Previously each cell was represented in the template as\n      // `<div cell-anchor=\"ID\">ID</div>` and the JS loop swapped the\n      // anchor for the real cell DOM. If any step failed (or rendered\n      // on a stale DOM snapshot), the anchor's text content — the raw\n      // cell ID like `_0xrafirbu` — leaked through visibly on canvas\n      // (user report 2026-04-18 after add-cell action). Fix: render the\n      // Grid wrapper EMPTY, then DOM-append each cell's domNode directly.\n      // No text placeholders → nothing to leak.\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        cells: [],\n        // wrapper only — cells attach below\n        cell_gap: this.cell_gap,\n        align_items: this.formatter.getFormat('align_items') || 'stretch'\n      });\n      var wrapper = this.domNode.firstElementChild;\n      if (!wrapper) return;\n      this.cells.forEach(function (cell) {\n        var cellDom = cell.render();\n        wrapper.appendChild(cellDom);\n        _this2.host.uiManager.addElement(cell);\n      });\n    }\n  }, {\n    key: \"addCell\",\n    value: function addCell() {\n      var cell = this.newCell();\n      cell.formatter.setFormat('width', this._defaultWidthForNewCell());\n      this.append(cell);\n      // 2026-04-18 auto-distribute on add: proportionally scale all %-cells\n      // (including the new one) so the row sums to exactly 100%. Prevents\n      // the \"new cell overflows canvas\" UX issue the user flagged. Keeps\n      // authored ratios between existing cells. The explicit Rebalance\n      // button (`.bjs-cell-manager-alert`) still fires for MANUAL width\n      // edits that break the 100% invariant — this block only handles the\n      // structural add/remove path.\n      //\n      // Incremental DOM append — DON'T full-re-render. A full render()\n      // was tearing down the settings panel (selection events cascade\n      // through uiManager.addElement for EVERY cell) while the\n      // GridControl was mid-repaint, so the cell-manager ended up on a\n      // detached DOM and never reflected the new count (2026-04-18\n      // regression).\n      this.rebalanceCellsProportional();\n      this._appendCellDom(cell);\n    }\n\n    /** Pick a reasonable width for a newly-added cell so it actually\n     *  appears on canvas. Mirrors existing cells' semantic:\n     *  - all cells bare-number grow-share → new cell gets the mean of\n     *    existing ratios (e.g. [50, 50] → new cell = 50, ratio 1:1:1)\n     *  - all cells % → new cell = 100 / (n + 1) as a % (auto-rebalance on\n     *    the new-cell side only; existing cells keep their values so the\n     *    user's carefully-set ratios aren't destroyed)\n     *  - cells in px/em/rem → new cell copies the last cell's width\n     *  - mixed / auto → new cell = 'auto' (grow-share 1 — safe default)\n     *\n     *  Does NOT mutate other cells. If the author later wants full\n     *  re-normalisation they use a layout preset.\n     */\n  }, {\n    key: \"_defaultWidthForNewCell\",\n    value: function _defaultWidthForNewCell() {\n      if (this.cells.length === 0) return 'auto';\n      var widths = this.cells.map(function (c) {\n        return c.formatter.getFormat('width', 'auto');\n      });\n\n      // All-% (post-legacy-upgrade normal case): pick 100/(n+1)% so the\n      // row sums > 100% (overflow). GridControl surfaces this via the\n      // rebalance alert banner — the user sees the overflow and chooses\n      // an action (see Lesson 22). We deliberately don't silently shrink\n      // existing cells — destroying authored ratios is worse UX than a\n      // visible banner.\n      var allPct = widths.every(function (w) {\n        return typeof w === 'string' && /%$/.test(String(w).trim());\n      });\n      if (allPct) {\n        var next = Math.floor(10000 / (this.cells.length + 1)) / 100;\n        return \"\".concat(next, \"%\");\n      }\n\n      // All grow-share bare (legacy 3rd-party data that escaped the\n      // GridElement.parse upgrade — possible for in-memory widgets built\n      // without going through parse()). Emit a % for the new cell so it\n      // stays visible.\n      var allBare = widths.every(function (w) {\n        return typeof w === 'number' || typeof w === 'string' && /^-?[\\d.]+$/.test(String(w).trim());\n      });\n      if (allBare) {\n        var nums = widths.map(function (w) {\n          return parseFloat(w);\n        });\n        var sum = nums.reduce(function (a, b) {\n          return a + b;\n        }, 0);\n        if (sum > 0) {\n          var mean = Math.round(sum / nums.length / sum * 10000) / 100;\n          return \"\".concat(mean, \"%\");\n        }\n        return '50%';\n      }\n\n      // All fixed-unit (px/em/rem/vw/vh): copy the last cell's width —\n      // author is in a pixel-grid mode and probably wants consistency.\n      var lastW = widths[widths.length - 1];\n      if (typeof lastW === 'string' && /(px|em|rem|vw|vh)$/i.test(lastW)) {\n        return lastW;\n      }\n\n      // Mixed (auto + something else) — new cell = 'auto' to avoid\n      // disturbing the other cells' implicit sizing assumptions.\n      return 'auto';\n    }\n  }, {\n    key: \"append\",\n    value: function append(cell) {\n      cell.container = this;\n      // Host injection — propagate this grid's host onto the new cell\n      // (and its subtree). Safe before the grid itself is adopted: in\n      // that case `this.host` is null and `_adopt` is a no-op; the\n      // caller's later `_adopt(grid)` will recurse and reach the cell.\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(cell);\n      }\n      this.cells.push(cell);\n    }\n  }, {\n    key: \"removeCellByIndex\",\n    value: function removeCellByIndex(index) {\n      var cell = this.cells[index];\n      this.cells.splice(index, 1);\n      if (cell && cell.domNode && cell.domNode.parentNode) {\n        cell.domNode.parentNode.removeChild(cell.domNode);\n      }\n      // Auto-refill — remaining %-cells scale up so the row sums back to\n      // 100%. Example: [25%, 25%, 25%, 25%] delete #3 → [33.33%, 33.33%,\n      // 33.34%]. Manual Rebalance button still exists for when the user\n      // drags sliders into an invalid sum.\n      this.rebalanceCellsProportional();\n    }\n  }, {\n    key: \"appendCells\",\n    value: function appendCells(cells) {\n      var _this3 = this;\n      cells.forEach(function (cell) {\n        _this3.append(cell);\n      });\n    }\n  }, {\n    key: \"removeElement\",\n    value: function removeElement(element) {\n      var _this4 = this;\n      this.cells.forEach(function (currentElement) {\n        if (currentElement == element) {\n          _this4.cells = _this4.cells.filter(function (el) {\n            return el !== element;\n          });\n          _this4.render();\n          if (!_this4.cells.length) {\n            _this4.remove();\n            _this4.host.unselect();\n          }\n        }\n      });\n    }\n  }, {\n    key: \"insertElementAfter\",\n    value: function insertElementAfter(element, newElement) {\n      var _this5 = this;\n      newElement.container = this;\n      this.cells.forEach(function (currentElement, i) {\n        if (currentElement === element) {\n          _this5.cells.splice(i + 1, 0, newElement);\n          _this5.render();\n          return;\n        }\n      });\n    }\n  }, {\n    key: \"newCell\",\n    value: function newCell() {\n      // Pre-existing bug surfaced 2026-04-18 when addCell() started calling\n      // cell.render() incrementally: `this.template` here is the GRID's\n      // template (e.g. 'Grid'), NOT the cell template. Rendering the Grid\n      // template as a cell threw `align_items is not defined`. The old flow\n      // never hit this because `addCell()` didn't render the new cell — it\n      // just pushed to this.cells. Fix: mirror existing cells' template,\n      // or fall back to 'Cell' (the canonical name used by GridWidget +\n      // every sample JSON's cell data).\n      var cellTemplate = this.cells.length > 0 ? this.cells[0].template : 'Cell';\n      var cell = new _CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](cellTemplate);\n      cell.container = this;\n      return cell;\n    }\n  }, {\n    key: \"addCellAt\",\n    value: function addCellAt(index) {\n      var newCell = this.newCell();\n      // Host injection — newCell is a fresh `new CellElement(...)` with\n      // no host yet. Adopt before insert so its overlays/controls can\n      // reach the bus + flags from first render.\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(newCell);\n      }\n      newCell.formatter.setFormat('width', this._defaultWidthForNewCell());\n      newCell.container = this;\n      if (index === 0) {\n        this.cells.unshift(newCell);\n      } else if (index >= this.cells.length) {\n        this.cells.push(newCell);\n      } else {\n        this.cells.splice(index, 0, newCell);\n      }\n      // Auto-distribute on insert — see addCell() for rationale.\n      this.rebalanceCellsProportional();\n      this._appendCellDom(newCell, index);\n      return newCell;\n    }\n\n    /** DOM-append (or insert at index) a single cell without triggering\n     *  full GridElement.render(). Preserves the existing cell DOM nodes\n     *  and their canvas selection state. */\n  }, {\n    key: \"_appendCellDom\",\n    value: function _appendCellDom(cell, index) {\n      if (!this.domNode) {\n        // No DOM yet — caller should invoke render() instead.\n        this.render();\n        return;\n      }\n      var wrapper = this.domNode.firstElementChild;\n      if (!wrapper) {\n        this.render();\n        return;\n      }\n      var cellDom = cell.render();\n      if (typeof index === 'number') {\n        var siblings = wrapper.querySelectorAll(':scope > [builder-element=\"CellElement\"]');\n        if (index >= siblings.length) {\n          wrapper.appendChild(cellDom);\n        } else {\n          wrapper.insertBefore(cellDom, siblings[index]);\n        }\n      } else {\n        wrapper.appendChild(cellDom);\n      }\n      this.host.uiManager.addElement(cell);\n    }\n\n    /** Apply a layout preset — overwrite cell count + per-cell widths in one\n     *  atomic change. Added cells get a default formatter; removed cells are\n     *  dropped wholesale. */\n  }, {\n    key: \"applyLayoutPreset\",\n    value: function applyLayoutPreset(widths) {\n      var target = widths.length;\n      while (this.cells.length < target) {\n        this.append(this.newCell());\n      }\n      while (this.cells.length > target) {\n        this.cells.pop();\n      }\n      // LAYOUT_PRESETS carries grow-share ratios (e.g. [1, 1] or [1, 2]).\n      // We convert those to explicit percents summing to 100% so the\n      // stored format matches the \"all-% authoring\" convention (2026-04-18).\n      // Mixed patterns like ['auto'] pass through unchanged.\n      var normalized = widths.map(function (w) {\n        if (w === 'auto' || w === null || w === undefined || w === '') return 'auto';\n        if (typeof w === 'string' && /%$/.test(w)) return w;\n        return w;\n      });\n      var barePattern = normalized.every(function (w) {\n        return typeof w === 'number' || typeof w === 'string' && /^-?\\d+(\\.\\d+)?$/.test(w.trim());\n      });\n      var finalWidths = normalized;\n      if (barePattern) {\n        var nums = normalized.map(function (w) {\n          return parseFloat(w);\n        });\n        var sum = nums.reduce(function (a, b) {\n          return a + b;\n        }, 0);\n        if (sum > 0) {\n          var pcts = nums.map(function (n) {\n            return Math.round(n / sum * 10000) / 100;\n          });\n          var residue = Math.round((100 - pcts.reduce(function (a, b) {\n            return a + b;\n          }, 0)) * 100) / 100;\n          if (Math.abs(residue) >= 0.01) pcts[pcts.length - 1] = Math.round((pcts[pcts.length - 1] + residue) * 100) / 100;\n          finalWidths = pcts.map(function (v) {\n            return \"\".concat(v, \"%\");\n          });\n        }\n      }\n      this.cells.forEach(function (cell, i) {\n        cell.formatter.setFormat('width', finalWidths[i]);\n      });\n      this.render();\n    }\n\n    /** Programmatic cell selection — called by GridControl when user clicks\n     *  a card. Routes through the host (per-instance) which handles the\n     *  highlight + settings panel rebuild. */\n  }, {\n    key: \"selectCellAt\",\n    value: function selectCellAt(index) {\n      var _this$host;\n      var cell = this.cells[index];\n      if (cell && typeof ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.selectElement) === 'function') {\n        this.host.selectElement(cell);\n      }\n    }\n  }, {\n    key: \"getSelectedCellIndex\",\n    value: function getSelectedCellIndex() {\n      if (!this.host || !this.host.selectedElement) return -1;\n      var sel = this.host.selectedElement;\n      for (var i = 0; i < this.cells.length; i++) {\n        if (this.cells[i] === sel) return i;\n      }\n      return -1;\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(GridElement, \"getData\", this, 3)([])), {}, {\n        cells: this.cells.map(function (cell) {\n          return cell.getData();\n        }),\n        cell_gap: this.cell_gap\n      });\n    }\n  }, {\n    key: \"rebalanceCellsProportional\",\n    value:\n    /** Rebalance percent cells so the row sums to exactly 100%. Proportional:\n     *  each cell's percent is scaled by `(100 / currentSum)`. Non-percent\n     *  cells are left untouched (nothing to scale — `auto`/`fill`/`px` don't\n     *  participate in the 100% budget). Used by the cell-manager alert banner\n     *  \"Rebalance\" action. */\n    function rebalanceCellsProportional() {\n      var _this6 = this;\n      var pcts = this.cells.map(function (c) {\n        var w = c.formatter.getFormat('width');\n        if (typeof w === 'string' && /%$/.test(w.trim())) return parseFloat(w);\n        return null;\n      });\n      var pctCells = pcts.map(function (v, i) {\n        return v !== null ? {\n          v: v,\n          i: i\n        } : null;\n      }).filter(Boolean);\n      var sum = pctCells.reduce(function (a, b) {\n        return a + b.v;\n      }, 0);\n      if (sum <= 0 || pctCells.length === 0) return;\n      var scaled = pctCells.map(function (_ref) {\n        var v = _ref.v,\n          i = _ref.i;\n        return {\n          i: i,\n          v: Math.round(v * 100 / sum * 100) / 100\n        };\n      });\n      // Distribute rounding residue to the last % cell so the total lands\n      // exactly on 100.\n      var residue = Math.round((100 - scaled.reduce(function (a, b) {\n        return a + b.v;\n      }, 0)) * 100) / 100;\n      if (Math.abs(residue) >= 0.01) scaled[scaled.length - 1].v = Math.round((scaled[scaled.length - 1].v + residue) * 100) / 100;\n      scaled.forEach(function (_ref2) {\n        var i = _ref2.i,\n          v = _ref2.v;\n        _this6.cells[i].formatter.setFormat('width', \"\".concat(v, \"%\"));\n        _this6.cells[i].render();\n      });\n    }\n\n    /** Equalize: every cell becomes 100/N percent. Replaces ALL widths\n     *  (including auto/fill/px) — the user has opted into a uniform row.\n     *  Used by the cell-manager alert \"Equalize\" action. */\n  }, {\n    key: \"equalizeCells\",\n    value: function equalizeCells() {\n      var n = this.cells.length;\n      if (n === 0) return;\n      var each = Math.floor(10000 / n) / 100; // 2 decimal places\n      var residue = Math.round((100 - each * n) * 100) / 100;\n      this.cells.forEach(function (cell, i) {\n        var v = i === n - 1 ? Math.round((each + residue) * 100) / 100 : each;\n        cell.formatter.setFormat('width', \"\".concat(v, \"%\"));\n        cell.render();\n      });\n    }\n\n    /** Move a cell from index `from` to index `to` (Phase-3 W6.1 drag-reorder).\n     *  `to` is the target SLOT index (0..cells.length), so the interpretation\n     *  mirrors the `+` insert slots: slot N means \"land at position N after\n     *  removing the source\". Identity moves and out-of-range args are no-ops.\n     *  DOM is reparented incrementally (no full GridElement.render()) so the\n     *  selected cell's canvas state + the sidebar panel structure survive. */\n  }, {\n    key: \"moveCell\",\n    value: function moveCell(from, to) {\n      if (!Array.isArray(this.cells)) return;\n      var n = this.cells.length;\n      if (n < 2) return;\n      if (from < 0 || from >= n) return;\n      var target = to;\n      if (target < 0) target = 0;\n      if (target > n) target = n;\n      // After removing `from`, adjacent `to` values collapse onto the same\n      // final position — skip those so we don't trigger a useless repaint.\n      if (target === from || target === from + 1) return;\n      var _this$cells$splice = this.cells.splice(from, 1),\n        _this$cells$splice2 = _slicedToArray(_this$cells$splice, 1),\n        cell = _this$cells$splice2[0];\n      var adjusted = target > from ? target - 1 : target;\n      this.cells.splice(adjusted, 0, cell);\n\n      // DOM reparent — find the wrapper the same way _appendCellDom does.\n      if (this.domNode) {\n        var wrapper = this.domNode.firstElementChild;\n        if (wrapper && cell.domNode && cell.domNode.parentNode === wrapper) {\n          var siblings = Array.from(wrapper.querySelectorAll(':scope > [builder-element=\"CellElement\"]'));\n          // Remove first, then insert at the new position.\n          wrapper.removeChild(cell.domNode);\n          var refSiblings = siblings.filter(function (s) {\n            return s !== cell.domNode;\n          });\n          if (adjusted >= refSiblings.length) {\n            wrapper.appendChild(cell.domNode);\n          } else {\n            wrapper.insertBefore(cell.domNode, refSiblings[adjusted]);\n          }\n        }\n      }\n    }\n\n    /** Resize a pair of adjacent cells atomically (Phase-3 W6.1 snap-ratios).\n     *  Used by the cell-manager edge-resizer grip. Writes both widths in the\n     *  same tick so there's no intermediate \"sum > 100%\" flash that could\n     *  trigger the rebalance banner. Values are % numbers (e.g. 33.33).\n     *  Clamps to [1, 99] to keep both cells visible — below 1% the cell is\n     *  unclickable and the grip disappears. */\n  }, {\n    key: \"resizeCellPair\",\n    value: function resizeCellPair(leftIdx, leftPct, rightPct) {\n      var n = this.cells.length;\n      if (leftIdx < 0 || leftIdx + 1 >= n) return;\n      var clamp = function clamp(v) {\n        return Math.max(1, Math.min(99, Math.round(v * 100) / 100));\n      };\n      var l = clamp(leftPct);\n      var r = clamp(rightPct);\n      this.cells[leftIdx].formatter.setFormat('width', \"\".concat(l, \"%\"));\n      this.cells[leftIdx + 1].formatter.setFormat('width', \"\".concat(r, \"%\"));\n      this.cells[leftIdx].render();\n      this.cells[leftIdx + 1].render();\n    }\n\n    /** Upgrade a pure-bare grid's cell widths to explicit percents summing\n     *  to 100%. Idempotent (already-% grids are untouched). Mixed grids\n     *  are left alone. Called from `parse()` + after `applyLayoutPreset()`. */\n  }, {\n    key: \"_upgradeLegacyBareWidths\",\n    value: function _upgradeLegacyBareWidths() {\n      if (!Array.isArray(this.cells) || this.cells.length === 0) return;\n      var kinds = this.cells.map(function (cell) {\n        var w = cell.formatter.getFormat('width');\n        if (w === null || w === undefined || w === '' || w === 'auto') return 'auto';\n        if (typeof w === 'number') return 'bare';\n        if (typeof w === 'string') {\n          var s = w.trim();\n          if (/^-?\\d+(\\.\\d+)?$/.test(s)) return 'bare';\n          if (/%$/.test(s)) return 'pct';\n          if (/(px|em|rem|vw|vh)$/i.test(s)) return 'unit';\n        }\n        return 'other';\n      });\n      var allBare = kinds.every(function (k) {\n        return k === 'bare';\n      });\n      if (!allBare) return;\n      var nums = this.cells.map(function (cell) {\n        return parseFloat(cell.formatter.getFormat('width'));\n      });\n      var sum = nums.reduce(function (a, b) {\n        return a + b;\n      }, 0);\n      if (sum <= 0 || !isFinite(sum)) return;\n\n      // Rescale so SUM = 100. Round to 2 decimal places; last cell absorbs\n      // rounding residue so the total stays exactly 100.\n      var pcts = nums.map(function (n) {\n        return Math.round(n / sum * 10000) / 100;\n      });\n      var residue = Math.round((100 - pcts.reduce(function (a, b) {\n        return a + b;\n      }, 0)) * 100) / 100;\n      if (Math.abs(residue) >= 0.01) pcts[pcts.length - 1] = Math.round((pcts[pcts.length - 1] + residue) * 100) / 100;\n      this.cells.forEach(function (cell, i) {\n        var v = pcts[i];\n        var str = Number.isInteger(v) ? \"\".concat(v, \"%\") : \"\".concat(v, \"%\");\n        cell.formatter.setFormat('width', str);\n      });\n    }\n  }, {\n    key: \"isAutoFormat\",\n    value: function isAutoFormat(key) {\n      var value = this.formatter.getFormat(key);\n      return value === null || value === undefined || value === '' || value === 'auto';\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this7 = this;\n      // ─────────────────────────────────────────────────────────────\n      // Grid panel — 2026-04-18 Phase 2.12 audit\n      // ─────────────────────────────────────────────────────────────\n      // Ordered by user priority: cells first (what people came to edit),\n      // then cell widths, then spacing + alignment, then background. All\n      // controls emit .bjs-* / DimensionControl — no Bootstrap fallbacks.\n\n      var controls = [];\n\n      // 1. Cell manager (visual editor + layout presets + click-to-select)\n      controls.push(new _GridControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cells'), {\n        getItemCount: function getItemCount() {\n          return _this7.cells.length;\n        },\n        getCellWidths: function getCellWidths() {\n          return _this7.cells.map(function (c) {\n            return c.formatter.getFormat('width', 'auto');\n          });\n        },\n        getSelectedIndex: function getSelectedIndex() {\n          return _this7.getSelectedCellIndex();\n        }\n      }, {\n        addCell: function addCell() {\n          return _this7.addCell();\n        },\n        addCellAt: function addCellAt(index) {\n          return _this7.addCellAt(index);\n        },\n        removeCell: function removeCell(index) {\n          _this7.removeCellByIndex(index);\n          // removeCellByIndex already detaches the cell DOM\n          // incrementally — no full render needed.\n        },\n        selectCell: function selectCell(index) {\n          return _this7.selectCellAt(index);\n        },\n        applyPreset: function applyPreset(widths) {\n          return _this7.applyLayoutPreset(widths);\n        },\n        rebalanceProportional: function rebalanceProportional() {\n          return _this7.rebalanceCellsProportional();\n        },\n        equalize: function equalize() {\n          return _this7.equalizeCells();\n        },\n        moveCell: function moveCell(from, to) {\n          return _this7.moveCell(from, to);\n        },\n        resizeCellPair: function resizeCellPair(leftIdx, leftPct, rightPct) {\n          return _this7.resizeCellPair(leftIdx, leftPct, rightPct);\n        },\n        removeCells: function removeCells(indices) {\n          // Bulk-remove — indices must be in descending order so\n          // later splices don't shift earlier ones. Caller guarantees\n          // this (GridControl.bulk handler sorts high→low).\n          indices.forEach(function (i) {\n            return _this7.removeCellByIndex(i);\n          });\n        }\n      }));\n\n      // 2. Cell widths section — one DimensionControl per cell, supports\n      //    %, px, em, rem, vw, auto. Canonical list view so user can scan\n      //    all widths at a glance.\n      controls.push(new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.cell_widths'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.cell_widths_desc')));\n      this.cells.forEach(function (cell, index) {\n        controls.push(new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_n', 'Cell'), \" #\").concat(index + 1), cell.formatter.getFormat('width', 'auto'), {\n          units: ['%', 'px', 'em', 'rem', 'vw', 'fill', 'auto'],\n          onChange: function onChange(value) {\n            cell.formatter.setFormat('width', value === null ? 'auto' : value);\n            cell.render();\n          }\n        }));\n      });\n\n      // 3. Spacing & alignment section\n      controls.push(new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.grid_spacing'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.grid_spacing_desc')));\n\n      // Cell gap — slider with common-value presets (0/8/16/24 = design-\n      // system multiples-of-8).\n      controls.push(new _RangeControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_gap'), this.cell_gap, 0, 200, 'px', 1, function (value) {\n        _this7.cell_gap = parseFloat(value) || 0;\n        _this7.render();\n      }, {\n        presets: [0, 8, 16, 24],\n        description: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_gap_desc')\n      }));\n\n      // Cell alignment — Option 3 escape hatch. Default `stretch` gives\n      // equal heights; user can override to Top/Center/Bottom for\n      // staggered layouts.\n      controls.push(new _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.cell_alignment'), this.formatter.getFormat('align_items', 'stretch'), function (value) {\n        _this7.formatter.setFormat('align_items', value);\n        _this7.render();\n      }, [{\n        value: 'stretch',\n        icon: 'height'\n      }, {\n        value: 'flex-start',\n        icon: 'vertical_align_top'\n      }, {\n        value: 'center',\n        icon: 'vertical_align_center'\n      }, {\n        value: 'flex-end',\n        icon: 'vertical_align_bottom'\n      }]));\n\n      // 4. Grid background — BackgroundControl renders its own header\n      // so we don't duplicate with a SectionLabelControl.\n      controls.push(new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.grid_background'), {\n        color: this.formatter.getFormat('background_color', '#ffffff'),\n        image: this.formatter.getFormat('background_image', ''),\n        position: this.formatter.getFormat('background_position', 'center'),\n        size: this.formatter.getFormat('background_size', '100'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n        blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n        opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n        filter: this.formatter.getFormat('filter', '')\n      }, {\n        setBackground: function setBackground(values) {\n          _this7.formatter.setFormat('background_color', values.color);\n          _this7.formatter.setFormat('background_image', values.image);\n          _this7.formatter.setFormat('background_position', values.position);\n          _this7.formatter.setFormat('background_size', values.size);\n          _this7.formatter.setFormat('background_repeat', values.repeat);\n          _this7.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n          _this7.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n          _this7.formatter.setFormat('filter', values.filter || null);\n          _this7.render();\n        }\n      }));\n      return controls;\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var gridElement = new this(data.template);\n      // Route through ElementFactory so specialised cell subclasses\n      // (FormContainerCell, future PricingCell, etc.) get instantiated\n      // based on the `name` field in JSON. Legacy data with missing\n      // `name` falls back to CellElement.\n      var cells = Array.isArray(data.cells) ? data.cells.map(function (cellData) {\n        if (cellData && cellData.name && cellData.name !== 'CellElement') {\n          try {\n            return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(cellData);\n          } catch (e) {\n            // Unknown cell subclass → degrade to CellElement so the\n            // canvas still renders instead of throwing on load.\n            return _CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].parse(cellData);\n          }\n        }\n        return _CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].parse(cellData);\n      }) : [];\n      gridElement.appendCells(cells);\n      gridElement.cell_gap = data.cell_gap || 0;\n      // W0.2c: parseFormats helper handles the typeof check + null guard\n      this.parseFormats(gridElement, data);\n      // 2026-04-18 legacy-width upgrade — bare numbers (\"50\") were the\n      // historical way to express grow-share ratios, but 90%+ of sample\n      // authors used them to mean percents. DimensionControl's bare\n      // fallback is now '%' (not 'px'), so if a pure-bare grid reaches\n      // the panel un-migrated, the displayed unit ('%') would not match\n      // the rendered semantic (grow-share). We upgrade at load time:\n      // every pure-bare grid's widths are rescaled so they SUM to 100%\n      // and serialized as explicit \"N%\" strings. The rescaling preserves\n      // the exact visual: flex grow-share at ratio a:b:c renders identical\n      // to explicit percents (a/sum*100)%, (b/sum*100)%, (c/sum*100)%\n      // when the row has a gap (percent branch in Cell.template.html\n      // subtracts its gap share, grow-share does so implicitly through\n      // flexbox math — the output pixels match to <1 sub-pixel).\n      //\n      // Mixed grids (auto + bare, or pct + bare) keep their bare values\n      // intact — grow-share remains a valid runtime primitive for the\n      // \"content-left + fill-right\" layout pattern that can't be\n      // expressed in pure percents. Samples we ship have all 22 such\n      // grids reviewed individually (docs/BUILDER.md §Lesson 22).\n      gridElement._upgradeLegacyBareWidths();\n      return gridElement;\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/GridElement.js?");

/***/ }),

/***/ "./src/includes/GridWidget.js":
/*!************************************!*\
  !*** ./src/includes/GridWidget.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _GridElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./GridElement.js */ \"./src/includes/GridElement.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\nvar GridWidget = /*#__PURE__*/function (_BaseWidget) {\n  function GridWidget() {\n    var _this;\n    _classCallCheck(this, GridWidget);\n    _this = _callSuper(this, GridWidget); // Call the parent class constructor\n\n    // Add a GridElement to the widget\n    var grid = new _GridElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Grid');\n    var cell_1 = new _CellElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Cell');\n    cell_1.formatter.setFormat('width', '50');\n    var cell_2 = new _CellElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Cell');\n    cell_2.formatter.setFormat('width', '50');\n    grid.cells = [cell_1, cell_2];\n\n    //\n    _this.block.appendElements([grid]);\n    return _this;\n  }\n  _inherits(GridWidget, _BaseWidget);\n  return _createClass(GridWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.grid');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'grid_view';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/GridWidget.js?");

/***/ }),

/***/ "./src/includes/H1Element.js":
/*!***********************************!*\
  !*** ./src/includes/H1Element.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H1Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n  function H1Element() {\n    _classCallCheck(this, H1Element);\n    return _callSuper(this, H1Element, arguments);\n  }\n  _inherits(H1Element, _LegacyHeadingAliasEl);\n  return _createClass(H1Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH1Element.headingType = 'h1';\nH1Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_1');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H1Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H1Element.js?");

/***/ }),

/***/ "./src/includes/H2Element.js":
/*!***********************************!*\
  !*** ./src/includes/H2Element.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H2Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n  function H2Element() {\n    _classCallCheck(this, H2Element);\n    return _callSuper(this, H2Element, arguments);\n  }\n  _inherits(H2Element, _LegacyHeadingAliasEl);\n  return _createClass(H2Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH2Element.headingType = 'h2';\nH2Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_2');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H2Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H2Element.js?");

/***/ }),

/***/ "./src/includes/H3Element.js":
/*!***********************************!*\
  !*** ./src/includes/H3Element.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H3Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n  function H3Element() {\n    _classCallCheck(this, H3Element);\n    return _callSuper(this, H3Element, arguments);\n  }\n  _inherits(H3Element, _LegacyHeadingAliasEl);\n  return _createClass(H3Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH3Element.headingType = 'h3';\nH3Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_3');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H3Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H3Element.js?");

/***/ }),

/***/ "./src/includes/H4Element.js":
/*!***********************************!*\
  !*** ./src/includes/H4Element.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H4Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n  function H4Element() {\n    _classCallCheck(this, H4Element);\n    return _callSuper(this, H4Element, arguments);\n  }\n  _inherits(H4Element, _LegacyHeadingAliasEl);\n  return _createClass(H4Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH4Element.headingType = 'h4';\nH4Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_4');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H4Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H4Element.js?");

/***/ }),

/***/ "./src/includes/H5Element.js":
/*!***********************************!*\
  !*** ./src/includes/H5Element.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LegacyHeadingAliasElement.js */ \"./src/includes/LegacyHeadingAliasElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar H5Element = /*#__PURE__*/function (_LegacyHeadingAliasEl) {\n  function H5Element() {\n    _classCallCheck(this, H5Element);\n    return _callSuper(this, H5Element, arguments);\n  }\n  _inherits(H5Element, _LegacyHeadingAliasEl);\n  return _createClass(H5Element);\n}(_LegacyHeadingAliasElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\nH5Element.headingType = 'h5';\nH5Element.headingLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading_5');\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (H5Element);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/H5Element.js?");

/***/ }),

/***/ "./src/includes/HTMLElement.js":
/*!*************************************!*\
  !*** ./src/includes/HTMLElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar HTMLElement = /*#__PURE__*/function (_BaseElement) {\n  function HTMLElement(template, html) {\n    var _this;\n    _classCallCheck(this, HTMLElement);\n    _this = _callSuper(this, HTMLElement); // Call the parent class constructor\n    _this.template = template;\n    _this.html = html;\n\n    // Node\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['html'];\n\n    // Formatter\n    _this.formatter = new Formatter({\n      // background\n      background_color: null,\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      // spacing\n      padding_top: 0,\n      padding_right: 0,\n      padding_bottom: 0,\n      padding_left: 0,\n      // border\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_width: null,\n      border_left_style: null,\n      border_left_color: null,\n      // border radius\n      border_radius: 0\n    });\n    return _this;\n  }\n  _inherits(HTMLElement, _BaseElement);\n  return _createClass(HTMLElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.html');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        html: this.html\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(HTMLElement, \"getData\", this, 3)([])), {}, {\n        html: this.html\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [new BackgroundControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this2.formatter.setFormat('background_color', values.color);\n          _this2.formatter.setFormat('background_image', values.image);\n          _this2.formatter.setFormat('background_position', values.position);\n          _this2.formatter.setFormat('background_size', values.size);\n          _this2.formatter.setFormat('background_repeat', values.repeat);\n          _this2.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this2.formatter.setFormat('border_top_style', border_top_style);\n          _this2.formatter.setFormat('border_top_width', border_top_width);\n          _this2.formatter.setFormat('border_top_color', border_top_color);\n          _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this2.formatter.setFormat('border_left_style', border_left_style);\n          _this2.formatter.setFormat('border_left_width', border_left_width);\n          _this2.formatter.setFormat('border_left_color', border_left_color);\n          _this2.formatter.setFormat('border_right_style', border_right_style);\n          _this2.formatter.setFormat('border_right_width', border_right_width);\n          _this2.formatter.setFormat('border_right_color', border_right_color);\n\n          // re-render\n          _this2.render();\n        }\n      }), new BorderRadiusControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this2.formatter.setFormat('border_radius', v);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.html), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HTMLElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HTMLElement.js?");

/***/ }),

/***/ "./src/includes/HeadingControl.js":
/*!****************************************!*\
  !*** ./src/includes/HeadingControl.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar HeadingControl = /*#__PURE__*/function () {\n  /**\n   * Heading-tag selector (h1–h6). Emits a direct callback (`setType(value)`),\n   * not the usual `{setValue}` shape, because HeadingElement pairs the type\n   * change with a font-size reset + panel re-render — the caller wants the\n   * raw new type value immediately.\n   */\n  function HeadingControl(label, type, setType) {\n    _classCallCheck(this, HeadingControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.type = type || 'h1';\n    this.setType = setType;\n    this.domNode = document.createElement(\"div\");\n    this.render();\n  }\n  return _createClass(HeadingControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var types = [{\n        value: 'h1',\n        labelKey: 'controls.h1_main_title'\n      }, {\n        value: 'h2',\n        labelKey: 'controls.h2_section_title'\n      }, {\n        value: 'h3',\n        labelKey: 'controls.h3_subsection_title'\n      }, {\n        value: 'h4',\n        labelKey: 'controls.h4_smaller_title'\n      }, {\n        value: 'h5',\n        labelKey: 'controls.h5_even_smaller_title'\n      }, {\n        value: 'h6',\n        labelKey: 'controls.h6_smallest_title'\n      }];\n      var optionsHtml = types.map(function (t) {\n        var selected = _this.type === t.value ? ' selected' : '';\n        return \"<option value=\\\"\".concat(t.value, \"\\\"\").concat(selected, \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(t.labelKey), \"</option>\");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-select\\\">\\n                        <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" data-control=\\\"type-select\\\">\").concat(optionsHtml, \"</select>\\n                        <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n      this.selectEl = this.domNode.querySelector('select');\n      this.selectEl.addEventListener('change', function (e) {\n        var val = e.target.value;\n        _this.type = val;\n        if (typeof _this.setType === 'function') {\n          _this.setType(val);\n        }\n      });\n    }\n  }, {\n    key: \"getTypeSelector\",\n    value: function getTypeSelector() {\n      return this.selectEl;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.type = newValue;\n      if (this.selectEl) this.selectEl.value = newValue;\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.type;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HeadingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HeadingControl.js?");

/***/ }),

/***/ "./src/includes/HeadingElement.js":
/*!****************************************!*\
  !*** ./src/includes/HeadingElement.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _HeadingControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingControl.js */ \"./src/includes/HeadingControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar HeadingElement = /*#__PURE__*/function (_BaseElement) {\n  function HeadingElement(template, type, text) {\n    var _this;\n    _classCallCheck(this, HeadingElement);\n    _this = _callSuper(this, HeadingElement);\n    _this.template = template;\n    _this.type = type; // h1, h2, h3, ...\n    _this.text = text;\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['text'];\n\n    // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n    _this.registerInlineEdit('text');\n\n    // Formatter. `text_decoration` and `font_style` exist because the\n    // template emits all formats via `toStyleStringAll()`, but they are\n    // managed by RichTextControl's inline tags — same reasoning as\n    // PElement (§2.7). No border_* declared — headings don't typically\n    // carry their own borders.\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      link_color: null,\n      paragraph_spacing: null,\n      text_align: null,\n      line_height: null,\n      letter_spacing: null,\n      text_direction: null,\n      text_decoration: null,\n      font_style: null,\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null\n    });\n    return _this;\n  }\n  _inherits(HeadingElement, _BaseElement);\n  return _createClass(HeadingElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.heading');\n    }\n\n    /**\n     * Full render. Used when `type` (h1…h6) or `text` changes — both require\n     * swapping the tag itself. Format-only changes go through\n     * `applyFormatStyles()` so the contenteditable cursor survives.\n     * Inline-edit wiring is auto-fired by BaseElement.afterRender() (W0.2b).\n     */\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged (W0.2c); type is heading-specific\n      this.domNode.innerHTML = this.renderTemplate({\n        type: this.type\n      });\n    }\n\n    /**\n     * Structure-preserving format update (§2.8 E). Patches the existing\n     * heading tag's inline style in place — no innerHTML swap, no tag\n     * re-creation. Contenteditable cursor, text selection, and focus state\n     * all survive typography tweaks.\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var target = this.domNode.querySelector('[inline-edit=\"text\"]');\n      if (!target) {\n        this.render();\n        return;\n      }\n      target.setAttribute('style', this.formatter.toStyleStringAll());\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(HeadingElement, \"getData\", this, 3)([])), {}, {\n        type: this.type,\n        text: this.text\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          _this2.formatter.setFormat(key, value);\n          _this2.applyFormatStyles();\n        };\n      };\n      // W3.1 — bus wiring for dual-view sync between sidebar and the\n      // canvas FontPopoverOverlay. Reads the bus off `this.host` so two\n      // Builders on the same page never share an EventEmitter.\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [\n      // Heading tag selector — type change is STRUCTURAL (swap <h1>↔<h2>),\n      // so it uses full render(). Also resets font_size so the new tag\n      // renders at its browser-default size.\n      new _HeadingControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.heading_type'), this.type, function (type) {\n        var _this2$host2;\n        _this2.type = type;\n        _this2.formatter.setFormat('font_size', null);\n        _this2.render();\n        (_this2$host2 = _this2.host) === null || _this2$host2 === void 0 || _this2$host2.renderElementControls(_this2);\n      }),\n      // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n      // Canvas inline-edit = text surface; sidebar = config panel only.\n      new FontFamilyControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }, busOpts('font_family')), new FontWeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }, busOpts('font_weight')), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: setFmt('text_color')\n      }), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: setFmt('link_color')\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('text_align'), {\n        setValue: setFmt('text_align')\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: setFmt('paragraph_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new LineHeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: setFmt('line_height')\n      }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: setFmt('letter_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new TextDirectionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: setFmt('text_direction')\n      })\n\n      // W3.8b — PaddingMarginControl removed. Padding is a\n      // container-only concern (Block/Cell/Page). Formatter keys\n      // remain so legacy JSON renders identically.\n      ];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.type, data.text), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HeadingElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HeadingElement.js?");

/***/ }),

/***/ "./src/includes/HeadingWidget.js":
/*!***************************************!*\
  !*** ./src/includes/HeadingWidget.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar HeadingWidget = /*#__PURE__*/function (_BaseWidget) {\n  function HeadingWidget() {\n    var _this;\n    _classCallCheck(this, HeadingWidget);\n    _this = _callSuper(this, HeadingWidget); // Call the parent class constructor\n    _this.elements = [];\n\n    // Add an H1Element to the widget\n    var h1 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Heading', 'h1', 'Heading');\n\n    // Append the new element to the block\n    _this.block.appendElements([h1]);\n    return _this;\n  }\n  _inherits(HeadingWidget, _BaseWidget);\n  return _createClass(HeadingWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.heading');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'title';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HeadingWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HeadingWidget.js?");

/***/ }),

/***/ "./src/includes/HistoryManager.js":
/*!****************************************!*\
  !*** ./src/includes/HistoryManager.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * HistoryManager — undo/redo state machine for BuilderJS.\n *\n * See docs/plans/PLAN_UNDO_REDO.md for the full spec.\n *\n * Usage (internal — Builder instantiates this in load()):\n *\n *   this.history = new HistoryManager(this, {\n *       maxSize: 50,\n *       debounceMs: 400,\n *       coalesceMs: 600,\n *       autoCloseTxMs: 5000,\n *   });\n *\n *   // Mutation sites call:\n *   builder.history.commit('history.format_text_color', {\n *       elementUid, elementType, change, source, oldValue, newValue,\n *   });\n *\n *   // Transaction (grouped mutations):\n *   builder.history.beginTransaction('history.structure_move', { ... });\n *   // ... multiple mutations ...\n *   builder.history.endTransaction();\n *\n * Events fired on `builder.events` bus:\n *   - 'history:commit'       { entry }\n *   - 'history:change'       { canUndo, canRedo, size, currentIndex, currentEntry }\n *   - 'history:before-apply' { direction, entry }\n *   - 'history:after-apply'  { direction, entry }\n *\n * CD-3 (AIBuilder Wave 4) — derived host-facing signals fired alongside the\n * 'history:commit' chokepoint so save.ts + SavedTicker subscribe to a single\n * canonical doc-mutation source instead of polling history.length:\n *   - 'document:changed'     {} — debounced inside the bus (default 120ms);\n *                                 collapses typing bursts into ONE host fire.\n *   - 'element:added'        { elementUid, elementType } — when commit's\n *                                 meta.change === 'structure:add'.\n *   - 'element:removed'      { elementUid, elementType } — when meta.change\n *                                 === 'structure:remove'.\n */\nvar HistoryManager = /*#__PURE__*/function () {\n  function HistoryManager(builder) {\n    var _opts$maxSize, _opts$debounceMs, _opts$coalesceMs, _opts$autoCloseTxMs;\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, HistoryManager);\n    this.builder = builder;\n    this.maxSize = (_opts$maxSize = opts.maxSize) !== null && _opts$maxSize !== void 0 ? _opts$maxSize : 50;\n    this.debounceMs = (_opts$debounceMs = opts.debounceMs) !== null && _opts$debounceMs !== void 0 ? _opts$debounceMs : 400;\n    this.coalesceMs = (_opts$coalesceMs = opts.coalesceMs) !== null && _opts$coalesceMs !== void 0 ? _opts$coalesceMs : 600;\n    this.autoCloseTxMs = (_opts$autoCloseTxMs = opts.autoCloseTxMs) !== null && _opts$autoCloseTxMs !== void 0 ? _opts$autoCloseTxMs : 5000;\n    this._stack = [];\n    this._pointer = -1;\n    this._seq = 0;\n    this._applying = false;\n    this._tx = null;\n    this._debounceTimer = null;\n    this._iframeDoc = null;\n\n    // PLAN_UNDO_REDO — smart debounce enrichment. When a Control emits\n    // `region:focus` (e.g. PaddingMarginControl on its 4-side inputs,\n    // TextControl on its text field), we snapshot { elementUid, regionKey }\n    // here so the next debounce-fallback commit can attach rich meta:\n    // \"Adjust padding-top on Block\" instead of generic \"Edit\".\n    this._lastFocusedRegion = null;\n    this._regionDisposers = [];\n  }\n\n  // ──────────────────────────────────────────────────────────────────\n  //  Lifecycle — called from Builder._historyInit()\n  // ──────────────────────────────────────────────────────────────────\n\n  /** Push the baseline snapshot. Labelled 'history.initial' — HistoryWidget\n   *  hides baseline from the dropdown list but keeps it in the stack as the\n   *  undo floor. Idempotent. */\n  return _createClass(HistoryManager, [{\n    key: \"pushBaseline\",\n    value: function pushBaseline() {\n      if (this._stack.length > 0) return;\n      this._pushEntry(this._buildEntry('history.initial', {\n        source: 'init'\n      }));\n    }\n\n    /** Subscribe to region:focus / region:blur on builder.events so the next\n     *  debounce commit carries { elementUid, regionKey } context. Controls\n     *  that don't emit region events simply produce a bare-ish \"Edit :type\"\n     *  label, which is still more informative than \"Edit\". */\n  }, {\n    key: \"bindRegionFocusTracking\",\n    value: function bindRegionFocusTracking() {\n      var _this = this;\n      if (!this.builder.events || typeof this.builder.events.on !== 'function') return;\n      var d1 = this.builder.events.on('region:focus', function (payload) {\n        _this._lastFocusedRegion = payload || null;\n      });\n      var d2 = this.builder.events.on('region:blur', function () {\n        _this._lastFocusedRegion = null;\n      });\n      this._regionDisposers.push(d1, d2);\n    }\n\n    /** Attach debounce-fallback listeners to iframe + settings. */\n  }, {\n    key: \"bindDebounceFallback\",\n    value: function bindDebounceFallback() {\n      var _this$builder$iframe$,\n        _this2 = this;\n      var iframeDoc = this.builder.iframe && (this.builder.iframe.contentDocument || ((_this$builder$iframe$ = this.builder.iframe.contentWindow) === null || _this$builder$iframe$ === void 0 ? void 0 : _this$builder$iframe$.document));\n      if (!iframeDoc) return;\n      this._iframeDoc = iframeDoc;\n      var deb = function deb() {\n        return _this2._scheduleDebouncedCommit();\n      };\n      iframeDoc.addEventListener('mouseup', deb);\n      iframeDoc.addEventListener('keyup', deb);\n      iframeDoc.addEventListener('drop', deb);\n      var settings = this.builder.settingsContainer;\n      if (settings) {\n        settings.addEventListener('mouseup', deb);\n        settings.addEventListener('change', deb);\n      }\n    }\n  }, {\n    key: \"_scheduleDebouncedCommit\",\n    value: function _scheduleDebouncedCommit() {\n      var _this$_tx,\n        _this3 = this;\n      if (this._applying || (_this$_tx = this._tx) !== null && _this$_tx !== void 0 && _this$_tx.active) return;\n      clearTimeout(this._debounceTimer);\n      this._debounceTimer = setTimeout(function () {\n        // PLAN_UNDO_REDO — rich meta: { elementUid, elementType, change,\n        // regionKey }. HistoryWidget renders the label via i18n using\n        // whichever key we pick. Priority:\n        //   1. regionKey known → try specific 'history.format_<key>'\n        //      (e.g. history.format_padding_top = \"Adjust padding\")\n        //   2. elementType known → 'history.edit_type' = \"Edit :type\"\n        //   3. Bare → 'history.edit' = \"Edit\"\n        var el = _this3.builder.selectedElement;\n        var region = _this3._lastFocusedRegion;\n        var meta = {\n          source: 'debounce'\n        };\n        if (el) {\n          var _el$constructor;\n          meta.elementUid = el.id;\n          meta.elementType = typeof el.getName === 'function' ? el.getName() : (_el$constructor = el.constructor) === null || _el$constructor === void 0 ? void 0 : _el$constructor.name;\n        }\n        var labelKey = 'history.edit';\n        if (region !== null && region !== void 0 && region.regionKey) {\n          meta.change = \"format:\".concat(region.regionKey);\n          meta.regionKey = region.regionKey;\n          // regionKey uses dashes ('padding-top') but i18n keys use\n          // underscores ('format_padding_top'). Normalize.\n          var normalized = String(region.regionKey).replace(/-/g, '_');\n          labelKey = \"history.format_\".concat(normalized);\n        } else if (el) {\n          labelKey = 'history.edit_type';\n        }\n        _this3.commit(labelKey, meta);\n      }, this.debounceMs);\n    }\n\n    // ──────────────────────────────────────────────────────────────────\n    //  Public API — commit + transaction\n    // ──────────────────────────────────────────────────────────────────\n  }, {\n    key: \"commit\",\n    value: function commit(labelKey) {\n      var _this$_tx2;\n      var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      if (this._applying) return;\n      if ((_this$_tx2 = this._tx) !== null && _this$_tx2 !== void 0 && _this$_tx2.active) {\n        this._tx.queuedCount++;\n        return;\n      }\n      var entry = this._buildEntry(labelKey, meta);\n      this._pushWithDedupe(entry);\n    }\n\n    /**\n     * Run `fn` with all `commit()` calls suppressed — for programmatic\n     * mass-mutation paths that would otherwise leak many low-level entries\n     * into the history dropdown (e.g. theme swap, AI replace-page, bulk\n     * delete, page clear). Caller should follow up with a single\n     * `commit('history.<summary>')` so the operation remains undo-able as\n     * one atomic step. Reentrant — nested `silent()` preserves the prior\n     * state, so calling silent() inside `_apply` (which already sets\n     * `_applying`) doesn't accidentally re-enable commits when the inner\n     * fn returns.\n     */\n  }, {\n    key: \"silent\",\n    value: function silent(fn) {\n      var prev = this._applying;\n      this._applying = true;\n      try {\n        return fn();\n      } finally {\n        this._applying = prev;\n      }\n    }\n  }, {\n    key: \"beginTransaction\",\n    value: function beginTransaction(labelKey) {\n      var _this$_tx3,\n        _this4 = this;\n      var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      if (this._applying) return;\n      if ((_this$_tx3 = this._tx) !== null && _this$_tx3 !== void 0 && _this$_tx3.active) this.endTransaction(); // nested → close prev\n      this._tx = {\n        active: true,\n        labelKey: labelKey,\n        meta: meta,\n        startedAt: Date.now(),\n        queuedCount: 0,\n        autoCloseTimer: setTimeout(function () {\n          return _this4._autoCloseTransaction();\n        }, this.autoCloseTxMs)\n      };\n    }\n  }, {\n    key: \"endTransaction\",\n    value: function endTransaction() {\n      var tx = this._tx;\n      if (!(tx !== null && tx !== void 0 && tx.active)) return;\n      clearTimeout(tx.autoCloseTimer);\n      this._tx = null;\n      var meta = Object.assign({}, tx.meta, {\n        childCount: tx.queuedCount\n      });\n      this._pushWithDedupe(this._buildEntry(tx.labelKey, meta));\n    }\n  }, {\n    key: \"abortTransaction\",\n    value: function abortTransaction() {\n      var tx = this._tx;\n      if (!(tx !== null && tx !== void 0 && tx.active)) return;\n      clearTimeout(tx.autoCloseTimer);\n      this._tx = null;\n    }\n  }, {\n    key: \"_autoCloseTransaction\",\n    value: function _autoCloseTransaction() {\n      var _this$_tx4;\n      if (!((_this$_tx4 = this._tx) !== null && _this$_tx4 !== void 0 && _this$_tx4.active)) return;\n      this.endTransaction();\n    }\n\n    // ──────────────────────────────────────────────────────────────────\n    //  Public API — undo / redo / jumpTo / clear\n    // ──────────────────────────────────────────────────────────────────\n  }, {\n    key: \"canUndo\",\n    value: function canUndo() {\n      return this._pointer > 0;\n    }\n  }, {\n    key: \"canRedo\",\n    value: function canRedo() {\n      return this._pointer < this._stack.length - 1;\n    }\n  }, {\n    key: \"size\",\n    value: function size() {\n      return this._stack.length;\n    }\n  }, {\n    key: \"getCurrentIndex\",\n    value: function getCurrentIndex() {\n      return this._pointer;\n    }\n  }, {\n    key: \"getEntries\",\n    value: function getEntries() {\n      return this._stack.map(function (e) {\n        return _objectSpread(_objectSpread({}, e), {}, {\n          data: null\n        });\n      });\n    }\n  }, {\n    key: \"undo\",\n    value: function () {\n      var _undo = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n        return _regeneratorRuntime().wrap(function _callee$(_context) {\n          while (1) switch (_context.prev = _context.next) {\n            case 0:\n              if (this.canUndo()) {\n                _context.next = 2;\n                break;\n              }\n              return _context.abrupt(\"return\", false);\n            case 2:\n              this._pointer--;\n              _context.next = 5;\n              return this._apply(this._stack[this._pointer], 'undo');\n            case 5:\n              return _context.abrupt(\"return\", true);\n            case 6:\n            case \"end\":\n              return _context.stop();\n          }\n        }, _callee, this);\n      }));\n      function undo() {\n        return _undo.apply(this, arguments);\n      }\n      return undo;\n    }()\n  }, {\n    key: \"redo\",\n    value: function () {\n      var _redo = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n        return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n          while (1) switch (_context2.prev = _context2.next) {\n            case 0:\n              if (this.canRedo()) {\n                _context2.next = 2;\n                break;\n              }\n              return _context2.abrupt(\"return\", false);\n            case 2:\n              this._pointer++;\n              _context2.next = 5;\n              return this._apply(this._stack[this._pointer], 'redo');\n            case 5:\n              return _context2.abrupt(\"return\", true);\n            case 6:\n            case \"end\":\n              return _context2.stop();\n          }\n        }, _callee2, this);\n      }));\n      function redo() {\n        return _redo.apply(this, arguments);\n      }\n      return redo;\n    }()\n  }, {\n    key: \"jumpTo\",\n    value: function () {\n      var _jumpTo = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(id) {\n        var idx, direction;\n        return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n          while (1) switch (_context3.prev = _context3.next) {\n            case 0:\n              idx = this._stack.findIndex(function (e) {\n                return e.id === id;\n              });\n              if (!(idx < 0 || idx === this._pointer)) {\n                _context3.next = 3;\n                break;\n              }\n              return _context3.abrupt(\"return\", false);\n            case 3:\n              direction = idx > this._pointer ? 'redo' : 'undo';\n              this._pointer = idx;\n              _context3.next = 7;\n              return this._apply(this._stack[this._pointer], direction);\n            case 7:\n              return _context3.abrupt(\"return\", true);\n            case 8:\n            case \"end\":\n              return _context3.stop();\n          }\n        }, _callee3, this);\n      }));\n      function jumpTo(_x) {\n        return _jumpTo.apply(this, arguments);\n      }\n      return jumpTo;\n    }()\n  }, {\n    key: \"clear\",\n    value: function clear() {\n      if (this._stack.length <= 1) return;\n      this._stack = [this._stack[this._pointer]];\n      this._pointer = 0;\n      this._notifyChange();\n    }\n\n    // ──────────────────────────────────────────────────────────────────\n    //  Internals\n    // ──────────────────────────────────────────────────────────────────\n  }, {\n    key: \"_buildEntry\",\n    value: function _buildEntry(labelKey) {\n      var _this$builder$selecte, _this$builder$selecte2;\n      var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      var data = this.builder.getData();\n      return {\n        id: \"h_\".concat(Date.now(), \"_\").concat(this._seq++),\n        data: JSON.parse(JSON.stringify(data)),\n        timestamp: Date.now(),\n        labelKey: labelKey || 'history.default_label',\n        labelParams: this._buildLabelParams(meta),\n        selectionUid: (_this$builder$selecte = (_this$builder$selecte2 = this.builder.selectedElement) === null || _this$builder$selecte2 === void 0 ? void 0 : _this$builder$selecte2.id) !== null && _this$builder$selecte !== void 0 ? _this$builder$selecte : null,\n        scrollTop: this._captureScrollTop(),\n        meta: meta\n      };\n    }\n  }, {\n    key: \"_buildLabelParams\",\n    value: function _buildLabelParams(meta) {\n      var params = {};\n      // meta.elementType should be the human-readable display name from\n      // element.getName() (e.g. \"Image\"), not the raw class name.\n      if (meta.elementType) params.type = meta.elementType;\n      if (meta.regionKey) params.region = String(meta.regionKey).replace(/[-_]/g, ' ');\n      if (meta.prompt) params.prompt = meta.prompt;\n      if (meta.oldValue !== undefined) params.oldValue = String(meta.oldValue);\n      if (meta.newValue !== undefined) params.newValue = String(meta.newValue);\n      return params;\n    }\n  }, {\n    key: \"_captureScrollTop\",\n    value: function _captureScrollTop() {\n      var _doc$documentElement, _doc$body;\n      var doc = this._iframeDoc;\n      if (!doc) return 0;\n      return ((_doc$documentElement = doc.documentElement) === null || _doc$documentElement === void 0 ? void 0 : _doc$documentElement.scrollTop) || ((_doc$body = doc.body) === null || _doc$body === void 0 ? void 0 : _doc$body.scrollTop) || 0;\n    }\n  }, {\n    key: \"_restoreScrollTop\",\n    value: function _restoreScrollTop(top) {\n      var doc = this._iframeDoc;\n      if (!doc || top == null) return;\n      if (doc.documentElement) doc.documentElement.scrollTop = top;\n      if (doc.body) doc.body.scrollTop = top;\n    }\n  }, {\n    key: \"_pushEntry\",\n    value: function _pushEntry(entry) {\n      this._pushWithDedupe(entry);\n    }\n  }, {\n    key: \"_pushWithDedupe\",\n    value: function _pushWithDedupe(entry) {\n      var _top$meta, _entry$meta, _entry$meta2;\n      var top = this._pointer >= 0 ? this._stack[this._pointer] : null;\n      if (top && this._dataEqual(top.data, entry.data)) return;\n\n      // Coalesce — same element + same change within window → merge\n      if (top && (_top$meta = top.meta) !== null && _top$meta !== void 0 && _top$meta.elementUid && top.meta.elementUid === ((_entry$meta = entry.meta) === null || _entry$meta === void 0 ? void 0 : _entry$meta.elementUid) && top.meta.change && top.meta.change === ((_entry$meta2 = entry.meta) === null || _entry$meta2 === void 0 ? void 0 : _entry$meta2.change) && entry.timestamp - top.timestamp < this.coalesceMs && this._pointer === this._stack.length - 1) {\n        top.data = entry.data;\n        top.timestamp = entry.timestamp;\n        top.meta.newValue = entry.meta.newValue;\n        top.meta.count = (top.meta.count || 1) + 1;\n        this._notifyChange();\n        this._emit('history:commit', {\n          entry: top\n        });\n        this._emitDocumentSignals(top);\n        return;\n      }\n      this._stack.length = this._pointer + 1;\n      this._stack.push(entry);\n      this._pointer = this._stack.length - 1;\n      if (this._stack.length > this.maxSize) {\n        var excess = this._stack.length - this.maxSize;\n        this._stack.splice(0, excess);\n        this._pointer -= excess;\n      }\n      this._notifyChange();\n      this._emit('history:commit', {\n        entry: entry\n      });\n      this._emitDocumentSignals(entry);\n    }\n\n    /**\n     * CD-3 (AIBuilder Wave 4) — fire `document:changed` (debounced inside the\n     * bus, default 120ms) for every committed mutation. Host listeners\n     * (Wave 4 SavedTicker, autosave) react to a SINGLE canonical signal\n     * instead of polling history.length.\n     *\n     * `element:added` / `element:removed` are NOT derived here on purpose:\n     * the history layer dedupes identical-data commits, but a Layers tree\n     * (Wave 14) needs to see every add/remove regardless of whether the\n     * resulting JSON is byte-equal to a prior state. Those events fire at\n     * the actual structure-mutation chokepoints (UIManager._commitStructureAdd\n     * + BaseElement.remove fadeOut callback + Builder.removeElement direct\n     * call) — see CD-3 wiring in those files.\n     */\n  }, {\n    key: \"_emitDocumentSignals\",\n    value: function _emitDocumentSignals(_entry) {\n      this._emit('document:changed', {});\n    }\n  }, {\n    key: \"_dataEqual\",\n    value: function _dataEqual(a, b) {\n      if (a === b) return true;\n      try {\n        return JSON.stringify(a) === JSON.stringify(b);\n      } catch (_) {\n        return false;\n      }\n    }\n  }, {\n    key: \"_apply\",\n    value: function () {\n      var _apply2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(entry, direction) {\n        var _this$builder$iframe$2;\n        var iframeDoc, iframeBody, win, raf;\n        return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n          while (1) switch (_context4.prev = _context4.next) {\n            case 0:\n              this._applying = true;\n\n              // PLAN_UNDO_REDO — suppress ALL iframe transitions/animations during\n              // the apply window. Matching CSS in Builder._getDebugCss:\n              //   body.bjs-history-applying * { transition: none !important;\n              //                                 animation: none !important; }\n              // Removed via 2x rAF AFTER render settles so real user interactions\n              // post-apply resume with full motion. Standard batch-update pattern\n              // (React flushSync, Vue nextTick + class-gated CSS). NOT a hack —\n              // it's the explicit \"don't animate frame-to-frame batches\" contract.\n              iframeDoc = this._iframeDoc || this.builder.iframe && (this.builder.iframe.contentDocument || ((_this$builder$iframe$2 = this.builder.iframe.contentWindow) === null || _this$builder$iframe$2 === void 0 ? void 0 : _this$builder$iframe$2.document));\n              iframeBody = iframeDoc === null || iframeDoc === void 0 ? void 0 : iframeDoc.body;\n              if (iframeBody) iframeBody.classList.add('bjs-history-applying');\n              _context4.prev = 4;\n              this._emit('history:before-apply', {\n                direction: direction,\n                entry: entry\n              });\n              this.builder.data = JSON.parse(JSON.stringify(entry.data));\n              if (!(typeof this.builder.render === 'function')) {\n                _context4.next = 10;\n                break;\n              }\n              _context4.next = 10;\n              return this.builder.render();\n            case 10:\n              if (entry.selectionUid && typeof this.builder.selectElementByUid === 'function') {\n                this.builder.selectElementByUid(entry.selectionUid);\n              } else if (typeof this.builder.unselect === 'function') {\n                this.builder.unselect();\n              }\n              this._restoreScrollTop(entry.scrollTop);\n              this._emit('history:after-apply', {\n                direction: direction,\n                entry: entry\n              });\n            case 13:\n              _context4.prev = 13;\n              this._applying = false;\n              if (iframeBody) {\n                win = iframeDoc.defaultView || window;\n                raf = win.requestAnimationFrame || requestAnimationFrame;\n                raf(function () {\n                  return raf(function () {\n                    iframeBody.classList.remove('bjs-history-applying');\n                  });\n                });\n              }\n              return _context4.finish(13);\n            case 17:\n              this._notifyChange();\n            case 18:\n            case \"end\":\n              return _context4.stop();\n          }\n        }, _callee4, this, [[4,, 13, 17]]);\n      }));\n      function _apply(_x2, _x3) {\n        return _apply2.apply(this, arguments);\n      }\n      return _apply;\n    }()\n  }, {\n    key: \"_emit\",\n    value: function _emit(event, payload) {\n      if (this.builder.events && typeof this.builder.events.emit === 'function') {\n        this.builder.events.emit(event, payload);\n      }\n    }\n  }, {\n    key: \"_notifyChange\",\n    value: function _notifyChange() {\n      var currentEntry = this._pointer >= 0 ? this._stack[this._pointer] : null;\n      this._emit('history:change', {\n        canUndo: this.canUndo(),\n        canRedo: this.canRedo(),\n        size: this.size(),\n        currentIndex: this._pointer,\n        currentEntry: currentEntry ? _objectSpread(_objectSpread({}, currentEntry), {}, {\n          data: null\n        }) : null\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HistoryManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HistoryManager.js?");

/***/ }),

/***/ "./src/includes/HistoryWidget.js":
/*!***************************************!*\
  !*** ./src/includes/HistoryWidget.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * HistoryWidget — floating undo/redo pill + expandable history dropdown.\n *\n * Mounts INSIDE the builder's `mainContainer` (host DOM), NOT inside the iframe.\n * Subscribes to `builder.events` for 'history:change' updates.\n *\n * Default position: bottom-left. Configurable via `options.historyUIPosition`.\n * Opt-out: pass `options.historyUI: false` on Builder constructor.\n *\n * See docs/plans/PLAN_UNDO_REDO.md §8.6 for the full design spec.\n */\n\n// ════════════════════════════════════════════════════════════════════════════\n//  Icon mapping — Material Symbols Rounded (host page loads the font)\n// ════════════════════════════════════════════════════════════════════════════\nvar ICON_FOR_CHANGE = {\n  'format:text_color': 'format_color_text',\n  'format:background': 'format_color_fill',\n  'format:padding_top': 'padding',\n  'format:padding_bottom': 'padding',\n  'format:padding_left': 'padding',\n  'format:padding_right': 'padding',\n  'format:font_size': 'format_size',\n  'format:font_family': 'font_download',\n  'format:border': 'border_style',\n  'format:align': 'format_align_left',\n  'format:size': 'crop_free',\n  'format:filter_brightness': 'brightness_6',\n  'format:filter_contrast': 'contrast',\n  'content:text': 'title',\n  'content:src': 'image',\n  'content:url': 'link',\n  'content:html': 'code',\n  'structure:add': 'add',\n  'structure:remove': 'delete',\n  'structure:move': 'swap_vert',\n  'structure:duplicate': 'content_copy',\n  'page:title': 'text_fields',\n  'page:theme': 'palette',\n  'page:block_gap': 'space_bar',\n  'page:clear': 'delete_sweep',\n  'ai:generate': 'auto_awesome',\n  'ai:rewrite': 'auto_fix_high',\n  'ai:inline_rewrite': 'auto_fix_normal'\n};\nvar ICON_DEFAULT = 'edit';\nvar ICON_INIT = 'flag';\nfunction iconForEntry(entry) {\n  var _entry$meta, _entry$meta2;\n  if ((entry === null || entry === void 0 || (_entry$meta = entry.meta) === null || _entry$meta === void 0 ? void 0 : _entry$meta.source) === 'init') return ICON_INIT;\n  return ICON_FOR_CHANGE[entry === null || entry === void 0 || (_entry$meta2 = entry.meta) === null || _entry$meta2 === void 0 ? void 0 : _entry$meta2.change] || ICON_DEFAULT;\n}\n\n// ════════════════════════════════════════════════════════════════════════════\n//  Relative time\n// ════════════════════════════════════════════════════════════════════════════\nfunction formatRelativeTime(ts) {\n  var s = Math.max(0, Math.floor((Date.now() - ts) / 1000));\n  if (s < 2) return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.just_now');\n  if (s < 60) return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.seconds_ago').replace(':n', String(s));\n  if (s < 3600) return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.minutes_ago').replace(':n', String(Math.floor(s / 60)));\n  return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.relative_time.hours_ago').replace(':n', String(Math.floor(s / 3600)));\n}\nfunction escapeHtml(s) {\n  return String(s !== null && s !== void 0 ? s : '').replace(/[&<>\"']/g, function (c) {\n    return {\n      '&': '&amp;',\n      '<': '&lt;',\n      '>': '&gt;',\n      '\"': '&quot;',\n      \"'\": '&#39;'\n    }[c];\n  });\n}\n\n// Platform shortcut label\nvar IS_MAC = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/i.test(navigator.platform || navigator.userAgent || '');\nvar KBD_MOD = IS_MAC ? '⌘' : 'Ctrl';\nvar KBD_SHIFT = IS_MAC ? '⇧' : 'Shift';\nvar TIP_UNDO = IS_MAC ? '⌘Z' : 'Ctrl+Z';\nvar TIP_REDO = IS_MAC ? '⌘⇧Z' : 'Ctrl+Shift+Z';\n\n// ════════════════════════════════════════════════════════════════════════════\n//  Widget class\n// ════════════════════════════════════════════════════════════════════════════\nvar HistoryWidget = /*#__PURE__*/function () {\n  // host-injection: `host` is the owning Builder instance — passed\n  // explicitly so multi-instance setups don't share state via a global.\n  // Stored as `this.host` (and `this.builder` alias for back-compat).\n  function HistoryWidget(host) {\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, HistoryWidget);\n    this.host = host;\n    this.builder = host;\n    this.history = host.history;\n    this.position = opts.position || 'bottom-left'; // 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'\n    this.minimal = !!opts.minimal; // no dropdown caret if true\n    this.extraClass = opts.className || '';\n    this.root = null;\n    this.pill = null;\n    this.btnUndo = null;\n    this.btnRedo = null;\n    this.btnToggle = null;\n    this.dropdown = null;\n    this.list = null;\n    this.count = null;\n    this.btnClear = null;\n    this._disposers = [];\n    this._outsideHandler = null;\n    this._refreshTimer = null;\n  }\n\n  // ────────────────────────────────────────────────────────────────────\n  //  Mount\n  // ────────────────────────────────────────────────────────────────────\n  return _createClass(HistoryWidget, [{\n    key: \"mount\",\n    value: function mount() {\n      var _this = this;\n      if (this.root) return;\n      var container = this.builder.mainContainer;\n      if (!container) return;\n\n      // Ensure the mainContainer can host an absolutely-positioned child.\n      // Only set if not already positioned (don't stomp host styles).\n      var cs = window.getComputedStyle(container);\n      if (cs.position === 'static') container.style.position = 'relative';\n      this.root = document.createElement('div');\n      this.root.className = 'bjs-history-widget' + (this.extraClass ? ' ' + this.extraClass : '');\n      this.root.setAttribute('data-bjs-history', 'true');\n      this._applyPositionAttrs();\n      this.root.innerHTML = this._buildHtml();\n      container.appendChild(this.root);\n      this._cacheRefs();\n      this._wireEvents();\n      this._renderState();\n\n      // Refresh relative time every 30s while dropdown is open\n      this._refreshTimer = setInterval(function () {\n        var _this$root;\n        if ((_this$root = _this.root) !== null && _this$root !== void 0 && _this$root.classList.contains('is-open')) _this._renderList();\n      }, 30000);\n    }\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      var _this$root2;\n      clearInterval(this._refreshTimer);\n      this._disposers.forEach(function (d) {\n        try {\n          d();\n        } catch (_) {}\n      });\n      this._disposers.length = 0;\n      if (this._outsideHandler) {\n        document.removeEventListener('click', this._outsideHandler, true);\n        this._outsideHandler = null;\n      }\n      if ((_this$root2 = this.root) !== null && _this$root2 !== void 0 && _this$root2.parentNode) this.root.parentNode.removeChild(this.root);\n      this.root = null;\n    }\n\n    // ────────────────────────────────────────────────────────────────────\n    //  DOM\n    // ────────────────────────────────────────────────────────────────────\n  }, {\n    key: \"_applyPositionAttrs\",\n    value: function _applyPositionAttrs() {\n      // CSS reads data-align / data-flip to pick dropdown direction.\n      var right = this.position.endsWith('right');\n      var top = this.position.startsWith('top');\n      this.root.setAttribute('data-bjs-history-position', this.position);\n      if (right) this.root.setAttribute('data-align', 'right');\n      if (top) this.root.setAttribute('data-flip', 'down');\n    }\n  }, {\n    key: \"_buildHtml\",\n    value: function _buildHtml() {\n      var caret = this.minimal ? '' : \"\\n            <span class=\\\"bjs-history-pill-divider\\\" aria-hidden=\\\"true\\\"></span>\\n            <button type=\\\"button\\\" class=\\\"bjs-history-btn\\\" data-bjs-history-action=\\\"toggle\\\"\\n                data-tooltip=\\\"\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\"\\n                aria-label=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\">\\n                <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n            </button>\");\n      return \"\\n            <div class=\\\"bjs-history-pill\\\" role=\\\"toolbar\\\" aria-label=\\\"\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\">\\n                <button type=\\\"button\\\" class=\\\"bjs-history-btn\\\" data-bjs-history-action=\\\"undo\\\"\\n                    data-tooltip=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.undo')), \" (\").concat(TIP_UNDO, \")\\\"\\n                    aria-label=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.undo')), \"\\\">\\n                    <span class=\\\"material-symbols-rounded\\\">undo</span>\\n                </button>\\n                <button type=\\\"button\\\" class=\\\"bjs-history-btn\\\" data-bjs-history-action=\\\"redo\\\"\\n                    data-tooltip=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.redo')), \" (\").concat(TIP_REDO, \")\\\"\\n                    aria-label=\\\"\").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.redo')), \"\\\">\\n                    <span class=\\\"material-symbols-rounded\\\">redo</span>\\n                </button>\\n                \").concat(caret, \"\\n            </div>\\n            \").concat(this.minimal ? '' : \"\\n            <div class=\\\"bjs-history-dropdown\\\" role=\\\"dialog\\\" aria-label=\\\"\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\\">\\n                <div class=\\\"bjs-history-header\\\">\\n                    <span class=\\\"bjs-history-header-title\\\">\\n                        <span class=\\\"material-symbols-rounded\\\">history</span>\\n                        \").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.title')), \"\\n                    </span>\\n                    <span class=\\\"bjs-history-header-count\\\" data-bjs-history-count>0</span>\\n                </div>\\n                <ul class=\\\"bjs-history-list\\\" data-bjs-history-list></ul>\\n                <div class=\\\"bjs-history-footer\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-history-clear\\\" data-bjs-history-action=\\\"clear\\\">\\n                        <span class=\\\"material-symbols-rounded\\\">delete_sweep</span>\\n                        \").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.clear')), \"\\n                    </button>\\n                    <span class=\\\"bjs-history-footer-hint\\\">\\n                        <kbd>\").concat(KBD_MOD, \"</kbd><kbd>Z</kbd>\\n                    </span>\\n                </div>\\n            </div>\"), \"\\n        \");\n    }\n  }, {\n    key: \"_cacheRefs\",\n    value: function _cacheRefs() {\n      var _this2 = this;\n      var q = function q(sel) {\n        return _this2.root.querySelector(sel);\n      };\n      this.pill = q('.bjs-history-pill');\n      this.btnUndo = q('[data-bjs-history-action=\"undo\"]');\n      this.btnRedo = q('[data-bjs-history-action=\"redo\"]');\n      this.btnToggle = q('[data-bjs-history-action=\"toggle\"]');\n      this.dropdown = q('.bjs-history-dropdown');\n      this.list = q('[data-bjs-history-list]');\n      this.count = q('[data-bjs-history-count]');\n      this.btnClear = q('[data-bjs-history-action=\"clear\"]');\n    }\n  }, {\n    key: \"_wireEvents\",\n    value: function _wireEvents() {\n      var _this$btnUndo,\n        _this3 = this,\n        _this$btnRedo,\n        _this$btnClear,\n        _this$btnToggle,\n        _this$builder$events,\n        _this$list;\n      // Buttons\n      (_this$btnUndo = this.btnUndo) === null || _this$btnUndo === void 0 || _this$btnUndo.addEventListener('click', function () {\n        return _this3.builder.undo();\n      });\n      (_this$btnRedo = this.btnRedo) === null || _this$btnRedo === void 0 || _this$btnRedo.addEventListener('click', function () {\n        return _this3.builder.redo();\n      });\n      (_this$btnClear = this.btnClear) === null || _this$btnClear === void 0 || _this$btnClear.addEventListener('click', function () {\n        return _this3.history.clear();\n      });\n      (_this$btnToggle = this.btnToggle) === null || _this$btnToggle === void 0 || _this$btnToggle.addEventListener('click', function (e) {\n        e.stopPropagation();\n        _this3._toggle();\n      });\n\n      // Subscribe to history:change\n      if ((_this$builder$events = this.builder.events) !== null && _this$builder$events !== void 0 && _this$builder$events.on) {\n        var disp1 = this.builder.events.on('history:change', function () {\n          return _this3._renderState();\n        });\n        var disp2 = this.builder.events.on('history:commit', function () {\n          var _this3$root;\n          if ((_this3$root = _this3.root) !== null && _this3$root !== void 0 && _this3$root.classList.contains('is-open')) _this3._renderList();\n        });\n        this._disposers.push(disp1, disp2);\n      }\n\n      // Outside click → close\n      this._outsideHandler = function (e) {\n        if (!_this3.root) return;\n        if (!_this3.root.contains(e.target)) _this3._close();\n      };\n      document.addEventListener('click', this._outsideHandler, true);\n\n      // Entry click → jumpTo\n      (_this$list = this.list) === null || _this$list === void 0 || _this$list.addEventListener('click', function (e) {\n        var li = e.target.closest('[data-bjs-history-entry-id]');\n        if (!li) return;\n        var id = li.getAttribute('data-bjs-history-entry-id');\n        if (id) _this3.history.jumpTo(id);\n      });\n    }\n  }, {\n    key: \"_toggle\",\n    value: function _toggle() {\n      if (this.root.classList.contains('is-open')) this._close();else this._open();\n    }\n  }, {\n    key: \"_open\",\n    value: function _open() {\n      this.root.classList.add('is-open');\n      this._renderList();\n      if (this.btnToggle) this.btnToggle.classList.add('is-active');\n    }\n  }, {\n    key: \"_close\",\n    value: function _close() {\n      this.root.classList.remove('is-open');\n      if (this.btnToggle) this.btnToggle.classList.remove('is-active');\n    }\n\n    // ────────────────────────────────────────────────────────────────────\n    //  Render\n    // ────────────────────────────────────────────────────────────────────\n  }, {\n    key: \"_renderState\",\n    value: function _renderState() {\n      if (!this.root) return;\n      var canUndo = this.history.canUndo();\n      var canRedo = this.history.canRedo();\n      if (this.btnUndo) this.btnUndo.disabled = !canUndo;\n      if (this.btnRedo) this.btnRedo.disabled = !canRedo;\n      if (this.btnClear) this.btnClear.disabled = this.history.size() <= 1;\n\n      // User-facing count excludes the baseline snapshot at index 0 —\n      // baseline is the \"before any edit\" floor, not a user-visible entry.\n      var visibleCount = Math.max(0, this.history.size() - 1);\n      if (this.count) {\n        this.count.textContent = visibleCount === 1 ? _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.entries_count_one').replace(':n', String(visibleCount)) : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.entries_count').replace(':n', String(visibleCount));\n      }\n      if (this.root.classList.contains('is-open')) this._renderList();\n    }\n  }, {\n    key: \"_renderList\",\n    value: function _renderList() {\n      if (!this.list) return;\n      var entries = this.history._stack;\n      var ptr = this.history._pointer;\n\n      // Hide baseline (index 0) from the visible list — it's the implicit\n      // \"before-any-edit\" floor. When only baseline exists → empty state.\n      var hasRealEntries = entries.length > 1;\n      if (!hasRealEntries) {\n        this.list.innerHTML = this._emptyStateHtml();\n        return;\n      }\n      var html = '';\n      // Iterate only real entries (skip baseline at i=0). Newest first.\n      for (var i = entries.length - 1; i >= 1; i--) {\n        var _e$labelParams, _e$meta, _e$meta2;\n        var e = entries[i];\n        var cls = i === ptr ? 'is-current' : i > ptr ? 'is-future' : '';\n        var label = escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(e.labelKey || 'history.default_label', e.labelParams));\n        var meta = escapeHtml(((_e$labelParams = e.labelParams) === null || _e$labelParams === void 0 ? void 0 : _e$labelParams.type) || '');\n        var icon = iconForEntry(e);\n        var badge = (_e$meta = e.meta) !== null && _e$meta !== void 0 && _e$meta.count && e.meta.count > 1 ? \"<span class=\\\"bjs-history-entry-badge\\\">\\xD7\".concat(e.meta.count, \"</span>\") : (_e$meta2 = e.meta) !== null && _e$meta2 !== void 0 && _e$meta2.childCount && e.meta.childCount > 0 ? \"<span class=\\\"bjs-history-entry-badge is-tx\\\">\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.tx')), \"</span>\") : '';\n        html += \"\\n                <li class=\\\"bjs-history-entry \".concat(cls, \"\\\" data-bjs-history-entry-id=\\\"\").concat(escapeHtml(e.id), \"\\\">\\n                    <span class=\\\"bjs-history-entry-icon\\\"><span class=\\\"material-symbols-rounded\\\">\").concat(icon, \"</span></span>\\n                    <span class=\\\"bjs-history-entry-label\\\">\").concat(label, \"</span>\\n                    <span class=\\\"bjs-history-entry-meta\\\">\").concat(meta).concat(badge ? ' ' + badge : '', \"</span>\\n                    <span class=\\\"bjs-history-entry-time\\\">\").concat(escapeHtml(formatRelativeTime(e.timestamp)), \"</span>\\n                </li>\");\n      }\n      this.list.innerHTML = html;\n    }\n  }, {\n    key: \"_emptyStateHtml\",\n    value: function _emptyStateHtml() {\n      return \"\\n            <div class=\\\"bjs-history-empty\\\">\\n                <svg class=\\\"bjs-history-empty-illust\\\" viewBox=\\\"0 0 100 100\\\" fill=\\\"none\\\" aria-hidden=\\\"true\\\">\\n                    <circle cx=\\\"50\\\" cy=\\\"50\\\" r=\\\"38\\\" stroke=\\\"var(--bjs-border)\\\" stroke-width=\\\"1\\\" stroke-dasharray=\\\"3 4\\\"/>\\n                    <rect x=\\\"34\\\" y=\\\"28\\\" width=\\\"32\\\" height=\\\"44\\\" rx=\\\"3\\\" fill=\\\"var(--bjs-bg)\\\" stroke=\\\"var(--bjs-border)\\\" stroke-width=\\\"1.5\\\"/>\\n                    <path d=\\\"M40 40 h20 M40 48 h20 M40 56 h14\\\" stroke=\\\"var(--bjs-text-disabled)\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/>\\n                    <path d=\\\"M30 78 q-8 0 -8 -10\\\" stroke=\\\"var(--bjs-primary)\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" fill=\\\"none\\\"/>\\n                    <path d=\\\"M18 72 l4 -4 l4 4\\\" stroke=\\\"var(--bjs-primary)\\\" stroke-width=\\\"2\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" fill=\\\"none\\\"/>\\n                </svg>\\n                <div class=\\\"bjs-history-empty-title\\\">\".concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.empty_title')), \"</div>\\n                <div class=\\\"bjs-history-empty-note\\\">\\n                    \").concat(escapeHtml(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.empty_note')), \"\\n                    <span class=\\\"bjs-history-empty-kbd\\\"><kbd>\").concat(KBD_MOD, \"</kbd><kbd>Z</kbd></span>\\n                </div>\\n            </div>\");\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HistoryWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HistoryWidget.js?");

/***/ }),

/***/ "./src/includes/HorizonAlignmentControl.js":
/*!*************************************************!*\
  !*** ./src/includes/HorizonAlignmentControl.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n// includes/HorizonAlignmentControl.js\nvar HorizonAlignmentControl = /*#__PURE__*/function () {\n  function HorizonAlignmentControl(label, value, callback) {\n    var cssProperty = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'align_items';\n    _classCallCheck(this, HorizonAlignmentControl);\n    this.id = '_' + Math.random().toString(36).slice(2, 9);\n    this.label = label || 'Horizon Alignment';\n    this.value = value || 'flex-start'; // flex-start | center | flex-end\n    this.callback = callback;\n    this.cssProperty = cssProperty;\n    this.options = [{\n      css: 'flex-start',\n      icon: 'vertical_align_top'\n    }, {\n      css: 'center',\n      icon: 'vertical_align_center'\n    }, {\n      css: 'flex-end',\n      icon: 'vertical_align_bottom'\n    }];\n    this.domNode = document.createElement('div');\n    HorizonAlignmentControl.injectStyles();\n    this.render();\n  }\n  return _createClass(HorizonAlignmentControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var radios = this.options.map(function (opt, i) {\n        var id = \"hz_\".concat(_this.id, \"_\").concat(i);\n        return \"\\n        <input type=\\\"radio\\\" class=\\\"btn-check\\\" name=\\\"hz_group_\".concat(_this.id, \"\\\"\\n               id=\\\"\").concat(id, \"\\\" value=\\\"\").concat(opt.css, \"\\\" \").concat(_this.value === opt.css ? 'checked' : '', \">\\n        <label class=\\\"btn builder-radio-btn builder-radio-option fw-bold\\\" for=\\\"\").concat(id, \"\\\">\\n          <span class=\\\"material-symbols-rounded\\\">\").concat(opt.icon, \"</span>\\n        </label>\\n      \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n      <div class=\\\"py-2 px-3 builder-radio-container\\\">\\n        <label class=\\\"form-label fw-semibold builder-radio-label\\\">\".concat(this.label, \"</label>\\n        <div class=\\\"btn-group builder-radio-group\\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n          \").concat(radios, \"\\n        </div>\\n      </div>\\n    \");\n      this.domNode.querySelectorAll(\"input[name=\\\"hz_group_\".concat(this.id, \"\\\"]\")).forEach(function (r) {\n        r.addEventListener('change', function (e) {\n          _this.value = e.target.value; // css value\n          if (_this.callback && typeof _this.callback.setValue === 'function') {\n            _this.callback.setValue(_this.value, _this.cssProperty);\n          }\n        });\n      });\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(cssValue) {\n      this.value = cssValue;\n      var radio = this.domNode.querySelector(\"input[value=\\\"\".concat(cssValue, \"\\\"]\"));\n      if (radio) radio.checked = true;\n      if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value, this.cssProperty);\n      }\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }], [{\n    key: \"injectStyles\",\n    value: function injectStyles() {\n      if (document.getElementById('hz-align-control-styles')) return;\n      var css = \"\\n      /* ===== \\u041E\\u0431\\u0449\\u0438\\u0439 \\u0432\\u0438\\u0434 \\u043A\\u0430\\u043A \\u0443 AlignControl ===== */\\n      .builder-radio-container{\\n        display:flex; align-items:center; justify-content:space-between;\\n        gap:12px; padding:8px 12px;\\n      }\\n      .builder-radio-label{ margin:0; font-weight:600; }\\n      .builder-radio-group{\\n        display:inline-flex; border-radius:8px; overflow:hidden;\\n        border:1px solid var(--bs-border-color,#dee2e6);\\n        height:32px; flex-shrink:0; width:180px;\\n      }\\n      .builder-radio-btn{\\n        display:flex; align-items:center; justify-content:center;\\n        width:60px; height:32px; border:0;\\n        border-right:1px solid var(--bs-border-color,#dee2e6);\\n        background:#fff; color:#212529;\\n      }\\n      .builder-radio-btn:last-of-type{ border-right:0; }\\n      .builder-radio-btn .material-symbols-rounded{ font-size:18px; line-height:1; }\\n      .btn-check:checked + .builder-radio-btn{ background:#495057; color:#fff; }\\n\\n      /* ===== \\u0421\\u043F\\u0440\\u044F\\u0442\\u0430\\u0442\\u044C \\xAB\\u0447\\u0438\\u043F/\\u0437\\u043D\\u0430\\u0447\\u0435\\u043D\\u0438\\u0435\\xBB, \\u043A\\u043E\\u0442\\u043E\\u0440\\u043E\\u0435 \\u0434\\u0432\\u0438\\u0436\\u043E\\u043A \\u043F\\u043E\\u0434\\u043C\\u0435\\u0448\\u0438\\u0432\\u0430\\u0435\\u0442 \\u043F\\u043E\\u0441\\u043B\\u0435 \\u0433\\u0440\\u0443\\u043F\\u043F\\u044B ===== */\\n      .builder-radio-container .builder-radio-group + *,\\n      .builder-radio-container .builder-radio-group ~ .badge,\\n      .builder-radio-container .builder-radio-group ~ .form-control,\\n      .builder-radio-container .builder-radio-group ~ .form-select {\\n        display:none !important;\\n      }\\n    \";\n      var style = document.createElement('style');\n      style.id = 'hz-align-control-styles';\n      style.textContent = css;\n      document.head.appendChild(style);\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HorizonAlignmentControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/HorizonAlignmentControl.js?");

/***/ }),

/***/ "./src/includes/I18n.js":
/*!******************************!*\
  !*** ./src/includes/I18n.js ***!
  \******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _lang_en_json__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../lang/en.json */ \"./src/lang/en.json\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar I18n = /*#__PURE__*/function () {\n  function I18n() {\n    _classCallCheck(this, I18n);\n  }\n  return _createClass(I18n, null, [{\n    key: \"init\",\n    value: function init(translations) {\n      I18n._messages = translations || {};\n    }\n  }, {\n    key: \"t\",\n    value: function t(key, params) {\n      var text = I18n._messages[key] || I18n._defaults[key] || key;\n      if (params) {\n        Object.keys(params).forEach(function (k) {\n          text = text.replace(new RegExp(':' + k, 'g'), params[k]);\n        });\n      }\n      return text;\n    }\n  }]);\n}();\n_defineProperty(I18n, \"_messages\", {});\n_defineProperty(I18n, \"_defaults\", _lang_en_json__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (I18n);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/I18n.js?");

/***/ }),

/***/ "./src/includes/IconPickerControl.js":
/*!*******************************************!*\
  !*** ./src/includes/IconPickerControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * IconPickerControl — compact trigger + popover icon picker.\n *\n * Renders as a .bjs-control-row with a trigger button showing the current\n * icon glyph + label + chevron. Click opens a popover with the full icon\n * grid (defaults to the pricingCardIcons registry) plus \"None\" and\n * \"Custom emoji\" options. Choosing \"Custom\" reveals an inline text input\n * inside the popover so the user can paste any emoji or glyph — the\n * trigger updates live as they type.\n *\n * Keyboard: Enter/Space opens the popover, arrows navigate, Enter selects,\n * Esc closes. ARIA: trigger=button w/ aria-haspopup, popover=radiogroup.\n *\n * Callback contract: `{ setValue(nextIconName) }`. Empty string = no icon.\n * Material-symbol names, emoji, and other short glyphs all flow through\n * the same string property (PricingCardIcons.render() handles dispatch).\n */\nvar IconPickerControl = /*#__PURE__*/function () {\n  function IconPickerControl(label, value, callback) {\n    var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, IconPickerControl);\n    this.label = label;\n    this.value = value || '';\n    this.callback = callback;\n    this.id = '_ip_' + Math.random().toString(36).slice(2, 9);\n    this.options = Array.isArray(config.options) && config.options.length ? config.options : IconPickerControl.defaultOptions();\n    this.isOpen = false;\n    this.isCustomOpen = this._detectCustom(value);\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-icon-picker-control');\n    this._documentClickHandler = null;\n    this._documentKeydownHandler = null;\n    this.render();\n  }\n  return _createClass(IconPickerControl, [{\n    key: \"_detectCustom\",\n    value: function _detectCustom(val) {\n      if (!val) return false;\n      var key = String(val).trim();\n      // If the value matches a registry entry, it's a preset — not custom.\n      return !_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(key);\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var currentKey = this.value || '';\n      var currentGlyph = currentKey ? _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(currentKey, {\n        size: 20,\n        color: 'currentColor'\n      }) : '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"><circle cx=\"10\" cy=\"10\" r=\"7.5\" stroke=\"currentColor\" stroke-width=\"1.25\" stroke-dasharray=\"2 2\" fill=\"none\"/></svg>';\n      var currentLabel = currentKey ? _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(currentKey) ? IconPickerControl.humanize(currentKey) : currentKey : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none');\n      var tilesHtml = this.options.map(function (opt) {\n        var checked = opt.key === _this.value ? 'true' : 'false';\n        var glyph = opt.key ? _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(opt.key, {\n          size: 22,\n          color: 'currentColor'\n        }) : '<svg viewBox=\"0 0 22 22\" xmlns=\"http://www.w3.org/2000/svg\" width=\"22\" height=\"22\"><line x1=\"4\" y1=\"4\" x2=\"18\" y2=\"18\" stroke=\"currentColor\" stroke-width=\"1.5\"/><line x1=\"18\" y1=\"4\" x2=\"4\" y2=\"18\" stroke=\"currentColor\" stroke-width=\"1.5\"/></svg>';\n        var title = opt.label || opt.key || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none');\n        return \"\\n                <button\\n                    type=\\\"button\\\"\\n                    class=\\\"bjs-icon-tile\\\"\\n                    role=\\\"radio\\\"\\n                    aria-checked=\\\"\".concat(checked, \"\\\"\\n                    data-key=\\\"\").concat(_this._esc(opt.key), \"\\\"\\n                    tabindex=\\\"\").concat(checked === 'true' ? '0' : '-1', \"\\\"\\n                    data-tooltip=\\\"\").concat(_this._esc(title), \"\\\"\\n                    aria-label=\\\"\").concat(_this._esc(title), \"\\\"\\n                >\\n                    <span class=\\\"bjs-icon-tile-glyph\\\" aria-hidden=\\\"true\\\">\").concat(glyph, \"</span>\\n                </button>\\n            \");\n      }).join('');\n\n      // Custom-emoji tile: visually distinct (text \"ABC\" placeholder), toggles the inline text input\n      var customActive = this.isCustomOpen || !_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(this.value) && this.value;\n      var customTile = \"\\n            <button\\n                type=\\\"button\\\"\\n                class=\\\"bjs-icon-tile bjs-icon-tile--custom \".concat(customActive ? 'is-active' : '', \"\\\"\\n                aria-checked=\\\"\").concat(customActive ? 'true' : 'false', \"\\\"\\n                role=\\\"radio\\\"\\n                data-key=\\\"__custom\\\"\\n                tabindex=\\\"\").concat(customActive ? '0' : '-1', \"\\\"\\n                data-tooltip=\\\"\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom')), \"\\\"\\n                aria-label=\\\"\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom')), \"\\\"\\n            >\\n                <span class=\\\"bjs-icon-tile-custom-label\\\">Aa</span>\\n            </button>\\n        \");\n      var customInputHtml = this.isCustomOpen ? \"\\n            <div class=\\\"bjs-icon-picker-custom\\\">\\n                <label class=\\\"bjs-icon-picker-custom-label\\\" for=\\\"icon-custom-\".concat(this.id, \"\\\">\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom_label')), \"</label>\\n                <input\\n                    type=\\\"text\\\"\\n                    id=\\\"icon-custom-\").concat(this.id, \"\\\"\\n                    class=\\\"bjs-text-input\\\"\\n                    data-control=\\\"icon-custom\\\"\\n                    value=\\\"\").concat(this._esc(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(this.value) ? '' : this.value), \"\\\"\\n                    placeholder=\\\"\").concat(this._esc(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.custom_placeholder')), \"\\\"\\n                    maxlength=\\\"16\\\"\\n                    autocomplete=\\\"off\\\"\\n                />\\n            </div>\\n        \") : '';\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <label class=\\\"bjs-control-label\\\">\".concat(this._esc(this.label), \"</label>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <button\\n                        type=\\\"button\\\"\\n                        class=\\\"bjs-icon-trigger\\\"\\n                        aria-haspopup=\\\"listbox\\\"\\n                        aria-expanded=\\\"\").concat(this.isOpen ? 'true' : 'false', \"\\\"\\n                        data-control=\\\"icon-trigger\\\"\\n                        id=\\\"icon-trigger-\").concat(this.id, \"\\\"\\n                    >\\n                        <span class=\\\"bjs-icon-trigger-glyph\\\" aria-hidden=\\\"true\\\">\").concat(currentGlyph, \"</span>\\n                        <span class=\\\"bjs-icon-trigger-label\\\">\").concat(this._esc(currentLabel), \"</span>\\n                        <span class=\\\"bjs-icon-trigger-caret\\\" aria-hidden=\\\"true\\\"><svg viewBox=\\\"0 0 16 16\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"14\\\" height=\\\"14\\\" style=\\\"display:block\\\"><path d=\\\"M4 6l4 4 4-4\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.8\\\" fill=\\\"none\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/></svg></span>\\n                    </button>\\n                </div>\\n            </div>\\n            <div\\n                class=\\\"bjs-icon-popover\").concat(this.isOpen ? ' is-open' : '', \"\\\"\\n                role=\\\"radiogroup\\\"\\n                aria-labelledby=\\\"icon-trigger-\").concat(this.id, \"\\\"\\n                data-control=\\\"icon-popover\\\"\\n            >\\n                <div class=\\\"bjs-icon-popover-grid\\\">\\n                    \").concat(tilesHtml, \"\\n                    \").concat(customTile, \"\\n                </div>\\n                \").concat(customInputHtml, \"\\n            </div>\\n        \");\n      this._bind();\n    }\n  }, {\n    key: \"_bind\",\n    value: function _bind() {\n      var _this2 = this;\n      var trigger = this.domNode.querySelector('[data-control=\"icon-trigger\"]');\n      var popover = this.domNode.querySelector('[data-control=\"icon-popover\"]');\n      if (!trigger || !popover) return;\n      trigger.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this2._toggle();\n      });\n      var tiles = Array.from(popover.querySelectorAll('.bjs-icon-tile'));\n      tiles.forEach(function (tile, idx) {\n        tile.addEventListener('click', function (e) {\n          e.preventDefault();\n          var key = tile.dataset.key;\n          if (key === '__custom') {\n            _this2.isCustomOpen = true;\n            _this2.render();\n            var input = _this2.domNode.querySelector('[data-control=\"icon-custom\"]');\n            if (input) input.focus();\n            return;\n          }\n          _this2._select(key);\n          _this2._close();\n        });\n        tile.addEventListener('keydown', function (e) {\n          var cols = 6;\n          var target = null;\n          if (e.key === 'ArrowRight') target = tiles[(idx + 1) % tiles.length];else if (e.key === 'ArrowLeft') target = tiles[(idx - 1 + tiles.length) % tiles.length];else if (e.key === 'ArrowDown') target = tiles[Math.min(idx + cols, tiles.length - 1)];else if (e.key === 'ArrowUp') target = tiles[Math.max(idx - cols, 0)];else if (e.key === 'Enter' || e.key === ' ') {\n            tile.click();\n            e.preventDefault();\n            return;\n          } else if (e.key === 'Escape') {\n            _this2._close();\n            trigger.focus();\n            e.preventDefault();\n            return;\n          }\n          if (target) {\n            e.preventDefault();\n            target.focus();\n          }\n        });\n      });\n      var customInput = this.domNode.querySelector('[data-control=\"icon-custom\"]');\n      if (customInput) {\n        var t = null;\n        customInput.addEventListener('input', function (e) {\n          var v = (e.target.value || '').trim();\n          // Debounce to avoid re-render thrash as user types\n          if (t) clearTimeout(t);\n          t = setTimeout(function () {\n            _this2.value = v;\n            _this2.callback && _this2.callback.setValue && _this2.callback.setValue(v);\n            _this2._refreshTrigger();\n          }, 180);\n        });\n        customInput.addEventListener('keydown', function (e) {\n          if (e.key === 'Escape') {\n            _this2._close();\n            trigger.focus();\n            e.preventDefault();\n          }\n        });\n      }\n    }\n  }, {\n    key: \"_toggle\",\n    value: function _toggle() {\n      if (this.isOpen) this._close();else this._open();\n    }\n  }, {\n    key: \"_open\",\n    value: function _open() {\n      var _this3 = this;\n      this.isOpen = true;\n      this.render();\n      var active = this.domNode.querySelector('.bjs-icon-tile[aria-checked=\"true\"]') || this.domNode.querySelector('.bjs-icon-tile');\n      if (active) active.focus();\n      this._documentClickHandler = function (e) {\n        if (!_this3.domNode.contains(e.target)) _this3._close();\n      };\n      this._documentKeydownHandler = function (e) {\n        if (e.key === 'Escape') _this3._close();\n      };\n      document.addEventListener('click', this._documentClickHandler);\n      document.addEventListener('keydown', this._documentKeydownHandler);\n    }\n  }, {\n    key: \"_close\",\n    value: function _close() {\n      if (!this.isOpen) return;\n      this.isOpen = false;\n      this.render();\n      if (this._documentClickHandler) document.removeEventListener('click', this._documentClickHandler);\n      if (this._documentKeydownHandler) document.removeEventListener('keydown', this._documentKeydownHandler);\n      this._documentClickHandler = null;\n      this._documentKeydownHandler = null;\n    }\n  }, {\n    key: \"_select\",\n    value: function _select(key) {\n      this.value = key || '';\n      this.isCustomOpen = false;\n      this.callback && this.callback.setValue && this.callback.setValue(this.value);\n      // Render() is invoked by _close() after this call.\n    }\n\n    // Update the trigger preview without a full re-render. Used while the\n    // user types in the custom-emoji input so the popover stays open but\n    // the trigger glyph + label updates live.\n  }, {\n    key: \"_refreshTrigger\",\n    value: function _refreshTrigger() {\n      var glyphEl = this.domNode.querySelector('.bjs-icon-trigger-glyph');\n      var labelEl = this.domNode.querySelector('.bjs-icon-trigger-label');\n      if (!glyphEl || !labelEl) return;\n      if (this.value) {\n        glyphEl.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(this.value, {\n          size: 20,\n          color: 'currentColor'\n        });\n        labelEl.textContent = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(this.value) ? IconPickerControl.humanize(this.value) : this.value;\n      } else {\n        glyphEl.innerHTML = '<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\"><circle cx=\"10\" cy=\"10\" r=\"7.5\" stroke=\"currentColor\" stroke-width=\"1.25\" stroke-dasharray=\"2 2\" fill=\"none\"/></svg>';\n        labelEl.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none');\n      }\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(value) {\n      this.value = value || '';\n      this.isCustomOpen = this._detectCustom(this.value);\n      this.render();\n    }\n  }, {\n    key: \"_esc\",\n    value: function _esc(s) {\n      return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n    }\n  }], [{\n    key: \"defaultOptions\",\n    value: function defaultOptions() {\n      // Build from the icon registry + a \"None\" option. \"Custom emoji\" is\n      // rendered last as a special tile (below the registry options).\n      var opts = [{\n        key: '',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('icon_picker.none')\n      }];\n      _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].allNames().forEach(function (name) {\n        opts.push({\n          key: name,\n          label: IconPickerControl.humanize(name)\n        });\n      });\n      return opts;\n    }\n  }, {\n    key: \"humanize\",\n    value: function humanize(name) {\n      return String(name).replace(/_/g, ' ').replace(/\\b\\w/g, function (c) {\n        return c.toUpperCase();\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (IconPickerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/IconPickerControl.js?");

/***/ }),

/***/ "./src/includes/ImageControl.js":
/*!**************************************!*\
  !*** ./src/includes/ImageControl.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n/**\n * ImageControl — sidebar preview + src/alt/url editor for ImageElement.\n *\n * Phase 1.8: Extends BaseControl so destroy() runs when the sidebar\n * rebuilds. Subscribes to element.render() via addSyncListener so overlay\n * mutations to element.src / element.alt auto-refresh here — the overlay\n * never needs to call this control directly (SA I13 observer pattern).\n * Legacy syncFromExternal(value) signature is preserved for back-compat.\n */\nvar ImageControl = /*#__PURE__*/function (_BaseControl) {\n  function ImageControl(label, value, callback) {\n    var _this;\n    _classCallCheck(this, ImageControl);\n    _this = _callSuper(this, ImageControl);\n    _this.label = label;\n    _this.value = value.src;\n    _this.alt = value.alt;\n    _this.callback = callback;\n    _this.UploadMode = true;\n    _this.PasteMode = false;\n    _this.domNode = document.createElement('div');\n    _this.debounceAltTimeout = null;\n    _this.debounceUrlTimeout = null;\n\n    // Phase 1.8 (SA I13) — subscribe via capability token. On notify,\n    // pull fresh state via readState() (primitives like src/alt aren't\n    // live references, so a getter is required). Overlay's Upload flow\n    // mutates element.src then calls element.render(); the element's\n    // notifySyncListeners invokes this subscriber automatically.\n    if (typeof value.subscribe === 'function' && typeof value.readState === 'function') {\n      _this.addDisposer(value.subscribe(function () {\n        var fresh = value.readState();\n        _this.syncFromExternal({\n          src: fresh.src,\n          alt: fresh.alt\n        });\n      }));\n    }\n\n    // Legacy shim — back-compat for overlay Upload call site that reads\n    // host._activeControls.image. Wired in afterRender() so host\n    // injection has already run; cleared in destroy().\n    // (NOTE: this.host is null at constructor time — Builder\n    //  assigns it AFTER getControls() returns, BEFORE afterRender().)\n\n    _this.render();\n    return _this;\n  }\n\n  /** Hook fires after Builder.renderElementControls has appended this\n   *  control's domNode AND assigned `this.host`. Safe place to register\n   *  the active-control slot used by ImageActionsOverlay's sync flow. */\n  _inherits(ImageControl, _BaseControl);\n  return _createClass(ImageControl, [{\n    key: \"afterRender\",\n    value: function afterRender() {\n      if (this.host) {\n        this.host._activeControls = this.host._activeControls || {};\n        this.host._activeControls.image = this;\n      }\n    }\n\n    /** Control teardown (SA I14). BaseControl runs stashed disposers;\n     *  additionally clear the legacy shim slot so orphaned overlay code\n     *  can't write to a ghost instance. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this.host && this.host._activeControls && this.host._activeControls.image === this) {\n        this.host._activeControls.image = null;\n      }\n      _superPropGet(ImageControl, \"destroy\", this, 3)([]);\n    }\n\n    /**\n     * Patch the sidebar preview in place to reflect a new image value\n     * sourced from outside this control (typically the canvas overlay's\n     * Upload / Replace flow). Does NOT call `builder.renderElementControls`\n     * — that would tear down + rebuild the entire panel + reset focus\n     * (NO-FLICKER, SA invariant I9).\n     *\n     * Patches per field:\n     *   - src: reassigns `this.value`, swaps the preview <img src=>, refreshes\n     *     filename + dimensions meta, and (in paste mode only, when not\n     *     focused) updates the URL input's value.\n     *   - alt: reassigns `this.alt` and (when not focused) updates the alt\n     *     <input> value. Skipping the focused-input write preserves any\n     *     in-flight typing the user is doing.\n     *\n     * Pass `undefined` for fields you don't want to touch; pass the new\n     * value (including `''`) for fields you DO want to update.\n     */\n  }, {\n    key: \"syncFromExternal\",\n    value: function syncFromExternal(value) {\n      if (!value || _typeof(value) !== 'object') return;\n      if (this._destroyed) return;\n      if (!this.domNode) return; // DOM gone — sidebar rebuilt or section destroyed\n\n      if (value.src !== undefined && value.src !== this.value) {\n        this.value = value.src;\n        var previewImg = this.domNode.querySelector('.bjs-image-preview img');\n        if (previewImg) previewImg.src = value.src;\n        var urlInput = this.domNode.querySelector('[name=\"image-url\"]');\n        if (urlInput && document.activeElement !== urlInput) {\n          urlInput.value = value.src;\n        }\n        this._updateImageMeta(value.src);\n      }\n      if (value.alt !== undefined && value.alt !== this.alt) {\n        this.alt = value.alt;\n        var altInput = this.domNode.querySelector('[name=\"alt-text\"]');\n        if (altInput && document.activeElement !== altInput) {\n          altInput.value = value.alt;\n        }\n      }\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack\\\">\\n                <div class=\\\"bjs-control-label\\\"><span>\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.mode'), \"</span></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-image-input\\\">\\n                        <div class=\\\"bjs-segmented bjs-image-input-mode\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.mode'), \"\\\">\\n                            <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\").concat(this.UploadMode ? ' is-active' : '', \"\\\"\\n                                data-mode=\\\"upload\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(this.UploadMode, \"\\\">\\n                                \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.upload_image'), \"\\n                            </button>\\n                            <button type=\\\"button\\\" class=\\\"bjs-segmented-btn\").concat(this.PasteMode ? ' is-active' : '', \"\\\"\\n                                data-mode=\\\"paste\\\" role=\\\"radio\\\" aria-checked=\\\"\").concat(this.PasteMode, \"\\\">\\n                                \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.paste_url'), \"\\n                            </button>\\n                        </div>\\n                        \").concat(this.UploadMode ? this._renderUploadMode() : this._renderPasteMode(), \"\\n                    </div>\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-control-stack\\\">\\n                <div class=\\\"bjs-control-label\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.alt_text'), \"</span></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"text\\\" name=\\\"alt-text\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.enter_alt'), \"\\\" value=\\\"\").concat(this._escAttr(this.alt), \"\\\">\\n                </div>\\n            </div>\\n        \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_renderUploadMode\",\n    value: function _renderUploadMode() {\n      var _this$host;\n      return \"\\n            <div class=\\\"bjs-image-input-body\\\">\\n                <div class=\\\"bjs-image-preview\\\">\\n                    <img src=\\\"\".concat(this.value, \"\\\" alt=\\\"\\\">\\n                </div>\\n                <div class=\\\"bjs-image-meta\\\">\\n                    <div class=\\\"bjs-image-meta-name\\\" data-field=\\\"name\\\">--</div>\\n                    <div class=\\\"bjs-image-meta-size\\\" data-field=\\\"size\\\">-- \\xD7 -- px</div>\\n                    <div class=\\\"bjs-image-actions\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"upload\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.upload'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">upload</span>\\n                        </button>\\n                        \").concat((_this$host = this.host) !== null && _this$host !== void 0 && _this$host.fileManager ? \"\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"browse\\\" aria-label=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.browse'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">folder_open</span>\\n                        </button>\\n                        \") : '', \"\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"reload\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.replace'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">sync</span>\\n                        </button>\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" data-control=\\\"delete\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.remove'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">delete</span>\\n                        </button>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_renderPasteMode\",\n    value: function _renderPasteMode() {\n      return \"\\n            <div class=\\\"bjs-image-input-body\\\">\\n                <div class=\\\"bjs-image-preview\\\">\\n                    <img src=\\\"\".concat(this.value, \"\\\" alt=\\\"\\\">\\n                </div>\\n                <div class=\\\"bjs-image-meta\\\">\\n                    <input type=\\\"url\\\" name=\\\"image-url\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.enter_url'), \"\\\" value=\\\"\").concat(this._escAttr(this.value), \"\\\">\\n                    <div class=\\\"bjs-image-meta-size\\\" data-field=\\\"size\\\">-- \\xD7 -- px</div>\\n                </div>\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      // Mode toggle\n      var modeGroup = this.domNode.querySelector('.bjs-image-input-mode');\n      if (modeGroup) {\n        modeGroup.addEventListener('click', function (e) {\n          var btn = e.target.closest('.bjs-segmented-btn');\n          if (!btn) return;\n          var mode = btn.dataset.mode;\n          if (mode) _this2._switchMode(mode);\n        });\n        modeGroup.addEventListener('keydown', function (e) {\n          if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n          e.preventDefault();\n          var buttons = Array.from(modeGroup.querySelectorAll('.bjs-segmented-btn'));\n          var currentIndex = buttons.findIndex(function (b) {\n            return b.classList.contains('is-active');\n          });\n          var nextIndex = currentIndex;\n          if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n            nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n          } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n            nextIndex = (currentIndex + 1) % buttons.length;\n          } else if (e.key === 'Home') {\n            nextIndex = 0;\n          } else if (e.key === 'End') {\n            nextIndex = buttons.length - 1;\n          }\n          var nextBtn = buttons[nextIndex];\n          if (nextBtn) {\n            _this2._switchMode(nextBtn.dataset.mode);\n            nextBtn.focus();\n          }\n        });\n      }\n\n      // Alt text input — debounce 300ms\n      var altInput = this.domNode.querySelector('[name=\"alt-text\"]');\n      if (altInput) {\n        altInput.addEventListener('input', function () {\n          clearTimeout(_this2.debounceAltTimeout);\n          _this2.debounceAltTimeout = setTimeout(function () {\n            _this2.alt = altInput.value;\n            _this2.callback.setAlt(_this2.alt);\n          }, 300);\n        });\n      }\n      if (this.UploadMode) {\n        this._bindUploadMode();\n      } else {\n        this._bindPasteMode();\n      }\n\n      // Update image meta in both modes (preview exists in both)\n      this._updateImageMeta(this.value);\n    }\n  }, {\n    key: \"_bindUploadMode\",\n    value: function _bindUploadMode() {\n      var _this3 = this;\n      var uploadBtn = this.domNode.querySelector('[data-control=\"upload\"]');\n      if (uploadBtn) {\n        uploadBtn.addEventListener('click', function () {\n          return _this3._openFileBrowser();\n        });\n      }\n      var browseBtn = this.domNode.querySelector('[data-control=\"browse\"]');\n      if (browseBtn) {\n        browseBtn.addEventListener('click', function () {\n          return _this3._openMediaBrowser();\n        });\n      }\n      var reloadBtn = this.domNode.querySelector('[data-control=\"reload\"]');\n      if (reloadBtn) {\n        reloadBtn.addEventListener('click', function () {\n          // Just refresh the image without full re-render\n          var img = _this3.domNode.querySelector('.bjs-image-preview img');\n          if (img) {\n            img.src = _this3.value + '?' + new Date().getTime();\n            _this3._updateImageMeta(_this3.value);\n          }\n        });\n      }\n      var deleteBtn = this.domNode.querySelector('[data-control=\"delete\"]');\n      if (deleteBtn) {\n        deleteBtn.addEventListener('click', function () {\n          var emptyImageUrl = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJMYXllcl8yIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyOTYgMjk2Ij48ZyBpZD0iTGF5ZXJfMS0yIj48cmVjdCB3aWR0aD0iMjk2IiBoZWlnaHQ9IjI5NiIgc3R5bGU9ImZpbGw6I2U2ZTZlNjsiLz48cGF0aCBkPSJNMjM2Ljk4LDk5LjQ0Yy0xLjEyLDAtMi4wMi45MS0yLjAyLDIuMDJ2OTMuMzZjMCw0LjktMi4zLDkuMjctNS44NywxMi4xMWwtNDYuMS00Ny4yM2MtLjc1LS43Ny0xLjk3LS44Mi0yLjc4LS4xMmwtMzIuMTgsMjcuOTgtNS43OS01Ljk1Yy0uNzgtLjgtMi4wNi0uODItMi44Ni0uMDQtLjguNzgtLjgyLDIuMDYtLjA0LDIuODZsNy4xMyw3LjMzYy43NS43NywxLjk3LjgyLDIuNzguMTJsMzIuMTgtMjcuOTgsNDQuMDksNDUuMThjLTEuODYuNzktMy45LDEuMjMtNi4wNSwxLjIzaC0xMTIuNjRjLTEuMTIsMC0yLjAyLjktMi4wMiwyLjAycy45MSwyLjAyLDIuMDIsMi4wMmgxMTIuNjRjMTAuNzcsMCwxOS41My04Ljc2LDE5LjUzLTE5LjUzdi05My4zNmMwLTEuMTItLjktMi4wMi0yLjAyLTIuMDJaIiBzdHlsZT0iZmlsbDpncmF5OyIvPjxwYXRoIGQ9Ik0yMzguNDgsNjYuOWMtLjc1LS44My0yLjAzLS45LTIuODYtLjE2bC0xNi45MywxNS4xOEg3Ni4zNmMtMTAuNzcsMC0xOS41Myw4Ljc2LTE5LjUzLDE5LjUzdjkzLjM2YzAsOS4xNiw2LjM2LDE2Ljg2LDE0Ljg5LDE4Ljk1bC0xNC4yMiwxMi43NWMtLjgzLjc0LS45LDIuMDMtLjE2LDIuODYuNC40NS45NS42NywxLjUxLjY3LjQ4LDAsLjk2LS4xNywxLjM1LS41MkwyMzguMzMsNjkuNzZjLjgzLS43NS45LTIuMDMuMTYtMi44NlpNNzYuMzYsODUuOThoMTM3LjgybC04OC4wOSw3OS4wMi0yMS44My0yMi40NWMtLjc2LS43OC0xLjk5LS44Mi0yLjgtLjA5bC00MC41NywzNi40NXYtNzcuNDVjMC04LjU0LDYuOTQtMTUuNDgsMTUuNDgtMTUuNDhaTTYwLjg4LDE5NC44MnYtMTAuNDdsNDEuODMtMzcuNTgsMjAuMzYsMjAuOTQtNDcuNDQsNDIuNTVjLTguMTktLjM5LTE0Ljc1LTcuMTUtMTQuNzUtMTUuNDRaIiBzdHlsZT0iZmlsbDpncmF5OyIvPjxwYXRoIGQ9Ik0xMjIuODMsMTI5LjEzYy04LjE5LDAtMTQuODUtNi42Ni0xNC44NS0xNC44NXM2LjY2LTE0Ljg1LDE0Ljg1LTE0Ljg1LDE0Ljg1LDYuNjYsMTQuODUsMTQuODUtNi42NiwxNC44NS0xNC44NSwxNC44NVpNMTIyLjgzLDEwMy40OGMtNS45NSwwLTEwLjgsNC44NC0xMC44LDEwLjhzNC44NCwxMC44LDEwLjgsMTAuOCwxMC44LTQuODQsMTAuOC0xMC44LTQuODQtMTAuOC0xMC44LTEwLjhaIiBzdHlsZT0iZmlsbDpncmF5OyIvPjwvZz48L3N2Zz4=';\n          _this3.value = emptyImageUrl;\n          _this3.callback.setImage(emptyImageUrl);\n          _this3.render();\n        });\n      }\n    }\n  }, {\n    key: \"_bindPasteMode\",\n    value: function _bindPasteMode() {\n      var _this4 = this;\n      var imageInput = this.domNode.querySelector('[name=\"image-url\"]');\n      if (!imageInput) return;\n      var applyUrl = function applyUrl() {\n        var newUrl = imageInput.value;\n        _this4.value = newUrl;\n        _this4.callback.setImage(newUrl);\n        var previewImg = _this4.domNode.querySelector('.bjs-image-preview img');\n        if (previewImg) previewImg.src = newUrl;\n        _this4._updateImageMeta(newUrl);\n      };\n      imageInput.addEventListener('input', function () {\n        clearTimeout(_this4.debounceUrlTimeout);\n        _this4.debounceUrlTimeout = setTimeout(applyUrl, 350);\n      });\n      imageInput.addEventListener('change', function () {\n        clearTimeout(_this4.debounceUrlTimeout);\n        applyUrl();\n      });\n    }\n  }, {\n    key: \"_switchMode\",\n    value: function _switchMode(mode) {\n      if (mode === 'upload') {\n        this.UploadMode = true;\n        this.PasteMode = false;\n      } else if (mode === 'paste') {\n        this.UploadMode = false;\n        this.PasteMode = true;\n      }\n      this.render();\n    }\n  }, {\n    key: \"_updateImageMeta\",\n    value: function _updateImageMeta(url) {\n      var nameField = this.domNode.querySelector('[data-field=\"name\"]');\n      var sizeField = this.domNode.querySelector('[data-field=\"size\"]');\n      if (!url) {\n        if (nameField) nameField.textContent = '--';\n        if (sizeField) sizeField.textContent = '-- × -- px';\n        return;\n      }\n\n      // Extract filename from URL (strip query string + path)\n      var filename = (url.split('/').pop() || '').split('?')[0] || '--';\n      if (nameField) nameField.textContent = filename;\n\n      // Use Image() to read natural dimensions — no blob fetch required\n      var img = new Image();\n      img.onload = function () {\n        if (sizeField) sizeField.textContent = \"\".concat(img.naturalWidth, \" \\xD7 \").concat(img.naturalHeight, \" px\");\n      };\n      img.onerror = function () {\n        if (sizeField) sizeField.textContent = '-- × -- px';\n      };\n      img.src = url;\n    }\n  }, {\n    key: \"_openFileBrowser\",\n    value: function _openFileBrowser() {\n      var _this5 = this;\n      var input = document.createElement('input');\n      input.type = 'file';\n      input.accept = 'image/*';\n      input.addEventListener('change', /*#__PURE__*/function () {\n        var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {\n          var file, formData, response, result;\n          return _regeneratorRuntime().wrap(function _callee$(_context) {\n            while (1) switch (_context.prev = _context.next) {\n              case 0:\n                file = event.target.files[0];\n                if (!file) {\n                  _context.next = 18;\n                  break;\n                }\n                formData = new FormData();\n                formData.append('file', file);\n                _context.prev = 4;\n                _context.next = 7;\n                return fetch(_this5.host.assetUploadHandler, {\n                  method: 'POST',\n                  body: formData\n                });\n              case 7:\n                response = _context.sent;\n                if (!response.ok) {\n                  _context.next = 13;\n                  break;\n                }\n                _context.next = 11;\n                return response.json();\n              case 11:\n                result = _context.sent;\n                if (result.url) {\n                  _this5.value = result.url;\n                  _this5.callback.setImage(result.url);\n                  _this5.render();\n                }\n              case 13:\n                _context.next = 18;\n                break;\n              case 15:\n                _context.prev = 15;\n                _context.t0 = _context[\"catch\"](4);\n                console.error('Error uploading file:', _context.t0);\n              case 18:\n              case \"end\":\n                return _context.stop();\n            }\n          }, _callee, null, [[4, 15]]);\n        }));\n        return function (_x) {\n          return _ref.apply(this, arguments);\n        };\n      }());\n      input.click();\n    }\n  }, {\n    key: \"_openMediaBrowser\",\n    value: function _openMediaBrowser() {\n      var _this$host2,\n        _this6 = this;\n      if (!((_this$host2 = this.host) !== null && _this$host2 !== void 0 && _this$host2.fileManager)) return;\n      this.host.browseMedia(function (url) {\n        if (url) {\n          _this6.value = url;\n          _this6.callback.setImage(url);\n          _this6.render();\n          _this6.host.closeBrowseMedia();\n        }\n      });\n    }\n  }, {\n    key: \"_escAttr\",\n    value: function _escAttr(str) {\n      return (str || '').replace(/\"/g, '&quot;').replace(/</g, '&lt;');\n    }\n  }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageControl.js?");

/***/ }),

/***/ "./src/includes/ImageCropControl.js":
/*!******************************************!*\
  !*** ./src/includes/ImageCropControl.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n/**\n * ImageCropControl\n *\n * CSS-based image crop / focus point / zoom selector.\n * Aspect ratio is expressed as TWO INTEGERS (ratioX:ratioY) — best practice for\n * responsive emails. The actual crop frame width is 100% of its parent; height\n * is auto-derived via CSS `aspect-ratio: X/Y`.\n *\n * Render output (in Image.template.html when crop.enabled):\n *   <div style=\"overflow:hidden; aspect-ratio: X/Y; width:100%\">\n *     <img style=\"object-fit:cover; object-position:X% Y%; transform:scale(N); ...\">\n *   </div>\n *\n * UI:\n *   - Toggle on/off\n *   - Email-compat info banner (Outlook 2007–2013 falls back to original image)\n *   - Live preview with rule-of-thirds grid, draggable focus dot, scroll-wheel zoom\n *   - Preset chips: Original, 1:1, 16:9, 4:3, 3:2, 2:3, 21:9, 9:16\n *     (\"Original\" loads image natural dimensions, GCD-reduces to integers)\n *   - Custom inputs: [X] : [Y] with swap button (rotate 90°)\n *   - Live \"Ratio: X:Y\" display\n *   - Sliders: Zoom (1×–3×), Focus X (0–100%), Focus Y (0–100%)\n *   - Reset button\n *\n * Phase 1.8 (SA I13/I14): Extends BaseControl → auto-dispose of the\n * sync-listener subscription when the sidebar rebuilds.\n */\nvar ImageCropControl = /*#__PURE__*/function (_BaseControl) {\n  function ImageCropControl(label, value, callback) {\n    var _this;\n    _classCallCheck(this, ImageCropControl);\n    _this = _callSuper(this, ImageCropControl);\n    _this.label = label;\n    _this.src = value.src;\n    var c = value.crop || {};\n    _this.crop = {\n      enabled: !!c.enabled,\n      ratioX: _this._safeRatio(c.ratioX, 3),\n      ratioY: _this._safeRatio(c.ratioY, 2),\n      zoom: typeof c.zoom === 'number' ? c.zoom : 1,\n      posX: typeof c.posX === 'number' ? c.posX : 50,\n      posY: typeof c.posY === 'number' ? c.posY : 50\n    };\n    _this.callback = callback;\n\n    // Phase 1.4 (SA invariant I4) — stash source reference so overlay-side\n    // mutations to element.crop can be re-read via syncFromExternal(). The\n    // caller (ImageElement.getControls) passes the element's own crop object\n    // via `value.crop` — storing value (not a copy) lets us re-read on demand.\n    _this._sourceValueRef = value;\n\n    // Phase 1.8 (SA I13) — subscribe to state-change notifications. The\n    // caller passes a narrow `subscribe(fn) → disposer` capability token\n    // (NOT the whole element). Control stays decoupled from element API;\n    // future infrastructure changes (render-hook → event bus → whatever)\n    // don't propagate here. Disposer auto-runs in BaseControl.destroy.\n    if (typeof value.subscribe === 'function') {\n      _this.addDisposer(value.subscribe(function () {\n        return _this.syncFromExternal();\n      }));\n    }\n\n    // Legacy shim slot is registered in afterRender() — this.host is\n    // null at constructor time. Cleared in destroy().\n\n    // Preset ratios — common photographic / video / mobile / cinema standards.\n    // \"original\" is special: resolved at click time from image natural size.\n    _this.presets = [{\n      x: null,\n      y: null,\n      label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.preset_original'),\n      original: true\n    }, {\n      x: 1,\n      y: 1,\n      label: '1:1'\n    }, {\n      x: 16,\n      y: 9,\n      label: '16:9'\n    }, {\n      x: 4,\n      y: 3,\n      label: '4:3'\n    }, {\n      x: 3,\n      y: 2,\n      label: '3:2'\n    }, {\n      x: 2,\n      y: 3,\n      label: '2:3'\n    }, {\n      x: 21,\n      y: 9,\n      label: '21:9'\n    }, {\n      x: 9,\n      y: 16,\n      label: '9:16'\n    }];\n    _this.zoomDef = {\n      min: 1,\n      max: 3,\n      step: 0.05,\n      def: 1\n    };\n    _this.RATIO_MAX = 99;\n    _this.domNode = document.createElement('div');\n    _this.domNode.className = 'ImageCropControl';\n    _this._dragging = false;\n    _this.render();\n    return _this;\n  }\n  _inherits(ImageCropControl, _BaseControl);\n  return _createClass(ImageCropControl, [{\n    key: \"_safeRatio\",\n    value: function _safeRatio(v, def) {\n      var n = parseInt(v, 10);\n      if (!Number.isFinite(n) || n < 1) return def;\n      return Math.min(this.RATIO_MAX, n);\n    }\n\n    /**\n     * Greatest common divisor for reducing image natural dimensions\n     * (e.g. 1920×1080 → 16:9, 4032×3024 → 4:3).\n     */\n  }, {\n    key: \"_gcd\",\n    value: function _gcd(a, b) {\n      a = Math.abs(a);\n      b = Math.abs(b);\n      while (b) {\n        var _ref = [b, a % b];\n        a = _ref[0];\n        b = _ref[1];\n      }\n      return a || 1;\n    }\n  }, {\n    key: \"isModified\",\n    value: function isModified() {\n      if (!this.crop.enabled) return false;\n      // Default = 3:2, zoom 1, focus 50/50\n      return this.crop.ratioX !== 3 || this.crop.ratioY !== 2 || this.crop.zoom !== 1 || this.crop.posX !== 50 || this.crop.posY !== 50;\n    }\n  }, {\n    key: \"_matchedPreset\",\n    value: function _matchedPreset() {\n      var _this2 = this;\n      return this.presets.find(function (p) {\n        return !p.original && p.x === _this2.crop.ratioX && p.y === _this2.crop.ratioY;\n      }) || null;\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      // Defensive: snap any rogue values back to safe defaults BEFORE rendering\n      // (guards against external code or async race conditions setting NaN/null).\n      this.crop.ratioX = this._safeRatio(this.crop.ratioX, 3);\n      this.crop.ratioY = this._safeRatio(this.crop.ratioY, 2);\n      if (!Number.isFinite(this.crop.zoom)) this.crop.zoom = 1;\n      if (!Number.isFinite(this.crop.posX)) this.crop.posX = 50;\n      if (!Number.isFinite(this.crop.posY)) this.crop.posY = 50;\n      var c = this.crop;\n      var matched = this._matchedPreset();\n      var presetChips = this.presets.map(function (p) {\n        var isActive = !p.original && matched && matched.label === p.label;\n        var dataAttrs = p.original ? \"data-preset=\\\"original\\\"\" : \"data-rx=\\\"\".concat(p.x, \"\\\" data-ry=\\\"\").concat(p.y, \"\\\"\");\n        return \"\\n                <button type=\\\"button\\\"\\n                    class=\\\"icrop-chip\".concat(isActive ? ' is-active' : '').concat(p.original ? ' icrop-chip-original' : '', \"\\\"\\n                    \").concat(dataAttrs, \"\\n                    \").concat(!c.enabled ? 'disabled' : '', \"\\n                    data-tooltip=\\\"\").concat(p.label, \"\\\">\").concat(p.label, \"</button>\\n            \");\n      }).join('');\n      var zoomPct = (c.zoom - this.zoomDef.min) / (this.zoomDef.max - this.zoomDef.min) * 100;\n      this.domNode.innerHTML = \"\\n        <div class=\\\"icrop-container\".concat(c.enabled ? ' is-enabled' : '', \"\\\" data-role=\\\"container\\\">\\n            <div class=\\\"icrop-header\\\">\\n                <label class=\\\"icrop-title\\\">\").concat(this.label, \"</label>\\n                <label class=\\\"icrop-toggle\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.toggle_hint'), \"\\\">\\n                    <input type=\\\"checkbox\\\" class=\\\"icrop-toggle-input\\\" data-role=\\\"enabled\\\" \").concat(c.enabled ? 'checked' : '', \">\\n                    <span class=\\\"icrop-toggle-slider\\\"></span>\\n                </label>\\n            </div>\\n\\n            <div class=\\\"icrop-body\\\" data-role=\\\"body\\\" \").concat(c.enabled ? '' : 'hidden', \">\\n                <div class=\\\"icrop-info\\\">\\n                    <span class=\\\"icrop-info-icon\\\" aria-hidden=\\\"true\\\">\\n                        <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\">\\n                            <circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"10\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\"/>\\n                            <path d=\\\"M12 8v5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.6\\\" stroke-linecap=\\\"round\\\"/>\\n                            <circle cx=\\\"12\\\" cy=\\\"16.2\\\" r=\\\"1\\\" fill=\\\"currentColor\\\"/>\\n                        </svg>\\n                    </span>\\n                    <span class=\\\"icrop-info-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.email_warning'), \"</span>\\n                </div>\\n\\n                <div class=\\\"icrop-preview-wrap\\\">\\n                    <div class=\\\"icrop-preview\\\" data-role=\\\"preview\\\" style=\\\"aspect-ratio:\").concat(c.ratioX, \"/\").concat(c.ratioY, \";\\\">\\n                        <img src=\\\"\").concat(this.src, \"\\\" alt=\\\"\\\"\\n                            class=\\\"icrop-preview-img\\\"\\n                            style=\\\"object-position:\").concat(c.posX, \"% \").concat(c.posY, \"%; transform:scale(\").concat(c.zoom, \"); transform-origin:\").concat(c.posX, \"% \").concat(c.posY, \"%;\\\"\\n                            draggable=\\\"false\\\">\\n                        <div class=\\\"icrop-focus-dot\\\" style=\\\"left:\").concat(c.posX, \"%; top:\").concat(c.posY, \"%;\\\" aria-hidden=\\\"true\\\"></div>\\n                        <div class=\\\"icrop-grid\\\" aria-hidden=\\\"true\\\">\\n                            <span></span><span></span><span></span><span></span>\\n                        </div>\\n                    </div>\\n                    <div class=\\\"icrop-preview-hint\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.preview_hint'), \"</div>\\n                </div>\\n\\n                <div class=\\\"icrop-section\\\">\\n                    <div class=\\\"icrop-section-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.aspect_ratio'), \"</div>\\n                    <div class=\\\"icrop-chips\\\">\").concat(presetChips, \"</div>\\n                </div>\\n\\n                <div class=\\\"icrop-section\\\">\\n                    <div class=\\\"icrop-section-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.custom_ratio'), \"</div>\\n                    <div class=\\\"icrop-ratio-row\\\">\\n                        <input type=\\\"number\\\" class=\\\"icrop-ratio-input\\\" data-role=\\\"ratioX\\\"\\n                            min=\\\"1\\\" max=\\\"\").concat(this.RATIO_MAX, \"\\\" step=\\\"1\\\"\\n                            value=\\\"\").concat(c.ratioX, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.ratio_x'), \"\\\">\\n                        <span class=\\\"icrop-ratio-sep\\\">:</span>\\n                        <input type=\\\"number\\\" class=\\\"icrop-ratio-input\\\" data-role=\\\"ratioY\\\"\\n                            min=\\\"1\\\" max=\\\"\").concat(this.RATIO_MAX, \"\\\" step=\\\"1\\\"\\n                            value=\\\"\").concat(c.ratioY, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.ratio_y'), \"\\\">\\n                        <button type=\\\"button\\\" class=\\\"icrop-ratio-swap\\\" data-role=\\\"swap\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.swap_hint'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.swap_hint'), \"\\\">\\n                            <svg width=\\\"14\\\" height=\\\"14\\\" viewBox=\\\"0 0 16 16\\\" fill=\\\"none\\\">\\n                                <path d=\\\"M3 5h9M3 5l3-3M3 5l3 3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.4\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n                                <path d=\\\"M13 11H4M13 11l-3-3M13 11l-3 3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.4\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n                            </svg>\\n                        </button>\\n                        <span class=\\\"icrop-ratio-display\\\">= \").concat(c.ratioX, \":\").concat(c.ratioY, \"</span>\\n                    </div>\\n                </div>\\n\\n                <div class=\\\"icrop-section\\\">\\n                    <div class=\\\"icrop-row\\\">\\n                        <label class=\\\"icrop-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.zoom'), \"</label>\\n                        <div class=\\\"icrop-slider-wrap\\\">\\n                            <input type=\\\"range\\\" class=\\\"icrop-slider\\\" data-role=\\\"zoom\\\"\\n                                min=\\\"\").concat(this.zoomDef.min, \"\\\" max=\\\"\").concat(this.zoomDef.max, \"\\\" step=\\\"\").concat(this.zoomDef.step, \"\\\"\\n                                value=\\\"\").concat(c.zoom, \"\\\" style=\\\"--pct:\").concat(zoomPct, \"%\\\">\\n                        </div>\\n                        <div class=\\\"icrop-value-wrap\\\">\\n                            <input type=\\\"number\\\" class=\\\"icrop-value-input\\\" data-role=\\\"zoom-num\\\"\\n                                min=\\\"\").concat(this.zoomDef.min, \"\\\" max=\\\"\").concat(this.zoomDef.max, \"\\\" step=\\\"\").concat(this.zoomDef.step, \"\\\"\\n                                value=\\\"\").concat(c.zoom.toFixed(2), \"\\\">\\n                            <span class=\\\"icrop-unit\\\">\\xD7</span>\\n                        </div>\\n                    </div>\\n\\n                    <div class=\\\"icrop-row\\\">\\n                        <label class=\\\"icrop-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.focus_x'), \"</label>\\n                        <div class=\\\"icrop-slider-wrap\\\">\\n                            <input type=\\\"range\\\" class=\\\"icrop-slider\\\" data-role=\\\"posX\\\"\\n                                min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\"\\n                                value=\\\"\").concat(c.posX, \"\\\" style=\\\"--pct:\").concat(c.posX, \"%\\\">\\n                        </div>\\n                        <div class=\\\"icrop-value-wrap\\\">\\n                            <input type=\\\"number\\\" class=\\\"icrop-value-input\\\" data-role=\\\"posX-num\\\"\\n                                min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(c.posX, \"\\\">\\n                            <span class=\\\"icrop-unit\\\">%</span>\\n                        </div>\\n                    </div>\\n\\n                    <div class=\\\"icrop-row\\\">\\n                        <label class=\\\"icrop-row-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.focus_y'), \"</label>\\n                        <div class=\\\"icrop-slider-wrap\\\">\\n                            <input type=\\\"range\\\" class=\\\"icrop-slider\\\" data-role=\\\"posY\\\"\\n                                min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\"\\n                                value=\\\"\").concat(c.posY, \"\\\" style=\\\"--pct:\").concat(c.posY, \"%\\\">\\n                        </div>\\n                        <div class=\\\"icrop-value-wrap\\\">\\n                            <input type=\\\"number\\\" class=\\\"icrop-value-input\\\" data-role=\\\"posY-num\\\"\\n                                min=\\\"0\\\" max=\\\"100\\\" step=\\\"1\\\" value=\\\"\").concat(c.posY, \"\\\">\\n                            <span class=\\\"icrop-unit\\\">%</span>\\n                        </div>\\n                    </div>\\n                </div>\\n\\n                <div class=\\\"icrop-actions\\\">\\n                    <button type=\\\"button\\\" class=\\\"icrop-reset\\\" data-role=\\\"reset\\\" \").concat(this.isModified() ? '' : 'disabled', \">\\n                        <svg width=\\\"11\\\" height=\\\"11\\\" viewBox=\\\"0 0 12 12\\\" fill=\\\"none\\\" style=\\\"margin-right:4px;vertical-align:-1px;\\\">\\n                            <path d=\\\"M2 6a4 4 0 1 0 1.2-2.83\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/>\\n                            <path d=\\\"M2 2v3h3\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"/>\\n                        </svg>\\n                        \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.reset'), \"\\n                    </button>\\n                </div>\\n            </div>\\n        </div>\");\n      this._setupListeners();\n    }\n  }, {\n    key: \"_setupListeners\",\n    value: function _setupListeners() {\n      var _this3 = this;\n      // Toggle enable/disable\n      var toggle = this.domNode.querySelector('.icrop-toggle-input');\n      toggle.addEventListener('change', function (e) {\n        _this3.crop.enabled = e.target.checked;\n        _this3._apply();\n        _this3.render();\n      });\n      if (!this.crop.enabled) return;\n\n      // Preset chips\n      this.domNode.querySelectorAll('.icrop-chip').forEach(function (chip) {\n        chip.addEventListener('click', function () {\n          if (chip.dataset.preset === 'original') {\n            _this3._applyOriginalRatio(chip);\n            return;\n          }\n          _this3.crop.ratioX = parseInt(chip.dataset.rx, 10);\n          _this3.crop.ratioY = parseInt(chip.dataset.ry, 10);\n          _this3._apply();\n          _this3.render();\n        });\n      });\n\n      // Custom ratio inputs (X / Y)\n      // While typing (input event), allow empty/partial values without re-rendering;\n      // only on blur do we commit + clamp. This way the user can clear and re-type\n      // without the field flicker-resetting to 1 on every keystroke.\n      ['ratioX', 'ratioY'].forEach(function (role) {\n        var input = _this3.domNode.querySelector(\".icrop-ratio-input[data-role=\\\"\".concat(role, \"\\\"]\"));\n        if (!input) return;\n        var debounce = null;\n        input.addEventListener('input', function () {\n          var v = parseInt(input.value, 10);\n          if (!Number.isFinite(v) || v < 1) return; // ignore intermediate empty/0 state\n          var clamped = Math.max(1, Math.min(_this3.RATIO_MAX, v));\n          _this3.crop[role] = clamped;\n          _this3._updatePreview();\n          _this3._updateRatioDisplay();\n          _this3._updateChipActive();\n          _this3._updateResetState();\n          clearTimeout(debounce);\n          debounce = setTimeout(function () {\n            return _this3._apply();\n          }, 200);\n        });\n        input.addEventListener('blur', function () {\n          var v = parseInt(input.value, 10);\n          // Clamp to bounds (NaN/empty → 1, negative/0 → 1, > MAX → MAX).\n          // Clamping > resetting because user intent was \"type a number\" — give\n          // them the closest valid one rather than discarding their attempt.\n          if (!Number.isFinite(v)) v = 1;\n          v = Math.max(1, Math.min(_this3.RATIO_MAX, v));\n          _this3.crop[role] = v;\n          input.value = v; // snap visible value\n          _this3._updatePreview();\n          _this3._updateRatioDisplay();\n          _this3._updateChipActive();\n          _this3._updateResetState();\n          _this3._apply();\n        });\n      });\n\n      // Swap X ↔ Y\n      var swap = this.domNode.querySelector('[data-role=\"swap\"]');\n      if (swap) {\n        swap.addEventListener('click', function () {\n          var t = _this3.crop.ratioX;\n          _this3.crop.ratioX = _this3.crop.ratioY;\n          _this3.crop.ratioY = t;\n          _this3._apply();\n          _this3.render();\n        });\n      }\n\n      // Zoom + focus sliders\n      var wireRow = function wireRow(role) {\n        var slider = _this3.domNode.querySelector(\".icrop-slider[data-role=\\\"\".concat(role, \"\\\"]\"));\n        var numInput = _this3.domNode.querySelector(\".icrop-value-input[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n        var sync = function sync(val, source) {\n          val = _this3._clamp(role, val);\n          _this3.crop[role] = role === 'zoom' ? Math.round(val * 100) / 100 : Math.round(val);\n          if (source !== 'slider') slider.value = _this3.crop[role];\n          if (source !== 'input') numInput.value = role === 'zoom' ? _this3.crop[role].toFixed(2) : _this3.crop[role];\n          var pct = role === 'zoom' ? (_this3.crop.zoom - _this3.zoomDef.min) / (_this3.zoomDef.max - _this3.zoomDef.min) * 100 : _this3.crop[role];\n          slider.style.setProperty('--pct', pct + '%');\n          _this3._updatePreview();\n          _this3._updateResetState();\n        };\n        var debounce = null;\n        slider.addEventListener('input', function (e) {\n          sync(parseFloat(e.target.value), 'slider');\n          clearTimeout(debounce);\n          debounce = setTimeout(function () {\n            return _this3._apply();\n          }, 80);\n        });\n        numInput.addEventListener('input', function (e) {\n          var v = parseFloat(e.target.value);\n          if (isNaN(v)) return;\n          sync(v, 'input');\n          clearTimeout(debounce);\n          debounce = setTimeout(function () {\n            return _this3._apply();\n          }, 150);\n        });\n        numInput.addEventListener('blur', function (e) {\n          var v = parseFloat(e.target.value);\n          if (isNaN(v)) v = role === 'zoom' ? 1 : 50;\n          sync(v, 'both');\n          _this3._apply();\n        });\n      };\n      wireRow('zoom');\n      wireRow('posX');\n      wireRow('posY');\n\n      // Drag focus on preview\n      var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n      if (preview) {\n        var move = function move(clientX, clientY) {\n          var rect = preview.getBoundingClientRect();\n          var x = Math.max(0, Math.min(100, (clientX - rect.left) / rect.width * 100));\n          var y = Math.max(0, Math.min(100, (clientY - rect.top) / rect.height * 100));\n          _this3.crop.posX = Math.round(x);\n          _this3.crop.posY = Math.round(y);\n          _this3._syncSlider('posX');\n          _this3._syncSlider('posY');\n          _this3._updatePreview();\n          _this3._updateResetState();\n        };\n        var onDown = function onDown(e) {\n          e.preventDefault();\n          _this3._dragging = true;\n          preview.classList.add('is-dragging');\n          var ev = e.touches ? e.touches[0] : e;\n          move(ev.clientX, ev.clientY);\n        };\n        var onMove = function onMove(e) {\n          if (!_this3._dragging) return;\n          var ev = e.touches ? e.touches[0] : e;\n          move(ev.clientX, ev.clientY);\n        };\n        var onUp = function onUp() {\n          if (!_this3._dragging) return;\n          _this3._dragging = false;\n          preview.classList.remove('is-dragging');\n          _this3._apply();\n        };\n        preview.addEventListener('mousedown', onDown);\n        window.addEventListener('mousemove', onMove);\n        window.addEventListener('mouseup', onUp);\n        preview.addEventListener('touchstart', onDown, {\n          passive: false\n        });\n        window.addEventListener('touchmove', onMove, {\n          passive: false\n        });\n        window.addEventListener('touchend', onUp);\n\n        // Wheel zoom\n        preview.addEventListener('wheel', function (e) {\n          e.preventDefault();\n          var delta = e.deltaY > 0 ? -0.1 : 0.1;\n          var z = _this3._clamp('zoom', _this3.crop.zoom + delta);\n          z = Math.round(z * 100) / 100;\n          _this3.crop.zoom = z;\n          _this3._syncSlider('zoom');\n          _this3._updatePreview();\n          _this3._updateResetState();\n          _this3._apply();\n        }, {\n          passive: false\n        });\n      }\n\n      // Reset\n      var resetBtn = this.domNode.querySelector('[data-role=\"reset\"]');\n      resetBtn.addEventListener('click', function () {\n        _this3.crop.ratioX = 3;\n        _this3.crop.ratioY = 2;\n        _this3.crop.zoom = 1;\n        _this3.crop.posX = 50;\n        _this3.crop.posY = 50;\n        _this3._apply();\n        _this3.render();\n      });\n    }\n\n    /**\n     * Find the integer pair (rx, ry) within [1, max] whose ratio rx/ry best\n     * approximates target = w/h. Linear scan — RATIO_MAX is small (99), trivial.\n     * Beats naive halving which discards precision (523:172 → 66:22 = 3.0\n     * vs target 3.04). This finds 95:31 = 3.065 → much closer.\n     */\n  }, {\n    key: \"_bestRatio\",\n    value: function _bestRatio(w, h, max) {\n      if (w <= max && h <= max) return [w, h]; // already fits\n      var target = w / h;\n      var best = [1, 1];\n      var bestDiff = Infinity;\n      // Search both axes to handle landscape and portrait equally well\n      for (var rx = 1; rx <= max; rx++) {\n        var ry = Math.round(rx / target);\n        if (ry < 1 || ry > max) continue;\n        var diff = Math.abs(rx / ry - target);\n        if (diff < bestDiff) {\n          bestDiff = diff;\n          best = [rx, ry];\n        }\n        if (diff < 1e-6) return best;\n      }\n      for (var _ry = 1; _ry <= max; _ry++) {\n        var _rx = Math.round(_ry * target);\n        if (_rx < 1 || _rx > max) continue;\n        var _diff = Math.abs(_rx / _ry - target);\n        if (_diff < bestDiff) {\n          bestDiff = _diff;\n          best = [_rx, _ry];\n        }\n        if (_diff < 1e-6) return best;\n      }\n      return best;\n    }\n\n    /**\n     * \"Original\" preset — load the image, read naturalWidth × naturalHeight,\n     * GCD-reduce to integer ratio (e.g. 1920×1080 → 16:9). When GCD-reduced\n     * pair exceeds RATIO_MAX, fall back to closest integer-pair approximation.\n     */\n  }, {\n    key: \"_applyOriginalRatio\",\n    value: function _applyOriginalRatio(chip) {\n      var _this4 = this;\n      var previewImg = this.domNode.querySelector('.icrop-preview-img');\n      var apply = function apply(w, h) {\n        if (!w || !h) return;\n        var g = _this4._gcd(w, h);\n        var rx = Math.round(w / g);\n        var ry = Math.round(h / g);\n        if (rx > _this4.RATIO_MAX || ry > _this4.RATIO_MAX) {\n          var _this4$_bestRatio = _this4._bestRatio(rx, ry, _this4.RATIO_MAX);\n          var _this4$_bestRatio2 = _slicedToArray(_this4$_bestRatio, 2);\n          rx = _this4$_bestRatio2[0];\n          ry = _this4$_bestRatio2[1];\n        }\n        _this4.crop.ratioX = Math.max(1, Math.min(_this4.RATIO_MAX, rx));\n        _this4.crop.ratioY = Math.max(1, Math.min(_this4.RATIO_MAX, ry));\n        _this4._apply();\n        _this4.render();\n      };\n      if (previewImg && previewImg.complete && previewImg.naturalWidth) {\n        apply(previewImg.naturalWidth, previewImg.naturalHeight);\n        return;\n      }\n\n      // Fall back to a fresh probe Image if preview isn't loaded yet\n      var probe = new Image();\n      probe.crossOrigin = 'anonymous';\n      if (chip) {\n        chip.disabled = true;\n        chip.classList.add('is-loading');\n      }\n      var restore = function restore() {\n        if (chip) {\n          chip.disabled = false;\n          chip.classList.remove('is-loading');\n        }\n      };\n      probe.onload = function () {\n        apply(probe.naturalWidth, probe.naturalHeight);\n        restore();\n      };\n      probe.onerror = restore;\n      probe.src = this.src;\n    }\n  }, {\n    key: \"_clamp\",\n    value: function _clamp(role, v) {\n      if (role === 'zoom') return Math.max(this.zoomDef.min, Math.min(this.zoomDef.max, v));\n      return Math.max(0, Math.min(100, v));\n    }\n  }, {\n    key: \"_syncSlider\",\n    value: function _syncSlider(role) {\n      var slider = this.domNode.querySelector(\".icrop-slider[data-role=\\\"\".concat(role, \"\\\"]\"));\n      var numInput = this.domNode.querySelector(\".icrop-value-input[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n      if (slider) {\n        slider.value = this.crop[role];\n        var pct = role === 'zoom' ? (this.crop.zoom - this.zoomDef.min) / (this.zoomDef.max - this.zoomDef.min) * 100 : this.crop[role];\n        slider.style.setProperty('--pct', pct + '%');\n      }\n      if (numInput) numInput.value = role === 'zoom' ? this.crop.zoom.toFixed(2) : this.crop[role];\n    }\n  }, {\n    key: \"_updatePreview\",\n    value: function _updatePreview() {\n      var img = this.domNode.querySelector('.icrop-preview-img');\n      var dot = this.domNode.querySelector('.icrop-focus-dot');\n      var preview = this.domNode.querySelector('[data-role=\"preview\"]');\n      if (!img) return;\n      img.style.objectPosition = \"\".concat(this.crop.posX, \"% \").concat(this.crop.posY, \"%\");\n      img.style.transform = \"scale(\".concat(this.crop.zoom, \")\");\n      img.style.transformOrigin = \"\".concat(this.crop.posX, \"% \").concat(this.crop.posY, \"%\");\n      if (dot) {\n        dot.style.left = this.crop.posX + '%';\n        dot.style.top = this.crop.posY + '%';\n      }\n      if (preview) {\n        preview.style.aspectRatio = \"\".concat(this.crop.ratioX, \"/\").concat(this.crop.ratioY);\n      }\n    }\n  }, {\n    key: \"_updateRatioDisplay\",\n    value: function _updateRatioDisplay() {\n      var display = this.domNode.querySelector('.icrop-ratio-display');\n      if (display) display.textContent = \"= \".concat(this.crop.ratioX, \":\").concat(this.crop.ratioY);\n    }\n  }, {\n    key: \"_updateChipActive\",\n    value: function _updateChipActive() {\n      var matched = this._matchedPreset();\n      this.domNode.querySelectorAll('.icrop-chip').forEach(function (chip) {\n        if (chip.dataset.preset === 'original') {\n          chip.classList.remove('is-active'); // never marked active (it's a one-shot action)\n          return;\n        }\n        var isMatch = matched && parseInt(chip.dataset.rx, 10) === matched.x && parseInt(chip.dataset.ry, 10) === matched.y;\n        chip.classList.toggle('is-active', !!isMatch);\n      });\n    }\n  }, {\n    key: \"_updateResetState\",\n    value: function _updateResetState() {\n      var btn = this.domNode.querySelector('[data-role=\"reset\"]');\n      if (btn) btn.disabled = !this.isModified();\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      this.callback.setCrop(_objectSpread({}, this.crop));\n    }\n\n    /**\n     * Phase 1.4 (SA invariant I4) — re-read external crop state and patch\n     * DOM in place, without a full control re-render (NO-FLICKER rule I9).\n     * Phase 1.8: now auto-triggered via addSyncListener on element.render().\n     *\n     * Handles every state-bearing DOM surface:\n     *   - Toggle checkbox                  (data-role=\"enabled\")\n     *   - Container `.is-enabled` class     (data-role=\"container\")\n     *   - Body `hidden` attribute           (data-role=\"body\")\n     *   - Ratio number inputs               (data-role=\"ratioX\" / \"ratioY\")\n     *   - Ratio display text                (.icrop-ratio-display)\n     *   - Sliders (zoom/posX/posY) + paired number inputs\n     *   - Slider `--pct` CSS variable\n     *   - Preview aspect-ratio + object-position + transform + focus-dot\n     *   - Preset chip active states + disabled state when crop off\n     *   - Reset button disabled state\n     *\n     * Does NOT call renderElementControls (NO-FLICKER, SA I9). Does NOT trigger\n     * `callback.setCrop` — the caller already committed state to the element.\n     *\n     * Mutates `this.crop` IN PLACE via Object.assign (SA I13 — reference\n     * stability; a replacement would break any sub-component holding the ref).\n     */\n  }, {\n    key: \"syncFromExternal\",\n    value: function syncFromExternal() {\n      var _this5 = this;\n      if (!this._sourceValueRef) return;\n      if (this._destroyed) return; // disposer should have unsubscribed\n      if (!this.domNode) return; // DOM gone — sidebar rebuilt or section destroyed\n      var c = this._sourceValueRef.crop || {};\n\n      // Copy external state into our local snapshot.\n      var next = {\n        enabled: !!c.enabled,\n        ratioX: this._safeRatio(c.ratioX, 3),\n        ratioY: this._safeRatio(c.ratioY, 2),\n        zoom: typeof c.zoom === 'number' ? c.zoom : 1,\n        posX: typeof c.posX === 'number' ? c.posX : 50,\n        posY: typeof c.posY === 'number' ? c.posY : 50\n      };\n      // Early-out if nothing changed (prevents DOM churn when sync fires\n      // but crop state was already identical — this happens every time\n      // element.render() runs for any unrelated reason).\n      var same = next.enabled === this.crop.enabled && next.ratioX === this.crop.ratioX && next.ratioY === this.crop.ratioY && next.zoom === this.crop.zoom && next.posX === this.crop.posX && next.posY === this.crop.posY;\n      if (same) return;\n      var enabledFlipped = next.enabled !== this.crop.enabled;\n\n      // Phase 1.8 (SA I13) — in-place mutation preserves this.crop's object\n      // identity in case sub-components (or future code) stash the ref.\n      Object.assign(this.crop, next);\n\n      // Patch DOM in place — avoid innerHTML rebuild.\n      try {\n        // Toggle checkbox\n        var enabledEl = this.domNode.querySelector('[data-role=\"enabled\"]');\n        if (enabledEl && 'checked' in enabledEl) enabledEl.checked = !!this.crop.enabled;\n\n        // Container `is-enabled` class + body `hidden` attribute.\n        // When enabled flips, the body's interactive elements (sliders,\n        // chips, etc.) don't exist in the DOM (the template only renders\n        // them inside the body div, which is `hidden` when disabled).\n        // If enabled just flipped ON, we need a full render() because the\n        // body child elements are absent — the subsequent patches would\n        // silently no-op. When it flipped OFF we just hide the body, no\n        // re-render needed.\n        var container = this.domNode.querySelector('[data-role=\"container\"]');\n        var body = this.domNode.querySelector('[data-role=\"body\"]');\n        if (enabledFlipped && this.crop.enabled) {\n          // Going OFF→ON — body contents don't exist yet. Only safe path\n          // is a full re-render, which is fine here because:\n          //   (a) NO-FLICKER rule is about renderElementControls (full\n          //       panel rebuild), not control-internal render();\n          //   (b) flipping the enable toggle is a discrete user action,\n          //       not a keystroke-frequency operation.\n          this.render();\n          return;\n        }\n        if (container) container.classList.toggle('is-enabled', this.crop.enabled);\n        if (body) {\n          if (this.crop.enabled) body.removeAttribute('hidden');else body.setAttribute('hidden', '');\n        }\n\n        // If crop is now disabled, the rest of the body elements are\n        // hidden and don't need further patching.\n        if (!this.crop.enabled) {\n          this._updateResetState();\n          return;\n        }\n\n        // Ratio number inputs (template uses .icrop-ratio-input class +\n        // data-role; be tolerant of either selector form for future renames).\n        var rxEl = this.domNode.querySelector('.icrop-ratio-input[data-role=\"ratioX\"]');\n        var ryEl = this.domNode.querySelector('.icrop-ratio-input[data-role=\"ratioY\"]');\n        if (rxEl && 'value' in rxEl && document.activeElement !== rxEl) rxEl.value = String(this.crop.ratioX);\n        if (ryEl && 'value' in ryEl && document.activeElement !== ryEl) ryEl.value = String(this.crop.ratioY);\n\n        // Ratio display text \"= X:Y\"\n        this._updateRatioDisplay();\n\n        // Sliders + paired number inputs. Template uses .icrop-slider[data-role=\"<name>\"]\n        // for range + .icrop-value-input[data-role=\"<name>-num\"] for the number.\n        ['zoom', 'posX', 'posY'].forEach(function (role) {\n          var slider = _this5.domNode.querySelector(\".icrop-slider[data-role=\\\"\".concat(role, \"\\\"]\"));\n          var numInput = _this5.domNode.querySelector(\".icrop-value-input[data-role=\\\"\".concat(role, \"-num\\\"]\"));\n          if (slider && 'value' in slider && document.activeElement !== slider) {\n            slider.value = String(_this5.crop[role]);\n          }\n          if (numInput && 'value' in numInput && document.activeElement !== numInput) {\n            numInput.value = role === 'zoom' ? _this5.crop[role].toFixed(2) : String(_this5.crop[role]);\n          }\n          // Filled-slider --pct variable re-sync.\n          if (slider) {\n            var val = role === 'zoom' ? (_this5.crop.zoom - _this5.zoomDef.min) / (_this5.zoomDef.max - _this5.zoomDef.min) * 100 : _this5.crop[role];\n            slider.style.setProperty('--pct', val + '%');\n          }\n        });\n\n        // Preset chip active states + disabled attr.\n        this._updateChipActive();\n        this.domNode.querySelectorAll('.icrop-chip').forEach(function (chip) {\n          chip.disabled = !_this5.crop.enabled;\n        });\n\n        // Preview transform + aspect-ratio + focus dot.\n        this._updatePreview();\n\n        // Reset button enabled-state.\n        this._updateResetState();\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.warn('[ImageCropControl] syncFromExternal: partial DOM patch failed:', err);\n      }\n    }\n\n    /** Builder hook — fires after host injection + DOM mount. Register\n     *  the legacy back-compat slot for any third-party code reading\n     *  host._activeControls.imageCrop. New code uses the observer pattern\n     *  via value.subscribe (set up in the constructor). */\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {\n      if (this.host) {\n        this.host._activeControls = this.host._activeControls || {};\n        this.host._activeControls.imageCrop = this;\n      }\n    }\n\n    /** Control teardown (SA I14). BaseControl runs stashed disposers (the\n     *  sync-listener removal). We additionally clear the legacy shim slot so\n     *  orphaned code can't read a ghost instance. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this.host && this.host._activeControls && this.host._activeControls.imageCrop === this) {\n        this.host._activeControls.imageCrop = null;\n      }\n      _superPropGet(ImageCropControl, \"destroy\", this, 3)([]);\n    }\n  }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageCropControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageCropControl.js?");

/***/ }),

/***/ "./src/includes/ImageEffectControl.js":
/*!********************************************!*\
  !*** ./src/includes/ImageEffectControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\nvar ImageEffectControl = /*#__PURE__*/function (_BaseControl) {\n  /**\n   * @param {string} label\n   * @param {object} value — supports both legacy + capability-token form:\n   *   { src, current_effects }                       — legacy primitive form\n   *   { src, current_effects, subscribe, readState } — observer-aware form\n   *     `subscribe(fn) → disposer`  — fires on every element.render\n   *                                   (Phase 1.8 SA I13 R3).\n   *     `readState() → freshEffects`— returns the current effect map\n   *                                   (e.g. () => element.effect).\n   *   Multiple instances of the SAME control (sidebar + popover) coexist;\n   *   both subscribe and stay in sync via syncFromExternal().\n   */\n  function ImageEffectControl(label, value, callback) {\n    var _this;\n    _classCallCheck(this, ImageEffectControl);\n    _this = _callSuper(this, ImageEffectControl);\n    _this.label = label;\n    _this.value = value.src;\n    _this.current_effects = value.current_effects || {};\n    _this.callback = callback;\n    _this._readState = typeof value.readState === 'function' ? value.readState : null;\n    if (typeof value.subscribe === 'function') {\n      // Disposer auto-runs in BaseControl.destroy(). Embedded\n      // popover instances must call control.destroy() in their\n      // beforeDestroy() so the listener Set stays bounded.\n      _this.addDisposer(value.subscribe(function () {\n        return _this.syncFromExternal();\n      }));\n    }\n\n    // Effect definitions: { key: { min, max, step, default, unit } }\n    _this.effectDefs = {\n      grayscale: {\n        min: 0,\n        max: 100,\n        step: 1,\n        def: 0,\n        unit: '%'\n      },\n      sepia: {\n        min: 0,\n        max: 100,\n        step: 1,\n        def: 0,\n        unit: '%'\n      },\n      invert: {\n        min: 0,\n        max: 100,\n        step: 1,\n        def: 0,\n        unit: '%'\n      },\n      blur: {\n        min: 0,\n        max: 10,\n        step: 0.1,\n        def: 0,\n        unit: 'px'\n      },\n      brightness: {\n        min: 0,\n        max: 200,\n        step: 1,\n        def: 100,\n        unit: '%'\n      },\n      contrast: {\n        min: 0,\n        max: 200,\n        step: 1,\n        def: 100,\n        unit: '%'\n      },\n      saturate: {\n        min: 0,\n        max: 300,\n        step: 1,\n        def: 100,\n        unit: '%'\n      },\n      hueRotate: {\n        min: 0,\n        max: 360,\n        step: 1,\n        def: 0,\n        unit: '°'\n      },\n      opacity: {\n        min: 0,\n        max: 100,\n        step: 1,\n        def: 100,\n        unit: '%'\n      }\n    };\n    _this.effectLabels = {\n      grayscale: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.grayscale'),\n      sepia: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.sepia'),\n      invert: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.invert'),\n      blur: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.blur'),\n      brightness: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.brightness'),\n      contrast: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.contrast'),\n      saturate: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.saturation'),\n      hueRotate: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.hue_rotate'),\n      opacity: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.opacity')\n    };\n    _this.domNode = document.createElement('div');\n    _this.domNode.className = 'ImageEffectControl';\n    _this.render();\n    return _this;\n  }\n  _inherits(ImageEffectControl, _BaseControl);\n  return _createClass(ImageEffectControl, [{\n    key: \"getCurrentValues\",\n    value: function getCurrentValues() {\n      var vals = {};\n      for (var _i = 0, _Object$entries = Object.entries(this.effectDefs); _i < _Object$entries.length; _i++) {\n        var _this$current_effects;\n        var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n          key = _Object$entries$_i[0],\n          def = _Object$entries$_i[1];\n        vals[key] = (_this$current_effects = this.current_effects[key]) !== null && _this$current_effects !== void 0 ? _this$current_effects : def.def;\n      }\n      return vals;\n    }\n  }, {\n    key: \"isDefault\",\n    value: function isDefault(key, value) {\n      return Number(value) === this.effectDefs[key].def;\n    }\n  }, {\n    key: \"isAllDefault\",\n    value: function isAllDefault(values) {\n      var _this2 = this;\n      return Object.entries(values).every(function (_ref) {\n        var _ref2 = _slicedToArray(_ref, 2),\n          k = _ref2[0],\n          v = _ref2[1];\n        return _this2.isDefault(k, v);\n      });\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this3 = this;\n      var current = this.getCurrentValues();\n      var allDefault = this.isAllDefault(current);\n      var sliderRows = Object.entries(this.effectDefs).map(function (_ref3) {\n        var _ref4 = _slicedToArray(_ref3, 2),\n          key = _ref4[0],\n          def = _ref4[1];\n        var val = current[key];\n        var modified = !_this3.isDefault(key, val);\n        var pct = (val - def.min) / (def.max - def.min) * 100;\n        return \"\\n            <div class=\\\"iec-row\".concat(modified ? ' iec-row--modified' : '', \"\\\" data-effect=\\\"\").concat(key, \"\\\">\\n                <label class=\\\"iec-row-label\\\">\").concat(_this3.effectLabels[key], \"</label>\\n                <div class=\\\"iec-slider-wrap\\\">\\n                    <input type=\\\"range\\\" class=\\\"iec-slider\\\"\\n                        min=\\\"\").concat(def.min, \"\\\" max=\\\"\").concat(def.max, \"\\\" step=\\\"\").concat(def.step, \"\\\" value=\\\"\").concat(val, \"\\\"\\n                        data-effect=\\\"\").concat(key, \"\\\"\\n                        style=\\\"--pct: \").concat(pct, \"%\\\">\\n                </div>\\n                <div class=\\\"iec-value-wrap\\\">\\n                    <input type=\\\"number\\\" class=\\\"iec-value-input\\\"\\n                        min=\\\"\").concat(def.min, \"\\\" max=\\\"\").concat(def.max, \"\\\" step=\\\"\").concat(def.step, \"\\\" value=\\\"\").concat(val, \"\\\"\\n                        data-effect=\\\"\").concat(key, \"\\\">\\n                    <span class=\\\"iec-unit\\\">\").concat(def.unit, \"</span>\\n                </div>\\n                <button type=\\\"button\\\" class=\\\"iec-row-reset\\\" data-effect=\\\"\").concat(key, \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.reset'), \"\\\" aria-label=\\\"reset \").concat(_this3.effectLabels[key], \"\\\">\\n                    <svg width=\\\"10\\\" height=\\\"10\\\" viewBox=\\\"0 0 12 12\\\" fill=\\\"none\\\"><path d=\\\"M2.5 2.5L9.5 9.5M9.5 2.5L2.5 9.5\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.5\\\" stroke-linecap=\\\"round\\\"/></svg>\\n                </button>\\n            </div>\");\n      }).join('');\n      this.domNode.innerHTML = \"\\n        <div class=\\\"iec-container\\\">\\n            <div class=\\\"iec-header\\\">\\n                <label class=\\\"iec-title\\\">\".concat(this.label, \"</label>\\n                <button type=\\\"button\\\" class=\\\"iec-reset-all\").concat(allDefault ? ' iec-hidden' : '', \"\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_effects.reset'), \"</button>\\n            </div>\\n\\n            <div class=\\\"iec-preview-wrap\\\">\\n                <div class=\\\"iec-preview\\\">\\n                    <img src=\\\"\").concat(this.value, \"\\\" style=\\\"filter: \").concat(this.generateFilterString(current), \";\\\">\\n                </div>\\n            </div>\\n\\n            <div class=\\\"iec-sliders\\\">\\n                \").concat(sliderRows, \"\\n            </div>\\n        </div>\");\n      this.setupListeners();\n    }\n  }, {\n    key: \"setupListeners\",\n    value: function setupListeners() {\n      var _this4 = this;\n      // Slider input (live drag)\n      this.domNode.querySelectorAll('.iec-slider').forEach(function (slider) {\n        var debounce = null;\n        slider.addEventListener('input', function (e) {\n          var key = e.target.dataset.effect;\n          var val = parseFloat(e.target.value);\n          _this4.syncValue(key, val, 'slider');\n\n          // Debounce callback for performance\n          clearTimeout(debounce);\n          debounce = setTimeout(function () {\n            return _this4.applyEffects();\n          }, 80);\n        });\n      });\n\n      // Number input\n      this.domNode.querySelectorAll('.iec-value-input').forEach(function (input) {\n        var debounce = null;\n        input.addEventListener('input', function (e) {\n          var key = e.target.dataset.effect;\n          var def = _this4.effectDefs[key];\n          var val = parseFloat(e.target.value);\n          if (isNaN(val)) return;\n          val = Math.min(def.max, Math.max(def.min, val));\n          _this4.syncValue(key, val, 'input');\n          clearTimeout(debounce);\n          debounce = setTimeout(function () {\n            return _this4.applyEffects();\n          }, 150);\n        });\n\n        // Commit clamped value on blur\n        input.addEventListener('blur', function (e) {\n          var key = e.target.dataset.effect;\n          var def = _this4.effectDefs[key];\n          var val = parseFloat(e.target.value);\n          if (isNaN(val)) val = def.def;\n          val = Math.min(def.max, Math.max(def.min, val));\n          e.target.value = val;\n          _this4.syncValue(key, val, 'input');\n          _this4.applyEffects();\n        });\n      });\n\n      // Per-row reset button\n      this.domNode.querySelectorAll('.iec-row-reset').forEach(function (btn) {\n        btn.addEventListener('click', function (e) {\n          e.stopPropagation();\n          var key = btn.dataset.effect;\n          var def = _this4.effectDefs[key].def;\n          _this4.syncValue(key, def, 'both');\n          _this4.applyEffects();\n        });\n      });\n\n      // Reset all button\n      var resetAll = this.domNode.querySelector('.iec-reset-all');\n      if (resetAll) {\n        resetAll.addEventListener('click', function () {\n          return _this4.resetAll();\n        });\n      }\n    }\n  }, {\n    key: \"syncValue\",\n    value: function syncValue(key, val, source) {\n      var row = this.domNode.querySelector(\".iec-row[data-effect=\\\"\".concat(key, \"\\\"]\"));\n      if (!row) return;\n      var slider = row.querySelector('.iec-slider');\n      var input = row.querySelector('.iec-value-input');\n      var def = this.effectDefs[key];\n      var modified = !this.isDefault(key, val);\n\n      // Skip the originator (source) AND any element the user is currently\n      // editing (SA I13 R4) — preserves in-flight typing / drag from other surfaces.\n      if (source !== 'slider' && document.activeElement !== slider) slider.value = val;\n      if (source !== 'input' && document.activeElement !== input) input.value = val;\n\n      // Fill-track percentage — single source of truth, always applied\n      // regardless of source, so external sync paints identical visual state.\n      var pct = (val - def.min) / (def.max - def.min) * 100;\n      slider.style.setProperty('--pct', pct + '%');\n\n      // Toggle modified state (controls visibility of reset button via CSS)\n      row.classList.toggle('iec-row--modified', modified);\n\n      // Update current_effects\n      this.current_effects[key] = val;\n\n      // Update preview\n      this.updatePreview();\n\n      // Update reset-all visibility\n      var allDefault = this.isAllDefault(this.getCurrentValues());\n      var resetAllBtn = this.domNode.querySelector('.iec-reset-all');\n      if (resetAllBtn) resetAllBtn.classList.toggle('iec-hidden', allDefault);\n    }\n  }, {\n    key: \"updatePreview\",\n    value: function updatePreview() {\n      var previewImg = this.domNode.querySelector('.iec-preview img');\n      if (!previewImg) return;\n      var current = this.getCurrentValues();\n      if (current.opacity <= 0) {\n        previewImg.style.visibility = 'hidden';\n      } else {\n        previewImg.style.visibility = 'visible';\n        previewImg.style.filter = this.generateFilterString(current);\n      }\n    }\n  }, {\n    key: \"generateFilterString\",\n    value: function generateFilterString(effects) {\n      return \"grayscale(\".concat(effects.grayscale, \"%) sepia(\").concat(effects.sepia, \"%) invert(\").concat(effects.invert, \"%) blur(\").concat(effects.blur, \"px) brightness(\").concat(effects.brightness, \"%) contrast(\").concat(effects.contrast, \"%) saturate(\").concat(effects.saturate, \"%) hue-rotate(\").concat(effects.hueRotate, \"deg) opacity(\").concat(effects.opacity, \"%)\");\n    }\n  }, {\n    key: \"resetAll\",\n    value: function resetAll() {\n      for (var _i2 = 0, _Object$entries2 = Object.entries(this.effectDefs); _i2 < _Object$entries2.length; _i2++) {\n        var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),\n          key = _Object$entries2$_i[0],\n          def = _Object$entries2$_i[1];\n        this.syncValue(key, def.def, 'both');\n      }\n      this.applyEffects();\n    }\n  }, {\n    key: \"applyEffects\",\n    value: function applyEffects() {\n      var effects = {};\n      for (var _i3 = 0, _Object$keys = Object.keys(this.effectDefs); _i3 < _Object$keys.length; _i3++) {\n        var _this$current_effects2;\n        var key = _Object$keys[_i3];\n        effects[key] = (_this$current_effects2 = this.current_effects[key]) !== null && _this$current_effects2 !== void 0 ? _this$current_effects2 : this.effectDefs[key].def;\n      }\n      this.callback.setEffects(effects);\n    }\n\n    /** Re-read effects from `readState()` (capability token) and delegate\n     *  each changed key to `syncValue()` — the single authoritative painter\n     *  for slider value, fill track (--pct), numeric input, modified-row\n     *  class, and reset-all visibility. `syncValue()` is focus-aware so\n     *  in-flight typing / drag on this surface is preserved (SA I13 R4).\n     *  Listener idempotence (SA I13 R7) — we early-out cheaply per-key\n     *  when the value is unchanged. */\n  }, {\n    key: \"syncFromExternal\",\n    value: function syncFromExternal() {\n      if (!this._readState) return;\n      if (this._destroyed) return;\n      if (!this.domNode) return;\n      var next = this._readState() || {};\n      for (var _i4 = 0, _Object$keys2 = Object.keys(this.effectDefs); _i4 < _Object$keys2.length; _i4++) {\n        var _this$current_effects3;\n        var key = _Object$keys2[_i4];\n        var newVal = next[key] !== undefined && next[key] !== null ? Number(next[key]) : this.effectDefs[key].def;\n        var curVal = (_this$current_effects3 = this.current_effects[key]) !== null && _this$current_effects3 !== void 0 ? _this$current_effects3 : this.effectDefs[key].def;\n        if (newVal !== Number(curVal)) {\n          this.syncValue(key, newVal, 'external');\n        }\n      }\n    }\n  }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageEffectControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageEffectControl.js?");

/***/ }),

/***/ "./src/includes/ImageElement.js":
/*!**************************************!*\
  !*** ./src/includes/ImageElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\n/* harmony import */ var _ImageControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ImageControl.js */ \"./src/includes/ImageControl.js\");\n/* harmony import */ var _ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ImageEffectControl.js */ \"./src/includes/ImageEffectControl.js\");\n/* harmony import */ var _ImageCropControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ImageCropControl.js */ \"./src/includes/ImageCropControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\n/* harmony import */ var _SectionGroupControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./SectionGroupControl.js */ \"./src/includes/SectionGroupControl.js\");\n/* harmony import */ var _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./InfoBannerControl.js */ \"./src/includes/InfoBannerControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _overlays_ImageActionsOverlay_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./overlays/ImageActionsOverlay.js */ \"./src/includes/overlays/ImageActionsOverlay.js\");\n/* harmony import */ var _overlays_ImageCropInlineOverlay_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./overlays/ImageCropInlineOverlay.js */ \"./src/includes/overlays/ImageCropInlineOverlay.js\");\n/* harmony import */ var _overlays_ImageCropPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./overlays/ImageCropPopoverOverlay.js */ \"./src/includes/overlays/ImageCropPopoverOverlay.js\");\n/* harmony import */ var _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./overlays/ImageResizeCornerOverlay.js */ \"./src/includes/overlays/ImageResizeCornerOverlay.js\");\n/* harmony import */ var _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./overlays/ImageEdgeResizerOverlay.js */ \"./src/includes/overlays/ImageEdgeResizerOverlay.js\");\n/* harmony import */ var _overlays_ImageResizeInlineOverlay_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./overlays/ImageResizeInlineOverlay.js */ \"./src/includes/overlays/ImageResizeInlineOverlay.js\");\n/* harmony import */ var _overlays_ImageResizePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./overlays/ImageResizePopoverOverlay.js */ \"./src/includes/overlays/ImageResizePopoverOverlay.js\");\n/* harmony import */ var _overlays_ImageEffectPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./overlays/ImageEffectPopoverOverlay.js */ \"./src/includes/overlays/ImageEffectPopoverOverlay.js\");\n/* harmony import */ var _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./overlays/LinkPopoverOverlay.js */ \"./src/includes/overlays/LinkPopoverOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar ImageElement = /*#__PURE__*/function (_BaseElement) {\n  function ImageElement(template) {\n    var _this;\n    var src = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTY5IDUxNiI+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImJnIiB4MT0iMCIgeTE9IjAiIHgyPSIwIiB5Mj0iMSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2YwZWZlZCIvPgogICAgICA8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNlOGU3ZTQiLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9Im0xIiB4MT0iLjUiIHkxPSIwIiB4Mj0iLjUiIHkyPSIxIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZDVkNGQwIi8+CiAgICAgIDxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2NkY2NjOCIvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0ibTIiIHgxPSIuNSIgeTE9IjAiIHgyPSIuNSIgeTI9IjEiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNjOWM4YzQiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjYzBiZmJiIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KCiAgPCEtLSBCYWNrZ3JvdW5kIC0tPgogIDxyZWN0IHdpZHRoPSIxNTY5IiBoZWlnaHQ9IjUxNiIgZmlsbD0idXJsKCNiZykiLz4KCiAgPCEtLSBTdW4gLS0+CiAgPGNpcmNsZSBjeD0iNTA1IiBjeT0iMTU1IiByPSI1MiIgZmlsbD0iI2RkZGNkOCIvPgoKICA8IS0tIE1haW4gbW91bnRhaW4gKHJvdW5kZWQgcGVhaykgLS0+CiAgPHBhdGggZD0iTTQ0MCw0NDAgTDY4MCwxNzAgUTc0OCwxMDAgODE2LDE3MCBMMTA1Niw0NDAgWiIgZmlsbD0idXJsKCNtMSkiLz4KCiAgPCEtLSBTbm93IGNhcCBhY2NlbnQgLS0+CiAgPHBhdGggZD0iTTcwMCwxOTAgUTc0OCwxMjAgNzk2LDE5MCBaIiBmaWxsPSIjZTVlNGUwIi8+CgogIDwhLS0gU2Vjb25kYXJ5IG1vdW50YWluIChyb3VuZGVkIHBlYWssIG92ZXJsYXBwaW5nIGZyb250KSAtLT4KICA8cGF0aCBkPSJNNzgwLDQ0MCBMOTUwLDI0MCBRMTAxMCwxODUgMTA3MCwyNDAgTDEyNDAsNDQwIFoiIGZpbGw9InVybCgjbTIpIi8+Cjwvc3ZnPgo=\";\n    var alt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : \"\";\n    var url = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : \"\";\n    var target = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : \"\";\n    _classCallCheck(this, ImageElement);\n    _this = _callSuper(this, ImageElement);\n    _this.src = src;\n    _this.alt = alt;\n    _this.url = url || '';\n    _this.target = target || '';\n    // Full-link semantics (parity with ButtonElement). LinkConfigControl\n    // edits all five — url + target + rel + title + download — and\n    // applyLinkAttrs() patches them on the rendered <a>. Default empty,\n    // so existing image data without these keys renders identically to\n    // before this upgrade.\n    _this.rel = '';\n    _this.title = '';\n    _this.download = '';\n    _this.template = template;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['src'];\n\n    // Formatter - similar to PElement but with image-specific properties\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"]({\n      // spacing\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      // image-specific sizing — stored as unit-qualified strings\n      // (\"300px\" | \"50%\" | \"1.5em\" | \"auto\") via DimensionControl.\n      // Legacy numeric values (e.g. 200) are treated as px for backward compat.\n      width: null,\n      height: null,\n      max_width: null,\n      max_height: null,\n      min_width: null,\n      min_height: null,\n      align: \"center\",\n      // left, center, right\n\n      // border\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_width: null,\n      border_left_style: null,\n      border_left_color: null,\n      border_radius: 0,\n      // box shadow\n      box_shadow: null\n    });\n    _this.effect = {\n      grayscale: null,\n      sepia: null,\n      invert: null,\n      blur: null,\n      brightness: null,\n      contrast: null,\n      saturate: null,\n      hueRotate: null,\n      opacity: null\n    };\n\n    // CSS-based crop / focus / zoom (no actual image bytes are altered)\n    // ratioX:ratioY define the aspect ratio of the crop frame as INTEGERS.\n    // Frame width is responsive (100% of parent); height auto via CSS aspect-ratio.\n    // Email best practice — pixel-locked crop sizes break on mobile.\n    _this.crop = {\n      enabled: false,\n      ratioX: 3,\n      // aspect ratio numerator (positive integer)\n      ratioY: 2,\n      // aspect ratio denominator (positive integer)\n      zoom: 1,\n      // 1 .. 3\n      posX: 50,\n      // 0..100 (object-position X%)\n      posY: 50 // 0..100 (object-position Y%)\n    };\n\n    // Per-element listener name counter — multiple instances of the\n    // same Control class can subscribe to element state without\n    // overwriting each other (BaseElement._syncListeners is a Map).\n    _this._listenerSeq = 0;\n\n    // Aspect-lock state for width/height coupling in Resize popover +\n    // Inline overlay. In-memory only (NOT serialized) so opening /\n    // closing the popover preserves the user's choice within the\n    // session while the saved template stays free of UI-preference\n    // fields. Defaults to true (matches corner-handle default +\n    // Figma/Canva \"lock engaged by default\" convention). Surfaces\n    // that opt in via `buildDimensionControl(..., { coupleAspect })`\n    // honor this flag; corners and edges do NOT (they have fixed\n    // semantics — corners aspect-locked, edges single-axis — per\n    // docs/core/OVERLAY.md §7.2). Mutation notifies sync listeners so any\n    // concurrent surface re-renders its toggle state.\n    _this._aspectLocked = true;\n    return _this;\n  }\n\n  /** Mutate the aspect-lock flag + notify listeners so any mounted\n   *  resize overlay re-reads and updates its toggle chrome.\n   *\n   *  On OFF→ON transition, flipping the toggle doubles as \"undo any\n   *  prior distortion\" — if the user has dragged an edge (or typed\n   *  mismatched width/height in the popover with lock off), the image\n   *  is sitting at a manual aspect. Flipping lock ON is the natural\n   *  cue to restore the image's intrinsic aspect, so we hand the\n   *  second axis back to the browser by setting `height: auto`\n   *  (preserving width — responsive convention, matches the native\n   *  `<img>` aspect fallback). Skipped when either axis is already\n   *  `auto` / unset (intrinsic aspect already in play — forcing\n   *  `height: auto` would be a no-op). */\n  _inherits(ImageElement, _BaseElement);\n  return _createClass(ImageElement, [{\n    key: \"setAspectLocked\",\n    value: function setAspectLocked(v) {\n      var next = !!v;\n      if (this._aspectLocked === next) return;\n      this._aspectLocked = next;\n      if (next) this._restoreIntrinsicAspectIfDistorted();\n      this.notifySyncListeners();\n    }\n\n    /** Restore intrinsic aspect by demoting `height` to `auto`, so the\n     *  browser re-derives height from width using the image's natural\n     *  ratio. Called ONLY on OFF→ON transition; the popover input\n     *  coupling path is separate (`_writeCoupledDimensions`) and handles\n     *  the \"edit a number after lock is on\" scenario. */\n  }, {\n    key: \"_restoreIntrinsicAspectIfDistorted\",\n    value: function _restoreIntrinsicAspectIfDistorted() {\n      var w = this.formatter.getFormat('width');\n      var h = this.formatter.getFormat('height');\n      var widthIntrinsic = this._isAutoOrEmpty(w);\n      var heightIntrinsic = this._isAutoOrEmpty(h);\n      if (widthIntrinsic || heightIntrinsic) return;\n      this.formatter.setFormat('height', 'auto');\n      this.render();\n    }\n  }, {\n    key: \"_isAutoOrEmpty\",\n    value: function _isAutoOrEmpty(v) {\n      if (v == null) return true;\n      var s = String(v).trim().toLowerCase();\n      return s === '' || s === 'auto';\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return \"Image\";\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c); ImageElement has no `text` field\n      this.domNode.innerHTML = this.renderTemplate({\n        src: this.transferMediaAbsUrl(this.src),\n        alt: this.alt,\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        effect: this.effect,\n        crop: this.crop\n      });\n\n      // Themes only render <a href + target>. Any rel/title/download\n      // stored on the element is patched in-place after render so\n      // existing themes light up the new semantics without edits.\n      this._applyExtendedLinkAttrs();\n\n      // W0.2a: notifySyncListeners() now auto-fires from BaseElement.render()\n      // lifecycle. Phase 1.8 (SA I13) sync listeners (e.g. ImageCropControl)\n      // still fire on every render — re-entrancy guard intact.\n    }\n\n    /**\n     * Patch rel/title/download on the existing <a> wrapper. Called at end of\n     * render() (themes only wire href+target); and as a fast path from\n     * applyLinkAttrs() when no structure change is needed. No-op when the\n     * theme didn't wrap the image in <a> (url was empty at render time).\n     */\n  }, {\n    key: \"_applyExtendedLinkAttrs\",\n    value: function _applyExtendedLinkAttrs() {\n      if (!this.domNode) return;\n      var a = this.domNode.querySelector('a');\n      if (!a) return;\n      if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n      if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n      if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n    }\n\n    /**\n     * Link-attrs hot path — parity with ButtonElement.applyLinkAttrs.\n     * Structure-preserving href/target/rel/title/download patch when the\n     * <a> already exists (or already doesn't); falls back to a full render\n     * when the url toggles between empty and set (because the theme\n     * conditionally wraps <img> in <a> based on url — structure change).\n     *\n     * Fires `notifySyncListeners()` at the end so both live Link controls\n     * (sidebar + popover) re-read element state.\n     */\n  }, {\n    key: \"applyLinkAttrs\",\n    value: function applyLinkAttrs() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var a = this.domNode.querySelector('a');\n      var hasAnchor = !!a;\n      var wantsAnchor = !!(this.url && this.url !== '#');\n      if (hasAnchor !== wantsAnchor) {\n        // Structure change — template toggles <a> on url presence.\n        this.render();\n        return;\n      }\n      if (!hasAnchor) {\n        // No <a> and no url: nothing to patch; still notify so controls\n        // can reconcile other shared state.\n        this.notifySyncListeners();\n        return;\n      }\n      a.setAttribute('href', this.url || '#');\n      if (this.target) a.setAttribute('target', this.target);else a.removeAttribute('target');\n      if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n      if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n      if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n      this.notifySyncListeners();\n    }\n\n    // Resolve the node that overlay chrome (selected-outline rainbow,\n    // 4 corner handles, 4 edge bars) should hug.\n    //\n    // Non-crop:  the <img> itself — its rect is the visible image.\n    // Crop on:   the wrapper div marked `data-bjs-crop-frame` — overflow:\n    //            hidden + aspect-ratio define the visible frame. The\n    //            inner <img> is scaled via transform (zoom) and its own\n    //            rect is the un-cropped content, NOT what the user sees;\n    //            hugging it makes handles float outside the crop box.\n    //\n    // Stable template contract (`data-bjs-crop-frame`) — no DOM-tree-\n    // walking from the <img>, survives template edits that reorder\n    // wrappers. Falls back to <img> if the marker is absent (older\n    // theme bundles) so behavior degrades gracefully.\n  }, {\n    key: \"_getHighlightTarget\",\n    value: function _getHighlightTarget() {\n      if (!this.domNode) return null;\n      if (this.crop && this.crop.enabled) {\n        var frame = this.domNode.querySelector('[data-bjs-crop-frame]');\n        if (frame) return frame;\n      }\n      var img = this.domNode.querySelector('img');\n      if (img) return img;\n      var divs = this.domNode.querySelectorAll('div');\n      if (divs && divs.length) return divs[divs.length - 1];\n      return this.domNode;\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(ImageElement, \"getData\", this, 3)([])), {}, {\n        src: this.src,\n        alt: this.alt,\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        effect: this.effect,\n        crop: this.crop\n      });\n    }\n  }, {\n    key: \"isAutoFormat\",\n    value: function isAutoFormat(key) {\n      return this.formatter.getFormat(key) === \"auto\";\n    }\n  }, {\n    key: \"setFormat\",\n    value: function setFormat(key, value) {\n      this.formatter.setFormat(key, value);\n      // Use render() (not update()) so notifySyncListeners fires —\n      // multi-surface DimensionControl instances depend on this to\n      // re-sync after the sidebar / popup / popover mutates a format\n      // (SA I13 R2). update() only rewrites innerHTML and skips the\n      // listener fire, leaving other surfaces with stale state.\n      this.render();\n    }\n\n    /**\n     * Build a DimensionControl bound to a formatter key — observer-aware\n     * factory. Multiple instances on the same key (sidebar + popup overlay\n     * + future anchored popover) all subscribe to element state via the\n     * `subscribe` capability token (SA I13 R3) and stay in sync via\n     * `syncFromExternal()`. The popup must call `instance.destroy()` in\n     * its teardown so the disposer fires and the listener Set stays\n     * bounded across open/close cycles.\n     *\n     * @param {string}   label   Already-translated label\n     * @param {string}   key     Formatter key ('width', 'max_width', ...)\n     * @param {string[]} units   Units to offer (defaults to full set for width/height,\n     *                           limited to px/% for min/max bounds)\n     */\n  }, {\n    key: \"buildDimensionControl\",\n    value: function buildDimensionControl(label, key, units) {\n      var _this2 = this;\n      var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n      // Unique listener name per instance — multiple instances of the\n      // SAME control (sidebar + popup + popover) coexist; sharing a\n      // name would let the LAST registration overwrite the others\n      // (BaseElement.addSyncListener uses a Map keyed by name).\n      var listenerId = \"DimensionControl:\".concat(key, \":\").concat(++this._listenerSeq);\n      // `coupleAspect: true` opts this control into width↔height\n      // coupling driven by `this._aspectLocked`. Resize popover + inline\n      // overlay pass it; sidebar controls do NOT (sidebar stays\n      // independent so existing single-field edits don't silently\n      // mutate the companion axis — matches pre-fix behavior).\n      var coupleAspect = !!options.coupleAspect;\n      return new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](label, {\n        initial: this.formatter.getFormat(key),\n        subscribe: function subscribe(fn) {\n          return _this2.addSyncListener(listenerId, fn);\n        },\n        readState: function readState() {\n          return _this2.formatter.getFormat(key);\n        }\n      }, {\n        units: units,\n        onChange: function onChange(serialized) {\n          if (coupleAspect && _this2._aspectLocked && (key === 'width' || key === 'height') && !_this2._inCoupleWrite) {\n            _this2._inCoupleWrite = true;\n            try {\n              _this2._writeCoupledDimensions(key, serialized);\n            } finally {\n              _this2._inCoupleWrite = false;\n            }\n            return;\n          }\n          // Mutate format + render — fires notifySyncListeners\n          // automatically (SA I13 R2). All other instances of\n          // this DimensionControl re-sync via their disposer.\n          _this2.setFormat(key, serialized);\n        }\n      });\n    }\n\n    /** Aspect ratio used for width↔height coupling. Priority:\n     *    1. Crop ratio (user-chosen explicit aspect) when crop.enabled\n     *    2. Natural image dims (stable, no drift from repeated edits)\n     *    3. Rendered bounding rect (fallback if image not loaded)\n     *    4. 1:1 safe default\n     *  Kept public-ish (underscore prefix) so corner/edge overlays or\n     *  future surfaces can reuse the same source of truth. */\n  }, {\n    key: \"_getAspectRatio\",\n    value: function _getAspectRatio() {\n      if (this.crop && this.crop.enabled) {\n        var rx = this.crop.ratioX || 0;\n        var ry = this.crop.ratioY || 0;\n        if (rx > 0 && ry > 0) return rx / ry;\n      }\n      var img = this.domNode && this.domNode.querySelector('img');\n      if (img && img.naturalWidth > 0 && img.naturalHeight > 0) {\n        return img.naturalWidth / img.naturalHeight;\n      }\n      var target = typeof this._getHighlightTarget === 'function' ? this._getHighlightTarget() : null;\n      if (target) {\n        var r = target.getBoundingClientRect();\n        if (r.height > 0) return r.width / r.height;\n      }\n      return 1;\n    }\n\n    /** Atomic write of width + height when aspect-lock coupling is\n     *  active. `editedKey` is the axis the user just edited; `serialized`\n     *  is its new DimensionControl-formatted string. The companion axis\n     *  is computed via `_getAspectRatio()` and written in `px` (matches\n     *  the established ImageResizeCornerOverlay convention), EXCEPT when\n     *  the companion was previously `auto` — leave it `auto` so the\n     *  browser's intrinsic aspect preservation keeps working (no reason\n     *  to force a concrete number if the markup was already responsive).\n     *\n     *  Both formats are set on the formatter directly, then a single\n     *  render() fires so only ONE notifySyncListeners pass runs —\n     *  prevents double paint + avoids re-entrancy surprises. */\n  }, {\n    key: \"_writeCoupledDimensions\",\n    value: function _writeCoupledDimensions(editedKey, serialized) {\n      var companionKey = editedKey === 'width' ? 'height' : 'width';\n      var ratio = this._getAspectRatio();\n      var companionCurrent = this.formatter.getFormat(companionKey);\n      var companionIsAuto = typeof companionCurrent === 'string' && companionCurrent.trim().toLowerCase() === 'auto';\n      this.formatter.setFormat(editedKey, serialized);\n      if (!companionIsAuto && ratio > 0) {\n        var editedPx = this._resolveDimensionPx(editedKey, serialized);\n        if (editedPx > 0 && Number.isFinite(editedPx)) {\n          var companionPx = editedKey === 'width' ? editedPx / ratio : editedPx * ratio;\n          var clamped = Math.max(16, Math.round(companionPx));\n          this.formatter.setFormat(companionKey, clamped + 'px');\n        }\n      }\n\n      // Single render → single notifySyncListeners → every embedded\n      // DimensionControl on this element re-reads the new formats.\n      this.render();\n    }\n\n    /** Resolve a DimensionControl-serialized value (e.g. \"300px\", \"50%\",\n     *  \"1.5em\", \"auto\") into an absolute pixel number for the given axis.\n     *  Used by aspect-lock coupling math. Returns 0 for unresolvable\n     *  inputs — callers should guard. */\n  }, {\n    key: \"_resolveDimensionPx\",\n    value: function _resolveDimensionPx(key, serialized) {\n      if (serialized == null) return 0;\n      var str = String(serialized).trim().toLowerCase();\n      if (str === '' || str === 'auto') return 0;\n      var num = parseFloat(str);\n      if (!Number.isFinite(num)) return 0;\n      if (/px$/.test(str)) return num;\n      if (/%$/.test(str)) {\n        var parent = this.domNode && this.domNode.parentElement;\n        if (!parent) return 0;\n        var rect = parent.getBoundingClientRect();\n        var base = key === 'width' ? rect.width : rect.height;\n        return num / 100 * base;\n      }\n      if (/(em|rem)$/.test(str)) {\n        var ref = this.domNode || document.body;\n        var fs = parseFloat(getComputedStyle(ref).fontSize) || 16;\n        return num * fs;\n      }\n      if (/vw$/.test(str)) return num / 100 * (window.innerWidth || 0);\n      if (/vh$/.test(str)) return num / 100 * (window.innerHeight || 0);\n      // Unknown unit — assume number alone means px (legacy data)\n      return num;\n    }\n\n    /** Shared renderer for the \"Lock aspect ratio\" toggle row used by\n     *  ImageResizePopoverOverlay + ImageResizeInlineOverlay. Single source\n     *  of truth for DOM structure, aria attributes, and the element-state\n     *  sync contract:\n     *    - toggle reflects `this._aspectLocked` on every mount\n     *    - click flips `this._aspectLocked` via `setAspectLocked()` which\n     *      fires notifySyncListeners → any concurrent surface re-syncs\n     *    - the overlay subscribes so external mutations re-paint the\n     *      toggle chrome (e.g. sidebar adds a sibling toggle one day)\n     *  Returns `{ row, dispose }`. Callers MUST invoke `dispose()` in\n     *  beforeDestroy to keep the sync-listener Map bounded (SA I14).\n     */\n  }, {\n    key: \"buildAspectLockRow\",\n    value: function buildAspectLockRow() {\n      var _this3 = this;\n      var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      var label = opts.label || 'Lock aspect ratio';\n      var hint = opts.hint || '';\n      var row = document.createElement('div');\n      row.className = 'bjs-ovl-image-resize-aspect-row';\n      var labelWrap = document.createElement('div');\n      labelWrap.className = 'bjs-ovl-image-crop-toggle-label';\n      var labelEl = document.createElement('span');\n      labelEl.className = 'bjs-ovl-image-crop-toggle-text';\n      labelEl.textContent = label;\n      labelWrap.appendChild(labelEl);\n      if (hint) {\n        var hintEl = document.createElement('span');\n        hintEl.className = 'bjs-ovl-image-crop-toggle-hint';\n        hintEl.textContent = hint;\n        labelWrap.appendChild(hintEl);\n      }\n      var toggle = document.createElement('button');\n      toggle.type = 'button';\n      toggle.className = 'bjs-ovl-image-crop-toggle';\n      toggle.setAttribute('role', 'switch');\n      toggle.setAttribute('aria-label', label);\n      var paint = function paint() {\n        var on = !!_this3._aspectLocked;\n        toggle.setAttribute('aria-checked', on ? 'true' : 'false');\n        toggle.classList.toggle('is-on', on);\n      };\n      toggle.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this3.setAspectLocked(!_this3._aspectLocked);\n        // setAspectLocked fires notifySyncListeners → paint() runs\n        // via the disposer below; but also paint synchronously for\n        // immediate UI feedback regardless of subscribe wiring.\n        paint();\n      });\n      row.appendChild(labelWrap);\n      row.appendChild(toggle);\n      paint();\n      var listenerId = \"AspectLockRow:\".concat(++this._listenerSeq);\n      var dispose = this.addSyncListener(listenerId, paint);\n      return {\n        row: row,\n        dispose: dispose\n      };\n    }\n\n    /** Build an ImageEffectControl — filter sliders (grayscale, sepia,\n     *  blur, brightness, contrast, saturate, hue-rotate, opacity) +\n     *  preview. Observer-aware factory; multiple instances coexist.\n     *  Used by the sidebar AND by ImageEffectPopoverOverlay so the on-\n     *  canvas Effects popover renders the SAME UI as the sidebar (no\n     *  duplicate slider math). */\n  }, {\n    key: \"buildEffectControl\",\n    value: function buildEffectControl(label) {\n      var _this4 = this;\n      var listenerId = \"ImageEffectControl:\".concat(++this._listenerSeq);\n      return new _ImageEffectControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](label || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.effects'), {\n        src: this.transferMediaAbsUrl(this.src),\n        current_effects: {\n          grayscale: this.effect.grayscale || 0,\n          sepia: this.effect.sepia || 0,\n          invert: this.effect.invert || 0,\n          blur: this.effect.blur || 0,\n          brightness: this.effect.brightness || 100,\n          contrast: this.effect.contrast || 100,\n          saturate: this.effect.saturate || 100,\n          hueRotate: this.effect.hueRotate || 0,\n          opacity: this.effect.opacity || 100\n        },\n        subscribe: function subscribe(fn) {\n          return _this4.addSyncListener(listenerId, fn);\n        },\n        readState: function readState() {\n          return {\n            grayscale: _this4.effect.grayscale || 0,\n            sepia: _this4.effect.sepia || 0,\n            invert: _this4.effect.invert || 0,\n            blur: _this4.effect.blur || 0,\n            brightness: _this4.effect.brightness || 100,\n            contrast: _this4.effect.contrast || 100,\n            saturate: _this4.effect.saturate || 100,\n            hueRotate: _this4.effect.hueRotate || 0,\n            opacity: _this4.effect.opacity || 100\n          };\n        }\n      }, {\n        setEffects: function setEffects(effects) {\n          // Mutate IN PLACE so any holder of `this.effect`\n          // reference (sidebar + popover instances) keeps its\n          // ref intact (SA I13 R1).\n          Object.assign(_this4.effect, {\n            grayscale: effects.grayscale || 0,\n            sepia: effects.sepia || 0,\n            invert: effects.invert || 0,\n            blur: effects.blur || 0,\n            brightness: effects.brightness || 100,\n            contrast: effects.contrast || 100,\n            saturate: effects.saturate || 100,\n            hueRotate: effects.hueRotate || 0,\n            opacity: effects.opacity || 100\n          });\n          _this4.render();\n        }\n      });\n    }\n\n    /** Build an ImageCropControl — the rich crop editor (preview + focus\n     *  dot + aspect chips + custom ratio + zoom + focus X/Y + reset).\n     *  Same observer-aware factory pattern as buildDimensionControl —\n     *  multiple instances stay in sync via the `subscribe` capability. */\n  }, {\n    key: \"buildCropControl\",\n    value: function buildCropControl(label) {\n      var _this5 = this;\n      // Unique listener name per instance — see buildDimensionControl.\n      var listenerId = \"ImageCropControl:\".concat(++this._listenerSeq);\n      return new _ImageCropControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](label || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.title'), {\n        src: this.transferMediaAbsUrl(this.src),\n        crop: this.crop,\n        subscribe: function subscribe(fn) {\n          return _this5.addSyncListener(listenerId, fn);\n        }\n      }, {\n        setCrop: function setCrop(cropData) {\n          var rx = parseInt(cropData.ratioX, 10);\n          var ry = parseInt(cropData.ratioY, 10);\n          if (!_this5.crop) _this5.crop = {};\n          Object.assign(_this5.crop, {\n            enabled: !!cropData.enabled,\n            ratioX: rx >= 1 ? rx : 3,\n            ratioY: ry >= 1 ? ry : 2,\n            zoom: typeof cropData.zoom === 'number' ? cropData.zoom : 1,\n            posX: typeof cropData.posX === 'number' ? cropData.posX : 50,\n            posY: typeof cropData.posY === 'number' ? cropData.posY : 50\n          });\n          _this5.render();\n        }\n      });\n    }\n  }, {\n    key: \"update\",\n    value: function update() {\n      if (this.domNode) {\n        this.domNode.innerHTML = this.renderTemplate({\n          src: this.transferMediaAbsUrl(this.src),\n          alt: this.alt,\n          url: this.url,\n          target: this.target,\n          effect: this.effect,\n          crop: this.crop\n        });\n      }\n    }\n\n    /**\n     * Canvas overlays — Image (Phase 1.4 + 2026-04-19 expand):\n     *   - ImageActionsOverlay     (select) — Upload / Replace / Resize / Crop / Link pill row\n     *   - ImageCropInlineOverlay  (edit)   — crop enable toggle + chip grid + Done/Cancel\n     *   - ImageResizeInlineOverlay (edit)  — width / height / aspect-lock + advanced max/min\n     *   - ImageResizeCornerOverlay × 4 (select) — NW/NE/SE/SW aspect-locked diagonal resize\n     *   - ImageEdgeResizerOverlay × 4 (select) — top/right/bottom/left single-axis resize\n     *\n     * Trigger mix:\n     *   - 'select' — Actions + 4 corners + 4 edges all mount on selection.\n     *   - 'edit' (named 'crop' / 'resize') — the two inline popups mount when\n     *     the Actions overlay dispatches enterEditMode('crop' / 'resize').\n     *     They are mutually exclusive (enterEditMode replaces the active mode).\n     *\n     * See docs/core/OVERLAY.md §7.2.\n     */\n  }, {\n    key: \"getOverlays\",\n    value: function getOverlays() {\n      var _this6 = this;\n      // Anchor function for the popover variants — reads the rect the\n      // ImageActionsOverlay stashed when the user clicked Crop/Resize\n      // (`element._lastActionAnchorRect`). Always returns a rect; the\n      // popover falls back to a viewport-centered position if rect is\n      // missing.\n      var anchorTo = function anchorTo() {\n        return _this6._lastActionAnchorRect || null;\n      };\n      return [new _overlays_ImageActionsOverlay_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](this),\n      // Edit-mode popups + popovers — both surfaces registered;\n      // ImageActionsOverlay's SURFACE_MODE map decides which one\n      // mounts on action click. Mode filter (BaseElement.mountOverlays\n      // edit-mode filter, SA I13) ensures only the matching one mounts.\n      new _overlays_ImageCropInlineOverlay_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"](this), new _overlays_ImageCropPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_15__[\"default\"](this, {\n        anchorTo: anchorTo,\n        side: 'right',\n        width: 360\n      }), new _overlays_ImageResizeInlineOverlay_js__WEBPACK_IMPORTED_MODULE_18__[\"default\"](this), new _overlays_ImageResizePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_19__[\"default\"](this, {\n        anchorTo: anchorTo,\n        side: 'right',\n        width: 320\n      }), new _overlays_ImageEffectPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_20__[\"default\"](this, {\n        anchorTo: anchorTo,\n        side: 'right',\n        width: 360,\n        maxHeight: 540\n      }),\n      // Link popover (trigger 'edit', mode 'link-popover') — replaces\n      // the legacy BuilderjsPopup.prompt() flow. Anchors next to the\n      // action-bar Link pill (shares _lastActionAnchorRect with\n      // crop/resize/effects). Generic primitive — any element with a\n      // `.url` field can mount the same overlay.\n      new _overlays_LinkPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_21__[\"default\"](this, {\n        anchorTo: anchorTo,\n        side: 'right',\n        width: 380\n      }),\n      // Canvas resize handles — always mounted on select.\n      new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n        corner: 'nw'\n      }), new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n        corner: 'ne'\n      }), new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n        corner: 'se'\n      }), new _overlays_ImageResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_16__[\"default\"](this, {\n        corner: 'sw'\n      }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n        edge: 'top'\n      }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n        edge: 'right'\n      }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n        edge: 'bottom'\n      }), new _overlays_ImageEdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_17__[\"default\"](this, {\n        edge: 'left'\n      })];\n    }\n\n    /**\n     * LinkConfigControl factory — full-feature link editor (Type / URL /\n     * Target / Title / Advanced rel + download). Same class used by\n     * ButtonElement, so both canvas elements share the exact same link\n     * UX on sidebar AND popover.\n     *\n     * Called by getControls() (sidebar) and LinkPopoverOverlay._embedded\n     * (canvas popover). Each call returns a FRESH control wired to this\n     * element via subscribe/readState (SA I13). Edits mutate all 5 link\n     * fields + call `applyLinkAttrs()`, which fires `notifySyncListeners()`\n     * — the OTHER live instance re-reads and patches itself in place.\n     */\n  }, {\n    key: \"buildLinkControl\",\n    value: function buildLinkControl() {\n      var _this7 = this;\n      return new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link'), {\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download\n      }, {\n        setLink: function setLink(_ref) {\n          var url = _ref.url,\n            target = _ref.target,\n            rel = _ref.rel,\n            title = _ref.title,\n            download = _ref.download;\n          _this7.url = url || '';\n          _this7.target = target || '';\n          _this7.rel = rel || '';\n          _this7.title = title || '';\n          _this7.download = download || '';\n          _this7.applyLinkAttrs();\n        }\n      }, {\n        subscribe: function subscribe(fn) {\n          return _this7.addSyncListener('LinkConfigControl:' + Math.random().toString(36).slice(2, 7), fn);\n        },\n        readState: function readState() {\n          return {\n            url: _this7.url,\n            target: _this7.target,\n            rel: _this7.rel,\n            title: _this7.title,\n            download: _this7.download\n          };\n        }\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this8 = this;\n      return [new _ImageControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.url'), {\n        src: this.transferMediaAbsUrl(this.src),\n        alt: this.alt,\n        // Phase 1.8 (SA I13) — narrow capability tokens.\n        // `subscribe` — register for state-change notifications.\n        // `readState` — read fresh primitives (src/alt are not\n        // refs, so a getter is required; object state like crop\n        // is read via value.crop directly since it's a live ref).\n        subscribe: function subscribe(fn) {\n          return _this8.addSyncListener('ImageControl', fn);\n        },\n        readState: function readState() {\n          return {\n            src: _this8.transferMediaAbsUrl(_this8.src),\n            alt: _this8.alt\n          };\n        }\n      }, {\n        setImage: function setImage(newSrc) {\n          _this8.src = newSrc;\n          _this8.render();\n        },\n        setAlt: function setAlt(alt) {\n          _this8.alt = alt;\n          _this8.render();\n        }\n      }),\n      // Link — dual-view (sidebar + popover) sync via subscribe/readState.\n      // See buildLinkControl() for the factory.\n      this.buildLinkControl(), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat(\"align\", \"\"), {\n        setValue: function setValue(value) {\n          _this8.setFormat(\"align\", value);\n        }\n      }),\n      // Collapsible IMAGE SIZE group (BORDERS-style header). One shared\n      // info banner inside, then six DimensionControls in a single row\n      // each. Removing the legacy dark SectionLabelControl.\n      new _SectionGroupControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"]({\n        title: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.image_size'),\n        description: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.image_size_desc'),\n        children: [new _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dimension.banner')), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), 'width', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), 'height', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.max_width'), 'max_width', ['px', '%', 'em', 'rem', 'vw']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.max_height'), 'max_height', ['px', '%', 'em', 'rem', 'vh']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.min_width'), 'min_width', ['px', '%', 'em', 'rem', 'vw']), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.min_height'), 'min_height', ['px', '%', 'em', 'rem', 'vh'])]\n      }),\n      // Effects control — Phase 1.8 (SA I13) factory. Sidebar instance.\n      // Multi-surface: ImageEffectPopoverOverlay instantiates the same\n      // factory and embeds the resulting domNode; both subscribe and\n      // stay in sync via syncFromExternal.\n      this.buildEffectControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image.effects')),\n      // Crop control — Phase 1.8 (SA I13) factory. Sidebar instance.\n      // Multi-surface: popup overlay instantiates the SAME factory\n      // and embeds the resulting domNode; both instances subscribe\n      // to element state and stay in sync via syncFromExternal.\n      this.buildCropControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('image_crop.title')), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.settings'), {\n        border_top_style: this.formatter.getFormat(\"border_top_style\", \"\"),\n        border_top_width: this.formatter.getFormat(\"border_top_width\", \"\"),\n        border_top_color: this.formatter.getFormat(\"border_top_color\", \"\"),\n        border_bottom_style: this.formatter.getFormat(\"border_bottom_style\", \"\"),\n        border_bottom_width: this.formatter.getFormat(\"border_bottom_width\", \"\"),\n        border_bottom_color: this.formatter.getFormat(\"border_bottom_color\", \"\"),\n        border_left_style: this.formatter.getFormat(\"border_left_style\", \"\"),\n        border_left_width: this.formatter.getFormat(\"border_left_width\", \"\"),\n        border_left_color: this.formatter.getFormat(\"border_left_color\", \"\"),\n        border_right_style: this.formatter.getFormat(\"border_right_style\", \"\"),\n        border_right_width: this.formatter.getFormat(\"border_right_width\", \"\"),\n        border_right_color: this.formatter.getFormat(\"border_right_color\", \"\")\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this8.setFormat(\"border_top_style\", border_top_style);\n          _this8.setFormat(\"border_top_width\", border_top_width);\n          _this8.setFormat(\"border_top_color\", border_top_color);\n          _this8.setFormat(\"border_bottom_style\", border_bottom_style);\n          _this8.setFormat(\"border_bottom_width\", border_bottom_width);\n          _this8.setFormat(\"border_bottom_color\", border_bottom_color);\n          _this8.setFormat(\"border_left_style\", border_left_style);\n          _this8.setFormat(\"border_left_width\", border_left_width);\n          _this8.setFormat(\"border_left_color\", border_left_color);\n          _this8.setFormat(\"border_right_style\", border_right_style);\n          _this8.setFormat(\"border_right_width\", border_right_width);\n          _this8.setFormat(\"border_right_color\", border_right_color);\n\n          // re-render\n          _this8.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('border.radius'), this.formatter.getFormat(\"border_radius\", 0), {\n        setRadius: function setRadius(v) {\n          _this8.setFormat(\"border_radius\", v);\n          _this8.render();\n        }\n      })];\n    }\n    /* SELECTED EFFECTS */\n  }, {\n    key: \"addSelectedHighlight\",\n    value: function addSelectedHighlight() {\n      var _this9 = this;\n      // render selected outbound\n      if (!this.selectedBox) {\n        this.selectedBox = document.createElement(\"div\");\n        this.selectedBox.classList.add(\"selected-box\");\n\n        // Append it to the body\n        document.body.appendChild(this.selectedBox);\n\n        //\n        this.matchingDomNode(this.selectedBox, 5);\n      }\n\n      // Render actions\n      if (!this.actionsBox) {\n        this.actionsBox = document.createElement(\"div\");\n        this.actionsBox.classList.add(\"actions-box\");\n        this.actionsBox.classList.add(\"d-flex\");\n        this.actionsBox.classList.add(\"align-items-center\");\n        // Opt out of canvas-clip — toolbar pill must escape canvas\n        // top edge. See BaseElement.addSelectedHighlight + OVERLAY.md §24.\n        this.actionsBox.classList.add(\"bjs-ovl-no-clip\");\n        // Append it to the body\n        document.body.appendChild(this.actionsBox);\n        //\n        this.matchingDomNode(this.actionsBox, 5, function () {\n          if (!_this9.actionsBox) {\n            return;\n          }\n\n          // PLAN_EFFECT W1.2 (final) — single unified pill.\n          // See BaseElement.js for the full rationale.\n          var domRect = _this9.domNode.getBoundingClientRect();\n          var iframe = _this9.domNode.ownerDocument.defaultView.frameElement;\n          var iframeRect = iframe.getBoundingClientRect();\n          var absoluteTop = iframeRect.top + domRect.top;\n          var absoluteLeft = iframeRect.left + domRect.left;\n          var toolbar = {\n            width: 240,\n            height: 36\n          };\n          var gap = 14;\n\n          // -1 px inset — aligns pill left with the selected-box\n          // outline's visible left edge (outline-offset: -1 px).\n          var pos = _this9.host.toolbarPositioner.compute({\n            elementRect: {\n              top: absoluteTop,\n              left: absoluteLeft - 1,\n              width: domRect.width,\n              height: domRect.height\n            },\n            toolbar: toolbar,\n            viewport: {\n              width: window.innerWidth,\n              height: window.innerHeight\n            },\n            gap: gap,\n            preferredSide: 'above'\n          });\n          _this9.actionsBox.dataset.side = pos.side;\n          _this9.actionsBox.dataset.didFlip = String(pos.didFlip);\n          _this9.actionsBox.dataset.didClamp = String(pos.didClamp);\n          Object.assign(_this9.actionsBox.style, {\n            position: \"fixed\",\n            top: \"\".concat(pos.top, \"px\"),\n            left: \"\".concat(pos.left, \"px\")\n          });\n        });\n\n        // Label\n        this.actionsBoxLabel = document.createElement(\"h5\");\n        this.actionsBoxLabel.classList.add(\"ms-2\");\n        this.actionsBoxLabel.classList.add(\"m-0\");\n        this.actionsBoxLabel.classList.add(\"text-light\");\n        this.actionsBoxLabel.innerHTML = '<span class=\"d-flex align-items-center\"><span class=\"material-symbols-rounded me-2\">apps</span>' + this.getName() + \"</span>\";\n        this.actionsBox.appendChild(this.actionsBoxLabel);\n        this.actionsBoxInner = document.createElement(\"div\");\n        this.actionsBoxInner.classList.add(\"actions-box-inner\");\n        this.actionsBoxInner.classList.add(\"btn-group\");\n        this.actionsBoxInner.classList.add(\"border\");\n        this.actionsBoxInner.classList.add(\"ms-auto\");\n        this.actionsBoxInner.classList.add(\"me-2\");\n        this.actionsBoxInner = document.createElement(\"div\");\n        this.actionsBoxInner.classList.add(\"actions-box-inner\");\n        this.actionsBoxInner.classList.add(\"btn-group\");\n        // this.actionsBoxInner.classList.add('border');\n        this.actionsBoxInner.classList.add(\"ms-auto\");\n        // Append it to the body\n        this.actionsBox.appendChild(this.actionsBoxInner);\n        this.getActions().forEach(function (action) {\n          var actionButton = document.createElement(\"button\");\n          actionButton.setAttribute(\"class\", \"element-action-item btn btn-light p-1 d-flex align-items-center\");\n          actionButton.setAttribute(\"data-tooltip\", action.label);\n          actionButton.setAttribute(\"aria-label\", action.label);\n          actionButton.innerHTML = \"\\n                    <span class=\\\"material-symbols-rounded fs-5\\\">\" + action.icon + \"</span>\\n                \";\n          _this9.actionsBoxInner.appendChild(actionButton);\n\n          // events\n          actionButton.addEventListener(\"click\", function () {\n            action.run();\n          });\n        });\n\n        // PLAN_EFFECT W1.4 — focus-dim toggle (shared BaseElement helper).\n        this._appendFocusDimToggle(this.actionsBoxInner);\n      }\n\n      // Add rainbow highlight around the first <img> (or fallback target)\n      if (!this.imageHighlightBox) {\n        this.imageHighlightBox = document.createElement('div');\n        this.imageHighlightBox.classList.add('image-highlight-box');\n        document.body.appendChild(this.imageHighlightBox);\n        this.matchingDomNode(this.imageHighlightBox, 0, function () {\n          if (!_this9.imageHighlightBox) return;\n          var target = _this9._getHighlightTarget();\n          if (!target) return;\n          var domRect = target.getBoundingClientRect();\n          var iframe = target.ownerDocument.defaultView.frameElement;\n          var iframeRect = iframe.getBoundingClientRect();\n          var absoluteTop = iframeRect.top + domRect.top;\n          var absoluteLeft = iframeRect.left + domRect.left;\n          Object.assign(_this9.imageHighlightBox.style, {\n            position: 'fixed',\n            top: \"\".concat(absoluteTop, \"px\"),\n            left: \"\".concat(absoluteLeft, \"px\"),\n            width: \"\".concat(domRect.width, \"px\"),\n            height: \"\".concat(domRect.height, \"px\"),\n            borderRadius: getComputedStyle(target).borderRadius || '6px'\n          });\n        });\n\n        // Add mouseenter/mouseleave to target for hover effect\n        var highlightBox = this.imageHighlightBox;\n        var imgTarget = this._getHighlightTarget();\n        if (imgTarget) {\n          // Remove   ous listeners if any\n          if (imgTarget._rainbowHoverHandler) {\n            imgTarget.removeEventListener('mouseenter', imgTarget._rainbowHoverHandler.enter);\n            imgTarget.removeEventListener('mouseleave', imgTarget._rainbowHoverHandler.leave);\n          }\n          // Add new listeners\n          var enter = function enter() {\n            return highlightBox.classList.add('hover');\n          };\n          var leave = function leave() {\n            return highlightBox.classList.remove('hover');\n          };\n          imgTarget.addEventListener('mouseenter', enter);\n          imgTarget.addEventListener('mouseleave', leave);\n          imgTarget._rainbowHoverHandler = {\n            enter: enter,\n            leave: leave\n          };\n        }\n      }\n    }\n  }, {\n    key: \"removeSelectedHighlight\",\n    value: function removeSelectedHighlight() {\n      // remove selected outbound\n      if (this.selectedBox) {\n        this.selectedBox.remove();\n      }\n      this.selectedBox = null;\n\n      // remove selected actions\n      if (this.actionsBox) {\n        this.actionsBox.remove();\n      }\n      this.actionsBox = null;\n\n      // remove image highlight\n      if (this.imageHighlightBox) {\n        this.imageHighlightBox.remove();\n      }\n      this.imageHighlightBox = null;\n\n      // Remove hover listeners from image\n      var imgTarget = this._getHighlightTarget();\n      if (imgTarget && imgTarget._rainbowHoverHandler) {\n        imgTarget.removeEventListener('mouseenter', imgTarget._rainbowHoverHandler.enter);\n        imgTarget.removeEventListener('mouseleave', imgTarget._rainbowHoverHandler.leave);\n        imgTarget._rainbowHoverHandler = null;\n      }\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var _data$alt, _data$url, _data$target, _data$rel, _data$title, _data$download;\n      var e = new ImageElement(data.template, data.src, (_data$alt = data.alt) !== null && _data$alt !== void 0 ? _data$alt : \"\", (_data$url = data.url) !== null && _data$url !== void 0 ? _data$url : \"\", (_data$target = data.target) !== null && _data$target !== void 0 ? _data$target : \"\");\n      e.rel = (_data$rel = data.rel) !== null && _data$rel !== void 0 ? _data$rel : '';\n      e.title = (_data$title = data.title) !== null && _data$title !== void 0 ? _data$title : '';\n      e.download = (_data$download = data.download) !== null && _data$download !== void 0 ? _data$download : '';\n\n      // Handle formats (W0.2c — via BaseElement.parseFormats helper)\n      this.parseFormats(e, data);\n      if (data.effect) {\n        var _data$effect$grayscal, _data$effect$sepia, _data$effect$invert, _data$effect$blur, _data$effect$brightne, _data$effect$contrast, _data$effect$saturate, _data$effect$hueRotat, _data$effect$opacity;\n        e.effect = {\n          grayscale: (_data$effect$grayscal = data.effect.grayscale) !== null && _data$effect$grayscal !== void 0 ? _data$effect$grayscal : null,\n          sepia: (_data$effect$sepia = data.effect.sepia) !== null && _data$effect$sepia !== void 0 ? _data$effect$sepia : null,\n          invert: (_data$effect$invert = data.effect.invert) !== null && _data$effect$invert !== void 0 ? _data$effect$invert : null,\n          blur: (_data$effect$blur = data.effect.blur) !== null && _data$effect$blur !== void 0 ? _data$effect$blur : null,\n          brightness: (_data$effect$brightne = data.effect.brightness) !== null && _data$effect$brightne !== void 0 ? _data$effect$brightne : null,\n          contrast: (_data$effect$contrast = data.effect.contrast) !== null && _data$effect$contrast !== void 0 ? _data$effect$contrast : null,\n          saturate: (_data$effect$saturate = data.effect.saturate) !== null && _data$effect$saturate !== void 0 ? _data$effect$saturate : null,\n          hueRotate: (_data$effect$hueRotat = data.effect.hueRotate) !== null && _data$effect$hueRotat !== void 0 ? _data$effect$hueRotat : null,\n          opacity: (_data$effect$opacity = data.effect.opacity) !== null && _data$effect$opacity !== void 0 ? _data$effect$opacity : null\n        };\n      }\n      if (data.crop) {\n        // Migration: convert legacy `aspectRatio` string ('16:9', 'free', ...)\n        // into ratioX/ratioY integers. Old data in the wild predates the ratio model.\n        var rx = typeof data.crop.ratioX === 'number' ? data.crop.ratioX : null;\n        var ry = typeof data.crop.ratioY === 'number' ? data.crop.ratioY : null;\n        if ((rx === null || ry === null) && typeof data.crop.aspectRatio === 'string') {\n          var m = data.crop.aspectRatio.match(/^(\\d+):(\\d+)$/);\n          if (m) {\n            rx = parseInt(m[1], 10);\n            ry = parseInt(m[2], 10);\n          }\n        }\n        // Final defaults if still missing (e.g. legacy 'free' or empty)\n        if (!rx || rx < 1) rx = 3;\n        if (!ry || ry < 1) ry = 2;\n        e.crop = {\n          enabled: !!data.crop.enabled,\n          ratioX: rx,\n          ratioY: ry,\n          zoom: typeof data.crop.zoom === 'number' ? data.crop.zoom : 1,\n          posX: typeof data.crop.posX === 'number' ? data.crop.posX : 50,\n          posY: typeof data.crop.posY === 'number' ? data.crop.posY : 50\n        };\n      }\n      return e;\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageElement.js?");

/***/ }),

/***/ "./src/includes/ImageTextBottomWidget.js":
/*!***********************************************!*\
  !*** ./src/includes/ImageTextBottomWidget.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextBottomWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ImageTextBottomWidget() {\n    var _this;\n    _classCallCheck(this, ImageTextBottomWidget);\n    _this = _callSuper(this, ImageTextBottomWidget); // Call the parent class constructor\n\n    //\n    var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 270.23 84.36'%3E%3Crect width='270.23' height='84.36' fill='%23f6f6f4'/%3E%3Cpath d='M123.15,57.18c-.86,0-1.58-.29-2.16-.87s-.87-1.3-.87-2.16v-23.94c0-.86.29-1.58.87-2.16s1.3-.87,2.16-.87h12.19c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-12.19c-.34,0-.61.11-.83.32-.22.22-.32.49-.32.83v23.94c0,.34.11.61.32.83.22.22.49.32.83.32h23.94c.34,0,.61-.11.83-.32.22-.22.32-.49.32-.83v-12.19c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v12.19c0,.86-.29,1.58-.87,2.16s-1.3.87-2.16.87h-23.94ZM125.31,50.4h19.62l-6.06-8.08-5.62,7.1-3.75-4.51-4.18,5.48ZM144.49,32.81h-2.81c-.27,0-.49-.09-.67-.27s-.27-.4-.27-.67.09-.49.27-.67.4-.27.67-.27h2.81v-2.81c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v2.81h2.81c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-2.81v2.81c0,.27-.09.49-.27.67s-.4.27-.67.27-.49-.09-.67-.27-.27-.4-.27-.67v-2.81Z' fill='%23afafae'/%3E%3C/svg%3E\");\n    img.formatter.parseFormats({\n      \"width\": \"100%\",\n      \"padding_top\": 17\n    });\n    var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    h2.formatter.parseFormats({\n      \"padding_bottom\": 12\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n    var button = new ButtonElement('Button', 'Learn More');\n    button.formatter.parseFormats({\n      \"align\": \"left\",\n      \"font_size\": 13,\n      \"text_color\": \"#FFFFFF\",\n      \"text_align\": \"center\",\n      \"background_color\": \"#000000\",\n      \"padding_top\": 8,\n      \"padding_right\": 16,\n      \"padding_bottom\": 8,\n      \"padding_left\": 16,\n      \"border_top_width\": 0,\n      \"border_right_width\": 0,\n      \"border_bottom_width\": 0,\n      \"border_left_width\": 0,\n      \"border_radius\": 0\n    });\n\n    //\n    _this.block.appendElements([h2, p, button, img]);\n    return _this;\n  }\n  _inherits(ImageTextBottomWidget, _BaseWidget);\n  return _createClass(ImageTextBottomWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_bottom');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 110'%3E%0A  %3Crect width='180' height='110' fill='%23F7F7F7'/%3E%0A  %3Crect x='14' y='14' width='72' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A  %3Crect x='14' y='28' width='140' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='40' width='44' height='10' rx='3' fill='%23404040'/%3E%0A  %3Crect x='14' y='58' width='152' height='46' rx='5' fill='%23EEEEEE'/%3E%0A  %3Ccircle cx='46' cy='74' r='7' fill='%23D8D8D8'/%3E%0A  %3Cpolygon points='60,94 84,70 108,94' fill='%23D0D0D0'/%3E%0A  %3Cpolygon points='96,94 114,78 132,94' fill='%23DCDCDC'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextBottomWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextBottomWidget.js?");

/***/ }),

/***/ "./src/includes/ImageTextDoubleWidget.js":
/*!***********************************************!*\
  !*** ./src/includes/ImageTextDoubleWidget.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextDoubleWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ImageTextDoubleWidget() {\n    var _this;\n    _classCallCheck(this, ImageTextDoubleWidget);\n    _this = _callSuper(this, ImageTextDoubleWidget); // Call the parent class constructor\n\n    //\n    var grid = new GridElement('Grid');\n    grid.cell_gap = 20;\n    var cell1 = new CellElement('Cell');\n    cell1.formatter.setFormat('width', 50);\n    var cell2 = new CellElement('Cell');\n    cell2.formatter.setFormat('width', 50);\n    grid.appendCells([cell1, cell2]);\n    _this.block.appendElements([grid]);\n\n    //\n    var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 134.73 71.64'%3E%3Crect width='134.73' height='71.64' fill='%23f6f6f4'/%3E%3Cpath d='M57.79,47.82c-.69,0-1.27-.23-1.73-.69s-.69-1.04-.69-1.73v-19.15c0-.69.23-1.27.69-1.73s1.04-.69,1.73-.69h9.75c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-9.75c-.27,0-.49.09-.66.26-.17.17-.26.39-.26.66v19.15c0,.27.09.49.26.66.17.17.39.26.66.26h19.15c.27,0,.49-.09.66-.26.17-.17.26-.39.26-.66v-9.75c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v9.75c0,.69-.23,1.27-.69,1.73s-1.04.69-1.73.69h-19.15ZM59.52,42.4h15.69l-4.85-6.46-4.5,5.68-3-3.61-3.35,4.38ZM74.87,28.32h-2.25c-.21,0-.39-.07-.53-.22s-.22-.32-.22-.54.07-.39.22-.53.32-.21.53-.21h2.25v-2.25c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v2.25h2.25c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-2.25v2.25c0,.21-.07.39-.22.53s-.32.22-.54.22-.39-.07-.53-.22-.21-.32-.21-.53v-2.25Z' fill='%23afafae'/%3E%3C/svg%3E\");\n    img.formatter.parseFormats({\n      \"width\": \"100%\"\n    });\n    var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    h2.formatter.parseFormats({\n      \"padding_bottom\": 12,\n      \"padding_top\": 12\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n    var button = new ButtonElement('Button', 'Learn More');\n    button.formatter.parseFormats({\n      \"align\": \"left\",\n      \"font_size\": 13,\n      \"text_color\": \"#FFFFFF\",\n      \"text_align\": \"center\",\n      \"background_color\": \"#000000\",\n      \"padding_top\": 8,\n      \"padding_right\": 16,\n      \"padding_bottom\": 8,\n      \"padding_left\": 16,\n      \"border_top_width\": 0,\n      \"border_right_width\": 0,\n      \"border_bottom_width\": 0,\n      \"border_left_width\": 0,\n      \"border_radius\": 0\n    });\n\n    //\n    var img_2 = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 134.73 71.64'%3E%3Crect width='134.73' height='71.64' fill='%23f6f6f4'/%3E%3Cpath d='M57.79,47.82c-.69,0-1.27-.23-1.73-.69s-.69-1.04-.69-1.73v-19.15c0-.69.23-1.27.69-1.73s1.04-.69,1.73-.69h9.75c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-9.75c-.27,0-.49.09-.66.26-.17.17-.26.39-.26.66v19.15c0,.27.09.49.26.66.17.17.39.26.66.26h19.15c.27,0,.49-.09.66-.26.17-.17.26-.39.26-.66v-9.75c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v9.75c0,.69-.23,1.27-.69,1.73s-1.04.69-1.73.69h-19.15ZM59.52,42.4h15.69l-4.85-6.46-4.5,5.68-3-3.61-3.35,4.38ZM74.87,28.32h-2.25c-.21,0-.39-.07-.53-.22s-.22-.32-.22-.54.07-.39.22-.53.32-.21.53-.21h2.25v-2.25c0-.21.07-.39.22-.53s.32-.22.54-.22.39.07.53.22.21.32.21.53v2.25h2.25c.21,0,.39.07.53.22s.22.32.22.54-.07.39-.22.53-.32.21-.53.21h-2.25v2.25c0,.21-.07.39-.22.53s-.32.22-.54.22-.39-.07-.53-.22-.21-.32-.21-.53v-2.25Z' fill='%23afafae'/%3E%3C/svg%3E\");\n    img_2.formatter.parseFormats({\n      \"width\": \"100%\"\n    });\n    var h2_2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    h2_2.formatter.parseFormats({\n      \"padding_bottom\": 12,\n      \"padding_top\": 12\n    });\n    var p_2 = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p_2.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n    var button_2 = new ButtonElement('Button', 'Learn More');\n    button_2.formatter.parseFormats({\n      \"align\": \"left\",\n      \"font_size\": 13,\n      \"text_color\": \"#FFFFFF\",\n      \"text_align\": \"center\",\n      \"background_color\": \"#000000\",\n      \"padding_top\": 8,\n      \"padding_right\": 16,\n      \"padding_bottom\": 8,\n      \"padding_left\": 16,\n      \"border_top_width\": 0,\n      \"border_right_width\": 0,\n      \"border_bottom_width\": 0,\n      \"border_left_width\": 0,\n      \"border_radius\": 0\n    });\n\n    //\n    var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block1.appendElements([img, h2, p, button]);\n    var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block2.appendElements([img_2, h2_2, p_2, button_2]);\n\n    //\n    cell1.appendBlock(block1);\n    cell2.appendBlock(block2);\n    return _this;\n  }\n  _inherits(ImageTextDoubleWidget, _BaseWidget);\n  return _createClass(ImageTextDoubleWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_double');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 210 120'%3E%0A  %3Crect width='210' height='120' fill='%23F7F7F7'/%3E%0A  %3Crect x='14' y='12' width='84' height='44' rx='4' fill='%23EEEEEE'/%3E%0A  %3Ccircle cx='34' cy='26' r='5' fill='%23D8D8D8'/%3E%0A  %3Cpolygon points='32,46 44,30 56,46' fill='%23D0D0D0'/%3E%0A  %3Cpolygon points='50,46 60,36 70,46' fill='%23DCDCDC'/%3E%0A  %3Crect x='14' y='64' width='56' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A  %3Crect x='14' y='78' width='84' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='88' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='102' width='36' height='10' rx='3' fill='%23404040'/%3E%0A  %3Crect x='112' y='12' width='84' height='44' rx='4' fill='%23EEEEEE'/%3E%0A  %3Ccircle cx='132' cy='26' r='5' fill='%23D8D8D8'/%3E%0A  %3Cpolygon points='130,46 142,30 154,46' fill='%23D0D0D0'/%3E%0A  %3Cpolygon points='148,46 158,36 168,46' fill='%23DCDCDC'/%3E%0A  %3Crect x='112' y='64' width='56' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A  %3Crect x='112' y='78' width='84' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='112' y='88' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='112' y='102' width='36' height='10' rx='3' fill='%23404040'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextDoubleWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextDoubleWidget.js?");

/***/ }),

/***/ "./src/includes/ImageTextLeftWidget.js":
/*!*********************************************!*\
  !*** ./src/includes/ImageTextLeftWidget.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextLeftWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ImageTextLeftWidget() {\n    var _this;\n    _classCallCheck(this, ImageTextLeftWidget);\n    _this = _callSuper(this, ImageTextLeftWidget); // Call the parent class constructor\n\n    //\n    var grid = new GridElement('Grid');\n    grid.cell_gap = 20;\n    var cell1 = new CellElement('Cell');\n    // Image cell — content-sized (intrinsic width from the image).\n    cell1.formatter.setFormat('width', 'auto');\n    var cell2 = new CellElement('Cell');\n    // Text cell — `fill` is the explicit \"absorb remaining space\" primitive\n    // (`flex: 1 1 0; min-width: 0`). Do NOT use `'100%'` here: that compiles\n    // to `flex: 0 0 calc(100% - gapShare); min-width: 0`, a fixed-basis,\n    // no-shrink cell. Paired with a sibling `auto` cell, the percentage\n    // basis exceeds the row width → text cell overflows past the right\n    // edge and the auto cell shrinks toward zero (image disappears).\n    cell2.formatter.setFormat('width', 'fill');\n    grid.appendCells([cell1, cell2]);\n    _this.block.appendElements([grid]);\n\n    //\n    var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.23 140.64'%3E%3Crect width='101.23' height='140.64' fill='%23f6f6f4'/%3E%3Cpath d='M34.96,89.94c-1.13,0-2.07-.38-2.83-1.13s-1.13-1.7-1.13-2.83v-31.31c0-1.13.38-2.07,1.13-2.83s1.7-1.13,2.83-1.13h15.94c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-15.94c-.44,0-.8.14-1.09.42-.28.28-.42.64-.42,1.09v31.31c0,.44.14.8.42,1.09.28.28.64.42,1.09.42h31.31c.44,0,.8-.14,1.09-.42.28-.28.42-.64.42-1.09v-15.94c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v15.94c0,1.13-.38,2.07-1.13,2.83s-1.7,1.13-2.83,1.13h-31.31ZM37.79,81.07h25.65l-7.92-10.56-7.36,9.29-4.9-5.9-5.47,7.17ZM62.88,58.06h-3.68c-.35,0-.64-.12-.87-.35s-.35-.53-.35-.87.12-.64.35-.87.53-.35.87-.35h3.68v-3.68c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v3.68h3.68c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-3.68v3.68c0,.35-.12.64-.35.87s-.53.35-.87.35-.64-.12-.87-.35-.35-.53-.35-.87v-3.68Z' fill='%23afafae'/%3E%3C/svg%3E\");\n    img.formatter.parseFormats({\n      \"height\": 300\n    });\n    var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    h2.formatter.parseFormats({\n      \"padding_bottom\": 12\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n    var button = new ButtonElement('Button', 'Learn More');\n    button.formatter.parseFormats({\n      \"align\": \"left\",\n      \"font_size\": 13,\n      \"text_color\": \"#FFFFFF\",\n      \"text_align\": \"center\",\n      \"background_color\": \"#000000\",\n      \"padding_top\": 8,\n      \"padding_right\": 16,\n      \"padding_bottom\": 8,\n      \"padding_left\": 16,\n      \"border_top_width\": 0,\n      \"border_right_width\": 0,\n      \"border_bottom_width\": 0,\n      \"border_left_width\": 0,\n      \"border_radius\": 0\n    });\n\n    //\n    var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block1.appendElements([img]);\n    var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block2.appendElements([h2, p, button]);\n\n    //\n    cell1.appendBlock(block1);\n    cell2.appendBlock(block2);\n    return _this;\n  }\n  _inherits(ImageTextLeftWidget, _BaseWidget);\n  return _createClass(ImageTextLeftWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_left');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 88'%3E%3Crect width='200' height='88' fill='%23F7F7F7'/%3E%3Crect x='14' y='14' width='72' height='60' rx='5' fill='%23EEEEEE'/%3E%3Ccircle cx='34' cy='32' r='6' fill='%23D8D8D8'/%3E%3Cpolygon points='30,58 44,40 58,58' fill='%23D0D0D0'/%3E%3Cpolygon points='50,58 60,46 70,58' fill='%23DCDCDC'/%3E%3Crect x='100' y='18' width='72' height='8' rx='4' fill='%23C0C0C0'/%3E%3Crect x='100' y='34' width='86' height='5' rx='2.5' fill='%23DEDEDE'/%3E%3Crect x='100' y='45' width='70' height='5' rx='2.5' fill='%23DEDEDE'/%3E%3Crect x='100' y='60' width='40' height='10' rx='3' fill='%23404040'/%3E%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextLeftWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextLeftWidget.js?");

/***/ }),

/***/ "./src/includes/ImageTextRightWidget.js":
/*!**********************************************!*\
  !*** ./src/includes/ImageTextRightWidget.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextRightWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ImageTextRightWidget() {\n    var _this;\n    _classCallCheck(this, ImageTextRightWidget);\n    _this = _callSuper(this, ImageTextRightWidget); // Call the parent class constructor\n\n    //\n    var grid = new GridElement('Grid');\n    grid.cell_gap = 20;\n    var cell1 = new CellElement('Cell');\n    // Image cell — content-sized (intrinsic width from the image).\n    cell1.formatter.setFormat('width', 'auto');\n    var cell2 = new CellElement('Cell');\n    // Text cell — `fill` is the explicit \"absorb remaining space\" primitive\n    // (`flex: 1 1 0; min-width: 0`). Do NOT use `'100%'` here: that compiles\n    // to `flex: 0 0 calc(100% - gapShare); min-width: 0`, a fixed-basis,\n    // no-shrink cell. Paired with a sibling `auto` cell, the percentage\n    // basis exceeds the row width → text cell overflows past the right\n    // edge and the auto cell shrinks toward zero (image disappears).\n    cell2.formatter.setFormat('width', 'fill');\n    // Order = [text, image] so the text cell renders on the LEFT and the\n    // image cell renders on the RIGHT (Image-Text-RIGHT layout).\n    grid.appendCells([cell2, cell1]);\n    _this.block.appendElements([grid]);\n\n    //\n    var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.23 140.64'%3E%3Crect width='101.23' height='140.64' fill='%23f6f6f4'/%3E%3Cpath d='M34.96,89.94c-1.13,0-2.07-.38-2.83-1.13s-1.13-1.7-1.13-2.83v-31.31c0-1.13.38-2.07,1.13-2.83s1.7-1.13,2.83-1.13h15.94c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-15.94c-.44,0-.8.14-1.09.42-.28.28-.42.64-.42,1.09v31.31c0,.44.14.8.42,1.09.28.28.64.42,1.09.42h31.31c.44,0,.8-.14,1.09-.42.28-.28.42-.64.42-1.09v-15.94c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v15.94c0,1.13-.38,2.07-1.13,2.83s-1.7,1.13-2.83,1.13h-31.31ZM37.79,81.07h25.65l-7.92-10.56-7.36,9.29-4.9-5.9-5.47,7.17ZM62.88,58.06h-3.68c-.35,0-.64-.12-.87-.35s-.35-.53-.35-.87.12-.64.35-.87.53-.35.87-.35h3.68v-3.68c0-.35.12-.64.35-.87s.53-.35.87-.35.64.12.87.35.35.53.35.87v3.68h3.68c.35,0,.64.12.87.35s.35.53.35.87-.12.64-.35.87-.53.35-.87.35h-3.68v3.68c0,.35-.12.64-.35.87s-.53.35-.87.35-.64-.12-.87-.35-.35-.53-.35-.87v-3.68Z' fill='%23afafae'/%3E%3C/svg%3E\");\n    img.formatter.parseFormats({\n      \"height\": 300\n    });\n    var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    h2.formatter.parseFormats({\n      \"padding_bottom\": 12\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n    var button = new ButtonElement('Button', 'Learn More');\n    button.formatter.parseFormats({\n      \"align\": \"left\",\n      \"font_size\": 13,\n      \"text_color\": \"#FFFFFF\",\n      \"text_align\": \"center\",\n      \"background_color\": \"#000000\",\n      \"padding_top\": 8,\n      \"padding_right\": 16,\n      \"padding_bottom\": 8,\n      \"padding_left\": 16,\n      \"border_top_width\": 0,\n      \"border_right_width\": 0,\n      \"border_bottom_width\": 0,\n      \"border_left_width\": 0,\n      \"border_radius\": 0\n    });\n\n    //\n    var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block1.appendElements([img]);\n    var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block2.appendElements([h2, p, button]);\n\n    //\n    cell1.appendBlock(block1);\n    cell2.appendBlock(block2);\n    return _this;\n  }\n  _inherits(ImageTextRightWidget, _BaseWidget);\n  return _createClass(ImageTextRightWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_right');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 88'%3E%0A  %3Crect width='200' height='88' fill='%23F7F7F7'/%3E%0A  %3Crect x='14' y='18' width='72' height='8' rx='4' fill='%23C0C0C0'/%3E%0A  %3Crect x='14' y='34' width='86' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='45' width='70' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='60' width='40' height='10' rx='3' fill='%23404040'/%3E%0A  %3Crect x='114' y='14' width='72' height='60' rx='5' fill='%23EEEEEE'/%3E%0A  %3Ccircle cx='134' cy='32' r='6' fill='%23D8D8D8'/%3E%0A  %3Cpolygon points='130,58 144,40 158,58' fill='%23D0D0D0'/%3E%0A  %3Cpolygon points='150,58 160,46 170,58' fill='%23DCDCDC'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextRightWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextRightWidget.js?");

/***/ }),

/***/ "./src/includes/ImageTextTopWidget.js":
/*!********************************************!*\
  !*** ./src/includes/ImageTextTopWidget.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ImageTextTopWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ImageTextTopWidget() {\n    var _this;\n    _classCallCheck(this, ImageTextTopWidget);\n    _this = _callSuper(this, ImageTextTopWidget); // Call the parent class constructor\n\n    //\n    var img = new ImageElement('Image', \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 270.23 84.36'%3E%3Crect width='270.23' height='84.36' fill='%23f6f6f4'/%3E%3Cpath d='M123.15,57.18c-.86,0-1.58-.29-2.16-.87s-.87-1.3-.87-2.16v-23.94c0-.86.29-1.58.87-2.16s1.3-.87,2.16-.87h12.19c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-12.19c-.34,0-.61.11-.83.32-.22.22-.32.49-.32.83v23.94c0,.34.11.61.32.83.22.22.49.32.83.32h23.94c.34,0,.61-.11.83-.32.22-.22.32-.49.32-.83v-12.19c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v12.19c0,.86-.29,1.58-.87,2.16s-1.3.87-2.16.87h-23.94ZM125.31,50.4h19.62l-6.06-8.08-5.62,7.1-3.75-4.51-4.18,5.48ZM144.49,32.81h-2.81c-.27,0-.49-.09-.67-.27s-.27-.4-.27-.67.09-.49.27-.67.4-.27.67-.27h2.81v-2.81c0-.27.09-.49.27-.67s.4-.27.67-.27.49.09.67.27.27.4.27.67v2.81h2.81c.27,0,.49.09.67.27s.27.4.27.67-.09.49-.27.67-.4.27-.67.27h-2.81v2.81c0,.27-.09.49-.27.67s-.4.27-.67.27-.49-.09-.67-.27-.27-.4-.27-.67v-2.81Z' fill='%23afafae'/%3E%3C/svg%3E\");\n    img.formatter.parseFormats({\n      \"width\": \"100%\",\n      \"padding_bottom\": 10\n    });\n    var h2 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    h2.formatter.parseFormats({\n      \"padding_bottom\": 12\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n    var button = new ButtonElement('Button', 'Learn More');\n    button.formatter.parseFormats({\n      \"align\": \"left\",\n      \"font_size\": 13,\n      \"text_color\": \"#FFFFFF\",\n      \"text_align\": \"center\",\n      \"background_color\": \"#000000\",\n      \"padding_top\": 8,\n      \"padding_right\": 16,\n      \"padding_bottom\": 8,\n      \"padding_left\": 16,\n      \"border_top_width\": 0,\n      \"border_right_width\": 0,\n      \"border_bottom_width\": 0,\n      \"border_left_width\": 0,\n      \"border_radius\": 0\n    });\n\n    //\n    _this.block.appendElements([img, h2, p, button]);\n    return _this;\n  }\n  _inherits(ImageTextTopWidget, _BaseWidget);\n  return _createClass(ImageTextTopWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image_text_top');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 110'%3E%0A  %3Crect width='180' height='110' fill='%23F7F7F7'/%3E%0A  %3Crect x='14' y='12' width='152' height='46' rx='5' fill='%23EEEEEE'/%3E%0A  %3Ccircle cx='46' cy='28' r='7' fill='%23D8D8D8'/%3E%0A  %3Cpolygon points='60,48 84,24 108,48' fill='%23D0D0D0'/%3E%0A  %3Cpolygon points='96,48 114,32 132,48' fill='%23DCDCDC'/%3E%0A  %3Crect x='14' y='68' width='72' height='7' rx='3.5' fill='%23C0C0C0'/%3E%0A  %3Crect x='14' y='82' width='140' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='94' width='44' height='10' rx='3' fill='%23404040'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageTextTopWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageTextTopWidget.js?");

/***/ }),

/***/ "./src/includes/ImageWidget.js":
/*!*************************************!*\
  !*** ./src/includes/ImageWidget.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ImageElement.js */ \"./src/includes/ImageElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar ImageWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ImageWidget() {\n    var _this;\n    _classCallCheck(this, ImageWidget);\n    _this = _callSuper(this, ImageWidget); // Call the parent class constructor\n    _this.elements = [];\n\n    // Add an ImageElement to the widget\n    var image = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Image');\n\n    // Append the new element to the block\n    _this.block.appendElements([image]);\n    return _this;\n  }\n  _inherits(ImageWidget, _BaseWidget);\n  return _createClass(ImageWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.image');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ImageWidget.js?");

/***/ }),

/***/ "./src/includes/InfoBannerControl.js":
/*!*******************************************!*\
  !*** ./src/includes/InfoBannerControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\n/**\n * InfoBannerControl — lightweight informational surface for settings panels.\n *\n * Renders a single tinted banner with an icon and short guidance text. Styling\n * uses the `.bjs-info-banner` tokens so it inherits theme-aware colours.\n *\n * Usage:\n *   new InfoBannerControl('Use px for email. % for responsive web pages.')\n *   new InfoBannerControl(text, { icon: 'ⓘ' })\n */\nvar InfoBannerControl = /*#__PURE__*/_createClass(function InfoBannerControl() {\n  var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';\n  var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n    _ref$icon = _ref.icon,\n    icon = _ref$icon === void 0 ? 'ⓘ' : _ref$icon;\n  _classCallCheck(this, InfoBannerControl);\n  this.domNode = document.createElement('div');\n  this.domNode.classList.add('bjs-info-banner');\n  this.domNode.innerHTML = \"\\n            <span class=\\\"bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\".concat(icon, \"</span>\\n            <span class=\\\"bjs-info-banner-text\\\">\").concat(text, \"</span>\\n        \");\n});\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InfoBannerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/InfoBannerControl.js?");

/***/ }),

/***/ "./src/includes/InlineSanitizer.js":
/*!*****************************************!*\
  !*** ./src/includes/InlineSanitizer.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   BLOCK_LEVEL_TAGS: () => (/* binding */ BLOCK_LEVEL_TAGS),\n/* harmony export */   EMAIL_SAFE_TAG_MAP: () => (/* binding */ EMAIL_SAFE_TAG_MAP),\n/* harmony export */   INLINE_TAG_WHITELIST: () => (/* binding */ INLINE_TAG_WHITELIST),\n/* harmony export */   NORMALIZE_TAG_MAP: () => (/* binding */ NORMALIZE_TAG_MAP),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * InlineSanitizer — T9 whitelist primitive for inline text content.\n *\n * BuilderJS is a full HTML5 page builder; email is one downgrade consumer\n * among many (page / site / form / popup / ad / email). The sanitizer has\n * three entry points corresponding to the three write paths each inline\n * text surface touches:\n *\n *   1. `sanitize(html, { mode })` — paste pipeline. Parses an untrusted\n *      HTML string (clipboard contents, pasted MS Word / Google Docs /\n *      Outlook / Notion), strips everything not in the T9 PAGE whitelist,\n *      removes Office mso-* attrs, and returns a clean HTML string. The\n *      W2.2 paste path (`Paste`, `Paste Plain`, `Paste and Match Style`)\n *      routes every clipboard read through this.\n *\n *   2. `normalize(rootNode)` — in-place pass after every `execCommand`.\n *      Canonicalises Safari/Chrome/Firefox markup divergence (`<b>` →\n *      `<strong>`, `<i>` → `<em>`, redundant nested `<span>` merged).\n *      Called from the W1.1 toolbar apply handlers so the element's\n *      serialised state is deterministic regardless of which browser\n *      the user edited in.\n *\n *   3. `emit(rootNode, { mode })` — serializer. Returns the canonical\n *      HTML string a caller writes out. Mode `'page'` preserves the full\n *      T9 PAGE whitelist verbatim (semantic tags survive round-trip).\n *      Mode `'email-safe'` applies the EMAIL downgrade table — semantic\n *      tags flatten to `<span style>`, `<ruby>`/`<rt>`/`<rp>` collapse\n *      to base text, inline `<img>` rejected. Every element whose\n *      container resolves `getOutputMode() === 'email-safe'` uses this\n *      mode; everyone else gets full page mode.\n *\n * HARD RULE T9 (TEXT_INLINE_PLAN §0.2): inline content lives INSIDE a\n * block element. Block tags (`<p>`, `<div>`, `<h1-h6>`, `<ul>`, `<ol>`,\n * `<li>`, `<blockquote>`, `<pre>`, `<hr>`, `<table>` and friends) are\n * forbidden at the inline level in BOTH modes. `sanitize()` unwraps\n * them (keeps text content, drops the tag). Container media\n * (`<video>`, `<audio>`, `<iframe>`, `<canvas>`, `<embed>`, `<object>`)\n * and raw `<svg>` are rejected — the content is dropped entirely since\n * a text-only \"script stub\" makes no sense for those. Scripting/meta\n * (`<script>`, `<style>`, `<link>`, `<meta>`, `<base>`, `<noscript>`)\n * is dropped for security.\n *\n * The sanitizer is pure: zero DOM mutation on the input HTML string,\n * zero side effects on the outer document. `normalize()` IS in-place\n * by design (it mutates its rootNode argument) — that is the contract.\n */\n\n/** T9 PAGE whitelist — every tag the inline toolbar UI can produce. */\nvar INLINE_TAG_WHITELIST = Object.freeze(new Set([\n// Structural\n'span', 'a',\n// Bold / italic / decorations\n'strong', 'b', 'em', 'i', 'u', 's', 'del', 'ins', 'mark', 'sub', 'sup',\n// Code / documentation\n'code', 'samp', 'kbd', 'var',\n// Type scale + citations\n'small', 'abbr', 'cite', 'dfn', 'q',\n// Machine-readable\n'time', 'data',\n// Bidi + Asian-language\n'bdi', 'bdo', 'ruby', 'rt', 'rp',\n// Line breaks + zero-width break\n'br', 'wbr',\n// Inline media\n'img']));\n\n/** Tags canonicalised by `normalize()` → replacement. */\nvar NORMALIZE_TAG_MAP = Object.freeze({\n  b: 'strong',\n  i: 'em'\n});\n\n/**\n * HTML5 block-level tags that auto-close an open `<p>` / `<h1..h6>` / `<li>` /\n * `<dd>` / `<dt>` when encountered by the fragment parser. Inside an\n * inline-edit host (`<p>`, `<h*>`) these MUST NEVER appear — otherwise\n * setting `host.innerHTML = …` round-trips through the HTML5 fragment parser\n * which silently closes the host before the block tag, kicking the block\n * tag's content out of the host as a sibling and stripping the inline style\n * on the host from the visible content.\n *\n * Set membership matches the WHATWG HTML \"close-on-p\" element list.\n * Lowercase tag names.\n *\n * Consumed by `_unwrapBlockLevel(root)` — walks descendants of an\n * inline-edit host and replaces every block-level wrapper with its\n * children, inserting a `<br>` separator BEFORE the lifted content so the\n * user's visual line-break (Enter key) survives round-trip.\n *\n * Root-cause incident: 2026-05-20 Ben-Ami Car Wash & Detail (email\n * campaign builder). Chrome's contenteditable default-paragraph-separator\n * is `'div'`, so every Enter inside a `<p inline-edit=\"text\">` inserted a\n * `<div>` block-level child. On the next full re-render (delete-sibling-\n * block cascade) the `<p>`'s inline `font-weight` / `text-align` /\n * `font-family` styles vanished because the parser kicked the `<div>`\n * blocks out of the `<p>`. See docs/BUILDER.md §9.4.\n */\nvar BLOCK_LEVEL_TAGS = Object.freeze(new Set(['address', 'article', 'aside', 'blockquote', 'details', 'dialog', 'dir', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'ul', 'li', 'dt', 'dd']));\n\n/**\n * EMAIL downgrade table — applied by `emit({ mode: 'email-safe' })`.\n * Each entry says: \"when emitting an X tag for email, replace with Y\".\n * `null` replacement means \"flatten to text\" (reject the tag, keep\n * children).\n */\nvar EMAIL_SAFE_TAG_MAP = Object.freeze({\n  // Bold/italic/decorations — Outlook 2007+ strips semantic tags inconsistently.\n  strong: {\n    tag: 'span',\n    style: 'font-weight:bold'\n  },\n  b: {\n    tag: 'span',\n    style: 'font-weight:bold'\n  },\n  em: {\n    tag: 'span',\n    style: 'font-style:italic'\n  },\n  i: {\n    tag: 'span',\n    style: 'font-style:italic'\n  },\n  u: {\n    tag: 'span',\n    style: 'text-decoration:underline'\n  },\n  mark: {\n    tag: 'span',\n    style: 'background-color:#ffff00'\n  },\n  ins: {\n    tag: 'span',\n    style: 'text-decoration:underline'\n  },\n  del: {\n    tag: 'span',\n    style: 'text-decoration:line-through'\n  },\n  // Semantic tags — strip, keep text + inline style carried over.\n  abbr: {\n    tag: 'span',\n    style: null\n  },\n  cite: {\n    tag: 'span',\n    style: null\n  },\n  dfn: {\n    tag: 'span',\n    style: null\n  },\n  q: {\n    tag: 'span',\n    style: null\n  },\n  time: {\n    tag: 'span',\n    style: null\n  },\n  data: {\n    tag: 'span',\n    style: null\n  },\n  kbd: {\n    tag: 'span',\n    style: null\n  },\n  \"var\": {\n    tag: 'span',\n    style: null\n  },\n  samp: {\n    tag: 'span',\n    style: null\n  },\n  // Bidi — keep dir attr so clients that respect it still align correctly.\n  bdi: {\n    tag: 'span',\n    style: null,\n    keepDirAttr: true\n  },\n  bdo: {\n    tag: 'span',\n    style: null,\n    keepDirAttr: true\n  },\n  // Ruby annotations — email strips these; flatten to base text only.\n  ruby: null,\n  // flatten children\n  rt: {\n    drop: true\n  },\n  // drop the annotation text entirely\n  rp: {\n    drop: true\n  },\n  // drop the bracket markers entirely\n  // Word-break hint — inconsistent across email clients; strip.\n  wbr: {\n    drop: true\n  },\n  // Inline image — produces render breaks in Outlook. Route to\n  // ImageElement block. In emit, we REPLACE with an HTML comment so\n  // the loss is visible to the caller rather than silent.\n  img: {\n    drop: true,\n    trace: '<!-- inline img removed (email mode): use ImageElement -->'\n  }\n});\n\n/**\n * Tags whose shell AND content must be dropped entirely (container\n * media + scripting). `sanitize()` rips these without keeping children.\n */\nvar DANGEROUS_TAGS = Object.freeze(new Set(['script', 'style', 'link', 'meta', 'base', 'noscript', 'video', 'audio', 'iframe', 'canvas', 'embed', 'object', 'svg', 'input', 'select', 'textarea', 'button', 'fieldset', 'legend', 'datalist', 'output', 'progress', 'meter', 'keygen', 'slot', 'template']));\n\n/**\n * Office / Google Docs / Outlook clipboard noise — tags that appear in\n * pasted content but carry no semantic value. Dropped in `sanitize()`\n * (shell removed, children kept so paragraph text survives).\n */\nvar OFFICE_NOISE_TAGS = Object.freeze(new Set(['o:p', 'w:sdt', 'w:sdtpr', 'w:sdtendpr', 'w:sdtcontent', 'm:t', 'm:r', 'xml']));\n\n/**\n * Attributes allowed on sanitised inline tags. Anything not listed is\n * stripped. `style` is allowed but heavily filtered per {@link FILTERED_STYLE_PROPS}.\n */\nvar ALLOWED_ATTRS = Object.freeze({\n  a: new Set(['href', 'target', 'rel', 'download', 'title', 'aria-label']),\n  img: new Set(['src', 'alt', 'width', 'height', 'title']),\n  span: new Set(['style', 'class', 'dir', 'data-merge-tag', 'contenteditable', 'data-bjs-inline-text']),\n  abbr: new Set(['title', 'style']),\n  time: new Set(['datetime', 'style']),\n  data: new Set(['value', 'style']),\n  bdi: new Set(['dir', 'style']),\n  bdo: new Set(['dir', 'style'])\n});\nvar UNIVERSAL_ALLOWED_ATTRS = Object.freeze(new Set(['style', 'class', 'dir']));\n\n/**\n * Inline CSS properties the sanitizer retains after paste. Everything\n * else (including Office `mso-*`, `font-family` — we own font family\n * via W3.1 FontPopoverOverlay, so pasted fonts would fight the toolbar)\n * is stripped.\n */\nvar FILTERED_STYLE_PROPS = Object.freeze(new Set(['color', 'background-color', 'font-weight', 'font-style', 'font-size', 'text-decoration', 'text-decoration-line', 'text-decoration-color', 'text-decoration-style', 'text-align', 'letter-spacing', 'line-height', 'vertical-align']));\nvar InlineSanitizer = /*#__PURE__*/function () {\n  function InlineSanitizer() {\n    _classCallCheck(this, InlineSanitizer);\n  }\n  return _createClass(InlineSanitizer, null, [{\n    key: \"INLINE_TAG_WHITELIST\",\n    get:\n    /**\n     * Expose the whitelists as static properties too — tests introspect\n     * these directly (no import gymnastics).\n     */\n    function get() {\n      return INLINE_TAG_WHITELIST;\n    }\n  }, {\n    key: \"NORMALIZE_TAG_MAP\",\n    get: function get() {\n      return NORMALIZE_TAG_MAP;\n    }\n  }, {\n    key: \"EMAIL_SAFE_TAG_MAP\",\n    get: function get() {\n      return EMAIL_SAFE_TAG_MAP;\n    }\n\n    /**\n     * Parse an untrusted HTML string, strip every tag not in the inline\n     * whitelist, drop Office noise + mso-* attrs + disallowed styles,\n     * and return a clean HTML string in PAGE or EMAIL mode.\n     *\n     * @param {string} html\n     * @param {Object} [opts]\n     * @param {'page'|'email-safe'} [opts.mode='page']\n     * @returns {string}\n     */\n  }, {\n    key: \"sanitize\",\n    value: function sanitize(html) {\n      var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      if (html === null || html === undefined) return '';\n      if (typeof html !== 'string') {\n        throw new TypeError('InlineSanitizer.sanitize: html must be a string');\n      }\n      var mode = opts.mode === 'email-safe' ? 'email-safe' : 'page';\n\n      // Pre-parse text cleanup:\n      //   1. ALL HTML comments (general, non-greedy) — covers both\n      //      Office conditional comments (`<!--[if gte mso 9]>...<![endif]-->`)\n      //      and descriptive author comments. Using a specialized\n      //      conditional-comment regex FIRST was a trap: when a\n      //      descriptive comment CONTAINED the literal text `<!--[if ...]>`,\n      //      the conditional regex would greedy-match from that inner\n      //      open to the later `<![endif]-->`, consuming the descriptive\n      //      comment's own `-->` terminator — leaving a dangling open\n      //      `<!--` that DOMParser treated as an unterminated comment\n      //      wrapping the rest of the document. The general\n      //      `<!--[\\s\\S]*?-->` regex handles both shapes cleanly because\n      //      it always anchors to the NEAREST terminator. Caught in the\n      //      W0.5 Word-2019 fixture test (2026-04-20).\n      //   2. XML / DOCTYPE shells from paste clipboards.\n      var cleanSource = html.replace(/<!--[\\s\\S]*?-->/g, '').replace(/<\\?xml[\\s\\S]*?\\?>/gi, '').replace(/<!DOCTYPE[^>]*>/gi, '');\n      var doc = new DOMParser().parseFromString(\"<div id=\\\"__bjs_sanitize_root\\\">\".concat(cleanSource, \"</div>\"), 'text/html');\n      var root = doc.getElementById('__bjs_sanitize_root');\n      if (!root) return '';\n      InlineSanitizer._walkClean(root);\n      if (mode === 'email-safe') {\n        InlineSanitizer._walkEmailDowngrade(root);\n      }\n      return root.innerHTML;\n    }\n\n    /**\n     * Canonicalize browser-divergent markup in-place. `<b>` → `<strong>`,\n     * `<i>` → `<em>`, consecutive nested `<span>` with no attributes\n     * merged. Called after every execCommand so the serialised state is\n     * deterministic.\n     *\n     * Mutates rootNode in place. Safe to call repeatedly — idempotent\n     * after first pass.\n     *\n     * @param {HTMLElement} rootNode\n     * @returns {HTMLElement} the same rootNode\n     */\n  }, {\n    key: \"normalize\",\n    value: function normalize(rootNode) {\n      if (!rootNode || rootNode.nodeType !== 1) {\n        throw new TypeError('InlineSanitizer.normalize: rootNode must be an HTMLElement');\n      }\n      // Order matters:\n      //   1. Unwrap block-level descendants FIRST — the `<div>`s Chrome\n      //      inserts for Enter contain inline children we want to keep.\n      //      Doing this before _normalizeTags lets the canonicalize pass\n      //      see the lifted children at the right depth.\n      //   2. Canonicalise `<b>→<strong>` / `<i>→<em>`.\n      //   3. Collapse attribute-less / nested `<span>`s — runs LAST so\n      //      any empty spans produced by step 1 are also removed.\n      InlineSanitizer._unwrapBlockLevel(rootNode);\n      InlineSanitizer._normalizeTags(rootNode);\n      InlineSanitizer._collapseEmptySpans(rootNode);\n      return rootNode;\n    }\n\n    /**\n     * Emit the canonical HTML for a root node in the chosen mode. PAGE\n     * mode preserves the full whitelist verbatim (round-trip invariant).\n     * EMAIL mode applies the downgrade table — semantic tags become\n     * `<span style>`, ruby annotations flatten, inline `<img>` rejected.\n     *\n     * Does NOT mutate rootNode. Caller gets a string.\n     *\n     * @param {HTMLElement} rootNode\n     * @param {Object} [opts]\n     * @param {'page'|'email-safe'} [opts.mode='page']\n     * @returns {string}\n     */\n  }, {\n    key: \"emit\",\n    value: function emit(rootNode) {\n      var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      if (!rootNode || rootNode.nodeType !== 1) {\n        throw new TypeError('InlineSanitizer.emit: rootNode must be an HTMLElement');\n      }\n      var mode = opts.mode === 'email-safe' ? 'email-safe' : 'page';\n      if (mode === 'page') return rootNode.innerHTML;\n\n      // Clone so we don't mutate the caller's DOM.\n      var clone = rootNode.cloneNode(true);\n      InlineSanitizer._walkEmailDowngrade(clone);\n      return clone.innerHTML;\n    }\n\n    /* ── Private — shared walkers ───────────────────────────────────── */\n\n    /**\n     * Walk rootNode descendants. For each element:\n     *   - If tag is DANGEROUS → remove the element (drop content too).\n     *   - If tag is OFFICE_NOISE → unwrap (keep children).\n     *   - If tag is NOT in INLINE_TAG_WHITELIST → unwrap (block tag; keep children).\n     *   - Else → prune attributes to ALLOWED_ATTRS for that tag +\n     *     UNIVERSAL, filter inline style to FILTERED_STYLE_PROPS,\n     *     preserve merge-tag chips verbatim.\n     */\n  }, {\n    key: \"_walkClean\",\n    value: function _walkClean(node) {\n      // Iterate snapshot because unwrap/remove mutates the live child list.\n      var children = Array.from(node.children);\n      for (var _i = 0, _children = children; _i < _children.length; _i++) {\n        var el = _children[_i];\n        InlineSanitizer._walkClean(el); // depth-first — attr + style handled after recurse\n        var tag = el.tagName.toLowerCase();\n        if (DANGEROUS_TAGS.has(tag)) {\n          el.remove();\n          continue;\n        }\n        if (OFFICE_NOISE_TAGS.has(tag) || tag.includes(':')) {\n          // Namespaced Office/Word tags (`o:p`, `w:sdt`, etc.) and\n          // plain OFFICE_NOISE_TAGS all unwrap.\n          InlineSanitizer._unwrap(el);\n          continue;\n        }\n\n        // Preserve merge-tag chip as-is (contenteditable=false + data-merge-tag).\n        if (tag === 'span' && el.getAttribute('contenteditable') === 'false' && el.hasAttribute('data-merge-tag')) {\n          // Still filter other attrs + style for hygiene.\n          InlineSanitizer._pruneAttributes(el, tag);\n          continue;\n        }\n        if (!INLINE_TAG_WHITELIST.has(tag)) {\n          // Block tag or anything else not in whitelist — unwrap.\n          InlineSanitizer._unwrap(el);\n          continue;\n        }\n        InlineSanitizer._pruneAttributes(el, tag);\n      }\n    }\n\n    /** In-place attribute prune + style filter for a whitelisted element. */\n  }, {\n    key: \"_pruneAttributes\",\n    value: function _pruneAttributes(el, tag) {\n      var allowed = ALLOWED_ATTRS[tag] || UNIVERSAL_ALLOWED_ATTRS;\n      var attrs = Array.from(el.attributes);\n      for (var _i2 = 0, _attrs = attrs; _i2 < _attrs.length; _i2++) {\n        var a = _attrs[_i2];\n        var name = a.name.toLowerCase();\n        // Drop mso-* / w:* / office attrs unconditionally.\n        if (name.startsWith('mso-') || name.startsWith('w:') || name.startsWith('o:')) {\n          el.removeAttribute(a.name);\n          continue;\n        }\n        // Keep if allowed OR universal allowed.\n        if (allowed.has(name) || UNIVERSAL_ALLOWED_ATTRS.has(name)) continue;\n        el.removeAttribute(a.name);\n      }\n      var style = el.getAttribute('style');\n      if (style) {\n        var filtered = InlineSanitizer._filterStyle(style);\n        if (filtered) {\n          el.setAttribute('style', filtered);\n        } else {\n          el.removeAttribute('style');\n        }\n      }\n    }\n\n    /** Filter an inline `style` string to FILTERED_STYLE_PROPS + drop mso-* props. */\n  }, {\n    key: \"_filterStyle\",\n    value: function _filterStyle(styleStr) {\n      var parts = styleStr.split(';');\n      var kept = [];\n      var _iterator = _createForOfIteratorHelper(parts),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var raw = _step.value;\n          var seg = raw.trim();\n          if (!seg) continue;\n          var colonIdx = seg.indexOf(':');\n          if (colonIdx < 0) continue;\n          var prop = seg.slice(0, colonIdx).trim().toLowerCase();\n          var val = seg.slice(colonIdx + 1).trim();\n          if (!prop || !val) continue;\n          if (prop.startsWith('mso-')) continue;\n          if (prop === 'font-family') continue; // W3.1 owns font family\n          if (!FILTERED_STYLE_PROPS.has(prop)) continue;\n          kept.push(\"\".concat(prop, \": \").concat(val));\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n      return kept.join('; ');\n    }\n\n    /** Replace `el` with its children in its parent, preserving order. */\n  }, {\n    key: \"_unwrap\",\n    value: function _unwrap(el) {\n      var parent = el.parentNode;\n      if (!parent) return;\n      while (el.firstChild) parent.insertBefore(el.firstChild, el);\n      parent.removeChild(el);\n    }\n\n    /* ── Private — normalize helpers ────────────────────────────────── */\n  }, {\n    key: \"_normalizeTags\",\n    value: function _normalizeTags(root) {\n      // `<b>` → `<strong>`, `<i>` → `<em>`. We do this by creating a\n      // replacement element + moving children, since setAttribute\n      // cannot rename a tag in place.\n      for (var _i3 = 0, _Object$entries = Object.entries(NORMALIZE_TAG_MAP); _i3 < _Object$entries.length; _i3++) {\n        var _Object$entries$_i = _slicedToArray(_Object$entries[_i3], 2),\n          from = _Object$entries$_i[0],\n          to = _Object$entries$_i[1];\n        var matches = root.querySelectorAll(from);\n        var _iterator2 = _createForOfIteratorHelper(matches),\n          _step2;\n        try {\n          for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n            var el = _step2.value;\n            var replacement = el.ownerDocument.createElement(to);\n            // Preserve attributes (post-normalize pass, attrs are\n            // trusted — we assume sanitize already ran).\n            for (var _i4 = 0, _Array$from = Array.from(el.attributes); _i4 < _Array$from.length; _i4++) {\n              var a = _Array$from[_i4];\n              replacement.setAttribute(a.name, a.value);\n            }\n            while (el.firstChild) replacement.appendChild(el.firstChild);\n            el.parentNode.replaceChild(replacement, el);\n          }\n        } catch (err) {\n          _iterator2.e(err);\n        } finally {\n          _iterator2.f();\n        }\n      }\n    }\n\n    /**\n     * Depth-first unwrap of every block-level descendant. Each removed\n     * wrapper leaves a `<br>` separator behind so a user's visual line\n     * break (Enter inside contenteditable, paste-with-paragraphs) round-\n     * trips as a single inline `<br>` instead of an invalid `<div>` /\n     * `<p>` inside `<p>`.\n     *\n     * Rules (preserves round-trip invariants):\n     *   - If the block is the FIRST child of its parent AND has no prior\n     *     sibling text → no `<br>` (avoids a leading blank line).\n     *   - If the previous sibling is already a `<br>` → no `<br>` (avoids\n     *     stacking).\n     *   - Block's element children are recursed FIRST so nested blocks\n     *     are flattened depth-first.\n     *   - Attributes on the block (`style`, `class`) are DROPPED. Users\n     *     style at the inline-edit host (`<p style>`) level via the\n     *     formatter; inline range-level styles live on whitelisted inline\n     *     tags (`<span style>` / `<strong>` / `<em>`). A user-introduced\n     *     `<div style=\"…\">` is treated as \"structural noise\" — the visual\n     *     style on a Chrome auto-inserted `<div>` is always the\n     *     contenteditable default (no useful authoring intent), so\n     *     stripping it never destroys real authoring.\n     *\n     * Idempotent.\n     */\n  }, {\n    key: \"_unwrapBlockLevel\",\n    value: function _unwrapBlockLevel(root) {\n      var doc = root.ownerDocument;\n      if (!doc) return;\n      var _walk = function walk(parent) {\n        var children = Array.from(parent.childNodes);\n        for (var _i5 = 0, _children2 = children; _i5 < _children2.length; _i5++) {\n          var child = _children2[_i5];\n          if (child.nodeType !== 1) continue; // ELEMENT_NODE\n          if (!BLOCK_LEVEL_TAGS.has(child.tagName.toLowerCase())) {\n            _walk(child);\n            continue;\n          }\n          // Recurse INTO the block first so nested blocks flatten.\n          _walk(child);\n          // Decide whether to insert a <br> separator before lifting.\n          var prev = child.previousSibling;\n          var hasMeaningfulPrev = prev !== null && !(prev.nodeType === 1 && prev.tagName.toLowerCase() === 'br');\n          if (hasMeaningfulPrev) {\n            var br = doc.createElement('br');\n            child.parentNode.insertBefore(br, child);\n          }\n          // Lift children out of the block, in document order.\n          while (child.firstChild) {\n            child.parentNode.insertBefore(child.firstChild, child);\n          }\n          child.parentNode.removeChild(child);\n        }\n      };\n      _walk(root);\n    }\n  }, {\n    key: \"_collapseEmptySpans\",\n    value: function _collapseEmptySpans(root) {\n      // Remove `<span>` with zero attributes, unwrap `<span>` nested\n      // inside another `<span>` when both carry no attributes.\n      // Idempotent — multiple passes converge to a fixed point.\n      var changed = true;\n      while (changed) {\n        changed = false;\n        var spans = root.querySelectorAll('span');\n        var _iterator3 = _createForOfIteratorHelper(spans),\n          _step3;\n        try {\n          for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n            var span = _step3.value;\n            if (span.attributes.length > 0) continue;\n            // No attrs — unwrap (keep children as siblings).\n            InlineSanitizer._unwrap(span);\n            changed = true;\n          }\n        } catch (err) {\n          _iterator3.e(err);\n        } finally {\n          _iterator3.f();\n        }\n      }\n    }\n\n    /* ── Private — email downgrade walker ───────────────────────────── */\n  }, {\n    key: \"_walkEmailDowngrade\",\n    value: function _walkEmailDowngrade(node) {\n      // Iterate snapshot because we restructure the tree.\n      var children = Array.from(node.children);\n      for (var _i6 = 0, _children3 = children; _i6 < _children3.length; _i6++) {\n        var el = _children3[_i6];\n        InlineSanitizer._walkEmailDowngrade(el);\n        var tag = el.tagName.toLowerCase();\n        // `tag in EMAIL_SAFE_TAG_MAP` — distinguishes \"not in map\"\n        // (skip, tag stays) from \"explicitly null\" (unwrap, for ruby).\n        // `if (!map)` would treat null as skip, a subtle bug caught in\n        // W0.5 test 17 — ruby kept its shell instead of flattening.\n        if (!(tag in EMAIL_SAFE_TAG_MAP)) continue;\n        var map = EMAIL_SAFE_TAG_MAP[tag];\n        if (map === null) {\n          // Ruby — flatten children (unwrap).\n          InlineSanitizer._unwrap(el);\n          continue;\n        }\n        if (map.drop) {\n          // rt/rp/wbr/img — drop entirely. If `trace`, leave a comment.\n          if (map.trace) {\n            var comment = el.ownerDocument.createComment(map.trace.replace(/^<!--\\s*|\\s*-->$/g, ''));\n            el.parentNode.replaceChild(comment, el);\n          } else {\n            el.remove();\n          }\n          continue;\n        }\n        if (map.tag) {\n          var replacement = el.ownerDocument.createElement(map.tag);\n          // Merge styles: caller-provided downgrade style + any\n          // inline style already on the element (post-sanitize).\n          var existingStyle = el.getAttribute('style') || '';\n          var downgradeStyle = map.style || '';\n          var combined = [existingStyle, downgradeStyle].filter(Boolean).map(function (s) {\n            return s.replace(/;\\s*$/, '');\n          }).join('; ');\n          if (combined) replacement.setAttribute('style', combined);\n          // Preserve class + dir if requested.\n          if (el.hasAttribute('class')) replacement.setAttribute('class', el.getAttribute('class'));\n          if (map.keepDirAttr && el.hasAttribute('dir')) {\n            replacement.setAttribute('dir', el.getAttribute('dir'));\n          }\n          while (el.firstChild) replacement.appendChild(el.firstChild);\n          el.parentNode.replaceChild(replacement, el);\n        }\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InlineSanitizer);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/InlineSanitizer.js?");

/***/ }),

/***/ "./src/includes/InnerPaddingControl.js":
/*!*********************************************!*\
  !*** ./src/includes/InnerPaddingControl.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * InnerPaddingControl — 4-side numeric editor for **intrinsic-shape**\n * padding. Sibling of `PaddingMarginControl`, deliberately NOT a\n * subclass. The two controls serve semantically different purposes:\n *\n *   | Control                | Use case                                         |\n *   | ---------------------- | ------------------------------------------------ |\n *   | PaddingMarginControl   | LAYOUT padding — space around child content in a |\n *   |                        | container (Block / Cell / Page). Has pin toggle  |\n *   |                        | + canvas visualiser bus.                         |\n *   | InnerPaddingControl    | INTRINSIC padding — shapes the element's own     |\n *   |                        | size (Button width/height via `padding: 12 24`,  |\n *   |                        | Alert box inner space, Table-cell padding, form  |\n *   |                        | input breathing room). No pin, no bus. Callback  |\n *   |                        | only.                                            |\n *\n * Mixing them is a bug. See BUILDER.md \"RULE B — Padding semantic\n * separation\" (2026-04-19, W3.8b).\n *\n * DOM reuses `.bjs-pm-*` primitive classes so CSS stays shared and the\n * visual design is identical; `InnerPaddingControl` just omits the pin\n * toggle slot and swaps the info-banner copy.\n */\nvar InnerPaddingControl = /*#__PURE__*/function () {\n  /**\n   * @param {string} label\n   * @param {object} values     initial { top, right, bottom, left }\n   * @param {object} callback   { setValues(values) }\n   */\n  function InnerPaddingControl(label, values, callback) {\n    _classCallCheck(this, InnerPaddingControl);\n    this.label = label;\n    this.top = values.top !== undefined ? values.top : null;\n    this.bottom = values.bottom !== undefined ? values.bottom : null;\n    this.left = values.left !== undefined ? values.left : null;\n    this.right = values.right !== undefined ? values.right : null;\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this._buildDom();\n    this._bindEvents();\n    this._syncPreview();\n  }\n  return _createClass(InnerPaddingControl, [{\n    key: \"_buildDom\",\n    value: function _buildDom() {\n      var _this = this;\n      var side = function side(name, labelKey) {\n        var value = _this[name];\n        var display = value === null ? '' : value;\n        var nullClass = value === null ? 'is-null' : '';\n        return \"\\n                <div class=\\\"bjs-pm-side\\\" data-side=\\\"\".concat(name, \"\\\">\\n                    <label class=\\\"bjs-pm-side-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"</label>\\n                    <div class=\\\"bjs-pm-side-stepper\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"\").concat(name, \"-clear\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">close</span>\\n                        </button>\\n                        <input type=\\\"number\\\" class=\\\"bjs-text-input bjs-pm-input \").concat(nullClass, \"\\\" name=\\\"\").concat(name, \"\\\" value=\\\"\").concat(display, \"\\\" placeholder=\\\"--\\\" min=\\\"0\\\" step=\\\"1\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"\\\">\\n                        <div class=\\\"bjs-vstepper\\\" role=\\\"group\\\">\\n                            <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-increase\\\" aria-label=\\\"+\\\">\\n                                <span class=\\\"material-symbols-rounded\\\">arrow_drop_up</span>\\n                            </button>\\n                            <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-decrease\\\" aria-label=\\\"\\u2212\\\">\\n                                <span class=\\\"material-symbols-rounded\\\">arrow_drop_down</span>\\n                            </button>\\n                        </div>\\n                    </div>\\n                </div>\\n            \");\n      };\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack bjs-pm-control bjs-pm-control--inner\\\">\\n                <div class=\\\"bjs-pm-label-row\\\" style=\\\"display:flex;align-items:center;gap:8px;\\\">\\n                    <label class=\\\"bjs-control-label\\\" style=\\\"margin:0;\\\">\".concat(this.label, \"</label>\\n                </div>\\n                <div class=\\\"bjs-info-banner bjs-info-banner--flush\\\" role=\\\"note\\\">\\n                    <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n                    <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('inner_padding.help'), \"</span>\\n                </div>\\n                <div class=\\\"bjs-pm-body\\\">\\n                    <div class=\\\"bjs-pm-grid\\\">\\n                        \").concat(side('top', 'padding.top'), \"\\n                        \").concat(side('left', 'padding.left'), \"\\n                        \").concat(side('right', 'padding.right'), \"\\n                        \").concat(side('bottom', 'padding.bottom'), \"\\n                    </div>\\n                    <div class=\\\"bjs-pm-preview\\\" aria-hidden=\\\"true\\\">\\n                        <div class=\\\"bjs-pm-preview-outer\\\" data-control=\\\"preview-outer\\\">\\n                            <div class=\\\"bjs-pm-preview-inner\\\" data-control=\\\"preview-inner\\\"></div>\\n                        </div>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      ['top', 'right', 'bottom', 'left'].forEach(function (position) {\n        var clearBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-clear\\\"]\"));\n        var decreaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-decrease\\\"]\"));\n        var increaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-increase\\\"]\"));\n        var input = _this2.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n        clearBtn.addEventListener('click', function () {\n          return _this2.clearValue(position);\n        });\n        decreaseBtn.addEventListener('click', function () {\n          return _this2.updateValue(position, -5);\n        });\n        increaseBtn.addEventListener('click', function () {\n          return _this2.updateValue(position, 5);\n        });\n        input.addEventListener('input', function (e) {\n          return _this2.setValue(position, e.target.value);\n        });\n        input.addEventListener('focus', function () {\n          return _this2._syncPreview();\n        });\n      });\n    }\n  }, {\n    key: \"clearValue\",\n    value: function clearValue(position) {\n      this[position] = null;\n      var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n      input.value = '';\n      input.classList.add('is-null');\n      this.callback.setValues(this.getValues());\n      this._syncPreview();\n    }\n  }, {\n    key: \"updateValue\",\n    value: function updateValue(position, delta) {\n      var currentValue = this[position] === null ? 0 : this[position];\n      this[position] = Math.max(0, currentValue + delta);\n      var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n      input.value = this[position];\n      input.classList.remove('is-null');\n      this.callback.setValues(this.getValues());\n      this._syncPreview();\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(position, value) {\n      if (value === '' || value === null || value === undefined) {\n        this[position] = null;\n        this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.add('is-null');\n      } else {\n        this[position] = Math.max(0, parseInt(value) || 0);\n        this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.remove('is-null');\n      }\n      this.callback.setValues(this.getValues());\n      this._syncPreview();\n    }\n  }, {\n    key: \"getValues\",\n    value: function getValues() {\n      return {\n        top: this.top,\n        bottom: this.bottom,\n        left: this.left,\n        right: this.right\n      };\n    }\n\n    // Identical preview scaling as PaddingMarginControl — 50px ≈ 10px inset,\n    // capped 22px so opposing sides can't collapse the inner box.\n  }, {\n    key: \"_syncPreview\",\n    value: function _syncPreview() {\n      var inner = this.domNode.querySelector('[data-control=\"preview-inner\"]');\n      if (!inner) return;\n      var clamp = function clamp(v) {\n        var n = v == null ? 0 : parseInt(v, 10) || 0;\n        return Math.max(0, Math.min(22, Math.round(n / 5)));\n      };\n      inner.style.top = clamp(this.top) + 'px';\n      inner.style.right = clamp(this.right) + 'px';\n      inner.style.bottom = clamp(this.bottom) + 'px';\n      inner.style.left = clamp(this.left) + 'px';\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InnerPaddingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/InnerPaddingControl.js?");

/***/ }),

/***/ "./src/includes/LabelElement.js":
/*!**************************************!*\
  !*** ./src/includes/LabelElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _RadiosControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./RadiosControl.js */ \"./src/includes/RadiosControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar LabelElement = /*#__PURE__*/function (_BaseElement) {\n  function LabelElement(template, text) {\n    var _this;\n    _classCallCheck(this, LabelElement);\n    _this = _callSuper(this, LabelElement); // Call the parent class constructor\n    _this.template = template;\n    _this.text = text;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['text'];\n\n    // Inline edit\n    // W0.2b note: LabelElement does NOT call registerInlineEdit('text').\n    // Label.template.html intentionally omits the inline-edit=\"text\" attr\n    // (labels render `<label><%- text %></label>` only — no editable\n    // surface). Users edit a Label's text via the sidebar RichTextControl.\n    // Pre-W0.2b this element declared `inlineEditParams = ['text']` but\n    // the per-element wire silently no-op'd because the template had no\n    // matching node. The strict W0.2b guards correctly surface this; the\n    // honest fix is to drop the dead declaration. If a future ship makes\n    // Label inline-editable on canvas, add `inline-edit=\"text\"` to\n    // Label.template.html FIRST then add `registerInlineEdit('text')` here.\n\n    // Formatter\n    _this.formatter = new Formatter({\n      // text styles\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      link_color: null,\n      paragraph_spacing: null,\n      text_align: 'left',\n      // left, center, right,\n      line_height: null,\n      letter_spacing: null,\n      text_direction: \"ltr\",\n      // ltr, rtl\n\n      // background\n      background_color: null,\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      // spacing\n      padding_top: 0,\n      padding_right: 0,\n      padding_bottom: 0,\n      padding_left: 0,\n      // border\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_width: null,\n      border_left_style: null,\n      border_left_color: null,\n      // border radius\n      border_radius: 0\n    });\n    return _this;\n  }\n  _inherits(LabelElement, _BaseElement);\n  return _createClass(LabelElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.label');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged (W0.2c); see W0.2b note above re: no inline-edit\n      this.domNode.innerHTML = this.renderTemplate({});\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(LabelElement, \"getData\", this, 3)([])), {}, {\n        text: this.text\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [\n      // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n      // Canvas inline-edit = text surface; sidebar = config panel only.\n      new FontFamilyControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_family', value);\n          _this2.render();\n        }\n      }, busOpts('font_family')), new FontWeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_weight', value);\n          _this2.render();\n        }\n      }, busOpts('font_weight')), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_size', value);\n          _this2.render();\n        }\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_color', value);\n          _this2.render();\n        }\n      }), new ColorPickerControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('link_color', value);\n          _this2.render();\n        }\n      }), new AlignControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_align', value);\n          _this2.render();\n        }\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('paragraph_spacing', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new LineHeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('line_height', value);\n          _this2.render();\n        }\n      }), new NumberControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('letter_spacing', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new TextDirectionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_direction', value);\n          _this2.render();\n        }\n      }), new BackgroundControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this2.formatter.setFormat('background_color', values.color);\n          _this2.formatter.setFormat('background_image', values.image);\n          _this2.formatter.setFormat('background_position', values.position);\n          _this2.formatter.setFormat('background_size', values.size);\n          _this2.formatter.setFormat('background_repeat', values.repeat);\n          _this2.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this2.formatter.setFormat('border_top_style', border_top_style);\n          _this2.formatter.setFormat('border_top_width', border_top_width);\n          _this2.formatter.setFormat('border_top_color', border_top_color);\n          _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this2.formatter.setFormat('border_left_style', border_left_style);\n          _this2.formatter.setFormat('border_left_width', border_left_width);\n          _this2.formatter.setFormat('border_left_color', border_left_color);\n          _this2.formatter.setFormat('border_right_style', border_right_style);\n          _this2.formatter.setFormat('border_right_width', border_right_width);\n          _this2.formatter.setFormat('border_right_color', border_right_color);\n\n          // re-render\n          _this2.render();\n        }\n      }), new BorderRadiusControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this2.formatter.setFormat('border_radius', v);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.text), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LabelElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LabelElement.js?");

/***/ }),

/***/ "./src/includes/LegacyHeadingAliasElement.js":
/*!***************************************************!*\
  !*** ./src/includes/LegacyHeadingAliasElement.js ***!
  \***************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\nvar LegacyHeadingAliasElement = /*#__PURE__*/function (_HeadingElement) {\n  function LegacyHeadingAliasElement(template, text) {\n    _classCallCheck(this, LegacyHeadingAliasElement);\n    return _callSuper(this, LegacyHeadingAliasElement, ['Heading', (this instanceof LegacyHeadingAliasElement ? this.constructor : void 0).headingType, text]);\n  }\n  _inherits(LegacyHeadingAliasElement, _HeadingElement);\n  return _createClass(LegacyHeadingAliasElement, [{\n    key: \"getClassName\",\n    value: function getClassName() {\n      return 'HeadingElement';\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return this.constructor.headingLabel;\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      // W0.2c: legacy aliases create a HeadingElement (forced type), not\n      // an instance of `this`, so we use HeadingElement.parseFormats\n      // (inherited via BaseElement) directly.\n      var element = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]('Heading', this.headingType, data.text || this.headingLabel);\n      return _HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].parseFormats(element, data);\n    }\n  }]);\n}(_HeadingElement_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\nLegacyHeadingAliasElement.headingType = 'h1';\nLegacyHeadingAliasElement.headingLabel = 'Heading 1';\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LegacyHeadingAliasElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LegacyHeadingAliasElement.js?");

/***/ }),

/***/ "./src/includes/LetterSpacingControl.js":
/*!**********************************************!*\
  !*** ./src/includes/LetterSpacingControl.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar LetterSpacingControl = /*#__PURE__*/function () {\n  function LetterSpacingControl(label, value, callback) {\n    _classCallCheck(this, LetterSpacingControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.value = value; // Initial /* left | center | right */\n    this.callback = callback; // Callback function to handle input changes\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n  }\n  return _createClass(LetterSpacingControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n      <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3\\\">\").concat(this.label, \"</label>\\n\\n      <div class=\\\"input-group flex-nowrap w-25 \\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"min-width:140px; height: 32px;\\\">\\n        <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"reduction\\\" type=\\\"button\\\">-</button>\\n        <input id=\\\"\").concat(this.id, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control text-center\\\" style=\\\"font-size: 0.875em;\\\" readonly>\\n        <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"increment\\\" type=\\\"button\\\">+</button>\\n      </div>\\n    </div>\");\n      var decrease = this.domNode.querySelector('[role=\"reduction\"]');\n      var increase = this.domNode.querySelector('[role=\"increment\"]');\n      var input = this.domNode.querySelector(\"#\".concat(this.id));\n      var step = 1;\n      var changeValue = function changeValue(delta) {\n        var numeric = parseFloat(_this.value);\n        if (isNaN(numeric)) numeric = 0;\n        numeric = numeric + delta;\n        numeric = Math.max(0, numeric);\n        numeric = Math.round(numeric * 10) / 10;\n        _this.setValue(numeric);\n      };\n      if (decrease) {\n        decrease.addEventListener('click', function (e) {\n          e.preventDefault();\n          changeValue(-step);\n        });\n      }\n      if (increase) {\n        increase.addEventListener('click', function (e) {\n          e.preventDefault();\n          changeValue(step);\n        });\n      }\n\n      // allow direct programmatic update keeping UI in sync\n      this._inputNode = input;\n\n      // normalize initial display\n      // this.setValue(this.value === undefined ? 0 : this.value);\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      var input = this.domNode.querySelector('input');\n      if (input) {\n        input.value = this.value;\n      }\n\n      // Support both function and object with setValue\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LetterSpacingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LetterSpacingControl.js?");

/***/ }),

/***/ "./src/includes/LineHeightControl.js":
/*!*******************************************!*\
  !*** ./src/includes/LineHeightControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar LineHeightControl = /*#__PURE__*/function () {\n  function LineHeightControl(label, value, callback) {\n    _classCallCheck(this, LineHeightControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n    this.presets = [{\n      name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_1_2'),\n      value: 1.2\n    }, {\n      name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_1_5'),\n      value: 1.5\n    }, {\n      name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_1_8'),\n      value: 1.8\n    }, {\n      name: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.line_2'),\n      value: 2\n    }];\n    this.domNode = document.createElement(\"div\");\n    this.render();\n  }\n\n  // Does the current value match one of the four preset buckets?\n  return _createClass(LineHeightControl, [{\n    key: \"_isPreset\",\n    value: function _isPreset(v) {\n      if (v === null || v === undefined || v === '') return false;\n      return this.presets.some(function (p) {\n        return String(p.value) === String(v);\n      });\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      // A preset is \"custom\" when the stored value is numeric but not one of\n      // the four preset values. Empty/null → \"not set\".\n      var isPresetValue = this._isPreset(this.value);\n      var isCustomValue = this.value !== null && this.value !== undefined && this.value !== '' && !isPresetValue;\n      var customValue = isCustomValue ? this.value : 1.5;\n      var optionsHtml = [\"<option value=\\\"\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_weight.not_set'), \"</option>\")].concat(_toConsumableArray(this.presets.map(function (p) {\n        var selected = String(p.value) === String(_this.value) ? ' selected' : '';\n        return \"<option value=\\\"\".concat(p.value, \"\\\"\").concat(selected, \">\").concat(p.name, \"</option>\");\n      })), [\"<option value=\\\"__custom__\\\"\".concat(isCustomValue ? ' selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.custom'), \"</option>\")]).join('');\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\"><label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-select\\\">\\n            <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"\\\" name=\\\"line-height\\\">\").concat(optionsHtml, \"</select>\\n            <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n          </div>\\n        </div>\\n      </div>\\n      <div class=\\\"bjs-control-row bjs-line-height-custom\\\"\").concat(isCustomValue ? '' : ' hidden', \">\\n        <div class=\\\"bjs-control-label\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('line_height.custom'), \"</span></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-number-input\\\">\\n            <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-action=\\\"dec\\\" aria-label=\\\"Decrease\\\">\\u2212</button>\\n            <input type=\\\"number\\\" class=\\\"bjs-number-value\\\" step=\\\"0.1\\\" min=\\\"0.1\\\" max=\\\"10\\\" value=\\\"\").concat(customValue, \"\\\">\\n            <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-action=\\\"inc\\\" aria-label=\\\"Increase\\\">+</button>\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      this.selectEl = this.domNode.querySelector('select');\n      this.customRow = this.domNode.querySelector('.bjs-line-height-custom');\n      this.numberInput = this.customRow.querySelector('input.bjs-number-value');\n      var dec = this.customRow.querySelector('[data-action=\"dec\"]');\n      var inc = this.customRow.querySelector('[data-action=\"inc\"]');\n      this.selectEl.addEventListener('change', function (e) {\n        var raw = e.target.value;\n        if (raw === '__custom__') {\n          _this2.customRow.hidden = false;\n          _this2.value = parseFloat(_this2.numberInput.value) || 1.5;\n          _this2._fireCallback(_this2.value);\n          try {\n            _this2.numberInput.focus();\n          } catch (err) {}\n        } else if (raw === '') {\n          _this2.customRow.hidden = true;\n          _this2.value = null;\n          _this2._fireCallback(null);\n        } else {\n          _this2.customRow.hidden = true;\n          _this2.value = parseFloat(raw);\n          _this2._fireCallback(_this2.value);\n        }\n      });\n      var commitNumber = function commitNumber() {\n        var n = parseFloat(_this2.numberInput.value);\n        if (isNaN(n)) n = 1.5;\n        n = Math.max(0.1, Math.min(10, +n.toFixed(2)));\n        _this2.numberInput.value = n;\n        _this2.value = n;\n        _this2._fireCallback(n);\n      };\n      this.numberInput.addEventListener('input', function () {\n        var raw = _this2.numberInput.value;\n        if (raw === '' || raw === '-') return;\n        var n = parseFloat(raw);\n        if (!isNaN(n)) {\n          _this2.value = n;\n          _this2._fireCallback(n);\n        }\n      });\n      this.numberInput.addEventListener('blur', commitNumber);\n      this.numberInput.addEventListener('keydown', function (e) {\n        if (e.key === 'ArrowUp') {\n          e.preventDefault();\n          _this2._step(+0.1);\n        }\n        if (e.key === 'ArrowDown') {\n          e.preventDefault();\n          _this2._step(-0.1);\n        }\n      });\n      dec.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this2._step(-0.1);\n      });\n      inc.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this2._step(+0.1);\n      });\n    }\n  }, {\n    key: \"_step\",\n    value: function _step(delta) {\n      var n = parseFloat(this.numberInput.value) || 1.5;\n      n = Math.max(0.1, Math.min(10, +(n + delta).toFixed(2)));\n      this.numberInput.value = n;\n      this.value = n;\n      this._fireCallback(n);\n    }\n  }, {\n    key: \"_fireCallback\",\n    value: function _fireCallback(val) {\n      if (typeof this.callback === 'function') {\n        this.callback(val);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(val);\n      }\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      this.render();\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LineHeightControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LineHeightControl.js?");

/***/ }),

/***/ "./src/includes/LinkColorControl.js":
/*!******************************************!*\
  !*** ./src/includes/LinkColorControl.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar LinkColorControl = /*#__PURE__*/function () {\n  function LinkColorControl(label, value, callback) {\n    _classCallCheck(this, LinkColorControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.value = value; // Initial /* left | center | right */\n    this.callback = callback; // Callback function to handle input changes\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n  }\n  return _createClass(LinkColorControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n      <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3 small\\\">\").concat(this.label, \"</label>\\n\\n        <div class=\\\"d-flex align-items-center border rounded p-1 ps-2 border-default\\\" style=\\\"gap:4px;min-width:140px; max-width:140px; max-height: 32px;\\\">\\n          <input id=\\\"\").concat(this.id, \"_color\\\" type=\\\"color\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control rounded form-control-color\\\">\\n          <input id=\\\"\").concat(this.id, \"_hex\\\" type=\\\"text\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control border-none text-center small\\\" style=\\\"height: 28px;font-size:0.875em !important;\\\" />\\n        </div>\\n    </div>\\n    <style>\\n      #\").concat(this.id, \"_color {\\n        border: none;\\n        padding: 0;\\n        width: 31px;\\n        height: 20px;\\n      }\\n      #\").concat(this.id, \"_hex {\\n        border: none;\\n        text-align: center;\\n      }\\n    </style>\\n    \");\n\n      // nodes\n      this.colorInput = this.domNode.querySelector(\"#\".concat(this.id, \"_color\"));\n      this.hexInput = this.domNode.querySelector(\"#\".concat(this.id, \"_hex\"));\n\n      // sync handlers\n      var notify = function notify(val) {\n        _this.value = val;\n        if (typeof _this.callback === \"function\") {\n          _this.callback(val);\n        } else if (_this.callback && typeof _this.callback.setValue === \"function\") {\n          _this.callback.setValue(val);\n        }\n      };\n      this.colorInput.addEventListener(\"input\", function (e) {\n        var v = e.target.value;\n        _this.hexInput.value = v;\n        notify(v);\n      });\n      this.hexInput.addEventListener(\"change\", function (e) {\n        var v = e.target.value.trim();\n        if (!v.startsWith(\"#\")) v = \"#\" + v;\n        // basic validation to 3/6 hex chars\n        if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) {\n          _this.colorInput.value = v;\n          _this.hexInput.value = v;\n          notify(v);\n        } else {\n          // revert to last known good\n          _this.hexInput.value = _this.value;\n        }\n      });\n\n      // keep UI in sync if value was set programmatically before render\n      // this.setValue(this.value);\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      var input = this.domNode.querySelector(\"input\");\n      if (input) {\n        input.value = this.value;\n      }\n\n      // Support both function and object with setValue\n      if (typeof this.callback === \"function\") {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === \"function\") {\n        this.callback.setValue(this.value);\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkColorControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LinkColorControl.js?");

/***/ }),

/***/ "./src/includes/LinkConfigControl.js":
/*!*******************************************!*\
  !*** ./src/includes/LinkConfigControl.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * LinkConfigControl — unified \"where does this click go?\" composite.\n *\n * Design decisions (Phase 2.9/2.10 — 2026-04-17):\n *  - **Type-first UX**: user picks what kind of link (Web URL / Email /\n *    Phone / Anchor) and the control shows type-appropriate fields.\n *    Beats a bare URL field because `mailto:` / `tel:` / `#anchor` are\n *    first-class CTAs, not URL variants users think in.\n *  - **`rel=\"noopener noreferrer\"` auto-added** whenever `target=_blank`.\n *    OWASP-recommended reverse-tabnabbing prevention — no user toggle, just\n *    a correct default.\n *  - **Advanced section collapsed by default**. Most links only need\n *    URL + target + title. Power features (`rel=nofollow|sponsored|ugc`,\n *    `download` filename) live in a `.bjs-group` expander.\n *  - **Failure-state audit (§2.8 C)**: every URL/email/phone/anchor is\n *    validated + errors surface via `.bjs-text-input.is-error` +\n *    `.bjs-link-error`.\n *  - **Uniform sidebar edges (§Composition rule #6)**: every child is a\n *    top-level `.bjs-*` primitive in a bare `<div>` wrapper — no double\n *    padding from an outer `.bjs-control-stack`.\n *\n * Shared by ButtonElement + LinkElement (+ callable by any future element\n * with a link action — ImageElement's existing LinkInputControl is a\n * simpler ancestor of this one).\n *\n * Constructor: `new LinkConfigControl(label, values, callback)`\n *   label    — control section header (e.g. \"Link\")\n *   values   — { url, target, rel, title, download }\n *              (no `type` — derived from url pattern on mount; user can\n *               switch type via dropdown to get type-specific fields)\n *   callback — { setLink: ({url, target, rel, title, download}) => void }\n *              fires whenever ANY field changes, after validation passes.\n *              Caller stores these on the element (not formatter) —\n *              they're link semantics, not visual styles.\n */\nvar LinkConfigControl = /*#__PURE__*/function () {\n  function LinkConfigControl(label, values, callback, caps) {\n    var _this = this;\n    _classCallCheck(this, LinkConfigControl);\n    this.id = '_lc_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.callback = callback || {};\n\n    // Seed state from incoming values (+ derive type from URL pattern)\n    var _ref = values || {},\n      url = _ref.url,\n      target = _ref.target,\n      rel = _ref.rel,\n      title = _ref.title,\n      download = _ref.download,\n      ariaLabel = _ref.ariaLabel;\n    this.state = {\n      url: url || '',\n      target: target || '',\n      // '' | '_blank'\n      title: title || '',\n      download: download || '',\n      // W4.3 — a11y-critical. Rendered as <a aria-label=\"…\">; consumers\n      // set it when the visible link text doesn't convey the action\n      // (e.g. icon-only link, \"Click here\"-style CTA).\n      ariaLabel: ariaLabel || '',\n      relFlags: this._parseUserRelFlags(rel || ''),\n      // W4.3 — UTM builder state. Seeded from URL query params on\n      // _hydrateFieldsFromUrl; rebuilt into the URL on _buildUrlForType.\n      utm: {\n        source: '',\n        medium: '',\n        campaign: '',\n        term: '',\n        content: ''\n      }\n    };\n    this.state.type = this._deriveType(this.state.url);\n    // Split fields derived from URL for editing per type\n    this._hydrateFieldsFromUrl();\n\n    // Dual-view sync — Phase 1.8 capability tokens (SA I13).\n    // `caps.subscribe(fn)` registers us with the element; `caps.readState()`\n    // returns fresh { url, target, rel, title, download }. Fires whenever\n    // the element mutates link state via ANY surface (sidebar, popover,\n    // programmatic). Idempotent: setValue just re-hydrates state — if the\n    // payload matches the currently-rendered state, the render() is still\n    // cheap (no external ref replacement, user caret lives inside the\n    // newly-built inputs so focus is preserved across edits from OTHER\n    // surfaces but not from keystrokes inside this control — those go\n    // through our own debounced input handler, never through the sync path).\n    if (caps && typeof caps.subscribe === 'function' && typeof caps.readState === 'function') {\n      this._readState = caps.readState;\n      this._disposeSync = caps.subscribe(function () {\n        return _this._syncFromExternal();\n      });\n    }\n    this.domNode = document.createElement('div');\n    this.render();\n  }\n\n  /** Idempotent re-hydrate triggered by element.notifySyncListeners().\n   *  MUST NOT fire `_commit` (would ping back → infinite loop). */\n  return _createClass(LinkConfigControl, [{\n    key: \"_syncFromExternal\",\n    value: function _syncFromExternal() {\n      if (!this._readState) return;\n      var next = this._readState() || {};\n      var same = next.url === this.state.url && next.target === this.state.target && next.title === this.state.title && next.download === this.state.download && (next.ariaLabel || '') === (this.state.ariaLabel || '');\n      if (same) return; // idempotent no-op (SA I13a)\n      this._muteCommit = true;\n      try {\n        this.setValue(next);\n      } finally {\n        this._muteCommit = false;\n      }\n    }\n\n    /** Called by Builder.renderElementControls at control-swap time (SA I14).\n     *  Disposer is required — leaking subscriptions into orphaned controls\n     *  leads to phantom writes into panels that no longer exist (SA I13c). */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._disposeSync) {\n        try {\n          this._disposeSync();\n        } catch (_) {/* no-op */}\n        this._disposeSync = null;\n      }\n      this._readState = null;\n    }\n\n    // ─── URL parsing / building ─────────────────────────────────────────\n  }, {\n    key: \"_deriveType\",\n    value: function _deriveType(url) {\n      if (!url) return 'web';\n      var s = url.trim();\n      if (/^mailto:/i.test(s)) return 'email';\n      if (/^tel:/i.test(s)) return 'phone';\n      // A bare `#` (common default-placeholder for \"no link yet\") counts\n      // as empty/web, not anchor. Only `#some-id` is a real anchor link.\n      if (/^#.+/.test(s)) return 'anchor';\n      return 'web';\n    }\n  }, {\n    key: \"_hydrateFieldsFromUrl\",\n    value: function _hydrateFieldsFromUrl() {\n      var _this$state = this.state,\n        url = _this$state.url,\n        type = _this$state.type;\n      // Defaults for each type's edit fields. Treat a bare `#` (common\n      // \"no link yet\" placeholder in legacy button samples) as empty —\n      // avoids tripping web-URL validation on the first panel open.\n      var webSeed = type === 'web' && url !== '#' ? url : '';\n      this.state.web = {\n        url: webSeed\n      };\n      this.state.email = {\n        to: '',\n        subject: '',\n        body: ''\n      };\n      this.state.phone = {\n        number: ''\n      };\n      this.state.anchor = {\n        id: ''\n      };\n      // Reset UTM state from scratch every hydrate — the \"seed fields\n      // from URL\" contract owns the whole state for this type.\n      this.state.utm = {\n        source: '',\n        medium: '',\n        campaign: '',\n        term: '',\n        content: ''\n      };\n      if (type === 'web' && webSeed) {\n        // W4.3 UTM — extract utm_* params from the web URL. Leave the\n        // URL's displayed value with the params still in it (user\n        // expects to see the full URL they pasted); the UTM fields\n        // mirror them. When the user edits either surface, _buildUrl\n        // rebuilds the URL from base + UTM state at commit time.\n        var qIdx = webSeed.indexOf('?');\n        if (qIdx !== -1) {\n          try {\n            var params = new URLSearchParams(webSeed.slice(qIdx + 1));\n            var utmSource = params.get('utm_source');\n            var utmMedium = params.get('utm_medium');\n            var utmCampaign = params.get('utm_campaign');\n            var utmTerm = params.get('utm_term');\n            var utmContent = params.get('utm_content');\n            if (utmSource) this.state.utm.source = utmSource;\n            if (utmMedium) this.state.utm.medium = utmMedium;\n            if (utmCampaign) this.state.utm.campaign = utmCampaign;\n            if (utmTerm) this.state.utm.term = utmTerm;\n            if (utmContent) this.state.utm.content = utmContent;\n          } catch (_) {/* malformed query — leave UTM empty */}\n        }\n      } else if (type === 'email' && url) {\n        var m = url.match(/^mailto:([^?]*)(?:\\?(.*))?$/i);\n        if (m) {\n          this.state.email.to = m[1] || '';\n          if (m[2]) {\n            var _params = new URLSearchParams(m[2]);\n            this.state.email.subject = _params.get('subject') || '';\n            this.state.email.body = _params.get('body') || '';\n          }\n        }\n      } else if (type === 'phone' && url) {\n        this.state.phone.number = url.replace(/^tel:/i, '');\n      } else if (type === 'anchor' && url) {\n        this.state.anchor.id = url.replace(/^#/, '');\n      }\n    }\n  }, {\n    key: \"_buildUrlForType\",\n    value: function _buildUrlForType() {\n      switch (this.state.type) {\n        case 'web':\n          return this._buildWebUrlWithUtm();\n        case 'email':\n          {\n            var _this$state$email = this.state.email,\n              to = _this$state$email.to,\n              subject = _this$state$email.subject,\n              body = _this$state$email.body;\n            if (!to) return '';\n            var params = new URLSearchParams();\n            if (subject) params.set('subject', subject);\n            if (body) params.set('body', body);\n            var qs = params.toString();\n            return 'mailto:' + to + (qs ? '?' + qs : '');\n          }\n        case 'phone':\n          {\n            var n = this.state.phone.number.trim();\n            return n ? 'tel:' + n.replace(/\\s+/g, '') : '';\n          }\n        case 'anchor':\n          {\n            var id = this.state.anchor.id.trim().replace(/^#/, '');\n            return id ? '#' + id : '';\n          }\n      }\n      return '';\n    }\n\n    /**\n     * W4.3 — rebuild a web URL with UTM params merged in. Strips any\n     * existing utm_* params from the base URL (so the user's UTM fields\n     * are the single source of truth) + appends only the UTM fields that\n     * are non-empty. Preserves every OTHER existing query param (e.g.\n     * `?ref=newsletter` stays; `?utm_source=old` gets overwritten by the\n     * UTM field's current value if set, or dropped entirely if empty).\n     */\n  }, {\n    key: \"_buildWebUrlWithUtm\",\n    value: function _buildWebUrlWithUtm() {\n      var raw = this.state.web && this.state.web.url || '';\n      if (!raw) return '';\n      var utm = this.state.utm || {};\n      var utmEntries = Object.entries({\n        utm_source: utm.source,\n        utm_medium: utm.medium,\n        utm_campaign: utm.campaign,\n        utm_term: utm.term,\n        utm_content: utm.content\n      }).filter(function (_ref2) {\n        var _ref3 = _slicedToArray(_ref2, 2),\n          v = _ref3[1];\n        return v && String(v).trim();\n      });\n\n      // If no UTM fields AND no utm_* in raw URL, short-circuit.\n      var qIdx = raw.indexOf('?');\n      var hashIdx = raw.indexOf('#');\n      var basePart = raw;\n      var queryPart = '';\n      var hashPart = '';\n      if (hashIdx !== -1) {\n        hashPart = raw.slice(hashIdx);\n        basePart = raw.slice(0, hashIdx);\n      }\n      var bQIdx = basePart.indexOf('?');\n      if (bQIdx !== -1) {\n        queryPart = basePart.slice(bQIdx + 1);\n        basePart = basePart.slice(0, bQIdx);\n      }\n\n      // Strip existing utm_* from the query (the UTM state is authoritative).\n      var params;\n      try {\n        params = new URLSearchParams(queryPart);\n      } catch (_) {\n        params = new URLSearchParams();\n      }\n      for (var _i = 0, _arr = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; _i < _arr.length; _i++) {\n        var key = _arr[_i];\n        params[\"delete\"](key);\n      }\n      // Append UTM fields that are non-empty.\n      var _iterator = _createForOfIteratorHelper(utmEntries),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var _step$value = _slicedToArray(_step.value, 2),\n            _key = _step$value[0],\n            value = _step$value[1];\n          params.set(_key, String(value).trim());\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n      var qs = params.toString();\n      return basePart + (qs ? '?' + qs : '') + hashPart;\n    }\n\n    /** Returns true if any UTM field is populated. Drives the \"Clear UTM\"\n     *  button visibility + the UTM summary chip. */\n  }, {\n    key: \"_hasUtm\",\n    value: function _hasUtm() {\n      var u = this.state.utm || {};\n      return !!(u.source || u.medium || u.campaign || u.term || u.content);\n    }\n\n    // ─── Rel handling ───────────────────────────────────────────────────\n\n    // User-toggleable rel flags. Security flags (`noopener`, `noreferrer`)\n    // are NOT in this list — they auto-attach whenever `target=_blank`\n    // per OWASP reverse-tabnabbing guidance, and making them user-\n    // toggleable would let a user accidentally disable them. Keep the\n    // auto-path as the single source of truth.\n    //\n    // W4.3 (2026-04-24) — extended from 3 to 5: added `bookmark` (signal\n    // the link is a permalink to a section anchor, useful for docs /\n    // TOC-style UIs) + `author` (the link points to the author's page,\n    // common on bylines + pull-quotes).\n  }, {\n    key: \"_parseUserRelFlags\",\n    value: function _parseUserRelFlags(rel) {\n      var tokens = rel.toLowerCase().split(/\\s+/).filter(Boolean);\n      return LinkConfigControl.USER_REL_FLAGS.filter(function (f) {\n        return tokens.includes(f);\n      });\n    }\n  }, {\n    key: \"_computeRel\",\n    value: function _computeRel() {\n      // User-toggled + auto-security (noopener noreferrer when _blank)\n      var auto = this.state.type === 'web' && this.state.target === '_blank' ? ['noopener', 'noreferrer'] : [];\n      var all = [].concat(_toConsumableArray(this.state.relFlags), auto);\n      return all.join(' ').trim();\n    }\n\n    // ─── Validation ─────────────────────────────────────────────────────\n  }, {\n    key: \"_validate\",\n    value: function _validate() {\n      var errors = {};\n      var s = this.state;\n      if (s.type === 'web') {\n        var v = s.web.url.trim();\n        if (v && !/^(https?:\\/\\/|\\/|\\.{0,2}\\/|blob:|data:)/i.test(v)) {\n          errors.web = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_web_url');\n        }\n      } else if (s.type === 'email') {\n        var _v = s.email.to.trim();\n        if (_v && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(_v)) {\n          errors.email = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_email');\n        }\n      } else if (s.type === 'phone') {\n        var _v2 = s.phone.number.trim();\n        if (_v2 && !/^[+()\\d\\s-]+$/.test(_v2)) {\n          errors.phone = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_phone');\n        }\n      } else if (s.type === 'anchor') {\n        var _v3 = s.anchor.id.trim();\n        if (_v3 && !/^[A-Za-z][\\w-]*$/.test(_v3.replace(/^#/, ''))) {\n          errors.anchor = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.err_anchor');\n        }\n      }\n      return errors;\n    }\n\n    // ─── Fire callback ──────────────────────────────────────────────────\n  }, {\n    key: \"_commit\",\n    value: function _commit() {\n      if (this._muteCommit) return; // suppress during _syncFromExternal\n      var errors = this._validate();\n      this._renderErrors(errors);\n      if (Object.keys(errors).length > 0) return; // swallow — don't propagate bad state\n\n      var url = this._buildUrlForType();\n      this.state.url = url;\n      var rel = this._computeRel();\n      this._renderAutoRelHint();\n      var payload = {\n        url: url,\n        target: this.state.type === 'web' ? this.state.target : '',\n        // target only meaningful for web\n        rel: rel,\n        title: this.state.title,\n        download: this.state.download,\n        // W4.3 — optional a11y override. Consumers apply as `aria-label`\n        // on the rendered `<a>`; empty string means \"let the visible\n        // link text provide the label\" (browser default).\n        ariaLabel: this.state.ariaLabel || ''\n      };\n      if (typeof this.callback.setLink === 'function') this.callback.setLink(payload);else if (typeof this.callback === 'function') this.callback(payload);\n    }\n\n    // ─── Render ─────────────────────────────────────────────────────────\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this2 = this;\n      var t = this.state.type;\n      var relHtml = LinkConfigControl.USER_REL_FLAGS.map(function (flag) {\n        return \"\\n            <label class=\\\"bjs-checkbox\\\" data-rel-label=\\\"\".concat(flag, \"\\\">\\n                <input type=\\\"checkbox\\\" class=\\\"bjs-checkbox-input\\\" value=\\\"\").concat(flag, \"\\\" \").concat(_this2.state.relFlags.includes(flag) ? 'checked' : '', \">\\n                <span class=\\\"bjs-checkbox-box\\\" aria-hidden=\\\"true\\\"></span>\\n                <span>\").concat(flag, \"</span>\\n            </label>\\n        \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n                <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">link</span>\\n                <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.banner'), \"</span>\\n            </div>\\n\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_type\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-select\\\">\\n                        <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"_type\\\" data-control=\\\"type\\\">\\n                            <option value=\\\"web\\\"    \").concat(t === 'web' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_web'), \"</option>\\n                            <option value=\\\"email\\\"  \").concat(t === 'email' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_email'), \"</option>\\n                            <option value=\\\"phone\\\"  \").concat(t === 'phone' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_phone'), \"</option>\\n                            <option value=\\\"anchor\\\" \").concat(t === 'anchor' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.type_anchor'), \"</option>\\n                        </select>\\n                        <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n                    </div>\\n                </div>\\n            </div>\\n\\n            <!-- WEB -->\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"web\\\" \").concat(t === 'web' ? '' : 'hidden', \">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_web\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.url'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-link-input\\\">\\n                        <input type=\\\"url\\\"\\n                            id=\\\"\").concat(this.id, \"_web\\\"\\n                            data-field=\\\"web.url\\\"\\n                            class=\\\"bjs-text-input\\\"\\n                            placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.url_placeholder'), \"\\\"\\n                            value=\\\"\").concat(this._escAttr(this.state.web.url), \"\\\"\\n                            autocomplete=\\\"url\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"clear-web\\\"\\n                                aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.clear'), \"\\\"\\n                                \").concat(this.state.web.url ? '' : 'hidden', \">\\n                            <span class=\\\"material-symbols-rounded\\\">close</span>\\n                        </button>\\n                    </div>\\n                    <span class=\\\"bjs-link-error\\\" data-error=\\\"web\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"web\\\" \").concat(t === 'web' ? '' : 'hidden', \">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_target\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.target'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-select\\\">\\n                        <select class=\\\"bjs-select-native\\\" id=\\\"\").concat(this.id, \"_target\\\" data-control=\\\"target\\\">\\n                            <option value=\\\"\\\"       \").concat(!this.state.target ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.target_self'), \"</option>\\n                            <option value=\\\"_blank\\\" \").concat(this.state.target === '_blank' ? 'selected' : '', \">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.target_blank'), \"</option>\\n                        </select>\\n                        <span class=\\\"material-symbols-rounded bjs-select-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n                    </div>\\n                </div>\\n            </div>\\n\\n            <!-- EMAIL -->\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"email\\\" \").concat(t === 'email' ? '' : 'hidden', \">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_email_to\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_to'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"email\\\" id=\\\"\").concat(this.id, \"_email_to\\\" data-field=\\\"email.to\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_to_placeholder'), \"\\\"\\n                        value=\\\"\").concat(this._escAttr(this.state.email.to), \"\\\">\\n                    <span class=\\\"bjs-link-error\\\" data-error=\\\"email\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"email\\\" \").concat(t === 'email' ? '' : 'hidden', \">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_email_subject\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_subject'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_email_subject\\\" data-field=\\\"email.subject\\\" class=\\\"bjs-text-input\\\"\\n                        value=\\\"\").concat(this._escAttr(this.state.email.subject), \"\\\">\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-control-stack\\\" data-type-view=\\\"email\\\" \").concat(t === 'email' ? '' : 'hidden', \">\\n                <label class=\\\"bjs-control-label\\\" for=\\\"\").concat(this.id, \"_email_body\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.email_body'), \"</span></label>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <textarea id=\\\"\").concat(this.id, \"_email_body\\\" data-field=\\\"email.body\\\" class=\\\"bjs-textarea\\\" rows=\\\"3\\\">\").concat(this._escAttr(this.state.email.body), \"</textarea>\\n                </div>\\n            </div>\\n\\n            <!-- PHONE -->\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"phone\\\" \").concat(t === 'phone' ? '' : 'hidden', \">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_phone\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.phone_number'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"tel\\\" id=\\\"\").concat(this.id, \"_phone\\\" data-field=\\\"phone.number\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.phone_placeholder'), \"\\\"\\n                        value=\\\"\").concat(this._escAttr(this.state.phone.number), \"\\\">\\n                    <span class=\\\"bjs-link-error\\\" data-error=\\\"phone\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n                </div>\\n            </div>\\n\\n            <!-- ANCHOR -->\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\" data-type-view=\\\"anchor\\\" \").concat(t === 'anchor' ? '' : 'hidden', \">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_anchor\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.anchor_id'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_anchor\\\" data-field=\\\"anchor.id\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.anchor_placeholder'), \"\\\"\\n                        value=\\\"\").concat(this._escAttr(this.state.anchor.id), \"\\\">\\n                    <span class=\\\"bjs-link-error\\\" data-error=\\\"anchor\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n                </div>\\n            </div>\\n\\n            <!-- TITLE (always visible) -->\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_title\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.title'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_title\\\" data-field=\\\"title\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.title_placeholder'), \"\\\"\\n                        value=\\\"\").concat(this._escAttr(this.state.title), \"\\\">\\n                </div>\\n            </div>\\n\\n            <!-- ARIA-LABEL (always visible \\u2014 W4.3) -->\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n                <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_aria\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.aria_label'), \"</span></label></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_aria\\\" data-field=\\\"ariaLabel\\\" class=\\\"bjs-text-input\\\"\\n                        placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.aria_label_placeholder'), \"\\\"\\n                        value=\\\"\").concat(this._escAttr(this.state.ariaLabel || ''), \"\\\">\\n                </div>\\n            </div>\\n\\n            <!-- AUTO-REL HINT (only when target=_blank) -->\\n            <div class=\\\"bjs-info-banner bjs-info-banner--success bjs-link-auto-rel\\\"\\n                 \").concat(this.state.type === 'web' && this.state.target === '_blank' ? '' : 'hidden', \">\\n                <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">shield</span>\\n                <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.auto_rel_notice'), \"</span>\\n            </div>\\n\\n            <!-- ADVANCED (collapsed by default) -->\\n            <div class=\\\"bjs-group is-collapsed\\\" data-group=\\\"advanced\\\">\\n                <div class=\\\"bjs-group-header\\\" role=\\\"button\\\" tabindex=\\\"0\\\" aria-expanded=\\\"false\\\">\\n                    <div>\\n                        <span class=\\\"bjs-group-header-title\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.advanced'), \"</span>\\n                        <span class=\\\"bjs-group-header-desc\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.advanced_desc'), \"</span>\\n                    </div>\\n                    <span class=\\\"material-symbols-rounded bjs-group-header-caret\\\" aria-hidden=\\\"true\\\">expand_more</span>\\n                </div>\\n                <div class=\\\"bjs-group-body\\\">\\n                    <div class=\\\"bjs-control-stack\\\">\\n                        <label class=\\\"bjs-control-label\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.rel'), \"</span></label>\\n                        <div class=\\\"bjs-control-input\\\" style=\\\"flex-direction: column; align-items: stretch; gap: var(--bjs-space-2);\\\">\\n                            \").concat(relHtml, \"\\n                        </div>\\n                    </div>\\n                    <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n                        <div class=\\\"bjs-control-label\\\"><label for=\\\"\").concat(this.id, \"_dl\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.download'), \"</span></label></div>\\n                        <div class=\\\"bjs-control-input\\\">\\n                            <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_dl\\\" data-field=\\\"download\\\" class=\\\"bjs-text-input\\\"\\n                                placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.download_placeholder'), \"\\\"\\n                                value=\\\"\").concat(this._escAttr(this.state.download), \"\\\">\\n                        </div>\\n                    </div>\\n\\n                    <!-- UTM BUILDER (web-only, W4.3) -->\\n                    \").concat(t === 'web' ? \"\\n                    <div class=\\\"bjs-control-stack bjs-link-utm\\\" data-group=\\\"utm\\\">\\n                        <label class=\\\"bjs-control-label\\\" style=\\\"display:flex; align-items:center; justify-content:space-between;\\\">\\n                            <span>\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm'), \"</span>\\n                            <button type=\\\"button\\\" class=\\\"bjs-btn bjs-btn--ghost bjs-link-utm-clear\\\"\\n                                    data-control=\\\"utm-clear\\\"\\n                                    \").concat(this._hasUtm() ? '' : 'hidden', \"\\n                                    style=\\\"font-size:11px; padding:2px 8px;\\\">\\n                                \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_clear'), \"\\n                            </button>\\n                        </label>\\n                        <div class=\\\"bjs-control-input\\\">\\n                            <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_source\\\" data-field=\\\"utm.source\\\" class=\\\"bjs-text-input\\\"\\n                                placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_source_placeholder'), \"\\\"\\n                                value=\\\"\").concat(this._escAttr(this.state.utm.source), \"\\\"\\n                                aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_source_placeholder'), \"\\\">\\n                        </div>\\n                        <div class=\\\"bjs-control-input\\\">\\n                            <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_medium\\\" data-field=\\\"utm.medium\\\" class=\\\"bjs-text-input\\\"\\n                                placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_medium_placeholder'), \"\\\"\\n                                value=\\\"\").concat(this._escAttr(this.state.utm.medium), \"\\\"\\n                                aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_medium_placeholder'), \"\\\">\\n                        </div>\\n                        <div class=\\\"bjs-control-input\\\">\\n                            <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_campaign\\\" data-field=\\\"utm.campaign\\\" class=\\\"bjs-text-input\\\"\\n                                placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_campaign_placeholder'), \"\\\"\\n                                value=\\\"\").concat(this._escAttr(this.state.utm.campaign), \"\\\"\\n                                aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_campaign_placeholder'), \"\\\">\\n                        </div>\\n                        <div class=\\\"bjs-control-input\\\">\\n                            <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_term\\\" data-field=\\\"utm.term\\\" class=\\\"bjs-text-input\\\"\\n                                placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_term_placeholder'), \"\\\"\\n                                value=\\\"\").concat(this._escAttr(this.state.utm.term), \"\\\"\\n                                aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_term_placeholder'), \"\\\">\\n                        </div>\\n                        <div class=\\\"bjs-control-input\\\">\\n                            <input type=\\\"text\\\" id=\\\"\").concat(this.id, \"_utm_content\\\" data-field=\\\"utm.content\\\" class=\\\"bjs-text-input\\\"\\n                                placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_content_placeholder'), \"\\\"\\n                                value=\\\"\").concat(this._escAttr(this.state.utm.content), \"\\\"\\n                                aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_config.utm_content_placeholder'), \"\\\">\\n                        </div>\\n                    </div>\\n                    \") : '', \"\\n                </div>\\n            </div>\\n        \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this3 = this;\n      var root = this.domNode;\n\n      // Type change → swap views\n      root.querySelector('[data-control=\"type\"]').addEventListener('change', function (e) {\n        _this3.state.type = e.target.value;\n        // Re-render so per-type fields swap; preserve existing state\n        _this3.render();\n        _this3._commit();\n      });\n\n      // Target change\n      var targetSel = root.querySelector('[data-control=\"target\"]');\n      if (targetSel) {\n        targetSel.addEventListener('change', function (e) {\n          _this3.state.target = e.target.value;\n          _this3._commit();\n        });\n      }\n\n      // Per-field inputs (debounced onInput + commit onBlur)\n      this._wireFieldInput(root, 'input[data-field=\"web.url\"]', function (v) {\n        _this3.state.web.url = v;\n      }, true);\n      this._wireFieldInput(root, 'input[data-field=\"email.to\"]', function (v) {\n        _this3.state.email.to = v;\n      }, true);\n      this._wireFieldInput(root, 'input[data-field=\"email.subject\"]', function (v) {\n        _this3.state.email.subject = v;\n      });\n      this._wireFieldInput(root, 'textarea[data-field=\"email.body\"]', function (v) {\n        _this3.state.email.body = v;\n      });\n      this._wireFieldInput(root, 'input[data-field=\"phone.number\"]', function (v) {\n        _this3.state.phone.number = v;\n      }, true);\n      this._wireFieldInput(root, 'input[data-field=\"anchor.id\"]', function (v) {\n        _this3.state.anchor.id = v;\n      }, true);\n      this._wireFieldInput(root, 'input[data-field=\"title\"]', function (v) {\n        _this3.state.title = v;\n      });\n      this._wireFieldInput(root, 'input[data-field=\"download\"]', function (v) {\n        _this3.state.download = v;\n      });\n      this._wireFieldInput(root, 'input[data-field=\"ariaLabel\"]', function (v) {\n        _this3.state.ariaLabel = v;\n      });\n\n      // W4.3 — UTM builder fields (web-only, present in DOM only when\n      // type === 'web'). Debounced commit via _wireFieldInput rebuilds\n      // the web URL with utm_* params merged via _buildWebUrlWithUtm.\n      this._wireFieldInput(root, 'input[data-field=\"utm.source\"]', function (v) {\n        _this3.state.utm.source = v;\n        _this3._toggleUtmClearBtn();\n      });\n      this._wireFieldInput(root, 'input[data-field=\"utm.medium\"]', function (v) {\n        _this3.state.utm.medium = v;\n        _this3._toggleUtmClearBtn();\n      });\n      this._wireFieldInput(root, 'input[data-field=\"utm.campaign\"]', function (v) {\n        _this3.state.utm.campaign = v;\n        _this3._toggleUtmClearBtn();\n      });\n      this._wireFieldInput(root, 'input[data-field=\"utm.term\"]', function (v) {\n        _this3.state.utm.term = v;\n        _this3._toggleUtmClearBtn();\n      });\n      this._wireFieldInput(root, 'input[data-field=\"utm.content\"]', function (v) {\n        _this3.state.utm.content = v;\n        _this3._toggleUtmClearBtn();\n      });\n\n      // W4.3 — \"Clear UTM\" button wipes all 5 UTM fields + rebuilds URL\n      // without utm_* params. Commits immediately (not debounced) since\n      // the action is explicit.\n      var utmClear = root.querySelector('[data-control=\"utm-clear\"]');\n      if (utmClear) {\n        utmClear.addEventListener('click', function () {\n          _this3.state.utm = {\n            source: '',\n            medium: '',\n            campaign: '',\n            term: '',\n            content: ''\n          };\n          // Clear visible inputs so the user sees state reset immediately.\n          ['source', 'medium', 'campaign', 'term', 'content'].forEach(function (k) {\n            var inp = root.querySelector(\"input[data-field=\\\"utm.\".concat(k, \"\\\"]\"));\n            if (inp) inp.value = '';\n          });\n          utmClear.setAttribute('hidden', '');\n          _this3._commit();\n        });\n      }\n\n      // Clear web URL\n      var clearWeb = root.querySelector('[data-control=\"clear-web\"]');\n      if (clearWeb) {\n        clearWeb.addEventListener('click', function () {\n          var inp = root.querySelector('input[data-field=\"web.url\"]');\n          if (inp) inp.value = '';\n          _this3.state.web.url = '';\n          clearWeb.setAttribute('hidden', '');\n          _this3._commit();\n        });\n      }\n\n      // Rel checkboxes\n      root.querySelectorAll('[data-rel-label] input[type=\"checkbox\"]').forEach(function (cb) {\n        cb.addEventListener('change', function () {\n          var flag = cb.value;\n          var idx = _this3.state.relFlags.indexOf(flag);\n          if (cb.checked && idx === -1) _this3.state.relFlags.push(flag);\n          if (!cb.checked && idx !== -1) _this3.state.relFlags.splice(idx, 1);\n          _this3._commit();\n        });\n      });\n\n      // Advanced group collapse toggle\n      var group = root.querySelector('[data-group=\"advanced\"]');\n      if (group) {\n        var header = group.querySelector('.bjs-group-header');\n        var toggle = function toggle() {\n          group.classList.toggle('is-collapsed');\n          header.setAttribute('aria-expanded', (!group.classList.contains('is-collapsed')).toString());\n        };\n        header.addEventListener('click', toggle);\n        header.addEventListener('keydown', function (e) {\n          if (e.key === 'Enter' || e.key === ' ') {\n            e.preventDefault();\n            toggle();\n          }\n        });\n      }\n    }\n  }, {\n    key: \"_wireFieldInput\",\n    value: function _wireFieldInput(root, selector, apply) {\n      var _this4 = this;\n      var alsoClearErrorOnInput = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n      var el = root.querySelector(selector);\n      if (!el) return;\n      var debounceId = null;\n      var commit = function commit() {\n        if (debounceId) clearTimeout(debounceId);\n        debounceId = null;\n        _this4._commit();\n      };\n      el.addEventListener('input', function () {\n        apply(el.value);\n        if (alsoClearErrorOnInput) {\n          el.classList.remove('is-error');\n          var errType = el.dataset.field.split('.')[0];\n          var errSpan = root.querySelector(\"[data-error=\\\"\".concat(errType, \"\\\"]\"));\n          if (errSpan) errSpan.textContent = '';\n        }\n        if (debounceId) clearTimeout(debounceId);\n        debounceId = setTimeout(commit, 350);\n\n        // Toggle clear button visibility for web URL\n        if (el.dataset.field === 'web.url') {\n          var clr = root.querySelector('[data-control=\"clear-web\"]');\n          if (clr) {\n            if (el.value) clr.removeAttribute('hidden');else clr.setAttribute('hidden', '');\n          }\n        }\n      });\n      el.addEventListener('blur', commit);\n    }\n  }, {\n    key: \"_renderErrors\",\n    value: function _renderErrors(errors) {\n      var _this5 = this;\n      ['web', 'email', 'phone', 'anchor'].forEach(function (kind) {\n        var input = _this5.domNode.querySelector(\"[data-field^=\\\"\".concat(kind, \"\\\"]\"));\n        var errSpan = _this5.domNode.querySelector(\"[data-error=\\\"\".concat(kind, \"\\\"]\"));\n        if (!input || !errSpan) return;\n        if (errors[kind]) {\n          input.classList.add('is-error');\n          errSpan.textContent = errors[kind];\n        } else {\n          input.classList.remove('is-error');\n          errSpan.textContent = '';\n        }\n      });\n    }\n  }, {\n    key: \"_renderAutoRelHint\",\n    value: function _renderAutoRelHint() {\n      var hint = this.domNode.querySelector('.bjs-link-auto-rel');\n      if (!hint) return;\n      var show = this.state.type === 'web' && this.state.target === '_blank';\n      if (show) hint.removeAttribute('hidden');else hint.setAttribute('hidden', '');\n    }\n\n    /** W4.3 — keep the \"Clear UTM\" button visible only while UTM state\n     *  is non-empty. Called on every UTM field input. */\n  }, {\n    key: \"_toggleUtmClearBtn\",\n    value: function _toggleUtmClearBtn() {\n      var btn = this.domNode.querySelector('[data-control=\"utm-clear\"]');\n      if (!btn) return;\n      if (this._hasUtm()) btn.removeAttribute('hidden');else btn.setAttribute('hidden', '');\n    }\n  }, {\n    key: \"_escAttr\",\n    value: function _escAttr(s) {\n      return String(s !== null && s !== void 0 ? s : '').replace(/\"/g, '&quot;');\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Called by element when data changes from outside\n  }, {\n    key: \"setValue\",\n    value: function setValue(values) {\n      var _ref4 = values || {},\n        url = _ref4.url,\n        target = _ref4.target,\n        rel = _ref4.rel,\n        title = _ref4.title,\n        download = _ref4.download,\n        ariaLabel = _ref4.ariaLabel;\n      this.state.url = url || '';\n      this.state.target = target || '';\n      this.state.title = title || '';\n      this.state.download = download || '';\n      this.state.ariaLabel = ariaLabel || '';\n      this.state.relFlags = this._parseUserRelFlags(rel || '');\n      this.state.type = this._deriveType(this.state.url);\n      this._hydrateFieldsFromUrl();\n      this.render();\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return {\n        url: this._buildUrlForType(),\n        target: this.state.type === 'web' ? this.state.target : '',\n        rel: this._computeRel(),\n        title: this.state.title,\n        download: this.state.download,\n        ariaLabel: this.state.ariaLabel || ''\n      };\n    }\n  }]);\n}();\n_defineProperty(LinkConfigControl, \"USER_REL_FLAGS\", ['nofollow', 'sponsored', 'ugc', 'bookmark', 'author']);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkConfigControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LinkConfigControl.js?");

/***/ }),

/***/ "./src/includes/LinkElement.js":
/*!*************************************!*\
  !*** ./src/includes/LinkElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\nvar LinkElement = /*#__PURE__*/function (_BaseElement) {\n  function LinkElement(template, text, url) {\n    var _this;\n    _classCallCheck(this, LinkElement);\n    _this = _callSuper(this, LinkElement);\n    _this.template = template;\n    _this.text = text;\n    // Link semantics — same shape as ButtonElement. Stored on the\n    // element, not the formatter (attribute-level, not visual).\n    _this.url = url || '';\n    _this.target = '';\n    _this.rel = '';\n    _this.title = '';\n    _this.download = '';\n    // W4.3 — optional a11y override for assistive tech. Serialized\n    // in getData + applied via `applyLinkAttrs` as `aria-label`.\n    _this.ariaLabel = '';\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['url'];\n\n    // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n    _this.registerInlineEdit('text');\n    _this.formatter = new Formatter({\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      link_color: null,\n      paragraph_spacing: null,\n      text_align: null,\n      line_height: null,\n      letter_spacing: null,\n      text_direction: null,\n      text_decoration: null\n    });\n    return _this;\n  }\n  _inherits(LinkElement, _BaseElement);\n  return _createClass(LinkElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.link');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        url: this.url || '#',\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download\n      });\n    }\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var a = this.domNode.querySelector('a');\n      if (!a) {\n        this.render();\n        return;\n      }\n      a.setAttribute('style', \"display: block;\".concat(this.formatter.toStyleStringAll()));\n    }\n  }, {\n    key: \"applyLinkAttrs\",\n    value: function applyLinkAttrs() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var a = this.domNode.querySelector('a');\n      if (!a) {\n        this.render();\n        return;\n      }\n      a.setAttribute('href', this.url || '#');\n      if (this.target) a.setAttribute('target', this.target);else a.removeAttribute('target');\n      if (this.rel) a.setAttribute('rel', this.rel);else a.removeAttribute('rel');\n      if (this.title) a.setAttribute('title', this.title);else a.removeAttribute('title');\n      if (this.download) a.setAttribute('download', this.download);else a.removeAttribute('download');\n      if (this.ariaLabel) a.setAttribute('aria-label', this.ariaLabel);else a.removeAttribute('aria-label');\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(LinkElement, \"getData\", this, 3)([])), {}, {\n        text: this.text,\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        ariaLabel: this.ariaLabel\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          _this2.formatter.setFormat(key, value);\n          _this2.applyFormatStyles();\n        };\n      };\n      // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [new TextControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text'), this.text, {\n        setText: function setText(text) {\n          _this2.text = text;\n          var a = _this2.domNode && _this2.domNode.querySelector('a');\n          if (a) a.innerHTML = text;else _this2.render();\n        }\n      }), new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link'), {\n        url: this.url,\n        target: this.target,\n        rel: this.rel,\n        title: this.title,\n        download: this.download,\n        ariaLabel: this.ariaLabel\n      }, {\n        setLink: function setLink(_ref) {\n          var url = _ref.url,\n            target = _ref.target,\n            rel = _ref.rel,\n            title = _ref.title,\n            download = _ref.download,\n            ariaLabel = _ref.ariaLabel;\n          _this2.url = url || '';\n          _this2.target = target || '';\n          _this2.rel = rel || '';\n          _this2.title = title || '';\n          _this2.download = download || '';\n          _this2.ariaLabel = ariaLabel || '';\n          _this2.applyLinkAttrs();\n        }\n      }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: setFmt('text_color')\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: setFmt('link_color')\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('text_align'), {\n        setValue: setFmt('text_align')\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: setFmt('paragraph_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: setFmt('line_height')\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: setFmt('letter_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: setFmt('text_direction')\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new this(data.template, data.text, data.url || '');\n      e.target = data.target || '';\n      e.rel = data.rel || '';\n      e.title = data.title || '';\n      e.download = data.download || '';\n      e.ariaLabel = data.ariaLabel || '';\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/LinkElement.js?");

/***/ }),

/***/ "./src/includes/ListControl.js":
/*!*************************************!*\
  !*** ./src/includes/ListControl.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/sortable.js */ \"./src/includes/ui/sortable.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * ListControl — generic [{label, url}] editor used by MenuElement + ListElement.\n *\n * 2026-04-17 audit: migrated from Bootstrap accordion to `.bjs-list--plain`\n * primitive (dark mode, tokens, no bootstrap collapse).\n *\n * 2026-04-18 Phase-3 W6.2: drag-reorder via shared bjsSortable, shift/\n * cmd-click multi-select + bulk toolbar, inline \"+\" insert slots.\n *\n * 2026-04-19 W3.8c (BUILDER.md RULE A cleanup): Control no longer holds\n * an Element reference. Callers pass `{ getDomNode: () => this.domNode }`\n * — a hook that late-binds to the element's current canvas domNode. The\n * hook is used only for **on-canvas item highlighting** (drawing a\n * floating box over the rendered `<li>` when the user expands a sidebar\n * row). Late-binding preserves the previous re-render-safe behaviour —\n * if the element's `this.render()` replaces its domNode between control\n * construction and highlight use, the next `getDomNode()` call returns\n * the fresh node. Window (iframe defaultView) stays shared across\n * re-renders so scroll/resize listener cleanup is stable.\n */\nvar ListControl = /*#__PURE__*/function () {\n  /**\n   * @param {string} label\n   * @param {Array<{label:string,url:string}>} items\n   * @param {{ setItems: (items) => void }} callback\n   * @param {object} [opts]\n   *   @param {() => HTMLElement|null} [opts.getDomNode]  late-bound hook\n   *     returning the host element's current canvas domNode. Required\n   *     to enable item highlighting. Absent → highlight is a no-op.\n   */\n  function ListControl(label, items, callback) {\n    var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, ListControl);\n    this.label = label;\n    this.items = items;\n    this.callback = callback;\n    // W3.8c — RULE A compliance: primitives + hooks, no element ref.\n    this._getDomNode = typeof opts.getDomNode === 'function' ? opts.getDomNode : null;\n    this.domNode = document.createElement('div');\n    this._multiSelected = new Set();\n    this.render();\n  }\n\n  /** Late-bind the element's current canvas domNode (can be null). */\n  return _createClass(ListControl, [{\n    key: \"_hostDomNode\",\n    value: function _hostDomNode() {\n      return this._getDomNode ? this._getDomNode() : null;\n    }\n  }, {\n    key: \"_t\",\n    value: function _t(key, fallback) {\n      try {\n        var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n        return v && v !== key ? v : fallback;\n      } catch (_e) {\n        return fallback;\n      }\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      // Prune stale multi-select indices (a remove shrinks items before\n      // the set is cleared on user Clear click).\n      this._multiSelected = new Set(Array.from(this._multiSelected).filter(function (i) {\n        return i >= 0 && i < _this.items.length;\n      }));\n      var itemsHtml = this.items.map(function (item, index) {\n        var safeLabel = (item.label || '').replace(/\"/g, '&quot;');\n        var safeUrl = (item.url || '').replace(/\"/g, '&quot;');\n        var displayName = item.label || \"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.item_fallback'), \" #\").concat(index + 1);\n        var isMulti = _this._multiSelected.has(index) ? ' is-multi-selected' : '';\n        return \"\\n                <li class=\\\"bjs-list-item\".concat(isMulti, \"\\\" data-index=\\\"\").concat(index, \"\\\" aria-expanded=\\\"false\\\">\\n                    <button class=\\\"bjs-list-item-handle\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.reorder'), \"\\\" type=\\\"button\\\" tabindex=\\\"0\\\">\\u2261</button>\\n                    <span class=\\\"bjs-list-item-label\\\" data-control=\\\"display-label\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(displayName, \"</span>\\n                    <div class=\\\"bjs-list-item-actions\\\">\\n                        <button class=\\\"bjs-icon-btn bjs-list-item-expand\\\" type=\\\"button\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.edit'), \"\\\" data-control=\\\"expand\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n                        </button>\\n                        <button class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" type=\\\"button\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.delete'), \"\\\" data-control=\\\"remove-item\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">delete</span>\\n                        </button>\\n                    </div>\\n                    <section class=\\\"bjs-list-item-body\\\">\\n                        <div class=\\\"bjs-list-field\\\">\\n                            <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.label'), \"</label>\\n                            <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" value=\\\"\").concat(safeLabel, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"label\\\">\\n                        </div>\\n                        <div class=\\\"bjs-list-field\\\">\\n                            <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.url'), \"</label>\\n                            <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" value=\\\"\").concat(safeUrl, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"url\\\">\\n                        </div>\\n                    </section>\\n                </li>\\n            \");\n      }).join('');\n\n      // Inline insert slots — one between each pair of items plus one before\n      // the first and one after the last. Absolute-positioned overlays so\n      // they don't take flex space. Visible on hover of the slot zone only.\n      var slotsHtml = '';\n      if (this.items.length > 0) {\n        for (var i = 0; i <= this.items.length; i++) {\n          slotsHtml += \"\\n                    <div class=\\\"bjs-list-insert-slot\\\" data-slot-index=\\\"\".concat(i, \"\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-list-insert-slot-btn\\\" data-control=\\\"insert-at\\\" data-index=\\\"\").concat(i, \"\\\" aria-label=\\\"\").concat(this._t('list.insert_here', 'Insert here'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">add</span>\\n                        </button>\\n                    </div>\\n                \");\n        }\n      }\n      var bulkHtml = this._renderBulkBar();\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-list bjs-list--plain\\\">\\n                <header class=\\\"bjs-list-header\\\">\\n                    <span class=\\\"bjs-list-title\\\">\".concat(this.label, \"</span>\\n                    <button class=\\\"bjs-btn\\\" type=\\\"button\\\" data-control=\\\"add-item\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;margin-right:2px\\\">add</span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.add'), \"\\n                    </button>\\n                </header>\\n                <div class=\\\"bjs-list-body\\\">\\n                    <ol class=\\\"bjs-list-items\\\">\\n                        \").concat(itemsHtml, \"\\n                    </ol>\\n                    \").concat(slotsHtml, \"\\n                </div>\\n                \").concat(bulkHtml, \"\\n            </div>\\n        \");\n      this._bindEvents();\n      this._positionInsertSlots();\n      this._bindSortable();\n    }\n  }, {\n    key: \"_renderBulkBar\",\n    value: function _renderBulkBar() {\n      var n = this._multiSelected.size;\n      if (n < 1) return '';\n      var label = this._t('list.bulk_selected', '{n} selected').replace('{n}', String(n));\n      return \"\\n            <div class=\\\"bjs-list-bulk\\\" role=\\\"status\\\" data-count=\\\"\".concat(n, \"\\\">\\n                <span class=\\\"bjs-list-bulk-count\\\">\").concat(label, \"</span>\\n                <span class=\\\"bjs-list-bulk-actions\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-list-bulk-btn\\\" data-control=\\\"bulk-delete\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">delete</span>\\n                        <span>\").concat(this._t('list.bulk_delete', 'Delete'), \"</span>\\n                    </button>\\n                    <button type=\\\"button\\\" class=\\\"bjs-list-bulk-btn bjs-list-bulk-btn--ghost\\\" data-control=\\\"bulk-clear\\\">\\n                        \").concat(this._t('list.bulk_clear', 'Clear'), \"\\n                    </button>\\n                </span>\\n            </div>\\n        \");\n    }\n\n    /** Position the inline insert-slot buttons on the real gap midpoints —\n     *  similar to GridControl._positionSlots but vertical. Keeps the \"+\"\n     *  centered on the border between two items regardless of per-item\n     *  height (an expanded item is taller than a collapsed one). */\n  }, {\n    key: \"_positionInsertSlots\",\n    value: function _positionInsertSlots() {\n      var body = this.domNode.querySelector('.bjs-list-body');\n      var ol = this.domNode.querySelector('.bjs-list-items');\n      if (!body || !ol) return;\n      var items = Array.from(ol.querySelectorAll(':scope > .bjs-list-item'));\n      var slots = Array.from(body.querySelectorAll(':scope > .bjs-list-insert-slot'));\n      if (!items.length || slots.length !== items.length + 1) return;\n      var bodyRect = body.getBoundingClientRect();\n      if (bodyRect.width === 0) return;\n      var olRect = ol.getBoundingClientRect();\n      slots.forEach(function (slot, i) {\n        slot.style.left = \"\".concat(olRect.left - bodyRect.left, \"px\");\n        slot.style.width = \"\".concat(olRect.width, \"px\");\n        var yPx;\n        if (i === 0) {\n          yPx = items[0].getBoundingClientRect().top - bodyRect.top - 4;\n        } else if (i === items.length) {\n          yPx = items[items.length - 1].getBoundingClientRect().bottom - bodyRect.top + 4;\n        } else {\n          var prev = items[i - 1].getBoundingClientRect();\n          var next = items[i].getBoundingClientRect();\n          yPx = (prev.bottom + next.top) / 2 - bodyRect.top;\n        }\n        slot.style.top = \"\".concat(yPx, \"px\");\n      });\n    }\n  }, {\n    key: \"_bindSortable\",\n    value: function _bindSortable() {\n      var _this2 = this;\n      if (this._sortable && typeof this._sortable.destroy === 'function') {\n        try {\n          this._sortable.destroy();\n        } catch (_e) {}\n      }\n      var ol = this.domNode.querySelector('.bjs-list-items');\n      if (!ol) return;\n      this._sortable = (0,_ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__.bjsSortable)(ol, {\n        itemSelector: '.bjs-list-item',\n        handleSelector: '.bjs-list-item-handle',\n        onReorder: function onReorder(from, to) {\n          var _this2$items$splice = _this2.items.splice(from, 1),\n            _this2$items$splice2 = _slicedToArray(_this2$items$splice, 1),\n            moved = _this2$items$splice2[0];\n          var adjusted = to > from ? to - 1 : to;\n          _this2.items.splice(adjusted, 0, moved);\n          // Reset multi-select — indices become ambiguous after reorder.\n          _this2._multiSelected.clear();\n          _this2.render();\n          _this2.callback && _this2.callback.setItems(_this2.items);\n        }\n      });\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this3 = this;\n      var add = this.domNode.querySelector('[data-control=\"add-item\"]');\n      if (add) {\n        add.addEventListener('click', function () {\n          _this3.items.push({\n            label: '',\n            url: ''\n          });\n          _this3.render();\n          _this3.callback && _this3.callback.setItems(_this3.items);\n        });\n      }\n\n      // Inline insert-at slots — click to insert a blank item at position N.\n      this.domNode.querySelectorAll('[data-control=\"insert-at\"]').forEach(function (btn) {\n        btn.addEventListener('click', function (e) {\n          e.stopPropagation();\n          var idx = parseInt(btn.getAttribute('data-index'), 10);\n          if (isNaN(idx)) return;\n          _this3.items.splice(idx, 0, {\n            label: '',\n            url: ''\n          });\n          _this3._multiSelected.clear();\n          _this3.render();\n          _this3.callback && _this3.callback.setItems(_this3.items);\n        });\n      });\n      this.domNode.querySelectorAll('.bjs-list-item').forEach(function (li) {\n        var index = parseInt(li.dataset.index, 10);\n\n        // Shift/Cmd-click on the collapsed-row label zone → multi-select.\n        // Plain click still expands via the expand button below.\n        var labelEl = li.querySelector('[data-control=\"display-label\"]');\n        if (labelEl) {\n          labelEl.addEventListener('click', function (e) {\n            if (!e.shiftKey && !e.metaKey && !e.ctrlKey) return;\n            e.preventDefault();\n            e.stopPropagation();\n            _this3._toggleMulti(index, e.shiftKey);\n          });\n        }\n        var expandBtn = li.querySelector('[data-control=\"expand\"]');\n        if (expandBtn) {\n          expandBtn.addEventListener('click', function (e) {\n            e.stopPropagation();\n            var expanded = li.getAttribute('aria-expanded') === 'true';\n            li.setAttribute('aria-expanded', expanded ? 'false' : 'true');\n            var caret = expandBtn.querySelector('.material-symbols-rounded');\n            if (caret) caret.textContent = expanded ? 'expand_more' : 'expand_less';\n            if (!expanded) _this3.highlightListItem(index);else _this3.removeListItemHighlight(index);\n            // Re-run slot positioning — expanded item height changes.\n            requestAnimationFrame(function () {\n              return _this3._positionInsertSlots();\n            });\n          });\n        }\n        var removeBtn = li.querySelector('[data-control=\"remove-item\"]');\n        if (removeBtn) {\n          removeBtn.addEventListener('click', function (e) {\n            e.preventDefault();\n            e.stopPropagation();\n            _this3.removeListItemHighlight(index);\n            _this3.items.splice(index, 1);\n            _this3._multiSelected.clear();\n            _this3.render();\n            _this3.callback && _this3.callback.setItems(_this3.items);\n          });\n        }\n        li.querySelectorAll('input[data-field]').forEach(function (input) {\n          input.addEventListener('input', function (e) {\n            var field = e.target.getAttribute('data-field');\n            var i = parseInt(e.target.getAttribute('data-index'), 10);\n            _this3.items[i][field] = e.target.value;\n            // Update the collapsed row label in-place\n            if (field === 'label') {\n              var disp = _this3.domNode.querySelector(\"[data-control=\\\"display-label\\\"][data-index=\\\"\".concat(i, \"\\\"]\"));\n              if (disp) disp.textContent = e.target.value || \"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('list.item_fallback'), \" #\").concat(i + 1);\n            }\n            _this3.callback && _this3.callback.setItems(_this3.items);\n          });\n        });\n      });\n\n      // Keyboard reorder on focused handle — ArrowUp / ArrowDown swap with\n      // neighbor. Mirrors GridControl's handle keyboard shortcuts for a11y.\n      this.domNode.querySelectorAll('.bjs-list-item-handle').forEach(function (handle) {\n        handle.addEventListener('keydown', function (e) {\n          if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n          var li = handle.closest('.bjs-list-item');\n          if (!li) return;\n          var idx = parseInt(li.dataset.index, 10);\n          var target = e.key === 'ArrowUp' ? idx - 1 : idx + 1;\n          if (target < 0 || target >= _this3.items.length) return;\n          e.preventDefault();\n          var _this3$items$splice = _this3.items.splice(idx, 1),\n            _this3$items$splice2 = _slicedToArray(_this3$items$splice, 1),\n            moved = _this3$items$splice2[0];\n          _this3.items.splice(target, 0, moved);\n          _this3._multiSelected.clear();\n          _this3.render();\n          _this3.callback && _this3.callback.setItems(_this3.items);\n          requestAnimationFrame(function () {\n            var newHandle = _this3.domNode.querySelector(\".bjs-list-item[data-index=\\\"\".concat(target, \"\\\"] .bjs-list-item-handle\"));\n            if (newHandle && typeof newHandle.focus === 'function') newHandle.focus();\n          });\n        });\n      });\n\n      // Bulk bar\n      var bulkDelete = this.domNode.querySelector('[data-control=\"bulk-delete\"]');\n      if (bulkDelete) {\n        bulkDelete.addEventListener('click', function () {\n          return _this3._bulkDelete();\n        });\n      }\n      var bulkClear = this.domNode.querySelector('[data-control=\"bulk-clear\"]');\n      if (bulkClear) {\n        bulkClear.addEventListener('click', function () {\n          _this3._multiSelected.clear();\n          _this3.render();\n        });\n      }\n    }\n  }, {\n    key: \"_toggleMulti\",\n    value: function _toggleMulti(index, isShift) {\n      if (isShift && this._multiSelected.size > 0) {\n        // Range-select: fill from the lowest existing selection up to\n        // clicked index (or down, whichever reaches).\n        var existing = Array.from(this._multiSelected);\n        var anchor = existing.reduce(function (a, b) {\n          return Math.abs(b - index) < Math.abs(a - index) ? b : a;\n        }, existing[0]);\n        var _ref = anchor < index ? [anchor, index] : [index, anchor],\n          _ref2 = _slicedToArray(_ref, 2),\n          lo = _ref2[0],\n          hi = _ref2[1];\n        for (var i = lo; i <= hi; i++) this._multiSelected.add(i);\n      } else {\n        if (this._multiSelected.has(index)) this._multiSelected[\"delete\"](index);else this._multiSelected.add(index);\n      }\n      this.render();\n    }\n  }, {\n    key: \"_bulkDelete\",\n    value: function _bulkDelete() {\n      var _this4 = this;\n      if (this._multiSelected.size === 0) return;\n      var descending = Array.from(this._multiSelected).sort(function (a, b) {\n        return b - a;\n      });\n      descending.forEach(function (i) {\n        return _this4.items.splice(i, 1);\n      });\n      this._multiSelected.clear();\n      this.render();\n      this.callback && this.callback.setItems(this.items);\n    }\n  }, {\n    key: \"highlightListItem\",\n    value: function highlightListItem(index) {\n      var host = this._hostDomNode();\n      if (!host) return;\n      var liElements = host.querySelectorAll('li');\n      var liElement = liElements[index];\n      if (!liElement) return;\n      var highlightBox = document.createElement('div');\n      highlightBox.classList.add('li-highlight-box', 'active-item-highlight');\n      document.body.appendChild(highlightBox);\n      if (!this.itemHighlightBoxes) this.itemHighlightBoxes = {};\n      this.itemHighlightBoxes[index] = highlightBox;\n      var updatePosition = function updatePosition() {\n        if (!highlightBox || !liElement) return;\n        var domRect = liElement.getBoundingClientRect();\n        var iframe = liElement.ownerDocument.defaultView.frameElement;\n        var iframeRect = iframe.getBoundingClientRect();\n        Object.assign(highlightBox.style, {\n          position: 'fixed',\n          top: \"\".concat(iframeRect.top + domRect.top, \"px\"),\n          left: \"\".concat(iframeRect.left + domRect.left, \"px\"),\n          width: \"\".concat(domRect.width, \"px\"),\n          height: \"\".concat(domRect.height, \"px\"),\n          borderRadius: getComputedStyle(liElement).borderRadius || '6px'\n        });\n      };\n      updatePosition();\n      var win = host.ownerDocument.defaultView;\n      win.addEventListener('scroll', updatePosition, true);\n      win.addEventListener('resize', updatePosition);\n      highlightBox._updatePosition = updatePosition;\n      // Pin the window used so removal uses the same reference even\n      // if the host domNode gets swapped during a re-render (iframe\n      // defaultView is stable within an editing session; this is\n      // belt-and-suspenders for future iframe recreation scenarios).\n      highlightBox._win = win;\n    }\n  }, {\n    key: \"removeListItemHighlight\",\n    value: function removeListItemHighlight(index) {\n      if (!this.itemHighlightBoxes || !this.itemHighlightBoxes[index]) return;\n      var highlightBox = this.itemHighlightBoxes[index];\n      if (highlightBox._updatePosition) {\n        var win = highlightBox._win || (this._hostDomNode() ? this._hostDomNode().ownerDocument.defaultView : null);\n        if (win) {\n          win.removeEventListener('scroll', highlightBox._updatePosition, true);\n          win.removeEventListener('resize', highlightBox._updatePosition);\n        }\n      }\n      highlightBox.remove();\n      delete this.itemHighlightBoxes[index];\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ListControl.js?");

/***/ }),

/***/ "./src/includes/ListElement.js":
/*!*************************************!*\
  !*** ./src/includes/ListElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _ListControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ListControl.js */ \"./src/includes/ListControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar ListElement = /*#__PURE__*/function (_BaseElement) {\n  function ListElement(template, items) {\n    var _this;\n    _classCallCheck(this, ListElement);\n    _this = _callSuper(this, ListElement); // Call the parent class constructor\n    _this.template = template;\n    _this.items = items;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['items'];\n\n    // formats\n    _this.formats = {\n      background_color: null,\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      padding_top: 0,\n      padding_right: 0,\n      padding_bottom: 0,\n      padding_left: 0\n    };\n    return _this;\n  }\n  _inherits(ListElement, _BaseElement);\n  return _createClass(ListElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.list');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // ListElement has no formatter; pass items + legacy `formats` field\n      var htmlContent = this.renderTemplate({\n        items: this.items,\n        formats: this.formats\n      });\n      this.domNode.innerHTML = htmlContent;\n      var bgImageValue = this.getFormat('background_image');\n      if (bgImageValue && bgImageValue.toString().trim() !== \"\") {\n        var bgImage = bgImageValue.toString().replace(/\\s*!important\\s*/, \"\").trim();\n        bgImage = this.transferMediaAbsUrl(bgImage);\n        this.domNode.style.backgroundImage = \"url('\".concat(bgImage, \"')\");\n\n        // Set background position\n        var position = this.getFormat('background_position', 'center');\n        this.domNode.style.backgroundPosition = position;\n\n        // Set background size\n        var size = this.getFormat('background_size', '100').toString().replace(/\\s*!important\\s*/, \"\").trim();\n        if (!isNaN(parseFloat(size)) && isFinite(size)) {\n          size = parseFloat(size) + '%';\n        }\n        this.domNode.style.backgroundSize = size;\n\n        // Set background repeat\n        var repeat = this.getFormat('background_repeat', 'no-repeat').toString();\n        this.domNode.style.backgroundRepeat = repeat;\n      } else {\n        // Explicitly clear background image and related styles\n        this.domNode.style.backgroundImage = \"\";\n        this.domNode.style.backgroundPosition = \"\";\n        this.domNode.style.backgroundSize = \"\";\n        this.domNode.style.backgroundRepeat = \"\";\n      }\n\n      // Apply background color\n      var bgColor = this.getFormat('background_color');\n      if (bgColor) {\n        this.domNode.style.backgroundColor = bgColor;\n      }\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      // ListElement uses legacy `formats` field (not formatter) — pass it\n      // explicitly. super.getData() returns name + template (no formats key\n      // because there's no this.formatter).\n      return _objectSpread(_objectSpread({}, _superPropGet(ListElement, \"getData\", this, 3)([])), {}, {\n        items: this.items,\n        formats: this.formats\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [new _ListControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.list_items'), this.items.map(function (item) {\n        return {\n          label: item\n        };\n      }), {\n        setItems: function setItems(items) {\n          _this2.items = items.map(function (item) {\n            return item.label;\n          });\n          _this2.render();\n        }\n      },\n      // W3.8c — RULE A: primitives + hooks only.\n      {\n        getDomNode: function getDomNode() {\n          return _this2.domNode;\n        }\n      })];\n    }\n  }, {\n    key: \"setFormat\",\n    value: function setFormat(key, value) {\n      this.formats[key] = value;\n    }\n  }, {\n    key: \"getFormat\",\n    value: function getFormat(key) {\n      var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n      return this.formats[key] !== undefined ? this.formats[key] : defaultValue;\n    }\n  }, {\n    key: \"_getHighlightTarget\",\n    value: function _getHighlightTarget() {\n      if (!this.domNode) return null;\n      var ul = this.domNode.querySelector('ul');\n      if (ul) return ul;\n      var ol = this.domNode.querySelector('ol');\n      if (ol) return ol;\n      return this.domNode;\n    }\n\n    /* SELECTED EFFECTS */\n  }, {\n    key: \"addSelectedHighlight\",\n    value: function addSelectedHighlight() {\n      var _this3 = this;\n      // render selected outbound\n      if (!this.selectedBox) {\n        this.selectedBox = document.createElement(\"div\");\n        this.selectedBox.classList.add(\"selected-box\");\n        document.body.appendChild(this.selectedBox);\n        this.matchingDomNode(this.selectedBox);\n      }\n\n      // Render actions\n      if (!this.actionsBox) {\n        this.actionsBox = document.createElement(\"div\");\n        this.actionsBox.classList.add(\"actions-box\");\n        this.actionsBox.classList.add(\"d-flex\");\n        this.actionsBox.classList.add(\"align-items-center\");\n        // Opt out of canvas-clip — toolbar pill must escape canvas\n        // top edge. See BaseElement.addSelectedHighlight + OVERLAY.md §24.\n        this.actionsBox.classList.add(\"bjs-ovl-no-clip\");\n        document.body.appendChild(this.actionsBox);\n        this.matchingDomNode(this.actionsBox, function () {\n          if (!_this3.actionsBox) return;\n          var domRect = _this3.domNode.getBoundingClientRect();\n          var iframe = _this3.domNode.ownerDocument.defaultView.frameElement;\n          var iframeRect = iframe.getBoundingClientRect();\n          var absoluteTop = iframeRect.top + domRect.top;\n          var absoluteLeft = iframeRect.left + domRect.left;\n          Object.assign(_this3.actionsBox.style, {\n            position: \"fixed\",\n            top: \"\".concat(absoluteTop - 38, \"px\"),\n            left: \"\".concat(absoluteLeft, \"px\"),\n            width: \"\".concat(domRect.width, \"px\"),\n            height: \"40px\"\n          });\n        });\n\n        // Label\n        this.actionsBoxLabel = document.createElement(\"h5\");\n        this.actionsBoxLabel.classList.add(\"ms-2\");\n        this.actionsBoxLabel.classList.add(\"m-0\");\n        this.actionsBoxLabel.classList.add(\"text-light\");\n        this.actionsBoxLabel.innerHTML = '<span class=\"d-flex align-items-center\"><span class=\"material-symbols-rounded me-2\">apps</span>' + this.getName() + \"</span>\";\n        this.actionsBox.appendChild(this.actionsBoxLabel);\n        this.actionsBoxInner = document.createElement(\"div\");\n        this.actionsBoxInner.classList.add(\"actions-box-inner\");\n        this.actionsBoxInner.classList.add(\"btn-group\");\n        this.actionsBoxInner.classList.add(\"ms-auto\");\n        this.actionsBox.appendChild(this.actionsBoxInner);\n        this.getActions().forEach(function (action) {\n          var actionButton = document.createElement(\"button\");\n          actionButton.setAttribute(\"class\", \"element-action-item btn btn-light p-1 d-flex align-items-center\");\n          actionButton.setAttribute(\"data-tooltip\", action.label);\n          actionButton.setAttribute(\"aria-label\", action.label);\n          actionButton.innerHTML = \"<span class=\\\"material-symbols-rounded fs-5\\\">\".concat(action.icon, \"</span>\");\n          _this3.actionsBoxInner.appendChild(actionButton);\n          actionButton.addEventListener(\"click\", function () {\n            action.run();\n          });\n        });\n      }\n\n      // Add rainbow highlight around all <li> elements\n      if (!this.liHighlightBoxes) {\n        this.liHighlightBoxes = [];\n\n        // Find all <li> elements in the rendered element\n        var liElements = this.domNode.querySelectorAll('li');\n        liElements.forEach(function (liElement) {\n          var highlightBox = document.createElement(\"div\");\n          highlightBox.classList.add(\"li-highlight-box\");\n          document.body.appendChild(highlightBox);\n          _this3.matchingDomNode(highlightBox, function () {\n            if (!highlightBox) return;\n            var domRect = liElement.getBoundingClientRect();\n            var iframe = liElement.ownerDocument.defaultView.frameElement;\n            var iframeRect = iframe.getBoundingClientRect();\n            var absoluteTop = iframeRect.top + domRect.top;\n            var absoluteLeft = iframeRect.left + domRect.left;\n            Object.assign(highlightBox.style, {\n              position: \"fixed\",\n              top: \"\".concat(absoluteTop, \"px\"),\n              left: \"\".concat(absoluteLeft, \"px\"),\n              width: \"\".concat(domRect.width, \"px\"),\n              height: \"\".concat(domRect.height, \"px\"),\n              borderRadius: getComputedStyle(liElement).borderRadius || \"6px\"\n            });\n          });\n\n          // Add mouseenter/mouseleave to each li for hover effect\n          var enter = function enter() {\n            return highlightBox.classList.add(\"hover\");\n          };\n          var leave = function leave() {\n            return highlightBox.classList.remove(\"hover\");\n          };\n          if (liElement._rainbowHoverHandler) {\n            liElement.removeEventListener(\"mouseenter\", liElement._rainbowHoverHandler.enter);\n            liElement.removeEventListener(\"mouseleave\", liElement._rainbowHoverHandler.leave);\n          }\n          liElement.addEventListener(\"mouseenter\", enter);\n          liElement.addEventListener(\"mouseleave\", leave);\n          liElement._rainbowHoverHandler = {\n            enter: enter,\n            leave: leave\n          };\n          _this3.liHighlightBoxes.push({\n            box: highlightBox,\n            element: liElement\n          });\n        });\n      }\n    }\n  }, {\n    key: \"removeSelectedHighlight\",\n    value: function removeSelectedHighlight() {\n      if (this.selectedBox) {\n        this.selectedBox.remove();\n      }\n      this.selectedBox = null;\n      if (this.actionsBox) {\n        this.actionsBox.remove();\n      }\n      this.actionsBox = null;\n      if (this.liHighlightBoxes) {\n        this.liHighlightBoxes.forEach(function (_ref) {\n          var box = _ref.box,\n            element = _ref.element;\n          box.remove();\n          if (element._rainbowHoverHandler) {\n            element.removeEventListener(\"mouseenter\", element._rainbowHoverHandler.enter);\n            element.removeEventListener(\"mouseleave\", element._rainbowHoverHandler.leave);\n            element._rainbowHoverHandler = null;\n          }\n        });\n      }\n      this.liHighlightBoxes = null;\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new ListElement(data.template, data.items);\n      if (data.formats && _typeof(data.formats) === 'object') {\n        e.formats = _objectSpread(_objectSpread({}, e.formats), data.formats);\n      }\n      return e;\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ListElement.js?");

/***/ }),

/***/ "./src/includes/ListWidget.js":
/*!************************************!*\
  !*** ./src/includes/ListWidget.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ListElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ListElement.js */ \"./src/includes/ListElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar ListWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ListWidget() {\n    var _this;\n    _classCallCheck(this, ListWidget);\n    _this = _callSuper(this, ListWidget); // Call the parent class constructor\n    _this.elements = [];\n\n    // Add a ListElement to the widget\n    var list = new _ListElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('List', ['Item 1', 'Item 2', 'Item 3']);\n    _this.elements.push(list);\n    return _this;\n  }\n  _inherits(ListWidget, _BaseWidget);\n  return _createClass(ListWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.list');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'format_list_bulleted';\n    }\n  }, {\n    key: \"getElements\",\n    value: function getElements() {\n      // Return the elements\n      return this.elements;\n    }\n  }, {\n    key: \"renderElements\",\n    value: function renderElements() {\n      // Clone all elements and return the cloned ones\n      return this.elements.map(function (element) {\n        var data = element.getData();\n        return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n      });\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ListWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ListWidget.js?");

/***/ }),

/***/ "./src/includes/MenuElement.js":
/*!*************************************!*\
  !*** ./src/includes/MenuElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _ListControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ListControl.js */ \"./src/includes/ListControl.js\");\n/* harmony import */ var _RangeControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _SeparatorControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./SeparatorControl.js */ \"./src/includes/SeparatorControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\nvar MenuElement = /*#__PURE__*/function (_BaseElement) {\n  function MenuElement(template, items) {\n    var _this;\n    _classCallCheck(this, MenuElement);\n    _this = _callSuper(this, MenuElement); // Call the parent class constructor\n    _this.template = template;\n    _this.items = items;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['items'];\n\n    // Formatter. Audit 2026-04-17: dropped `link_color` (dead — a menu\n    // is all-links, so the single `text_color` already colors every <a>;\n    // previous `link-color:` kebab was invalid CSS, silently no-op).\n    // `text_align` now renders meaningfully via the Menu template in\n    // both orientations (outer <div> text-align for horizontal, <ul>\n    // align-items for vertical).\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n      align: 'center',\n      // text styles\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      text_align: null,\n      // separator between items (string like \"|\" or \"•\")\n      separator: null,\n      // spacing around separator in px\n      separator_gap: null,\n      // orientation: 'horizontal' | 'vertical'\n      orientation: 'horizontal'\n    });\n\n    // settings (legacy gap control)\n    _this.menu_gap = 10;\n    return _this;\n  }\n  _inherits(MenuElement, _BaseElement);\n  return _createClass(MenuElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.menu');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c). `formats` is also passed because the\n      // Menu template historically reads it as a separate var.\n      this.domNode.innerHTML = this.renderTemplate({\n        items: this.items,\n        formats: this.formats,\n        menu_gap: this.menu_gap\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(MenuElement, \"getData\", this, 3)([])), {}, {\n        items: this.items,\n        menu_gap: this.menu_gap\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      // IMPORTANT behavior rule (2026-04-17 audit pass-4, user-flagged):\n      // setters MUST NOT call `builder.renderElementControls(this)`. That\n      // rebuilds the whole panel on every value change → text inputs lose\n      // focus mid-keystroke, segmented clicks feel twitchy, every control\n      // gets destroyed+recreated (ListControl's accordion closes, etc.).\n      //\n      // For controls whose visibility depends on element state (Separator\n      // gap, Item alignment), we stash control refs on `this` and toggle\n      // `display: none` via `_syncControlVisibility()`. Cheap, preserves\n      // focus, matches the PElement/HeadingElement structure-preserving\n      // pattern (`applyFormatStyles` — patch in place, don't rebuild).\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          _this2.formatter.setFormat(key, value);\n          _this2.render();\n          _this2._syncControlVisibility();\n        };\n      };\n\n      // `orientation` doesn't map to a `format_align_*` Material Symbol\n      // (only left/center/right/justify exist). Pass explicit icon names\n      // so the glyph renders instead of the ligature-fallback text.\n      var ORIENTATION_OPTIONS = [{\n        value: 'horizontal',\n        icon: 'view_week'\n      },\n      // column layout icon\n      {\n        value: 'vertical',\n        icon: 'view_agenda'\n      } // stacked rows icon\n      ];\n\n      // Info-banner guidance row (matches Video / Button / Link pattern).\n      var bannerNode = document.createElement('div');\n      bannerNode.innerHTML = \"\\n            <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n                <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">menu</span>\\n                <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('menu.banner'), \"</span>\\n            </div>\\n        \");\n      var banner = {\n        domNode: bannerNode.firstElementChild\n      };\n\n      // Microtask runs right after the caller (renderElementControls)\n      // appends our controls' domNodes. By then `this._separatorGapControl`\n      // and `this._itemAlignmentControl` are set (assigned inline during\n      // array construction below) and their .domNodes are in the DOM.\n      // Syncing here paints the initial visibility (hidden state if\n      // separator is null / orientation is horizontal on open).\n      queueMicrotask(function () {\n        return _this2._syncControlVisibility();\n      });\n      return [banner, new _ListControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.list_items'), this.items.map(function (item) {\n        return {\n          label: item.text,\n          url: item.url\n        };\n      }), {\n        setItems: function setItems(items) {\n          _this2.items = items.map(function (item) {\n            return {\n              text: item.label,\n              url: item.url\n            };\n          });\n          _this2.render();\n        }\n      },\n      // W3.8c — RULE A compliance: primitives + hooks only, no\n      // element ref. `getDomNode` late-binds to the current\n      // canvas node so highlighting survives re-render swaps.\n      {\n        getDomNode: function getDomNode() {\n          return _this2.domNode;\n        }\n      }),\n      // Outer-block alignment (the whole menu list in its container)\n      new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_alignment'), this.formatter.getFormat('align'), {\n        setValue: setFmt('align')\n      }, ['left', 'center', 'right']),\n      // Orientation: row (horizontal) vs column (vertical). Explicit\n      // icons because AlignControl's default `format_align_*` glyphs\n      // don't exist for these values. setFmt('orientation') triggers\n      // _syncControlVisibility → Item alignment row appears/hides\n      // without rebuilding the panel.\n      new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.orientation'), this.formatter.getFormat('orientation'), {\n        setValue: setFmt('orientation')\n      }, ORIENTATION_OPTIONS),\n      // Items gap — migrated from RangeControl (Bootstrap .form-range)\n      // to the already-.bjs-*-compliant NumberControl so the menu\n      // panel stops drifting from the showcase.\n      new _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.items_gap'), this.menu_gap, {\n        setValue: function setValue(value) {\n          _this2.menu_gap = value;\n          _this2.render();\n        }\n      }, {\n        defaultValue: 10,\n        minValue: 0,\n        maxValue: 500,\n        suffix: 'px',\n        allowZero: true\n      }),\n      // Separator picker — segmented presets + 50%-width custom input\n      // on its own row when Custom is chosen. setText only calls\n      // element render() + sync (no panel rebuild) so the custom\n      // text input keeps focus across keystrokes.\n      new _SeparatorControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.separator'), this.formatter.getFormat('separator'), {\n        setText: function setText(value) {\n          _this2.formatter.setFormat('separator', value);\n          _this2.render();\n          _this2._syncControlVisibility();\n        }\n      }),\n      // Separator gap — always mounted; `_syncControlVisibility` hides\n      // the row when there is no separator (a user nudging the gap\n      // with no separator would be a dead tap — the <li> never\n      // renders). Stashed on `this` so the sync method can find it.\n      this._separatorGapControl = new _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.separator_gap'), this.formatter.getFormat('separator_gap') || this.menu_gap, {\n        setValue: setFmt('separator_gap')\n      }, {\n        defaultValue: 10,\n        minValue: 0,\n        maxValue: 200,\n        suffix: 'px',\n        allowZero: true\n      }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, {\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: setFmt('text_color')\n      }),\n      // Item alignment — always mounted; `_syncControlVisibility`\n      // hides the row for horizontal orientation where <a>s are\n      // inline and text-align is a visual no-op.\n      this._itemAlignmentControl = new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.item_alignment'), this.formatter.getFormat('text_align'), {\n        setValue: setFmt('text_align')\n      }, ['left', 'center', 'right'])];\n    }\n\n    /**\n     * Toggle the display of state-dependent controls without rebuilding the\n     * panel. Called synchronously after every setter; also called once after\n     * initial getControls() (see below — we return the array then trigger\n     * the sync via a microtask because the caller hasn't mounted the\n     * domNodes yet on first call, but the domNodes themselves exist).\n     */\n  }, {\n    key: \"_syncControlVisibility\",\n    value: function _syncControlVisibility() {\n      if (this._separatorGapControl && this._separatorGapControl.domNode) {\n        var sep = this.formatter.getFormat('separator');\n        var hide = sep == null || sep === '';\n        this._separatorGapControl.domNode.style.display = hide ? 'none' : '';\n      }\n      if (this._itemAlignmentControl && this._itemAlignmentControl.domNode) {\n        var _hide = this.formatter.getFormat('orientation') !== 'vertical';\n        this._itemAlignmentControl.domNode.style.display = _hide ? 'none' : '';\n      }\n    }\n    // 2026-04-17 audit: removed the custom addSelectedHighlight /\n    // removeSelectedHighlight overrides. They called\n    // `matchingDomNode(box, callback)` using the OLD 2-arg signature,\n    // but BaseElement has long since evolved to\n    // `matchingDomNode(box, padding=0, setPosSize=null, afterPosSize=null)`.\n    // The callback was silently consumed as `padding`, the real position\n    // callback never ran, and the canvas action-bar header (with the\n    // \"Menu\" label + parent/copy/delete/unselect icons) never positioned\n    // itself — users saw only the blue selected-box ring.\n    // MenuElement now inherits BaseElement's standard overlay — the same\n    // one every other element uses. The rainbow per-<li> hover was\n    // decorative and not worth keeping the broken override alive for.\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new MenuElement(data.template, data.items);\n      e.menu_gap = data.menu_gap || 10;\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MenuElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/MenuElement.js?");

/***/ }),

/***/ "./src/includes/MenuWidget.js":
/*!************************************!*\
  !*** ./src/includes/MenuWidget.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _MenuElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MenuElement.js */ \"./src/includes/MenuElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar MenuWidget = /*#__PURE__*/function (_BaseWidget) {\n  function MenuWidget() {\n    var _this;\n    _classCallCheck(this, MenuWidget);\n    _this = _callSuper(this, MenuWidget); // Call the parent class constructor\n\n    // Add elements to the widget\n    var menu = new _MenuElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Menu', [{\n      url: '#',\n      text: 'Home'\n    }, {\n      url: '#',\n      text: 'About'\n    }, {\n      url: '#',\n      text: 'Contact'\n    }]);\n\n    // Append the new element to the block\n    _this.block.appendElements([menu]);\n    return _this;\n  }\n  _inherits(MenuWidget, _BaseWidget);\n  return _createClass(MenuWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.menu');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'menu_open';\n    }\n  }, {\n    key: \"getElements\",\n    value: function getElements() {\n      // Return the elements\n      return this.elements;\n    }\n  }, {\n    key: \"renderElements\",\n    value: function renderElements() {\n      // Clone all elements and return the cloned ones\n      return this.elements.map(function (element) {\n        var data = element.getData();\n        return _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(data);\n      });\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (MenuWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/MenuWidget.js?");

/***/ }),

/***/ "./src/includes/NumberControl.js":
/*!***************************************!*\
  !*** ./src/includes/NumberControl.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * NumberControl — numeric stepper with ± buttons + direct input +\n * arrow-key fine adjust + unit suffix.\n *\n * 2026-04-24 (W3.1) — optional `options.bus` + `options.elementUid` +\n * `options.formatterKey` add dual-mount bus sync. Same pattern as\n * AlignControl (W1.1b) / FontFamilyControl / FontWeightControl:\n * opt-in, zero regression for the 10+ legacy callsites that pass only\n * defaultValue/minValue/maxValue/step/suffix/allowZero/allowNegative.\n */\nvar NumberControl = /*#__PURE__*/function () {\n  function NumberControl(label, value, callback) {\n    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, NumberControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value === null || value === undefined ? options.defaultValue || 0 : value;\n    this.callback = callback;\n    this.options = _objectSpread({\n      defaultValue: 0,\n      minValue: 0,\n      maxValue: null,\n      step: 1,\n      suffix: '',\n      allowZero: true,\n      allowNegative: false\n    }, options);\n\n    // W3.1 — bus wiring carried on the same `options` arg (opt-in).\n    this._bus = options.bus || null;\n    this._elementUid = options.elementUid || null;\n    this._formatterKey = options.formatterKey || null;\n    this._busOff = null;\n    this._busSource = 'number-control:' + this.id;\n    this.domNode = document.createElement(\"div\");\n    this.render();\n    this._attachBusSubscription();\n  }\n  return _createClass(NumberControl, [{\n    key: \"render\",\n    value: function render() {\n      var suffixHtml = this.options.suffix ? \"<span class=\\\"bjs-number-unit\\\">\".concat(this.options.suffix, \"</span>\") : '';\n      var minAttr = this.options.minValue !== null && this.options.minValue !== undefined ? \" min=\\\"\".concat(this.options.minValue, \"\\\"\") : '';\n      var maxAttr = this.options.maxValue !== null ? \" max=\\\"\".concat(this.options.maxValue, \"\\\"\") : '';\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-number-input\\\">\\n            <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" aria-label=\\\"Decrease\\\">\\u2212</button>\\n            <input type=\\\"number\\\" class=\\\"bjs-number-value\\\" id=\\\"\").concat(this.id, \"\\\"\\n                   value=\\\"\").concat(this.value, \"\\\"\").concat(minAttr).concat(maxAttr, \"\\n                   step=\\\"\").concat(this.options.step, \"\\\">\\n            \").concat(suffixHtml, \"\\n            <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" aria-label=\\\"Increase\\\">+</button>\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      var decrease = this.domNode.querySelector('[aria-label=\"Decrease\"]');\n      var increase = this.domNode.querySelector('[aria-label=\"Increase\"]');\n      var input = this.domNode.querySelector('.bjs-number-value');\n      if (decrease) {\n        decrease.addEventListener('click', function (e) {\n          e.preventDefault();\n          _this._changeValue(-1);\n        });\n      }\n      if (increase) {\n        increase.addEventListener('click', function (e) {\n          e.preventDefault();\n          _this._changeValue(1);\n        });\n      }\n      if (input) {\n        // Direct typing support\n        input.addEventListener('input', function (e) {\n          var raw = e.target.value;\n          if (raw === '' || raw === '-') return; // allow partial typing\n          var numeric = parseFloat(raw);\n          if (!isNaN(numeric)) {\n            _this.value = _this._clamp(numeric);\n            _this._fireCallback();\n            _this._emitBus();\n          }\n        });\n\n        // Clamp + format on blur\n        input.addEventListener('blur', function (e) {\n          var raw = e.target.value;\n          var numeric = parseFloat(raw);\n          if (isNaN(numeric)) {\n            _this.value = _this.options.defaultValue;\n          } else {\n            _this.value = _this._clamp(numeric);\n          }\n          e.target.value = _this.value;\n          _this._fireCallback();\n          _this._emitBus();\n        });\n\n        // Arrow keys in input for fine adjustment\n        input.addEventListener('keydown', function (e) {\n          if (e.key === 'ArrowUp') {\n            e.preventDefault();\n            _this._changeValue(1);\n          } else if (e.key === 'ArrowDown') {\n            e.preventDefault();\n            _this._changeValue(-1);\n          }\n        });\n      }\n      this._inputNode = input;\n    }\n  }, {\n    key: \"_changeValue\",\n    value: function _changeValue(delta) {\n      var numeric = parseFloat(this.value) || 0;\n      numeric += delta * this.options.step;\n      this.value = this._clamp(numeric);\n      this._syncInput();\n      this._fireCallback();\n      this._emitBus();\n    }\n  }, {\n    key: \"_clamp\",\n    value: function _clamp(numeric) {\n      if (this.options.maxValue !== null) {\n        numeric = Math.min(this.options.maxValue, numeric);\n      }\n      if (!this.options.allowNegative) {\n        numeric = Math.max(this.options.allowZero ? 0 : this.options.step, numeric);\n      } else {\n        numeric = Math.max(this.options.minValue, numeric);\n      }\n      return numeric;\n    }\n  }, {\n    key: \"_syncInput\",\n    value: function _syncInput() {\n      var input = this.domNode.querySelector('.bjs-number-value');\n      if (input) input.value = this.value;\n    }\n  }, {\n    key: \"_fireCallback\",\n    value: function _fireCallback() {\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$silent = _ref.silent,\n        silent = _ref$silent === void 0 ? false : _ref$silent;\n      this.value = newValue === null || newValue === undefined ? this.options.defaultValue : newValue;\n      this._syncInput();\n      if (silent) return;\n      this._fireCallback();\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n\n    /** Control teardown — drops bus subscription. Called by\n     *  `Builder.renderElementControls` (SA I14) on sidebar rebuild. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._busOff) {\n        this._busOff();\n        this._busOff = null;\n      }\n    }\n  }, {\n    key: \"_attachBusSubscription\",\n    value: function _attachBusSubscription() {\n      var _this2 = this;\n      if (!this._bus || !this._elementUid || !this._formatterKey) return;\n      if (typeof this._bus.on !== 'function') return;\n      this._busOff = this._bus.on('formatter:change', function (payload) {\n        if (!payload) return;\n        if (payload.elementUid !== _this2._elementUid) return;\n        if (payload.key !== _this2._formatterKey) return;\n        if (payload.source === _this2._busSource) return;\n        _this2.setValue(payload.value, {\n          silent: true\n        });\n      });\n    }\n  }, {\n    key: \"_emitBus\",\n    value: function _emitBus() {\n      if (!this._bus || !this._elementUid || !this._formatterKey) return;\n      if (typeof this._bus.emit !== 'function') return;\n      this._bus.emit('formatter:change', {\n        elementUid: this._elementUid,\n        key: this._formatterKey,\n        value: this.value,\n        source: this._busSource\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NumberControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/NumberControl.js?");

/***/ }),

/***/ "./src/includes/PElement.js":
/*!**********************************!*\
  !*** ./src/includes/PElement.js ***!
  \**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\nvar PElement = /*#__PURE__*/function (_BaseElement) {\n  function PElement(template, text) {\n    var _this;\n    _classCallCheck(this, PElement);\n    _this = _callSuper(this, PElement);\n    _this.template = template;\n    _this.text = text;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['text'];\n\n    // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n    _this.registerInlineEdit('text');\n\n    // Formatter. `text_decoration` and `font_style` exist as entries\n    // because the template emits all formats via `toStyleStringAll()`,\n    // but they are managed by RichTextControl's inline `<b>/<i>/<u>`\n    // tags (character-level), not by paragraph-level formats — so no\n    // panel control is needed. Paragraph-level `border_*` + `border_radius`\n    // are declared but unreachable (no BorderControl in a text panel\n    // would add ~270 lines of noise to every paragraph's settings).\n    // Audited 2026-04-17, Phase 2.7 — keeping the keys so future\n    // sessions can opt in without a data migration.\n    _this.formatter = new Formatter({\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      link_color: null,\n      paragraph_spacing: null,\n      text_align: null,\n      line_height: null,\n      letter_spacing: null,\n      text_direction: null,\n      text_decoration: null,\n      font_style: null,\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      border_radius: null\n    });\n    return _this;\n  }\n  _inherits(PElement, _BaseElement);\n  return _createClass(PElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.paragraph');\n    }\n\n    /**\n     * Full render — emits the template's innerHTML. Inline-edit wiring is\n     * auto-fired by BaseElement.afterRender() (W0.2b). Used only when\n     * structure/text changes; prefer `applyFormatStyles()` for format-only\n     * tweaks so the canvas <p> stays alive (contenteditable cursor + text\n     * selection + RichText editor state preserved). PHASE_2_PLAN §2.8 E.\n     */\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged by BaseElement.renderTemplate (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({});\n    }\n\n    /**\n     * Structure-preserving format update. Patches the existing <p> element's\n     * style attribute in place (no innerHTML swap), so contenteditable\n     * cursor + any in-flight text selection survive every font/colour/\n     * alignment tweak. PHASE_2_PLAN §2.8 rule E.\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode) {\n        this.render();\n        return;\n      }\n      var target = this.domNode.querySelector('[inline-edit=\"text\"]');\n      if (!target) {\n        this.render();\n        return;\n      }\n      target.setAttribute('style', this.formatter.toStyleStringAll());\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      // name + template + formats baseline merged from super (W0.2c)\n      return _objectSpread(_objectSpread({}, _superPropGet(PElement, \"getData\", this, 3)([])), {}, {\n        text: this.text\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          _this2.formatter.setFormat(key, value);\n          _this2.applyFormatStyles();\n        };\n      };\n      // W3.1 — bus wiring for dual-view sync between sidebar and the\n      // canvas FontPopoverOverlay. Each sidebar font control mirrors\n      // popover writes via `formatter:change` + silent setValue.\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [\n      // TEXT_INLINE_PLAN W8 (2026-04-24) — RichTextControl retired.\n      // Canvas inline-edit host is the text-edit surface (W0.2b marker\n      // + W1.1 floating toolbar + W1.2/W1.3 popovers). Sidebar is now\n      // the element-level config panel only — no text-content editor.\n      new FontFamilyControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }, busOpts('font_family')), new FontWeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: setFmt('text_color')\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: setFmt('link_color')\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('text_align'), {\n        setValue: setFmt('text_align')\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: setFmt('paragraph_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new LineHeightControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: setFmt('line_height')\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: setFmt('letter_spacing')\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new TextDirectionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: setFmt('text_direction')\n      })\n      // W3.8b — PaddingMarginControl removed. Padding is a\n      // container-only concern (Block/Cell/Page). Formatter keys\n      // remain so legacy JSON renders identically.\n      ];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.text || ''), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PElement.js?");

/***/ }),

/***/ "./src/includes/PaddingMarginControl.js":
/*!**********************************************!*\
  !*** ./src/includes/PaddingMarginControl.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * PaddingMarginControl — 4-side numeric editor (Top/Right/Bottom/Left)\n * used by BlockElement/CellElement/PageElement for padding. Each side\n * has stepper −/+ buttons and a direct-entry input with an explicit\n * \"Clear\" (✕) to return to the null/default state. A small live\n * preview at the top visualises how the 4 values inset an inner box\n * from the outer container.\n *\n * 2026-04-17 audit (§2.12 + UX-bugs pass): migrated from Bootstrap\n * `.input-group` + `.form-control` + `.btn btn-outline-secondary` +\n * hardcoded-color preview to the panel's `.bjs-*` primitives with\n * tokenised preview. Rows sit flush to the panel edges (parent\n * `.bjs-control-stack` provides inset — no double-padding), icon\n * buttons and the numeric input are all `var(--bjs-control-h)` tall\n * so the stepper rows look square and uniform.\n *\n * Structure stable across interactions (no innerHTML rebuild on value\n * change) — each keystroke/click mutates `input.value` + the `is-null`\n * class + preview inner-box offsets only. Per the no-flicker rule\n * (BUILDER.md Lesson 19).\n */\nvar PaddingMarginControl = /*#__PURE__*/function () {\n  /**\n   * @param {string} label\n   * @param {object} values         initial { top, right, bottom, left }\n   * @param {object} callback       { setValues(values) }\n   * @param {object} [opts]         W3.8a decoupled API. Control takes ONLY\n   *   primitives + pre-constructed shared singletons — NEVER an element\n   *   reference. See BUILDER.md \"Controls take primitives + hooks\" RULE.\n   *   @param {string}               [opts.elementUid]  primitive id used\n   *       to scope bus payloads + pin-set keys. Absent → pin button hidden,\n   *       bus inert, control behaves as the pre-W3.2 3-arg caller.\n   *   @param {string}               [opts.namespace]   defaults 'padding'.\n   *       A non-default value (e.g. 'block_padding') isolates pin-set +\n   *       bus payloads so one element can carry two controls without\n   *       cross-talk (Page: page_padding + block_padding).\n   *   @param {CanvasHighlightBus}   [opts.bus]         injected singleton.\n   *       `null` → bus emissions skipped.\n   *   @param {Set<string>}          [opts.pinSet]      injected singleton.\n   *       `null` → pin state lives only in-control (button still toggles\n   *       aria-pressed but nothing else sees it).\n   */\n  function PaddingMarginControl(label, values, callback) {\n    var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    _classCallCheck(this, PaddingMarginControl);\n    this.label = label;\n    this.top = values.top !== undefined ? values.top : null;\n    this.bottom = values.bottom !== undefined ? values.bottom : null;\n    this.left = values.left !== undefined ? values.left : null;\n    this.right = values.right !== undefined ? values.right : null;\n    this.callback = callback;\n    // Host-injection — supersedes the W3.8a prop-drilled bus / pinSet\n    // options. Caller still passes elementUid + namespace (plain\n    // primitives — host-agnostic). bus / pinSet are derived from\n    // `this.host` at lookup time inside _getBus() / _getPinSet().\n    this.elementUid = opts.elementUid || null;\n    this.namespace = opts.namespace || 'padding';\n    // Host is set later by Builder.renderElementControls (host injection).\n    this.host = null;\n    this._panelBlurTimer = null;\n    this._panelFocusedNow = false;\n    this.domNode = document.createElement('div');\n    this._buildDom();\n    this._bindEvents();\n    this._syncPreview();\n  }\n  return _createClass(PaddingMarginControl, [{\n    key: \"_buildDom\",\n    value: function _buildDom() {\n      var _this = this;\n      var side = function side(name, labelKey) {\n        var value = _this[name];\n        var display = value === null ? '' : value;\n        var nullClass = value === null ? 'is-null' : '';\n        return \"\\n                <div class=\\\"bjs-pm-side\\\" data-side=\\\"\".concat(name, \"\\\">\\n                    <label class=\\\"bjs-pm-side-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"</label>\\n                    <div class=\\\"bjs-pm-side-stepper\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-icon-btn\\\" data-control=\\\"\").concat(name, \"-clear\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.clear'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">close</span>\\n                        </button>\\n                        <input type=\\\"number\\\" class=\\\"bjs-text-input bjs-pm-input \").concat(nullClass, \"\\\" name=\\\"\").concat(name, \"\\\" value=\\\"\").concat(display, \"\\\" placeholder=\\\"--\\\" min=\\\"0\\\" step=\\\"1\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey), \"\\\">\\n                        <div class=\\\"bjs-vstepper\\\" role=\\\"group\\\">\\n                            <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-increase\\\" aria-label=\\\"+\\\">\\n                                <span class=\\\"material-symbols-rounded\\\">arrow_drop_up</span>\\n                            </button>\\n                            <button type=\\\"button\\\" class=\\\"bjs-vstepper-btn\\\" data-control=\\\"\").concat(name, \"-decrease\\\" aria-label=\\\"\\u2212\\\">\\n                                <span class=\\\"material-symbols-rounded\\\">arrow_drop_down</span>\\n                            </button>\\n                        </div>\\n                    </div>\\n                </div>\\n            \");\n      };\n\n      // Pin toggle. Rendered only when caller provides an elementUid\n      // (container elements — Block/Cell/Page). 3-arg legacy callers\n      // stay pin-less. W3.3: icon + text label (\"Pin preview\" /\n      // \"Pinned\") — icon alone isn't self-explanatory.\n      var pinned = this._isPinned();\n      var pinToggleHtml = this.elementUid ? \"\\n            <button type=\\\"button\\\"\\n                    class=\\\"bjs-pm-pin-toggle\\\"\\n                    data-control=\\\"pin-toggle\\\"\\n                    aria-pressed=\\\"\".concat(pinned ? 'true' : 'false', \"\\\"\\n                    data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(pinned ? 'padding.pin_off' : 'padding.pin_on'), \"\\\"\\n                    aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(pinned ? 'padding.pin_off' : 'padding.pin_on'), \"\\\">\\n                <span class=\\\"material-symbols-rounded bjs-pm-pin-icon\\\" aria-hidden=\\\"true\\\">push_pin</span>\\n                <span class=\\\"bjs-pm-pin-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(pinned ? 'padding.pin_label_on' : 'padding.pin_label_off'), \"</span>\\n            </button>\") : '';\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack bjs-pm-control\\\">\\n                <div class=\\\"bjs-pm-label-row\\\" style=\\\"display:flex;align-items:center;gap:8px;\\\">\\n                    <label class=\\\"bjs-control-label\\\" style=\\\"margin:0;\\\">\".concat(this.label, \"</label>\\n                    \").concat(pinToggleHtml, \"\\n                </div>\\n                <div class=\\\"bjs-info-banner bjs-info-banner--flush\\\" role=\\\"note\\\">\\n                    <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n                    <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('padding.help'), \"</span>\\n                </div>\\n                <div class=\\\"bjs-pm-body\\\">\\n                    <div class=\\\"bjs-pm-grid\\\">\\n                        \").concat(side('top', 'padding.top'), \"\\n                        \").concat(side('left', 'padding.left'), \"\\n                        \").concat(side('right', 'padding.right'), \"\\n                        \").concat(side('bottom', 'padding.bottom'), \"\\n                    </div>\\n                    <div class=\\\"bjs-pm-preview\\\" aria-hidden=\\\"true\\\">\\n                        <div class=\\\"bjs-pm-preview-outer\\\" data-control=\\\"preview-outer\\\">\\n                            <div class=\\\"bjs-pm-preview-inner\\\" data-control=\\\"preview-inner\\\"></div>\\n                        </div>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      ['top', 'right', 'bottom', 'left'].forEach(function (position) {\n        var clearBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-clear\\\"]\"));\n        var decreaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-decrease\\\"]\"));\n        var increaseBtn = _this2.domNode.querySelector(\"[data-control=\\\"\".concat(position, \"-increase\\\"]\"));\n        var input = _this2.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n        clearBtn.addEventListener('click', function () {\n          return _this2.clearValue(position);\n        });\n        decreaseBtn.addEventListener('click', function () {\n          _this2._activeSide = position;\n          _this2.updateValue(position, -5);\n        });\n        increaseBtn.addEventListener('click', function () {\n          _this2._activeSide = position;\n          _this2.updateValue(position, 5);\n        });\n        input.addEventListener('input', function (e) {\n          return _this2.setValue(position, e.target.value);\n        });\n\n        // PLAN_EFFECT W3.2 — emit bus events on focus/blur so the\n        // PaddingVisualizerOverlay can highlight the corresponding\n        // side on the canvas. No-ops for legacy callers without an\n        // element (this.elementUid null → early return).\n        input.addEventListener('focus', function () {\n          _this2._activeSide = position;\n          _this2._syncPreview();\n          _this2._emitRegionFocus(position);\n          _this2._notifyPanelFocus();\n        });\n        input.addEventListener('blur', function () {\n          _this2._emitRegionBlur(position);\n          // Panel-blur is deferred — if the user is tabbing to\n          // another input inside the panel, a new focus fires\n          // within the same microtask and cancels this timer.\n          _this2._schedulePanelBlur();\n        });\n      });\n\n      // Pin toggle click handler — scoped by elementUid presence.\n      var pinBtn = this.domNode.querySelector('[data-control=\"pin-toggle\"]');\n      if (pinBtn && this.elementUid) {\n        pinBtn.addEventListener('click', function () {\n          return _this2._togglePin();\n        });\n      }\n    }\n\n    // ─── Host injection — supersedes W3.8a prop-drilling ─────────────────\n    // The control reads its bus + pin-set off `this.host` (set by\n    // Builder.renderElementControls when emitted by an element's\n    // getControls()). Each Builder owns its own EventEmitter +\n    // _pinnedPaddingElements Set — multi-instance isolation is automatic.\n    // See Lesson \"Host Injection\" in BUILDER.md.\n  }, {\n    key: \"_getBus\",\n    value: function _getBus() {\n      var _this$host;\n      return ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events) || null;\n    }\n  }, {\n    key: \"_getPinSet\",\n    value: function _getPinSet() {\n      var _this$host2;\n      return ((_this$host2 = this.host) === null || _this$host2 === void 0 ? void 0 : _this$host2._pinnedPaddingElements) || null;\n    }\n  }, {\n    key: \"_pinKey\",\n    value: function _pinKey() {\n      // W3.6 — default namespace keeps the bare UID for back-compat\n      // with existing Set members + existing tests. Other namespaces\n      // compose a distinct key so Page's Page Padding + Block Padding\n      // pin independently.\n      return this.namespace === 'padding' ? this.elementUid : \"\".concat(this.elementUid, \"::\").concat(this.namespace);\n    }\n  }, {\n    key: \"_isPinned\",\n    value: function _isPinned() {\n      if (!this.elementUid) return false;\n      var set = this._getPinSet();\n      return set ? set.has(this._pinKey()) : false;\n    }\n  }, {\n    key: \"_payload\",\n    value: function _payload(extra) {\n      return Object.assign({\n        elementUid: this.elementUid,\n        namespace: this.namespace\n      }, extra || {});\n    }\n  }, {\n    key: \"_emitRegionFocus\",\n    value: function _emitRegionFocus(position) {\n      if (!this.elementUid) return;\n      var bus = this._getBus();\n      if (bus) bus.emit('region:focus', this._payload({\n        regionKey: \"padding-\".concat(position)\n      }));\n    }\n  }, {\n    key: \"_emitRegionBlur\",\n    value: function _emitRegionBlur(position) {\n      if (!this.elementUid) return;\n      var bus = this._getBus();\n      if (bus) bus.emit('region:blur', this._payload({\n        regionKey: \"padding-\".concat(position)\n      }));\n    }\n  }, {\n    key: \"_notifyPanelFocus\",\n    value: function _notifyPanelFocus() {\n      // Cancel any pending panel-blur — a new focus inside the panel\n      // means the panel is still active. Same 120ms debounce window\n      // as UIManager's 50ms hover debounce (SA I1) — prevents flap\n      // when Tab-ing between sides.\n      if (this._panelBlurTimer) {\n        clearTimeout(this._panelBlurTimer);\n        this._panelBlurTimer = null;\n      }\n      if (this._panelFocusedNow) return;\n      if (!this.elementUid) return;\n      this._panelFocusedNow = true;\n      var bus = this._getBus();\n      if (bus) bus.emit('region:panel-focus', this._payload());\n    }\n  }, {\n    key: \"_schedulePanelBlur\",\n    value: function _schedulePanelBlur() {\n      var _this3 = this;\n      if (!this.elementUid) return;\n      if (this._panelBlurTimer) clearTimeout(this._panelBlurTimer);\n      this._panelBlurTimer = setTimeout(function () {\n        _this3._panelBlurTimer = null;\n        if (!_this3._panelFocusedNow) return;\n        var active = document.activeElement;\n        if (active && _this3.domNode.contains(active)) return;\n        _this3._panelFocusedNow = false;\n        var bus = _this3._getBus();\n        if (bus) bus.emit('region:panel-blur', _this3._payload());\n      }, 120);\n    }\n\n    /**\n     * Hook fires after Builder.renderElementControls has appended this\n     * control AND assigned `this.host`. Re-syncs the pin-toggle UI from\n     * the host's pin Set — `_buildDom` ran in the constructor when\n     * `this.host` was still null and rendered the button as not-pinned.\n     */\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {\n      if (!this.elementUid) return;\n      var pinBtn = this.domNode.querySelector('[data-control=\"pin-toggle\"]');\n      if (!pinBtn) return;\n      var on = this._isPinned();\n      pinBtn.setAttribute('aria-pressed', on ? 'true' : 'false');\n      var tipKey = on ? 'padding.pin_off' : 'padding.pin_on';\n      var lblKey = on ? 'padding.pin_label_on' : 'padding.pin_label_off';\n      pinBtn.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n      pinBtn.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n      var label = pinBtn.querySelector('.bjs-pm-pin-label');\n      if (label) label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(lblKey);\n    }\n  }, {\n    key: \"_togglePin\",\n    value: function _togglePin() {\n      if (!this.elementUid) return;\n      var set = this._getPinSet();\n      var bus = this._getBus();\n      if (!set) return;\n      var key = this._pinKey();\n      var pinBtn = this.domNode.querySelector('[data-control=\"pin-toggle\"]');\n\n      // Shared DOM patch — structure preserving, no innerHTML rebuild.\n      var updateBtn = function updateBtn(on) {\n        if (!pinBtn) return;\n        pinBtn.setAttribute('aria-pressed', on ? 'true' : 'false');\n        var tipKey = on ? 'padding.pin_off' : 'padding.pin_on';\n        var lblKey = on ? 'padding.pin_label_on' : 'padding.pin_label_off';\n        pinBtn.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n        pinBtn.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(tipKey));\n        var label = pinBtn.querySelector('.bjs-pm-pin-label');\n        if (label) label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(lblKey);\n      };\n      if (set.has(key)) {\n        set[\"delete\"](key);\n        if (bus) bus.emit('padding:unpin', this._payload());\n        updateBtn(false);\n      } else {\n        set.add(key);\n        if (bus) bus.emit('padding:pin', this._payload());\n        updateBtn(true);\n      }\n    }\n  }, {\n    key: \"clearValue\",\n    value: function clearValue(position) {\n      this[position] = null;\n      var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n      input.value = '';\n      input.classList.add('is-null');\n      this.callback.setValues(this.getValues());\n      this._syncPreview();\n    }\n  }, {\n    key: \"updateValue\",\n    value: function updateValue(position, delta) {\n      var currentValue = this[position] === null ? 0 : this[position];\n      this[position] = Math.max(0, currentValue + delta);\n      var input = this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\"));\n      input.value = this[position];\n      input.classList.remove('is-null');\n      this.callback.setValues(this.getValues());\n      this._syncPreview();\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(position, value) {\n      if (value === '' || value === null || value === undefined) {\n        this[position] = null;\n        this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.add('is-null');\n      } else {\n        this[position] = Math.max(0, parseInt(value) || 0);\n        this.domNode.querySelector(\"[name=\\\"\".concat(position, \"\\\"]\")).classList.remove('is-null');\n      }\n      this.callback.setValues(this.getValues());\n      this._syncPreview();\n    }\n  }, {\n    key: \"getValues\",\n    value: function getValues() {\n      return {\n        top: this.top,\n        bottom: this.bottom,\n        left: this.left,\n        right: this.right\n      };\n    }\n\n    // Scales the 4 values into inset-from-each-edge pixels so the inner\n    // box visibly shrinks in proportion to the padding. The preview is\n    // 72×72; each inset is capped so the inner box never collapses\n    // completely when users push large values on opposing sides.\n  }, {\n    key: \"_syncPreview\",\n    value: function _syncPreview() {\n      var inner = this.domNode.querySelector('[data-control=\"preview-inner\"]');\n      if (!inner) return;\n      var clamp = function clamp(v) {\n        var n = v == null ? 0 : parseInt(v, 10) || 0;\n        // 50px padding ≈ 10px inset; max 22px so top+bottom (or left+right)\n        // combined can be ≤44px, leaving ≥28px inner content.\n        return Math.max(0, Math.min(22, Math.round(n / 5)));\n      };\n      inner.style.top = clamp(this.top) + 'px';\n      inner.style.right = clamp(this.right) + 'px';\n      inner.style.bottom = clamp(this.bottom) + 'px';\n      inner.style.left = clamp(this.left) + 'px';\n    }\n\n    /**\n     * PLAN_EFFECT W3.2 — the legacy `renderRuler` / `renderEdgeRuler` /\n     * `createRulerEl` / `hideRuler` methods lived here pre-2026-04-19.\n     * They rendered a translucent band + \"Npx\" label directly in the\n     * host document on every input focus. The approach suffered three\n     * bugs (wrong-side label for top, stale `0px` when value was the\n     * active one, forced disappear via setTimeout clashing with the\n     * user's focus cadence).\n     *\n     * Replaced by the Canvas Highlight Bus + PaddingVisualizerOverlay\n     * (W0.1 + W0.2). This control now only emits events; the overlay\n     * owns all on-canvas visualisation. All 4 sides react simultaneously\n     * to panel focus; a single side gets emphasis when its input is\n     * focused specifically. See docs/core/OVERLAY.md §18 + §5.7.\n     */\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PaddingMarginControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PaddingMarginControl.js?");

/***/ }),

/***/ "./src/includes/PageElement.js":
/*!*************************************!*\
  !*** ./src/includes/PageElement.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _RangeControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./RangeControl.js */ \"./src/includes/RangeControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./overlays/PaddingVisualizerOverlay.js */ \"./src/includes/overlays/PaddingVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\nvar PageElement = /*#__PURE__*/function (_BaseElement) {\n  function PageElement(builder) {\n    var _this;\n    _classCallCheck(this, PageElement);\n    _this = _callSuper(this, PageElement); // Call the parent class constructor\n    _this.builder = builder;\n    _this.blocks = [];\n    _this.iframe = null; // Reference to the iframe\n\n    //\n    _this.template = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['page'];\n\n    // \n    _this.page_title = null;\n\n    // Formatter\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]({\n      // background\n      background_color: null,\n      background_image: null,\n      background_position: null,\n      background_size: null,\n      background_repeat: null,\n      background_blend_mode: null,\n      opacity: null,\n      filter: null,\n      // padding\n      padding_top: 0,\n      padding_right: 0,\n      padding_bottom: 0,\n      padding_left: 0,\n      // typography\n      font_family: null\n    });\n\n    // more attributes\n    _this.block_gap = 0;\n\n    // container width\n    _this.container_width = 'auto';\n\n    // block padding\n    _this.block_padding_bottom = 0;\n    _this.block_padding_top = 0;\n    _this.block_padding_right = 0;\n    _this.block_padding_left = 0;\n\n    // default block background color\n    _this.default_block_background_color = null;\n    return _this;\n  }\n  _inherits(PageElement, _BaseElement);\n  return _createClass(PageElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.page');\n    }\n  }, {\n    key: \"isDroppable\",\n    value: function isDroppable() {\n      return true;\n    }\n\n    /**\n     * PLAN_EFFECT W3.6 — Page Padding visualiser.\n     *\n     * Mounts a single overlay under the default 'padding' namespace that\n     * tracks the page's own padding_top/right/bottom/left (formatter-\n     * backed). The Block Padding control on PageElement uses a separate\n     * namespace ('block_padding') — its overlay belongs on each child\n     * Block that cascades from page.block_padding_* (lands in W3.7);\n     * drawing one giant overlay at the Page level for \"block default\n     * padding\" would be visually confusing, so we don't.\n     */\n  }, {\n    key: \"getOverlays\",\n    value: function getOverlays() {\n      // Always emit; overlay self-disposes in afterMount() when host's\n      // usePaddingVisualizer flag is off. (See CellElement /\n      // BlockElement for the same pattern + rationale.)\n      return [new _overlays_PaddingVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](this)];\n    }\n\n    /** Host-injection recursion hook — returns this page's blocks so\n     *  Builder._adopt() can walk down the tree. See BUILDER.md \"Host\n     *  Injection\" lesson. */\n  }, {\n    key: \"getChildren\",\n    value: function getChildren() {\n      return this.blocks || [];\n    }\n  }, {\n    key: \"canDropInside\",\n    value: function canDropInside() {\n      // ─────────────────────────────────────────────────────────────────\n      // RULE: drop-inside is allowed on a PageElement ONLY when it's empty.\n      // ─────────────────────────────────────────────────────────────────\n      //\n      // Why this rule exists:\n      //   Previously canDropInside() always returned true. When the user\n      //   dragged a widget over a page that already contained blocks, the\n      //   *entire page* lit up with the drop-inside highlight. The user\n      //   could not tell where the new block would land — and on drop, it\n      //   silently appended to the bottom of the page (appendBlock). That\n      //   is bad UX: the highlight does not match the actual landing spot.\n      //\n      // The new rule:\n      //   • Empty page → drop-inside is allowed. The whole page lights up,\n      //     the user drops anywhere, the block becomes the first child.\n      //     This is the only situation where \"drop anywhere inside\" makes\n      //     sense, because there is no other reference point.\n      //   • Page with ≥1 block → drop-inside is DISABLED. The user must\n      //     hover an existing block and drop above/below it (handled by\n      //     BlockElement.canDropBefore / canDropAfter). The landing\n      //     position is then unambiguous and matches the highlight.\n      //\n      // Where this is enforced:\n      //   UIManager.dragOver() consults canDropInside() AFTER checking\n      //   canDropBefore/canDropAfter, so blocks always win over the page.\n      //   When this method returns false and the user is hovering directly\n      //   on the page background (not on any block), no highlight appears\n      //   and UIManager.drop() is a no-op for that target. The user gets\n      //   immediate visual feedback that \"you must drop on a block\".\n      //\n      // Mirrored in CellElement.canDropInside() — same rule, same reason.\n      //\n      // Regression tests: e2e/drop-inside-empty-only.spec.js\n      return this.blocks.length === 0;\n    }\n  }, {\n    key: \"render\",\n    value: function () {\n      var _render = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n        var _this2 = this;\n        var htmlContent, parser, doc, iframe, docx, scrollTop;\n        return _regeneratorRuntime().wrap(function _callee$(_context) {\n          while (1) switch (_context.prev = _context.next) {\n            case 0:\n              //\n              htmlContent = this.renderTemplate({\n                page: '<div builder-element=\"PageElement\"></div>',\n                // page title\n                page_title: this.page_title || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('page.untitled'),\n                // Formatter (also pass formats string for templates that consume it)\n                formats: this.formatter.getFormats(),\n                // more attributes\n                block_gap: this.block_gap,\n                // container width\n                container_width: this.container_width,\n                // block padding\n                block_padding_bottom: this.block_padding_bottom,\n                block_padding_top: this.block_padding_top,\n                block_padding_right: this.block_padding_right,\n                block_padding_left: this.block_padding_left,\n                // default block background color\n                default_block_background_color: this.default_block_background_color\n              }); // parse data first time then re-render if second time\n              if (!this.domNode) {\n                // write to iframe\n                this.builder.iframeDoc.open();\n                this.builder.iframeDoc.write(htmlContent);\n                this.builder.iframeDoc.close();\n\n                // set page dom\n                this.domNode = this.builder.iframeDoc.body.querySelector('[builder-element=\"PageElement\"]');\n\n                //  initialize UI manager: for drag and drop, hovering, etc. @todo: clean it up later\n                this.builder.uiManager.init();\n                this.builder.uiManager.addElement(this);\n              } else {\n                // inside htmlContent get <head> only and re-render current iframe head\n                parser = new DOMParser();\n                doc = parser.parseFromString(htmlContent, 'text/html'); // replace head\n                this.builder.iframeDoc.head.innerHTML = doc.head.innerHTML;\n\n                // Reset the page body container before appending the new\n                // block list. `parse()` already wipes it via `removeAllBlocks`,\n                // but the host can also call `builder.render()` after a direct\n                // `builder.data = ...` assignment without going through parse\n                // (the legacy demo/element.php's AI applyPageData was the\n                // original driver — its `applyPageData` callback assigned to\n                // `builder.data` then called `builder.render()` directly) —\n                // without this,\n                // re-renders would stack child block DOM on top of stale DOM\n                // from the previous render, producing the duplicate-DOM jitter\n                // we observed on undo/redo + AI replace flows.\n                if (this.domNode) this.domNode.innerHTML = '';\n              }\n\n              // The head replacement above (and the initial iframeDoc.write on first\n              // render) wipes any builder-helper <style> we injected previously —\n              // most critically the autosize override that pins PageElement\n              // min-height to 0 instead of 100vh. Re-inject so the next syncHeight()\n              // pass measures the page without the viewport-unit feedback loop.\n              // Idempotent — bails fast when helpers are already present.\n              if (typeof this.builder._injectIframeHelpers === 'function') {\n                this.builder._injectIframeHelpers();\n              }\n\n              // save current scroll position\n              iframe = this.host.iframe;\n              docx = iframe.contentDocument || iframe.contentWindow.document;\n              scrollTop = docx.documentElement.scrollTop || docx.body.scrollTop; //\n              this.blocks.forEach(function (block) {\n                // render block\n                var domNode = block.render();\n\n                // Dome append child\n                _this2.domNode.appendChild(domNode);\n\n                //\n                _this2.host.uiManager.addElement(block);\n                _this2.host.uiManager.addDraggableItem(block);\n              });\n\n              // Empty page placeholder — share helpers with the surgical\n              // removeElement / addBlock* paths so the placeholder transition\n              // logic has a single source of truth.\n              if (this.blocks.length === 0) {\n                this._showEmptyPlaceholder();\n              } else {\n                this._hideEmptyPlaceholder();\n              }\n\n              // formats\n              this.domNode.style.cssText = this.formatter.toStyleStringAll();\n\n              // restore scroll position\n              docx.documentElement.scrollTop = scrollTop;\n              docx.body.scrollTop = scrollTop;\n              return _context.abrupt(\"return\", this.domNode);\n            case 12:\n            case \"end\":\n              return _context.stop();\n          }\n        }, _callee, this);\n      }));\n      function render() {\n        return _render.apply(this, arguments);\n      }\n      return render;\n    }()\n  }, {\n    key: \"addBlockAfter\",\n    value: function addBlockAfter(newBlock, referenceBlock) {\n      newBlock.container = this; // set container\n\n      var index = this.blocks.indexOf(referenceBlock);\n      if (index === -1) {\n        throw new Error('Reference block not found');\n      }\n      this.blocks.splice(index + 1, 0, newBlock);\n      this._mountBlockDom(newBlock, {\n        afterDomNode: referenceBlock.domNode\n      });\n    }\n  }, {\n    key: \"addBlockBefore\",\n    value: function addBlockBefore(newBlock, referenceBlock) {\n      newBlock.container = this; // set container\n\n      var index = this.blocks.indexOf(referenceBlock);\n      if (index === -1) {\n        throw new Error('Reference block not found');\n      }\n      this.blocks.splice(index, 0, newBlock);\n      this._mountBlockDom(newBlock, {\n        beforeDomNode: referenceBlock.domNode\n      });\n    }\n\n    /**\n     * Empty-page placeholder helpers — extracted so the surgical\n     * removeElement / addBlock* paths use the same logic as the full\n     * `render()` path. Idempotent.\n     */\n  }, {\n    key: \"_emptyPlaceholderHtml\",\n    value: function _emptyPlaceholderHtml() {\n      return \"<div data-control=\\\"page-empty-placeholder\\\" style=\\\"display: flex;\\n                    align-items: center;\\n                    justify-content: center;\\n                    min-height: 480px;\\n                    background-color: rgba(34,83,159,0.05);\\n                    border: dashed 1px rgba(120, 130, 150, 0.5);\\n                    \\\">\\n                    <svg style=\\\"width: 100px;\\n                        display: inline-block;\\n                        margin: auto;\\n                        opacity: 1;\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"48px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"48px\\\" fill=\\\"#808080\\\"><path d=\\\"M345-285q-24 0-42-18t-18-42v-435q0-24 18-42t42-18h435q24 0 42 18t18 42v435q0 24-18 42t-42 18H345Zm0-60h435v-435H345v435ZM149.82-615q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm0 165q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Zm165 0q-12.82 0-21.32-8.68-8.5-8.67-8.5-21.5 0-12.82 8.68-21.32 8.67-8.5 21.5-8.5 12.82 0 21.32 8.68 8.5 8.67 8.5 21.5 0 12.82-8.68 21.32-8.67 8.5-21.5 8.5Z\\\"/></svg>\\n\\n                </div>\";\n    }\n  }, {\n    key: \"_showEmptyPlaceholder\",\n    value: function _showEmptyPlaceholder() {\n      if (!this.domNode) return;\n      if (this.domNode.querySelector('[data-control=\"page-empty-placeholder\"]')) return;\n      this.domNode.insertAdjacentHTML('beforeend', this._emptyPlaceholderHtml());\n    }\n  }, {\n    key: \"_hideEmptyPlaceholder\",\n    value: function _hideEmptyPlaceholder() {\n      if (!this.domNode) return;\n      var ph = this.domNode.querySelector('[data-control=\"page-empty-placeholder\"]');\n      if (ph) ph.remove();\n    }\n\n    /**\n     * Mount a freshly-added block into the live DOM at the right\n     * position. Called from the surgical add paths (`addBlockBefore`,\n     * `addBlockAfter`, `appendBlock`). Hides the empty-page placeholder.\n     *\n     * `position` is one of:\n     *   - { afterDomNode: ref }   — insert after `ref`\n     *   - { beforeDomNode: ref }  — insert before `ref`\n     *   - { append: true }        — append at end\n     *\n     * No-op if `this.domNode` isn't mounted yet (block was added before\n     * first PageElement.render); the full render path will pick it up.\n     */\n  }, {\n    key: \"_mountBlockDom\",\n    value: function _mountBlockDom(block, position) {\n      if (!this.domNode) return;\n      this._hideEmptyPlaceholder();\n      var rendered = block.render();\n      if (position && position.afterDomNode && position.afterDomNode.parentNode === this.domNode) {\n        this.domNode.insertBefore(rendered, position.afterDomNode.nextSibling);\n      } else if (position && position.beforeDomNode && position.beforeDomNode.parentNode === this.domNode) {\n        this.domNode.insertBefore(rendered, position.beforeDomNode);\n      } else {\n        this.domNode.appendChild(rendered);\n      }\n      if (this.builder && this.builder.uiManager) {\n        this.builder.uiManager.addElement(block);\n        this.builder.uiManager.addDraggableItem(block);\n      }\n    }\n\n    /**\n     * Programmatic mass-teardown — used by `parse()` and `clear()`.\n     *\n     * Why NOT route through `block.remove()` (the user-delete API)?\n     *   1. `BaseElement.remove()` fires `commit('history.structure_remove')`\n     *      in its fadeOut callback — outside `_apply`, this leaks N entries\n     *      per cleared page (one per block), spamming the history dropdown\n     *      with \"Delete Block\" rows on every clear/template-swap/AI-replace.\n     *   2. Its callback calls `container.removeElement(this)` which itself\n     *      triggers a full `PageElement.render()` mid-iteration — N nested\n     *      re-renders + N head replacements during a single clear, causing\n     *      visible reflow storm.\n     *   3. During HistoryManager `_apply`, `fadeOut` early-returns\n     *      synchronously WITHOUT setting `display: none` (that's only set in\n     *      the `transitionend` handler) — so old block DOM stays visible\n     *      while the next render appends new ones, causing the duplicate-DOM\n     *      jitter on undo/redo.\n     *\n     * This path does the minimal correct teardown: detach overlays, drop\n     * UIManager registrations, wipe the body container in one shot.\n     */\n  }, {\n    key: \"removeAllBlocks\",\n    value: function removeAllBlocks() {\n      var _this3 = this;\n      this.blocks.forEach(function (block) {\n        block.unmountOverlays('*');\n        _this3.builder.uiManager.removeElement(block);\n        _this3.builder.uiManager.removeDraggableItem(block);\n      });\n      // Reset hover/drag-over lists wholesale — references to torn-down\n      // blocks would otherwise linger and break highlight cleanup.\n      this.builder.uiManager.dragOveringElements = [];\n      this.builder.uiManager.hoveringElements = [];\n\n      // Unselect — every block instance (and every descendant element\n      // instance held by them) is about to be discarded; any selection\n      // pointer would dangle into a torn-down element.\n      if (typeof this.builder.getSelectedElement === 'function' && this.builder.getSelectedElement() && typeof this.builder.unselect === 'function') {\n        this.builder.unselect();\n      }\n      this.blocks = [];\n\n      // Wholesale DOM clear — kills orphan child DOM, drag anchors, any\n      // overlay residue. Cheaper + less buggy than per-block DOM surgery.\n      if (this.domNode) this.domNode.innerHTML = '';\n    }\n  }, {\n    key: \"clear\",\n    value: function clear() {\n      this.removeAllBlocks();\n      this.render();\n    }\n  }, {\n    key: \"appendBlock\",\n    value: function appendBlock(block) {\n      // private\n      block.container = this; // set container\n\n      // Host injection — adopt the new block before it joins the page\n      // tree so its overlays + control emissions can reach the bus\n      // from first render. UIManager.addBlockInside also pre-adopts at\n      // its boundary; double-adopt is a no-op (idempotent).\n      if (this.host && typeof this.host._adopt === 'function') {\n        this.host._adopt(block);\n      }\n\n      // Add block to blocks array.\n      this.blocks.push(block);\n\n      // Surgical DOM mount when the page is already live. During\n      // `parse()` the page hasn't rendered yet (domNode null), so\n      // `_mountBlockDom` is a no-op and the full `render()` that\n      // follows picks up the block.\n      this._mountBlockDom(block, {\n        append: true\n      });\n    }\n\n    /**\n     * Surgical remove — BUILDER.md Lesson 21 + customer fix 2026-05-20.\n     *\n     * Pre-fix this called `this.render()`, which wipes iframe head + body\n     * and re-renders EVERY remaining block. Each block's `_doRender()`\n     * then assigned `domNode.innerHTML = …`, round-tripping its children's\n     * `this.text` through the HTML5 fragment parser. With customer content\n     * that contained `<div>` block children inside a `<p inline-edit>`\n     * (Chrome's default-paragraph-separator behaviour), the parser auto-\n     * closed the `<p>` and kicked the `<div>` content out — stripping\n     * inline `font-weight` / `text-align` / `font-family`. Even after\n     * defence-in-depth (defaultParagraphSeparator + InlineSanitizer\n     * unwrap) the cascade re-render is wasteful and triggers a\n     * MutationObserver firehose in host integrations (acelle's blade\n     * pushes one history snapshot per mutation).\n     *\n     * Surgical path: drop from blocks array, detach domNode, transition\n     * the empty placeholder. Sibling DOM untouched — every contenteditable\n     * cursor, sidebar control closure, overlay anchor, UIManager\n     * registration survives byte-perfect.\n     */\n  }, {\n    key: \"removeElement\",\n    value: function removeElement(element) {\n      var idx = this.blocks.indexOf(element);\n      if (idx === -1) return;\n      this.blocks.splice(idx, 1);\n      if (element.domNode && element.domNode.parentNode) {\n        element.domNode.remove();\n      }\n      if (this.blocks.length === 0) {\n        this._showEmptyPlaceholder();\n      }\n    }\n  }, {\n    key: \"insertElementAfter\",\n    value: function insertElementAfter(element, newElement) {\n      newElement.container = this; // set container\n\n      var idx = this.blocks.indexOf(element);\n      if (idx === -1) return;\n      this.blocks.splice(idx + 1, 0, newElement);\n      this._mountBlockDom(newElement, {\n        afterDomNode: element.domNode\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      // Return JSON encoded representation of the PageElement\n      return _objectSpread(_objectSpread({}, _superPropGet(PageElement, \"getData\", this, 3)([])), {}, {\n        page_title: this.page_title,\n        blocks: this.blocks.map(function (block) {\n          return block.getData();\n        }),\n        block_gap: this.block_gap,\n        container_width: this.container_width,\n        block_padding_bottom: this.block_padding_bottom,\n        block_padding_top: this.block_padding_top,\n        block_padding_right: this.block_padding_right,\n        block_padding_left: this.block_padding_left,\n        default_block_background_color: this.default_block_background_color\n      });\n    }\n  }, {\n    key: \"parse\",\n    value: function parse(data) {\n      var _this4 = this;\n      // Clear existing blocks\n      this.removeAllBlocks();\n\n      // Guard: if data is null/undefined or missing required fields,\n      // initialize with safe defaults so the builder opens an empty canvas\n      // instead of crashing with a TypeError.\n      if (!data || _typeof(data) !== 'object') {\n        data = {\n          template: 'Page',\n          blocks: []\n        };\n      }\n\n      // Set template\n      this.template = data.template || 'Page';\n\n      // Parse blocks\n      (data.blocks || []).forEach(function (blockData) {\n        var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(blockData);\n        block.container = _this4;\n        _this4.appendBlock(block);\n      });\n\n      // page title\n      this.page_title = data.page_title || null;\n\n      // Formatter\n      this.formatter.parseFormats(data.formats || {});\n\n      // more attributes\n      this.block_gap = data.block_gap || 0;\n\n      // container width\n      this.container_width = data.container_width || 'auto';\n\n      // block padding\n      this.block_padding_bottom = data.block_padding_bottom || 0;\n      this.block_padding_top = data.block_padding_top || 0;\n      this.block_padding_right = data.block_padding_right || 0;\n      this.block_padding_left = data.block_padding_left || 0;\n\n      // default block background color\n      this.default_block_background_color = data.default_block_background_color || null;\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this5 = this;\n      return [new _RangeControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](\n      //label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_gap'),\n      // current value\n      this.block_gap,\n      // min\n      0,\n      // max\n      500,\n      // unit\n      'px',\n      // step\n      1,\n      // callback\n      function (value) {\n        _this5.block_gap = value;\n        _this5.render();\n      }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: function setValue(value) {\n          _this5.formatter.setFormat('font_family', value);\n          _this5.render();\n        }\n      }), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.container_width'), this.container_width || 'auto', [{\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.auto_full'),\n        value: 'auto'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.narrow'),\n        value: 'narrow'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.medium'),\n        value: 'medium'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.wide'),\n        value: 'wide'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.xl'),\n        value: 'xl'\n      }, {\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dropdown.full_bleed'),\n        value: 'full'\n      }], function (value) {\n        _this5.container_width = value || 'auto';\n        _this5.render();\n      }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.page_padding'),\n      // value\n      {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      },\n      // callback\n      {\n        setValues: function setValues(values) {\n          _this5.formatter.setFormat('padding_top', values.top);\n          _this5.formatter.setFormat('padding_right', values.right);\n          _this5.formatter.setFormat('padding_bottom', values.bottom);\n          _this5.formatter.setFormat('padding_left', values.left);\n          _this5.render();\n        }\n      },\n      // Host-injection — control reads bus + pinSet off\n      // `this.host` directly. No prop-drilling needed.\n      {\n        elementUid: this.id\n      }), new _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.block_padding'),\n      // value\n      {\n        top: this.block_padding_top,\n        right: this.block_padding_right,\n        bottom: this.block_padding_bottom,\n        left: this.block_padding_left\n      },\n      // callback\n      {\n        setValues: function setValues(values) {\n          _this5.block_padding_top = values.top;\n          _this5.block_padding_right = values.right;\n          _this5.block_padding_bottom = values.bottom;\n          _this5.block_padding_left = values.left;\n          _this5.render();\n        }\n      },\n      // Host-injection — namespace isolates this Block-Padding\n      // control from the Page-Padding one above so their\n      // bus events don't cross-talk on the same element.\n      {\n        elementUid: this.id,\n        namespace: 'block_padding'\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.default_block_background'), this.default_block_background_color, {\n        setValue: function setValue(value) {\n          _this5.default_block_background_color = value;\n          _this5.render();\n        }\n      }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat'),\n        blendMode: this.formatter.getFormat('background_blend_mode', 'normal'),\n        opacity: Math.round((parseFloat(this.formatter.getFormat('opacity', 1)) || 1) * 100),\n        filter: this.formatter.getFormat('filter', '')\n      }, {\n        setBackground: function setBackground(values) {\n          _this5.formatter.setFormat('background_color', values.color);\n          _this5.formatter.setFormat('background_image', values.image);\n          _this5.formatter.setFormat('background_position', values.position);\n          _this5.formatter.setFormat('background_size', values.size);\n          _this5.formatter.setFormat('background_repeat', values.repeat);\n          _this5.formatter.setFormat('background_blend_mode', values.blendMode === 'normal' ? null : values.blendMode);\n          _this5.formatter.setFormat('opacity', values.opacity === 1 ? null : values.opacity);\n          _this5.formatter.setFormat('filter', values.filter || null);\n          _this5.render();\n        }\n      })];\n    }\n  }, {\n    key: \"getActions\",\n    value: function getActions() {\n      var _this6 = this;\n      var actions = [];\n      actions.push({\n        icon: 'remove_selection',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('actions.unselect'),\n        run: function run() {\n          _this6.host.unselect();\n        }\n      });\n      return actions;\n    }\n  }, {\n    key: \"addContainerHightlight\",\n    value: function addContainerHightlight() {\n      // do nothing\n    }\n  }, {\n    key: \"removeContainerHightlight\",\n    value: function removeContainerHightlight() {\n      // do nothing\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PageElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PageElement.js?");

/***/ }),

/***/ "./src/includes/ParagraphSpacingControl.js":
/*!*************************************************!*\
  !*** ./src/includes/ParagraphSpacingControl.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar ParagraphSpacingControl = /*#__PURE__*/function () {\n  function ParagraphSpacingControl(label, value, callback) {\n    _classCallCheck(this, ParagraphSpacingControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.value = value; // Initial /* left | center | right */\n    this.callback = callback; // Callback function to handle input changes\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n  }\n  return _createClass(ParagraphSpacingControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n      <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3\\\">\").concat(this.label, \"</label>\\n\\n\\n      <div class=\\\"input-group flex-nowrap w-25 \\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\" style=\\\"min-width:140px; height: 32px;\\\">\\n        <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"reduction\\\" type=\\\"button\\\">-</button>\\n        <input id=\\\"\").concat(this.id, \"\\\" value=\\\"\").concat(this.value, \"\\\" class=\\\"form-control text-center\\\" style=\\\"font-size: 0.875em;\\\" readonly>\\n        <button class=\\\"btn btn-outline-secondary border-default\\\" role=\\\"increment\\\" type=\\\"button\\\">+</button>\\n      </div>\\n    </div>\");\n      var decrease = this.domNode.querySelector('[role=\"reduction\"]');\n      var increase = this.domNode.querySelector('[role=\"increment\"]');\n      var input = this.domNode.querySelector(\"#\".concat(this.id));\n      var step = 1;\n      var changeValue = function changeValue(delta) {\n        var numeric = parseFloat(_this.value);\n        if (isNaN(numeric)) numeric = 0;\n        numeric = numeric + delta;\n        numeric = Math.max(0, numeric); // allow 0 and fractional values\n        // round to one decimal to avoid float noise\n        numeric = Math.round(numeric * 10) / 10;\n        _this.setValue(numeric);\n      };\n      if (decrease) {\n        decrease.addEventListener('click', function (e) {\n          e.preventDefault();\n          changeValue(-step);\n        });\n      }\n      if (increase) {\n        increase.addEventListener('click', function (e) {\n          e.preventDefault();\n          changeValue(step);\n        });\n      }\n\n      // allow direct programmatic update keeping UI in sync\n      this._inputNode = input;\n\n      // normalize initial display\n      // this.setValue(this.value === undefined ? 0 : this.value);\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      var input = this.domNode.querySelector('input');\n      if (input) {\n        input.value = this.value;\n      }\n\n      // Support both function and object with setValue\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ParagraphSpacingControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ParagraphSpacingControl.js?");

/***/ }),

/***/ "./src/includes/ParagraphWidget.js":
/*!*****************************************!*\
  !*** ./src/includes/ParagraphWidget.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar ParagraphWidget = /*#__PURE__*/function (_BaseWidget) {\n  function ParagraphWidget() {\n    var _this;\n    _classCallCheck(this, ParagraphWidget);\n    _this = _callSuper(this, ParagraphWidget); // Call the parent class constructor\n\n    // New element for Paragraph\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'This is a sample paragraph.');\n\n    // Append the new element to the block\n    _this.block.appendElements([p]);\n    return _this;\n  }\n  _inherits(ParagraphWidget, _BaseWidget);\n  return _createClass(ParagraphWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.paragraph');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'subject';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ParagraphWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ParagraphWidget.js?");

/***/ }),

/***/ "./src/includes/PointerCaptureRegistry.js":
/*!************************************************!*\
  !*** ./src/includes/PointerCaptureRegistry.js ***!
  \************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/*\n * PointerCaptureRegistry — single source of truth for \"is a drag in flight?\"\n *\n * See docs/core/OVERLAY.md §10 for full spec.\n * See docs/archived/OVERLAY_PLAN.md §4.I5 for the lostpointercapture invariant.\n *\n * What this registry DOES:\n *   - Acquire pointer capture on a DOM node (wraps setPointerCapture + try/catch).\n *   - Track all currently-captured nodes in a Set.\n *   - Auto-cleanup via `lostpointercapture` listener when a node is detached\n *     mid-drag (W3C spec: browser silently releases capture; pointerup may\n *     NOT fire reliably on Safari).\n *   - Expose hasActive() for UIManager to suspend hover recompute during\n *     active drags (pointerdown → pointerup).\n *\n * What this registry DOES NOT do:\n *   - Replace the 50ms _hideTimeout debounce in UIManager.mouseout. That\n *     debounce fixes idle-hover ping-pong (user hovering with NO button\n *     pressed) — pointer capture only activates on pointerdown. Different\n *     bug class. The debounce stays. (§4.I1)\n *\n * Used by:\n *   - DraggableHandleOverlay (pointer-driven gestures: grid separator, crop,\n *     resize corner)\n *\n * NOT used by:\n *   - NativeDragHandleOverlay (HTML5 DnD participants: Block drag anchor).\n *     Those wire dragstart only; pointer capture is incompatible with HTML5\n *     DnD on the same node (§4.I2).\n */\nvar active = new Set();\nvar PointerCaptureRegistry = {\n  /**\n   * Acquire pointer capture on `node` for `pointerId`. MUST be called\n   * from a pointerdown handler. Registers automatic cleanup on\n   * `lostpointercapture` so detaching `node` mid-drag doesn't leak\n   * the registry (§4.I5).\n   */\n  acquire: function acquire(node, pointerId) {\n    try {\n      node.setPointerCapture(pointerId);\n    } catch (_) {\n      // Some browsers throw if node is detached or pointer already released.\n      // Non-fatal — don't poison the registry.\n      return;\n    }\n    active.add(node);\n\n    // W3C: if the captured node is removed from the DOM, the browser\n    // releases capture silently. pointerup may NOT fire on all browsers\n    // (Safari is unreliable). `lostpointercapture` DOES fire in that\n    // case. Without this listener, the Set would leak → hasActive()\n    // returns true forever → UIManager hover frozen forever.\n    var _onLost = function onLost() {\n      active[\"delete\"](node);\n      node.removeEventListener('lostpointercapture', _onLost);\n    };\n    node.addEventListener('lostpointercapture', _onLost);\n  },\n  /**\n   * Release pointer capture. MUST be called from pointerup / pointercancel.\n   * Internally try/catch-guarded — browser may have already released.\n   */\n  release: function release(node, pointerId) {\n    try {\n      node.releasePointerCapture(pointerId);\n    } catch (_) {}\n    active[\"delete\"](node);\n  },\n  /**\n   * Returns true iff at least one pointer is currently captured on any node.\n   * Read by UIManager.mouseover/out at line 1 to suspend hover recompute\n   * during active drags. Inexpensive (Set.size > 0).\n   */\n  hasActive: function hasActive() {\n    return active.size > 0;\n  },\n  /**\n   * Dev-mode peek — testing only. Do NOT branch production logic on this.\n   */\n  _activeCount: function _activeCount() {\n    return active.size;\n  }\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PointerCaptureRegistry);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PointerCaptureRegistry.js?");

/***/ }),

/***/ "./src/includes/PricingCardElement.js":
/*!********************************************!*\
  !*** ./src/includes/PricingCardElement.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _CellElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CellElement.js */ \"./src/includes/CellElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./InfoBannerControl.js */ \"./src/includes/InfoBannerControl.js\");\n/* harmony import */ var _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ActionButtonControl.js */ \"./src/includes/ActionButtonControl.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * PricingCardElement — a Cell that visually presents itself as a pricing card.\n *\n * Different from a plain CellElement in four ways:\n *   1. Uses template \"PricingCard\" — the cell DOM is wrapped in a styled\n *      <section class=\"pricing-card\"> whose visual treatment (radius / pad /\n *      shadow / border / bg) is driven by the parent PricingCardsElement's\n *      `style` prop, combined with this cell's own meta (highlighted, badge,\n *      icon, accent_color). One template, ten style branches, fully inline.\n *   2. Card-level metadata lives on the cell (highlighted, badge, icon,\n *      accent_color). The children (Heading, PElements, Button…) stay native\n *      and editable through their own controls — we never wrap them in the\n *      RichText blob pattern the retired PricingTableElement used.\n *   3. Overrides `renderEmptyPlaceholder()` with a pricing-specific dashed\n *      card that invites the user to drop plan content (heading, price, CTA).\n *   4. Overrides `canDropOn()` to reject drops *of* this cell INTO another\n *      cell (mirrors the CellElement rule — cells never nest inside cells).\n *\n * Retired legacy: PricingTableElement (HTML blob) + PricingGridElement\n * (orphan prototype). See docs/plans/DESIGN_PRICING_ELEMENT.md.\n */\nvar PricingCardElement = /*#__PURE__*/function (_CellElement) {\n  function PricingCardElement(template) {\n    var _this;\n    var meta = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, PricingCardElement);\n    _this = _callSuper(this, PricingCardElement, [template]);\n    _this.highlighted = !!meta.highlighted;\n    _this.badge = typeof meta.badge === 'string' ? meta.badge : '';\n    _this.icon = typeof meta.icon === 'string' ? meta.icon : '';\n    _this.accent_color = typeof meta.accent_color === 'string' ? meta.accent_color : '';\n    return _this;\n  }\n\n  // Hard-code class name so webpack can't mangle it — getData() must always\n  // write `name: \"PricingCardElement\"` so the registry lookup succeeds.\n  _inherits(PricingCardElement, _CellElement);\n  return _createClass(PricingCardElement, [{\n    key: \"getClassName\",\n    value: function getClassName() {\n      return 'PricingCardElement';\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.pricing_card');\n    }\n  }, {\n    key: \"getStyle\",\n    value: function getStyle() {\n      return this.container && this.container.style || 'minimal';\n    }\n\n    // Override CellElement.isHoverable() (false by default). Pricing cards\n    // are self-contained visual units — users should hover/click the whole\n    // card to select it (then the panel reveals card-meta controls). Without\n    // this, hover feedback only appears on inner native elements, making\n    // \"select the card\" feel invisible.\n  }, {\n    key: \"isHoverable\",\n    value: function isHoverable() {\n      return true;\n    }\n  }, {\n    key: \"getResolvedAccent\",\n    value: function getResolvedAccent() {\n      if (this.accent_color && String(this.accent_color).trim()) return this.accent_color;\n      var fallback = PricingCardElement.STYLE_ACCENTS[this.getStyle()];\n      return fallback || '#ffcc2a';\n    }\n\n    // Walk the cell's blocks and collect every element. Used by the\n    // style-preset applier to tour buttons + text elements and push\n    // style-consistent formats onto their Formatters. `instanceof` (not\n    // getClassName()) because webpack can mangle constructor.name in\n    // production and break a string comparison.\n  }, {\n    key: \"_collectElements\",\n    value: function _collectElements() {\n      var out = [];\n      (this.blocks || []).forEach(function (block) {\n        (block.elements || []).forEach(function (el) {\n          if (el) out.push(el);\n        });\n      });\n      return out;\n    }\n\n    // Semantic role for an element in the pricing-card context. We tag\n    // elements at newCell() time (`el._pricing_role = 'heading'|…`) and\n    // read that tag here. If the tag is missing (card was loaded from\n    // older JSON, or user added a custom element), fall back to a\n    // positional heuristic: HeadingElement → heading; first big-font\n    // PElement → price; small PElement directly after heading → desc;\n    // etc. The heuristic is only used when no explicit role tag exists,\n    // so custom user elements won't be mis-themed once they've been\n    // re-authored.\n  }, {\n    key: \"_roleOf\",\n    value: function _roleOf(el, index, all) {\n      if (el && typeof el._pricing_role === 'string' && el._pricing_role) {\n        return el._pricing_role;\n      }\n      if (el instanceof _ButtonElement_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"]) return 'cta';\n      if (el instanceof _HeadingElement_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"]) return 'heading';\n      if (el instanceof _PElement_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"]) {\n        var size = parseInt(el.formatter.getFormat('font_size'), 10) || 16;\n        if (size >= 28) return 'price';\n        return 'muted';\n      }\n      return '';\n    }\n\n    // Apply the parent-style-aware preset to every eligible element in\n    // this card. Covers:\n    //   - CTA button (bg / text color / border / radius / padding / weight)\n    //   - Text colors for heading, price (primary), muted (desc / period),\n    //     feature (list lines)\n    // Intent: each card style ships with a visually coherent default —\n    // editorial → outline amber button + serif dark text; neon → cyan\n    // filled button + light text on dark card; mailchimp/banded → yellow\n    // pill + serif. Without this, dark-background styles render text\n    // invisibly (hardcoded dark text-color from newCell bleeds through\n    // inheritance).\n    //\n    // Users can override any element manually after; this is just the\n    // default that matches the chosen style. Called at newCell() time,\n    // whenever setStyle() runs, and when the cell's highlighted or\n    // accent flags change.\n  }, {\n    key: \"applyStylePreset\",\n    value: function applyStylePreset() {\n      var _this2 = this;\n      var style = this.getStyle();\n      var accent = this.getResolvedAccent();\n      var highlighted = !!this.highlighted;\n      var buttonFormats = PricingCardElement.resolveButtonFormats(style, accent, highlighted);\n      var textFormats = PricingCardElement.resolveTextFormats(style, accent, highlighted);\n      var all = this._collectElements();\n      all.forEach(function (el, i) {\n        var role = _this2._roleOf(el, i, all);\n        var formats = role === 'cta' ? buttonFormats : textFormats[role];\n        if (!formats) return;\n        Object.entries(formats).forEach(function (_ref) {\n          var _ref2 = _slicedToArray(_ref, 2),\n            key = _ref2[0],\n            value = _ref2[1];\n          if (el.formatter.isKeyValid(key)) {\n            el.formatter.setFormat(key, value);\n          }\n        });\n      });\n    }\n\n    // Back-compat alias — some callsites were written against the\n    // original \"button-only\" helper. Keep until all callsites migrate.\n  }, {\n    key: \"applyButtonPreset\",\n    value: function applyButtonPreset() {\n      return this.applyStylePreset();\n    }\n\n    // Inject card-meta + parent style into every PricingCard render pass.\n    // CellElement._doRender() calls this.renderTemplate(vars); we augment\n    // vars with the card's visual state. W0.2c: dropped the redundant\n    // `if (template === 'PricingCard')` dispatch — element identity ↔\n    // template = 1:1 invariant after A2 pure refactor (see BUILDER.md\n    // Lesson 50), so this override only fires when `this` is a\n    // PricingCardElement instance which always renders 'PricingCard'.\n  }, {\n    key: \"renderTemplate\",\n    value: function renderTemplate() {\n      var vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      var parent = this.container || {};\n      var showIcons = parent.show_icons !== false;\n      var showBadges = parent.show_badges !== false;\n      // Cell index/count — needed by the `banded` style (first/last\n      // cell get outer radius, middle cells get inner dividers)\n      // and by `tier` (staircase offset keyed on index). Falls\n      // back to (0, 1) for orphan cells outside a container.\n      var siblings = Array.isArray(parent.cells) ? parent.cells : [];\n      var cellIndex = siblings.indexOf(this);\n      var cellCount = siblings.length;\n      return _superPropGet(PricingCardElement, \"renderTemplate\", this, 3)([_objectSpread({\n        style: this.getStyle(),\n        highlighted: !!this.highlighted,\n        badge: showBadges ? this.badge || '' : '',\n        icon: showIcons ? this.icon || '' : '',\n        accent: this.getResolvedAccent(),\n        cell_index: cellIndex >= 0 ? cellIndex : 0,\n        cell_count: cellCount > 0 ? cellCount : 1,\n        renderIcon: function renderIcon(name, size, color) {\n          return _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"].render(name, {\n            size: size,\n            color: color\n          });\n        }\n      }, vars)]);\n    }\n\n    // Override CellElement.render() to strip stale attributes (data-style,\n    // data-highlighted, inline style) before the parent's attribute-copy\n    // pass. Without this, switching parent style (e.g. highlighted →\n    // featured) left the previous `style=\"\"` value partially intact because\n    // CellElement only calls setAttribute on keys the NEW template emits —\n    // any attribute the old template had but the new one omits stays.\n    // Result: badge/border from old style bleeds into the new render.\n    // PricingCardElement is one of the few elements that legitimately overrides\n    // `render()` directly — it needs a PRE-render attribute strip before the\n    // BaseElement render lifecycle runs. After W0.2a, super.render() hits the\n    // BaseElement Template Method (which calls CellElement._doRender + afterRender +\n    // notifySyncListeners) so the lifecycle is preserved end-to-end.\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this3 = this;\n      if (this.domNode) {\n        // Strip every non-essential attribute before super.render() repaints.\n        // Keep only the framework-owned `builder-element` tag.\n        var keep = new Set(['builder-element']);\n        var toRemove = [];\n        var _iterator = _createForOfIteratorHelper(this.domNode.attributes),\n          _step;\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var attr = _step.value;\n            if (!keep.has(attr.name)) toRemove.push(attr.name);\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n        toRemove.forEach(function (name) {\n          return _this3.domNode.removeAttribute(name);\n        });\n      }\n      return _superPropGet(PricingCardElement, \"render\", this, 3)([]);\n    }\n\n    // One-shot inspector rebuild — safe for discrete clicks (reset\n    // button). No-op unless this cell is the selected element; the\n    // panel will rebuild naturally next time it's selected otherwise.\n  }, {\n    key: \"_refreshInspector\",\n    value: function _refreshInspector() {\n      if (!this.host) return;\n      var host = this.host;\n      if (typeof host.renderElementControls !== 'function') return;\n      if (typeof host.getSelectedElement === 'function' && host.getSelectedElement() !== this) {\n        return;\n      }\n      host.renderElementControls(this);\n    }\n  }, {\n    key: \"renderEmptyPlaceholder\",\n    value: function renderEmptyPlaceholder() {\n      var title = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.card_empty_title');\n      var hint = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.card_empty_hint');\n      return \"\\n            <div builder-no-select style=\\\"\\n                display: flex;\\n                flex-direction: column;\\n                align-items: center;\\n                justify-content: center;\\n                gap: 8px;\\n                min-height: 160px;\\n                padding: 24px 16px;\\n                margin: 0;\\n                border-radius: 10px;\\n                background: rgba(148, 163, 184, 0.08);\\n                border: 1px dashed rgba(148, 163, 184, 0.45);\\n                color: #6b7280;\\n                font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\\n                text-align: center;\\n                user-select: none;\\n                pointer-events: none;\\n            \\\">\\n                <span class=\\\"material-symbols-rounded\\\" style=\\\"font-size: 28px; color: #9ca3af;\\\">view_column</span>\\n                <div style=\\\"font-size: 13px; font-weight: 600; color: #374151;\\\">\".concat(title, \"</div>\\n                <div style=\\\"font-size: 11px; color: #6b7280; max-width: 220px; line-height: 1.5;\\\">\").concat(hint, \"</div>\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      var base = _superPropGet(PricingCardElement, \"getData\", this, 3)([]);\n      base.highlighted = this.highlighted;\n      base.badge = this.badge;\n      base.icon = this.icon;\n      base.accent_color = this.accent_color;\n      return base;\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this4 = this;\n      var onMetaChange = function onMetaChange() {\n        return _this4.render();\n      };\n      // highlighted + accent mutations flip button treatment in 3 styles\n      // (highlighted / featured / brutalist) and recolor the button in\n      // a further 4 (compact / pill / neon / editorial). Re-apply the\n      // preset BEFORE render so the button's Formatter holds the new\n      // values by the time the cell repaints.\n      var onVisualMetaChange = function onVisualMetaChange() {\n        _this4.applyStylePreset();\n        _this4.render();\n      };\n      var currentStyle = this.getStyle();\n      var currentStyleLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing_style.' + currentStyle + '_label');\n      return [new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_card_meta'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_card_meta_desc')),\n      // Tell the user exactly which style's defaults this card is\n      // inheriting — and that the accent color they pick here\n      // overrides the style default. Kills the \"why is my button\n      // still orange after I picked blue\" confusion.\n      new _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.card_style_hint').replace('{style}', currentStyleLabel)), new _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlighted_label'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlighted_desc'), this.highlighted, function (v) {\n        _this4.highlighted = !!v;\n        onVisualMetaChange();\n      }), new _TextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.badge_label'), this.badge, {\n        setText: function setText(v) {\n          _this4.badge = v || '';\n          onMetaChange();\n        }\n      }), new _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.icon_label'), this.icon, {\n        setValue: function setValue(v) {\n          _this4.icon = v || '';\n          onMetaChange();\n        }\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.accent_label'), this.accent_color, {\n        setColor: function setColor(v) {\n          _this4.accent_color = v || '';\n          onVisualMetaChange();\n        }\n      }),\n      // Per-card escape hatch — strips accent_color override,\n      // clears icon/badge/highlight, and re-applies the style's\n      // default button + text colors. Useful when the user\n      // wants one card to \"go back to defaults\" without wiping\n      // every other card too.\n      new _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"]({\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_card_label'),\n        hint: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_card_hint').replace('{style}', currentStyleLabel),\n        buttonText: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_card_button'),\n        variant: 'default',\n        onClick: function onClick() {\n          _this4.accent_color = '';\n          _this4.icon = '';\n          _this4.badge = '';\n          _this4.highlighted = false;\n          _this4.applyStylePreset();\n          _this4.render();\n          // Rebuild inspector so the accent ColorPicker,\n          // badge TextControl, icon IconPicker, and\n          // highlighted Checkbox all snap back to their\n          // cleared state. Without this, the canvas\n          // repaints but the panel keeps the pre-reset\n          // values — user sees \"Reset\" do nothing.\n          _this4._refreshInspector();\n        }\n      })].concat(_toConsumableArray(_superPropGet(PricingCardElement, \"getControls\", this, 3)([])));\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var meta = {\n        highlighted: !!data.highlighted,\n        badge: typeof data.badge === 'string' ? data.badge : '',\n        icon: typeof data.icon === 'string' ? data.icon : '',\n        accent_color: typeof data.accent_color === 'string' ? data.accent_color : ''\n      };\n      var cell = new this(data.template || 'PricingCard', meta);\n      var blocks = Array.isArray(data.blocks) ? data.blocks : [];\n      blocks.forEach(function (blockData) {\n        var block = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].createElement(blockData);\n        block.container = cell;\n        cell.appendBlock(block);\n      });\n      cell.vertical_align = data.vertical_align || 'top';\n      return this.parseFormats(cell, data);\n    }\n  }]);\n}(_CellElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/**\n * Default accent color per parent style. Cell-level `accent_color` overrides.\n * Keep in sync with PricingCard.template.html STYLE_TOKENS.\n */\nPricingCardElement.STYLE_ACCENTS = {\n  minimal: '#ffcc2a',\n  highlighted: '#ffcc2a',\n  featured: '#ff4c6a',\n  compact: '#1b8a5a',\n  glass: '#6366f1',\n  pill: '#f59e0b',\n  neon: '#00e5ff',\n  brutalist: '#ff4c6a',\n  editorial: '#b45309',\n  gradient: '#7c3aed',\n  // Mailchimp yellow — same warm-mustard hue Mailchimp ships on its\n  // public pricing page (visual reference: image in task).\n  banded: '#ffe01b',\n  // Indigo — conveys elevation/tier/upgrade in SaaS pricing pages.\n  tier: '#4f46e5',\n  // Soft periwinkle — works with neumorphism's pale gray-blue\n  // surface without overwhelming the soft shadow play.\n  neo: '#818cf8'\n};\n\n// Tiny helper that emits a full 4-side border spec from a single shorthand.\n// ButtonElement's Formatter stores borders per-side (border_top_*, …);\n// the preset resolvers below only care about \"all sides the same\" so we\n// expand once here.\nfunction _border(style, width, color) {\n  return {\n    border_top_style: style,\n    border_top_width: width,\n    border_top_color: color,\n    border_right_style: style,\n    border_right_width: width,\n    border_right_color: color,\n    border_bottom_style: style,\n    border_bottom_width: width,\n    border_bottom_color: color,\n    border_left_style: style,\n    border_left_width: width,\n    border_left_color: color\n  };\n}\n\n/**\n * Per-style button preset resolvers. Each returns a flat formats object\n * that gets merged into the CTA ButtonElement's Formatter — only keys\n * that already exist in the Formatter are applied (see applyButtonPreset).\n *\n * The design intent is that each card style ships with a button that\n * looks \"native\" to that visual language — the old hardcoded dark pill\n * looked foreign on Glass (dark navy card-text, glass bg → navy button),\n * Editorial (thin amber outlines → outline button), Brutalist (hard\n * shadow + thick border → match), Gradient (white-on-gradient → white\n * button). Second argument `accent` is the cell's resolved accent (per-\n * cell override → style default). Third argument `highlighted` is the\n * per-cell flag; three styles (highlighted, featured, brutalist) use it\n * to swap the button fill to the accent on the stand-out card.\n */\nvar STYLE_BUTTON_RESOLVERS = {\n  minimal: function minimal(accent, highlighted) {\n    return Object.assign({\n      background_color: '#111827',\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '700',\n      border_radius: '8px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, '#111827'));\n  },\n  highlighted: function highlighted(accent, _highlighted) {\n    return _highlighted ? Object.assign({\n      background_color: accent,\n      text_color: '#1a1a1a',\n      link_color: '#1a1a1a',\n      font_weight: '800',\n      border_radius: '8px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, accent)) : Object.assign({\n      background_color: '#111827',\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '700',\n      border_radius: '8px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, '#111827'));\n  },\n  featured: function featured(accent, highlighted) {\n    return highlighted ? Object.assign({\n      background_color: accent,\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '800',\n      border_radius: '999px',\n      padding_top: 13,\n      padding_bottom: 13,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, accent)) : Object.assign({\n      background_color: '#111827',\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '700',\n      border_radius: '999px',\n      padding_top: 13,\n      padding_bottom: 13,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, '#111827'));\n  },\n  compact: function compact(accent, highlighted) {\n    return Object.assign({\n      background_color: accent,\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '700',\n      border_radius: '4px',\n      padding_top: 10,\n      padding_bottom: 10,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, accent));\n  },\n  glass: function glass(accent, highlighted) {\n    return Object.assign({\n      background_color: '#312e81',\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '700',\n      border_radius: '999px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 16,\n      padding_right: 16\n    }, _border('solid', 0, '#312e81'));\n  },\n  pill: function pill(accent, highlighted) {\n    return Object.assign({\n      background_color: accent,\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '700',\n      border_radius: '999px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 16,\n      padding_right: 16\n    }, _border('solid', 0, accent));\n  },\n  neon: function neon(accent, highlighted) {\n    return Object.assign({\n      background_color: accent,\n      text_color: '#0a0a0f',\n      link_color: '#0a0a0f',\n      font_weight: '800',\n      border_radius: '6px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, accent));\n  },\n  brutalist: function brutalist(accent, highlighted) {\n    // Highlighted brutalist card is flooded with accent + white text,\n    // so flip the button to white-on-black hard border to keep the\n    // \"stamped block\" look from disappearing. Non-highlighted cards\n    // get the classic solid-black rectangle.\n    return highlighted ? Object.assign({\n      background_color: '#ffffff',\n      text_color: '#000000',\n      link_color: '#000000',\n      font_weight: '900',\n      border_radius: 0,\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 16,\n      padding_right: 16\n    }, _border('solid', '2px', '#000000')) : Object.assign({\n      background_color: '#000000',\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '900',\n      border_radius: 0,\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 16,\n      padding_right: 16\n    }, _border('solid', '2px', '#000000'));\n  },\n  editorial: function editorial(accent, highlighted) {\n    // Outline-only amber button — matches the editorial card's thin\n    // serif/underline treatment. Transparent bg → the card's cream\n    // paper shows through.\n    return Object.assign({\n      background_color: 'transparent',\n      text_color: accent,\n      link_color: accent,\n      font_weight: '700',\n      border_radius: 0,\n      padding_top: 11,\n      padding_bottom: 11,\n      padding_left: 18,\n      padding_right: 18\n    }, _border('solid', '1px', accent));\n  },\n  gradient: function gradient(accent, highlighted) {\n    // White filled button on the gradient card bg — maximum contrast\n    // against any accent. Text reads the card's background gradient\n    // through dark-slate ink.\n    return Object.assign({\n      background_color: '#ffffff',\n      text_color: '#1f2937',\n      link_color: '#1f2937',\n      font_weight: '800',\n      border_radius: '8px',\n      padding_top: 12,\n      padding_bottom: 12,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, '#ffffff'));\n  },\n  banded: function banded(accent, highlighted) {\n    // Mailchimp-style yellow pill with a subtle dark \"underline\"\n    // border at the bottom. Fully rounded, dark ink text. Works on\n    // white/near-white card surface. The thin 1.5px bottom border\n    // is the Mailchimp signature touch.\n    return {\n      background_color: accent,\n      text_color: '#1a1a1a',\n      link_color: '#1a1a1a',\n      font_weight: '800',\n      border_radius: '999px',\n      padding_top: 13,\n      padding_bottom: 13,\n      padding_left: 16,\n      padding_right: 16,\n      border_top_style: 'solid',\n      border_top_width: 0,\n      border_top_color: accent,\n      border_right_style: 'solid',\n      border_right_width: 0,\n      border_right_color: accent,\n      border_bottom_style: 'solid',\n      border_bottom_width: '2px',\n      border_bottom_color: '#1a1a1a',\n      border_left_style: 'solid',\n      border_left_width: 0,\n      border_left_color: accent\n    };\n  },\n  tier: function tier(accent, highlighted) {\n    // Indigo filled rounded — feels elevated / premium. Slight text\n    // tracking (\"letter_spacing\") would help, but ButtonElement\n    // formatter doesn't expose it. Weight 800 alone handles pop.\n    return Object.assign({\n      background_color: accent,\n      text_color: '#ffffff',\n      link_color: '#ffffff',\n      font_weight: '800',\n      border_radius: '10px',\n      padding_top: 13,\n      padding_bottom: 13,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', 0, accent));\n  },\n  neo: function neo(accent, highlighted) {\n    // Neumorphism-style button — pale surface, accent text, soft\n    // border. Real neumorphism would need dual box-shadows (outer\n    // light + outer dark) which ButtonElement can't express via\n    // Formatter; we approximate with a thin accent border + tinted\n    // bg. The card wrapper's box-shadow carries the neu feel.\n    return Object.assign({\n      background_color: '#eef1f6',\n      text_color: accent,\n      link_color: accent,\n      font_weight: '700',\n      border_radius: '14px',\n      padding_top: 13,\n      padding_bottom: 13,\n      padding_left: 14,\n      padding_right: 14\n    }, _border('solid', '1px', '#d6dbe4'));\n  }\n};\nPricingCardElement.resolveButtonFormats = function (style, accent, highlighted) {\n  var fn = STYLE_BUTTON_RESOLVERS[style] || STYLE_BUTTON_RESOLVERS.highlighted;\n  return fn(accent, highlighted);\n};\nPricingCardElement.STYLE_BUTTON_RESOLVERS = STYLE_BUTTON_RESOLVERS;\n\n/**\n * Per-style text-format resolvers. Each returns a dict keyed by element\n * role ('heading' | 'price' | 'muted' | 'feature') with format overrides.\n * Only keys present in the element's Formatter are applied, so unrelated\n * text-format keys (letter_spacing on Heading, text_color on PElement)\n * coexist safely.\n *\n * Styles with a dark card surface (neon, brutalist+highlighted, gradient)\n * need light text — the default dark text colors seeded at newCell time\n * would render invisibly. Editorial wants serif. Banded (Mailchimp-like)\n * also wants serif + slightly warmer tone. Glass wants navy ink to match\n * its native accent.\n */\nvar STYLE_TEXT_RESOLVERS = {\n  minimal: function minimal(accent, hl) {\n    return {\n      heading: {\n        text_color: '#111827'\n      },\n      price: {\n        text_color: '#111827'\n      },\n      muted: {\n        text_color: 'rgba(15,23,42,0.6)'\n      },\n      feature: {\n        text_color: '#1f2937'\n      }\n    };\n  },\n  highlighted: function highlighted(accent, hl) {\n    return {\n      heading: {\n        text_color: '#111827'\n      },\n      price: {\n        text_color: '#111827'\n      },\n      muted: {\n        text_color: 'rgba(15,23,42,0.6)'\n      },\n      feature: {\n        text_color: '#1f2937'\n      }\n    };\n  },\n  featured: function featured(accent, hl) {\n    return {\n      heading: {\n        text_color: '#111827'\n      },\n      price: {\n        text_color: '#111827'\n      },\n      muted: {\n        text_color: 'rgba(15,23,42,0.62)'\n      },\n      feature: {\n        text_color: '#1f2937'\n      }\n    };\n  },\n  compact: function compact(accent, hl) {\n    return {\n      heading: {\n        text_color: '#0f172a'\n      },\n      price: {\n        text_color: '#0f172a'\n      },\n      muted: {\n        text_color: 'rgba(15,23,42,0.58)'\n      },\n      feature: {\n        text_color: '#1e293b'\n      }\n    };\n  },\n  glass: function glass(accent, hl) {\n    // Card sets color: '#312e81' at wrapper level; reinforce that on\n    // children so overrides from hardcoded newCell colors don't\n    // punch through.\n    return {\n      heading: {\n        text_color: '#1e1b4b'\n      },\n      price: {\n        text_color: '#1e1b4b'\n      },\n      muted: {\n        text_color: 'rgba(49,46,129,0.65)'\n      },\n      feature: {\n        text_color: '#312e81'\n      }\n    };\n  },\n  pill: function pill(accent, hl) {\n    return {\n      heading: {\n        text_color: '#111827'\n      },\n      price: {\n        text_color: '#111827'\n      },\n      muted: {\n        text_color: 'rgba(15,23,42,0.58)'\n      },\n      feature: {\n        text_color: '#1f2937'\n      }\n    };\n  },\n  neon: function neon(accent, hl) {\n    // Dark cyberpunk surface. Light text everywhere; muted = 60%.\n    // Price gets a subtle glow via text-shadow — BUT formatter has\n    // no text-shadow key; template wrapper supplies the shadow via\n    // inherited color rules. Here we just own the colors.\n    return {\n      heading: {\n        text_color: '#e5e7eb'\n      },\n      price: {\n        text_color: accent\n      },\n      muted: {\n        text_color: 'rgba(229,231,235,0.6)'\n      },\n      feature: {\n        text_color: '#d1d5db'\n      }\n    };\n  },\n  brutalist: function brutalist(accent, hl) {\n    // Highlighted brutalist card is flooded with accent + dark text\n    // needed on accent backdrop. Non-highlighted: default black text\n    // on white.\n    if (hl) {\n      return {\n        heading: {\n          text_color: '#ffffff'\n        },\n        price: {\n          text_color: '#ffffff'\n        },\n        muted: {\n          text_color: 'rgba(255,255,255,0.78)'\n        },\n        feature: {\n          text_color: '#ffffff'\n        }\n      };\n    }\n    return {\n      heading: {\n        text_color: '#000000'\n      },\n      price: {\n        text_color: '#000000'\n      },\n      muted: {\n        text_color: 'rgba(0,0,0,0.6)'\n      },\n      feature: {\n        text_color: '#111111'\n      }\n    };\n  },\n  editorial: function editorial(accent, hl) {\n    // Warm paper card, serif, amber accent. Slightly warmer ink than\n    // default black for that \"printed magazine\" feel.\n    return {\n      heading: {\n        text_color: '#1c1917',\n        font_family: 'Georgia, \"Times New Roman\", serif'\n      },\n      price: {\n        text_color: '#1c1917',\n        font_family: 'Georgia, \"Times New Roman\", serif'\n      },\n      muted: {\n        text_color: 'rgba(28,25,23,0.65)',\n        font_family: 'Georgia, \"Times New Roman\", serif'\n      },\n      feature: {\n        text_color: '#44403c',\n        font_family: 'Georgia, \"Times New Roman\", serif'\n      }\n    };\n  },\n  gradient: function gradient(accent, hl) {\n    // White text on gradient card bg. Muted is 75% white (not lower —\n    // goes illegible on bright gradient stops).\n    return {\n      heading: {\n        text_color: '#ffffff'\n      },\n      price: {\n        text_color: '#ffffff'\n      },\n      muted: {\n        text_color: 'rgba(255,255,255,0.78)'\n      },\n      feature: {\n        text_color: '#ffffff'\n      }\n    };\n  },\n  banded: function banded(accent, hl) {\n    // Mailchimp-style: serif \"Cooper\" / \"Sharp Grotesk\" vibe →\n    // Georgia fallback. Muted reads like editorial body copy.\n    return {\n      heading: {\n        text_color: '#1c1917',\n        font_family: 'Georgia, \"Times New Roman\", serif'\n      },\n      price: {\n        text_color: '#1c1917',\n        font_family: 'Georgia, \"Times New Roman\", serif'\n      },\n      muted: {\n        text_color: 'rgba(28,25,23,0.68)'\n      },\n      feature: {\n        text_color: '#1f2937'\n      }\n    };\n  },\n  tier: function tier(accent, hl) {\n    // Deep indigo inked primary; muted stays slate. Heading gets\n    // a hint of accent tint via letter_spacing would be nice but\n    // Formatter owns that on a per-element basis — the heading in\n    // newCell already sets 0.08em. Leave it alone.\n    return {\n      heading: {\n        text_color: '#1e1b4b'\n      },\n      price: {\n        text_color: '#1e1b4b'\n      },\n      muted: {\n        text_color: 'rgba(30,27,75,0.6)'\n      },\n      feature: {\n        text_color: '#312e81'\n      }\n    };\n  },\n  neo: function neo(accent, hl) {\n    // Soft gray-blue surface wants ink that isn't pure black — it\n    // fights the neumorphic glow. Slate 800 feels right.\n    return {\n      heading: {\n        text_color: '#1e293b'\n      },\n      price: {\n        text_color: '#1e293b'\n      },\n      muted: {\n        text_color: 'rgba(30,41,59,0.62)'\n      },\n      feature: {\n        text_color: '#334155'\n      }\n    };\n  }\n};\nPricingCardElement.resolveTextFormats = function (style, accent, highlighted) {\n  var fn = STYLE_TEXT_RESOLVERS[style] || STYLE_TEXT_RESOLVERS.minimal;\n  return fn(accent, highlighted);\n};\nPricingCardElement.STYLE_TEXT_RESOLVERS = STYLE_TEXT_RESOLVERS;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PricingCardElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PricingCardElement.js?");

/***/ }),

/***/ "./src/includes/PricingCardsElement.js":
/*!*********************************************!*\
  !*** ./src/includes/PricingCardsElement.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _GridElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./GridElement.js */ \"./src/includes/GridElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ButtonElement.js */ \"./src/includes/ButtonElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _StyleControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./StyleControl.js */ \"./src/includes/StyleControl.js\");\n/* harmony import */ var _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./SectionLabelControl.js */ \"./src/includes/SectionLabelControl.js\");\n/* harmony import */ var _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./DropdownControl.js */ \"./src/includes/DropdownControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./InfoBannerControl.js */ \"./src/includes/InfoBannerControl.js\");\n/* harmony import */ var _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./ActionButtonControl.js */ \"./src/includes/ActionButtonControl.js\");\n/* harmony import */ var _PricingCardElement_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./PricingCardElement.js */ \"./src/includes/PricingCardElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * PricingCardsElement — a Grid of PricingCardElements (pricing plan cards).\n *\n * Extends GridElement (per Builder composition rule: only Grid subclasses may\n * host cells). Cells are PricingCardElement instances, each holding native\n * BlockElement children (Heading, PElements, Button, ListElement, etc.) that\n * the user edits with the native controls already in the codebase — no\n * HTML-blob / RichText shortcut.\n *\n * Visual treatment is driven by a single parent-level `style` prop (1 of 10\n * presets). Each card reads `this.container.style` at render time to shape\n * its wrapper (see PricingCard.template.html). Per-card metadata (highlighted,\n * badge, icon, accent_color) lives on the cell.\n *\n * Replaces retired: PricingTableElement (HTML-blob) + PricingGridElement\n * (orphan prototype). See docs/plans/DESIGN_PRICING_ELEMENT.md.\n */\n\nvar VALID_STYLES = ['minimal', 'highlighted', 'featured', 'compact', 'glass', 'pill', 'neon', 'brutalist', 'editorial', 'gradient',\n// 2026-04-18 PRO-audit round: three new presets adding distinct\n// visual languages — joined table (banded), staircase elevation\n// (tier), and soft neumorphism (neo). See DESIGN_PRICING_ELEMENT.md.\n'banded', 'tier', 'neo'];\nvar DEFAULT_STYLE = 'highlighted';\n\n// Per-style default gap between cards — MUST cover every style in\n// VALID_STYLES so setStyle() can authoritatively re-apply the right\n// spacing on every switch. Earlier version only listed the three new\n// presets (banded/tier/neo), which meant: pick \"banded\" (gap=0), then\n// switch to any other style → gap stayed 0 forever because the lookup\n// missed and the guard preserved the prior value. By covering all 13\n// the gap now always reflects the chosen style's intent.\nvar STYLE_DEFAULT_GAPS = {\n  minimal: 20,\n  highlighted: 20,\n  featured: 24,\n  compact: 8,\n  glass: 20,\n  pill: 20,\n  neon: 20,\n  brutalist: 16,\n  editorial: 24,\n  gradient: 20,\n  banded: 0,\n  tier: 16,\n  neo: 24\n};\nvar PricingCardsElement = /*#__PURE__*/function (_GridElement) {\n  function PricingCardsElement(template) {\n    var _this;\n    _classCallCheck(this, PricingCardsElement);\n    _this = _callSuper(this, PricingCardsElement, [template || 'PricingCards']);\n    _this.style = DEFAULT_STYLE;\n    _this.cell_gap = 20;\n    // Parent-level toggles — cell template reads these via its container\n    // reference to decide whether to render per-cell icon / badge.\n    _this.show_icons = true;\n    _this.show_badges = true;\n    return _this;\n  }\n  _inherits(PricingCardsElement, _GridElement);\n  return _createClass(PricingCardsElement, [{\n    key: \"getClassName\",\n    value: function getClassName() {\n      return 'PricingCardsElement';\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.pricing_cards');\n    }\n\n    // Override GridElement.isHoverable() (which returns false for plain Grids\n    // because hover-highlighting a Grid that fills the canvas would be noisy).\n    // Pricing Cards is a discrete visual block — users expect to hover/click\n    // the whole set to select + move it.\n  }, {\n    key: \"isHoverable\",\n    value: function isHoverable() {\n      return true;\n    }\n\n    // Inject `style` into the parent wrapper template so the grid root can\n    // emit `data-pricing-cards-style` — selectors and global style rules can\n    // then target a specific preset. W0.2c: dropped the redundant\n    // `if (template === 'PricingCards')` dispatch — element identity ↔\n    // template = 1:1 invariant after A2 pure refactor (BUILDER.md Lesson 50).\n  }, {\n    key: \"renderTemplate\",\n    value: function renderTemplate() {\n      var vars = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      return _superPropGet(PricingCardsElement, \"renderTemplate\", this, 3)([_objectSpread({\n        style: this.style\n      }, vars)]);\n    }\n  }, {\n    key: \"setStyle\",\n    value: function setStyle(nextStyle) {\n      this.style = VALID_STYLES.indexOf(nextStyle) !== -1 ? nextStyle : DEFAULT_STYLE;\n      // Apply the style's default cell_gap. STYLE_DEFAULT_GAPS covers\n      // every style, so the fallback branch only runs for unknown\n      // keys (shouldn't happen once VALID_STYLES gates the input).\n      if (Object.prototype.hasOwnProperty.call(STYLE_DEFAULT_GAPS, this.style)) {\n        this.cell_gap = STYLE_DEFAULT_GAPS[this.style];\n      }\n      // Reset per-card visual theming so the new style's defaults take\n      // effect — accent_color, button formats, and text colors all get\n      // rewritten to the new style's preset. Per-card highlighted /\n      // badge / icon are preserved (they're orthogonal to theming).\n      this.cells.forEach(function (cell) {\n        if (cell && typeof cell.accent_color !== 'undefined') cell.accent_color = '';\n        if (cell && typeof cell.applyStylePreset === 'function') cell.applyStylePreset();\n      });\n      this.render();\n      // Rebuild inspector so cell_gap slider, info-banner ({style}\n      // placeholder), and any StyleControl state all reflect the new\n      // preset. Without this the Range slider on Cell Gap keeps\n      // showing the previous numeric value even though cell_gap was\n      // just overwritten.\n      this._refreshInspector();\n    }\n\n    // Create a seeded pricing card with default native content: Heading\n    // (plan name), PElement (price), PElement (period), PElements (features)\n    // and a ButtonElement CTA. Same idea as the retired PricingGridElement\n    // newCell, but emits PricingCardElement (Cell subclass) with card meta.\n  }, {\n    key: \"newCell\",\n    value: function newCell() {\n      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n      var planIndex = this.cells.length;\n      var cell = new _PricingCardElement_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"]('PricingCard', {\n        highlighted: false,\n        badge: '',\n        icon: '',\n        accent_color: ''\n      });\n      cell.container = this;\n      cell.formatter.setFormat('width', this._defaultWidthForNewCell());\n      cell.vertical_align = 'top';\n      var block = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Block');\n      block.container = cell;\n      block.formatter.setFormat('padding_top', 0);\n      block.formatter.setFormat('padding_bottom', 0);\n      block.formatter.setFormat('padding_left', 0);\n      block.formatter.setFormat('padding_right', 0);\n      var planName = options.planName || \"Plan \".concat(planIndex + 1);\n      var planDesc = options.planDesc || 'Describe this plan in one short line.';\n      var planPriceText = options.planPrice || '$0';\n      var planPeriodText = options.planPeriod || 'per month';\n      var planSubText = options.planSub || '';\n      var features = Array.isArray(options.features) && options.features.length ? options.features : ['Feature one', 'Feature two', 'Feature three', 'Feature four'];\n      var ctaText = options.ctaText || 'Get started';\n\n      // Tag each element with a `_pricing_role` hint so the style\n      // preset resolver knows how to theme it. Role tags let us pick\n      // the right text color per style (primary vs muted vs feature)\n      // without relying on positional heuristics that break when the\n      // user inserts / reorders elements.\n      var heading = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h3', planName);\n      heading._pricing_role = 'heading';\n      heading.formatter.setFormat('font_size', 18);\n      heading.formatter.setFormat('font_weight', 'bolder');\n      heading.formatter.setFormat('letter_spacing', '0.08em');\n      var desc = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planDesc);\n      desc._pricing_role = 'muted';\n      desc.formatter.setFormat('font_size', 13);\n      desc.formatter.setFormat('padding_bottom', 4);\n      var price = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planPriceText);\n      price._pricing_role = 'price';\n      price.formatter.setFormat('font_size', 42);\n      price.formatter.setFormat('font_weight', '800');\n      price.formatter.setFormat('line_height', '1');\n      price.formatter.setFormat('padding_top', 4);\n      var period = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planPeriodText);\n      period._pricing_role = 'muted';\n      period.formatter.setFormat('font_size', 14);\n      var elements = [heading, desc, price, period];\n      if (planSubText) {\n        var sub = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', planSubText);\n        sub._pricing_role = 'muted';\n        sub.formatter.setFormat('font_size', 13);\n        sub.formatter.setFormat('padding_bottom', 8);\n        elements.push(sub);\n      }\n      features.forEach(function (line, i) {\n        var f = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', \"\\u2713 \" + line);\n        f._pricing_role = 'feature';\n        f.formatter.setFormat('font_size', 14);\n        f.formatter.setFormat('padding_top', 4);\n        f.formatter.setFormat('padding_bottom', 4);\n        // Extra breathing room above the last feature so the upcoming CTA\n        // button has space to \"land\" without touching the features list.\n        if (i === features.length - 1) f.formatter.setFormat('padding_bottom', 20);\n        elements.push(f);\n      });\n      var cta = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]('Button', ctaText, options.ctaUrl || '#');\n      cta._pricing_role = 'cta';\n      // Font-size + alignment stay constant across all 10 styles — only\n      // the style preset swaps color / border / radius. See\n      // PricingCardElement.STYLE_BUTTON_RESOLVERS.\n      cta.formatter.setFormat('font_size', 14);\n      cta.formatter.setFormat('align', 'stretch');\n      elements.push(cta);\n      cell.appendBlock(block);\n      block.appendElements(elements);\n\n      // Apply the current style's preset (button + text colors).\n      // Without this the CTA would render with ButtonElement's stock\n      // blue — foreign to every pricing style — and text colors\n      // would stay fixed-dark even on dark card surfaces (neon,\n      // brutalist-highlighted, gradient). The preset is hard-written\n      // to each element's Formatter so opening the inspector panel\n      // shows the actual values (no \"empty bg color\" confusion).\n      cell.applyStylePreset();\n      return cell;\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      var base = _superPropGet(PricingCardsElement, \"getData\", this, 3)([]);\n      base.style = this.style;\n      base.show_icons = this.show_icons;\n      base.show_badges = this.show_badges;\n      return base;\n    }\n  }, {\n    key: \"getStyleOptions\",\n    value: function getStyleOptions() {\n      return VALID_STYLES.map(function (key) {\n        return {\n          key: key,\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing_style.' + key + '_label'),\n          thumb: PricingCardsElement.THUMBS[key] || ''\n        };\n      });\n    }\n\n    // Highlight-plan helper (parent-level). Mutates per-cell `highlighted` so\n    // only cell at `index` is highlighted (0-based). Pass -1 to clear.\n  }, {\n    key: \"setHighlightIndex\",\n    value: function setHighlightIndex(index) {\n      var n = parseInt(index, 10);\n      this.cells.forEach(function (cell, i) {\n        if (typeof cell.highlighted === 'boolean') cell.highlighted = i === n;\n      });\n      this.render();\n    }\n  }, {\n    key: \"setShowIcons\",\n    value: function setShowIcons(value) {\n      this.show_icons = !!value;\n      this.render();\n    }\n  }, {\n    key: \"setShowBadges\",\n    value: function setShowBadges(value) {\n      this.show_badges = !!value;\n      this.render();\n    }\n\n    // Reset per-cell overrides → clears accent_color, icon, badge on each\n    // card, un-highlights them all, and re-applies the currently\n    // selected style's preset (button + text colors). Kept as a\n    // parent-level \"Clean up\" action so the user can wipe manual\n    // tweaks and start from a coherent preset. Preserves card CONTENT\n    // (heading text, price text, feature lines, CTA label/URL) — only\n    // visual theming is rewritten.\n  }, {\n    key: \"resetCards\",\n    value: function resetCards() {\n      this.cells.forEach(function (cell) {\n        if (!cell) return;\n        cell.accent_color = '';\n        cell.icon = '';\n        cell.badge = '';\n        cell.highlighted = false;\n        if (typeof cell.applyStylePreset === 'function') cell.applyStylePreset();\n      });\n      // Also reset parent-level toggles so \"Reset all\" is a true\n      // clean-slate — if the user toggled Show icons / badges OFF\n      // earlier, reset restores the as-shipped visibility too.\n      this.show_icons = true;\n      this.show_badges = true;\n      // Re-apply the current style's gap default too — the user may\n      // have dragged Cell Gap manually; reset should restore the\n      // style's canonical spacing.\n      if (Object.prototype.hasOwnProperty.call(STYLE_DEFAULT_GAPS, this.style)) {\n        this.cell_gap = STYLE_DEFAULT_GAPS[this.style];\n      }\n      this.render();\n      // Rebuild inspector so Highlight-plan dropdown flips back to\n      // \"None\", Show-icons/badges toggles flip ON, and the Cell Gap\n      // slider snaps back to the style default. Without this, the\n      // canvas repaints correctly but the panel keeps stale values\n      // (the bug the user reported as \"resets ko update settings\").\n      this._refreshInspector();\n    }\n\n    // One-shot inspector rebuild — safe to call from discrete user\n    // actions (reset buttons, style picker). Guarded so it only fires\n    // when this element is the currently selected one; otherwise it's\n    // a no-op (the panel will rebuild naturally when the element gets\n    // selected). Avoids the \"renderElementControls-in-setter flicker\"\n    // trap by skipping rapid-fire paths (no cell_gap slider binds to\n    // this).\n  }, {\n    key: \"_refreshInspector\",\n    value: function _refreshInspector() {\n      if (!this.host) return;\n      var host = this.host;\n      if (typeof host.renderElementControls !== 'function') return;\n      if (typeof host.getSelectedElement === 'function' && host.getSelectedElement() !== this) {\n        return;\n      }\n      host.renderElementControls(this);\n    }\n  }, {\n    key: \"_currentHighlightIndex\",\n    value: function _currentHighlightIndex() {\n      for (var i = 0; i < this.cells.length; i++) {\n        if (this.cells[i] && this.cells[i].highlighted) return i;\n      }\n      return -1;\n    }\n  }, {\n    key: \"_highlightOptions\",\n    value: function _highlightOptions() {\n      var opts = [{\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlight_none'),\n        value: '-1'\n      }];\n      this.cells.forEach(function (_, i) {\n        opts.push({\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlight_card_n').replace('{n}', i + 1),\n          value: String(i)\n        });\n      });\n      return opts;\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      var parentControls = _superPropGet(PricingCardsElement, \"getControls\", this, 3)([]);\n      var currentStyleLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing_style.' + this.style + '_label');\n      return [new _SectionLabelControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_style'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.section_style_desc')), new _StyleControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.style_label'), this.style, this.getStyleOptions(), {\n        setValue: function setValue(v) {\n          return _this2.setStyle(v);\n        }\n      }),\n      // Info hint — makes explicit that switching styles wipes\n      // per-card visual overrides (accent / button / text colors)\n      // and that badge / icon / highlight choices survive. Without\n      // this, a user who custom-colored a button and then switched\n      // style would wonder \"where did my color go?\". Helper text\n      // surfaces the rule up-front.\n      new _InfoBannerControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.style_switch_hint').replace('{style}', currentStyleLabel)), new _DropdownControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.highlight_label'), String(this._currentHighlightIndex()), this._highlightOptions(), function (v) {\n        return _this2.setHighlightIndex(v);\n      }), new _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_icons_label'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_icons_desc'), this.show_icons, function (v) {\n        return _this2.setShowIcons(v);\n      }), new _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_badges_label'), _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.show_badges_desc'), this.show_badges, function (v) {\n        return _this2.setShowBadges(v);\n      }),\n      // Parent-level escape hatch — wipes accent/badge/icon/highlight\n      // on every card and re-applies style preset. Useful after\n      // heavy per-card experimentation.\n      new _ActionButtonControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"]({\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_all_label'),\n        hint: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_all_hint').replace('{style}', currentStyleLabel),\n        buttonText: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.reset_all_button'),\n        variant: 'danger',\n        onClick: function onClick() {\n          return _this2.resetCards();\n        }\n      })].concat(_toConsumableArray(parentControls));\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var element = new this(data.template || 'PricingCards');\n      var nextStyle = data.style;\n      element.style = VALID_STYLES.indexOf(nextStyle) !== -1 ? nextStyle : DEFAULT_STYLE;\n      element.cell_gap = typeof data.cell_gap === 'number' ? data.cell_gap : element.cell_gap;\n      if (typeof data.show_icons === 'boolean') element.show_icons = data.show_icons;\n      if (typeof data.show_badges === 'boolean') element.show_badges = data.show_badges;\n      this.parseFormats(element, data);\n      var cells = Array.isArray(data.cells) ? data.cells : [];\n      cells.forEach(function (cellData) {\n        // Accept: new PricingCardElement, legacy plain CellElement, or\n        // Arch-A legacy cell shape (`{ details: 'HTML' }`). The ElementFactory\n        // auto-migration lifts old shapes to PricingCardElement before we\n        // see them here, but guard defensively:\n        if (cellData && _typeof(cellData) === 'object' && !cellData.name) {\n          cellData.name = 'PricingCardElement';\n          cellData.template = cellData.template || 'PricingCard';\n        }\n        var cell = _ElementFactory_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"].createElement(cellData);\n        cell.container = element;\n        element.append(cell);\n      });\n      return element;\n    }\n  }]);\n}(_GridElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]); // 10 thumbnail SVGs for the style picker. 120×72 viewBox, 4 card columns.\nPricingCardsElement.THUMBS = {\n  minimal: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f9fafb\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <rect x=\\\"12\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\"   fill=\\\"#9ca3af\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\"   fill=\\\"#9ca3af\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\"   fill=\\\"#9ca3af\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"17\\\" width=\\\"12\\\" height=\\\"2\\\"   fill=\\\"#9ca3af\\\"/>\\n  <text x=\\\"12\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"32\\\" font-family=\\\"-apple-system,sans-serif\\\" font-size=\\\"7.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n  <g fill=\\\"#d1d5db\\\">\\n    <rect x=\\\"12\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"12\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"12\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1.2\\\"/>\\n    <rect x=\\\"40\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"40\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"40\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1.2\\\"/>\\n    <rect x=\\\"68\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"68\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1.2\\\"/><rect x=\\\"68\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1.2\\\"/>\\n    <rect x=\\\"95\\\" y=\\\"38\\\" width=\\\"12\\\" height=\\\"1.2\\\"/><rect x=\\\"95\\\" y=\\\"42\\\" width=\\\"12\\\" height=\\\"1.2\\\"/><rect x=\\\"95\\\" y=\\\"46\\\" width=\\\"12\\\" height=\\\"1.2\\\"/>\\n  </g>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n</svg>\",\n  highlighted: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f9fafb\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"6\\\"  width=\\\"24\\\" height=\\\"60\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#ffcc2a\\\" stroke-width=\\\"1.5\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"6\\\"  width=\\\"24\\\" height=\\\"7\\\"  fill=\\\"#ffcc2a\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"4\\\" fill=\\\"#fff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <text x=\\\"38\\\" y=\\\"11.2\\\" font-size=\\\"3\\\" font-weight=\\\"800\\\" fill=\\\"#1a1a1a\\\">POPULAR</text>\\n  <text x=\\\"12\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n  <text x=\\\"68\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n  <text x=\\\"95\\\" y=\\\"32\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#ffcc2a\\\"/>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#111827\\\"/>\\n</svg>\",\n  featured: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fff5f2\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"14\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"14\\\" width=\\\"20\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#fff\\\" stroke=\\\"#f0d0c8\\\"/>\\n  <rect x=\\\"42\\\" y=\\\"10\\\" width=\\\"12\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ff4c6a\\\"/>\\n  <text x=\\\"44\\\" y=\\\"14.5\\\" font-size=\\\"3\\\" font-weight=\\\"800\\\" fill=\\\"#fff\\\">BEST</text>\\n  <circle cx=\\\"20\\\"  cy=\\\"24\\\" r=\\\"5\\\" fill=\\\"#ff4c6a22\\\"/>\\n  <circle cx=\\\"48\\\"  cy=\\\"24\\\" r=\\\"5\\\" fill=\\\"#ff4c6a22\\\"/>\\n  <circle cx=\\\"76\\\"  cy=\\\"24\\\" r=\\\"5\\\" fill=\\\"#ff4c6a22\\\"/>\\n  <circle cx=\\\"102\\\" cy=\\\"24\\\" r=\\\"4\\\" fill=\\\"#ff4c6a22\\\"/>\\n  <text x=\\\"14\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n  <text x=\\\"42\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n  <text x=\\\"70\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n  <text x=\\\"96\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#ff4c6a\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#111827\\\"/>\\n  <rect x=\\\"94\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#111827\\\"/>\\n</svg>\",\n  compact: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f3f4f6\\\"/>\\n  <rect x=\\\"6\\\"  y=\\\"8\\\"  width=\\\"26\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n  <rect x=\\\"34\\\" y=\\\"8\\\"  width=\\\"26\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n  <rect x=\\\"62\\\" y=\\\"8\\\"  width=\\\"26\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n  <rect x=\\\"90\\\" y=\\\"8\\\"  width=\\\"24\\\" height=\\\"58\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d1d5db\\\"/>\\n  <text x=\\\"10\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$0</text>\\n  <text x=\\\"38\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$19</text>\\n  <text x=\\\"66\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$49</text>\\n  <text x=\\\"94\\\" y=\\\"22\\\" font-size=\\\"4.5\\\" font-weight=\\\"800\\\" fill=\\\"#111827\\\">$99</text>\\n  <g fill=\\\"#9ca3af\\\">\\n    <rect x=\\\"10\\\" y=\\\"28\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"32\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"36\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"40\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"44\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"48\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"10\\\" y=\\\"52\\\" width=\\\"16\\\" height=\\\"0.8\\\"/>\\n    <rect x=\\\"38\\\" y=\\\"28\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"32\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"36\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"40\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"44\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"48\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"38\\\" y=\\\"52\\\" width=\\\"16\\\" height=\\\"0.8\\\"/>\\n    <rect x=\\\"66\\\" y=\\\"28\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"32\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"36\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"40\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"44\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"48\\\" width=\\\"16\\\" height=\\\"0.8\\\"/><rect x=\\\"66\\\" y=\\\"52\\\" width=\\\"16\\\" height=\\\"0.8\\\"/>\\n    <rect x=\\\"94\\\" y=\\\"28\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"32\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"36\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"40\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"44\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"48\\\" width=\\\"14\\\" height=\\\"0.8\\\"/><rect x=\\\"94\\\" y=\\\"52\\\" width=\\\"14\\\" height=\\\"0.8\\\"/>\\n  </g>\\n  <rect x=\\\"10\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n  <rect x=\\\"38\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n  <rect x=\\\"66\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n  <rect x=\\\"94\\\" y=\\\"58\\\" width=\\\"10\\\" height=\\\"2\\\" fill=\\\"#1b8a5a\\\"/>\\n</svg>\",\n  glass: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <defs>\\n    <linearGradient id=\\\"pc-bg-glass\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\">\\n      <stop offset=\\\"0\\\"   stop-color=\\\"#a5b4fc\\\"/>\\n      <stop offset=\\\"0.5\\\" stop-color=\\\"#fca5a5\\\"/>\\n      <stop offset=\\\"1\\\"   stop-color=\\\"#fde68a\\\"/>\\n    </linearGradient>\\n    <linearGradient id=\\\"pc-glass\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"0\\\" y2=\\\"1\\\">\\n      <stop offset=\\\"0\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"0.7\\\"/>\\n      <stop offset=\\\"1\\\" stop-color=\\\"#ffffff\\\" stop-opacity=\\\"0.35\\\"/>\\n    </linearGradient>\\n  </defs>\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"url(#pc-bg-glass)\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"url(#pc-glass)\\\" stroke=\\\"#ffffff\\\" stroke-opacity=\\\"0.6\\\"/>\\n  <text x=\\\"12\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#312e81\\\">$99</text>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#312e81\\\"/>\\n</svg>\",\n  pill: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fefce8\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"12\\\" fill=\\\"#fff\\\"/>\\n  <text x=\\\"20\\\"  y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\uD83D\\uDE80</text>\\n  <text x=\\\"48\\\"  y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\u26A1</text>\\n  <text x=\\\"76\\\"  y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\uD83D\\uDC8E</text>\\n  <text x=\\\"102\\\" y=\\\"26\\\" font-size=\\\"10\\\" text-anchor=\\\"middle\\\">\\uD83C\\uDFC6</text>\\n  <text x=\\\"20\\\"  y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$0</text>\\n  <text x=\\\"48\\\"  y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$19</text>\\n  <text x=\\\"76\\\"  y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$49</text>\\n  <text x=\\\"102\\\" y=\\\"40\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" text-anchor=\\\"middle\\\" fill=\\\"#111827\\\">$99</text>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n  <rect x=\\\"96\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#f59e0b\\\"/>\\n</svg>\",\n  neon: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#0a0a0f\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"0.6\\\" stroke-opacity=\\\"0.9\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"1.6\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"0.6\\\" stroke-opacity=\\\"0.9\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"#14141c\\\" stroke=\\\"#00e5ff\\\" stroke-width=\\\"0.6\\\" stroke-opacity=\\\"0.9\\\"/>\\n  <text x=\\\"12\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"30\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#00e5ff\\\">$99</text>\\n  <g fill=\\\"#6b7280\\\">\\n    <rect x=\\\"12\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"12\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"12\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1\\\"/>\\n    <rect x=\\\"40\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"40\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"40\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1\\\"/>\\n    <rect x=\\\"68\\\" y=\\\"38\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"68\\\" y=\\\"42\\\" width=\\\"14\\\" height=\\\"1\\\"/><rect x=\\\"68\\\" y=\\\"46\\\" width=\\\"14\\\" height=\\\"1\\\"/>\\n    <rect x=\\\"95\\\" y=\\\"38\\\" width=\\\"12\\\" height=\\\"1\\\"/><rect x=\\\"95\\\" y=\\\"42\\\" width=\\\"12\\\" height=\\\"1\\\"/><rect x=\\\"95\\\" y=\\\"46\\\" width=\\\"12\\\" height=\\\"1\\\"/>\\n  </g>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#00e5ff\\\"/>\\n</svg>\",\n  brutalist: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fef08a\\\"/>\\n  <rect x=\\\"9\\\"  y=\\\"9\\\"  width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"8\\\"  width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#fff\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n  <rect x=\\\"37\\\" y=\\\"9\\\"  width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"8\\\"  width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#ff4c6a\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n  <rect x=\\\"65\\\" y=\\\"9\\\"  width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"8\\\"  width=\\\"24\\\" height=\\\"52\\\" fill=\\\"#fff\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n  <rect x=\\\"93\\\" y=\\\"9\\\"  width=\\\"20\\\" height=\\\"52\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"8\\\"  width=\\\"20\\\" height=\\\"52\\\" fill=\\\"#fff\\\" stroke=\\\"#000\\\" stroke-width=\\\"1.5\\\"/>\\n  <text x=\\\"12\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#000\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#000\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"28\\\" font-size=\\\"10\\\" font-weight=\\\"900\\\" fill=\\\"#000\\\">$99</text>\\n  <rect x=\\\"12\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"50\\\" width=\\\"14\\\" height=\\\"5\\\" fill=\\\"#000\\\"/>\\n</svg>\",\n  editorial: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#faf7f2\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"2\\\" fill=\\\"#fff\\\" stroke=\\\"#d4d4aa\\\"/>\\n  <text x=\\\"12\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\"  font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Free</text>\\n  <text x=\\\"40\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\"  font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Basic</text>\\n  <text x=\\\"68\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\"  font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Standard</text>\\n  <text x=\\\"95\\\" y=\\\"22\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"5\\\"  font-style=\\\"italic\\\" fill=\\\"#57534e\\\">Premium</text>\\n  <rect x=\\\"12\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"25\\\" width=\\\"10\\\" height=\\\"0.6\\\" fill=\\\"#b45309\\\"/>\\n  <text x=\\\"12\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"38\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$99</text>\\n  <rect x=\\\"12\\\" y=\\\"55\\\" width=\\\"14\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"55\\\" width=\\\"14\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"55\\\" width=\\\"14\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"55\\\" width=\\\"12\\\" height=\\\"4.5\\\" rx=\\\"0\\\" fill=\\\"none\\\" stroke=\\\"#b45309\\\" stroke-width=\\\"0.8\\\"/>\\n</svg>\",\n  gradient: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <defs>\\n    <linearGradient id=\\\"pc-g1\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#94a3b8\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#cbd5e1\\\"/></linearGradient>\\n    <linearGradient id=\\\"pc-g2\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#7c3aed\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#db2777\\\"/></linearGradient>\\n    <linearGradient id=\\\"pc-g3\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#0891b2\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#06b6d4\\\"/></linearGradient>\\n    <linearGradient id=\\\"pc-g4\\\" x1=\\\"0\\\" y1=\\\"0\\\" x2=\\\"1\\\" y2=\\\"1\\\"><stop offset=\\\"0\\\" stop-color=\\\"#dc2626\\\"/><stop offset=\\\"1\\\" stop-color=\\\"#f97316\\\"/></linearGradient>\\n  </defs>\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f9fafb\\\"/>\\n  <rect x=\\\"8\\\"  y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g1)\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g2)\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"10\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g3)\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"52\\\" rx=\\\"6\\\" fill=\\\"url(#pc-g4)\\\"/>\\n  <text x=\\\"12\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"30\\\" font-size=\\\"8\\\" font-weight=\\\"900\\\" fill=\\\"#fff\\\">$99</text>\\n  <rect x=\\\"12\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"54\\\" width=\\\"14\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"54\\\" width=\\\"12\\\" height=\\\"4\\\" rx=\\\"2\\\" fill=\\\"#fff\\\"/>\\n</svg>\",\n  banded: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#fafafa\\\"/>\\n  <!-- one joined bar: outer radius on ends, dividers between -->\\n  <rect x=\\\"8\\\" y=\\\"10\\\" width=\\\"104\\\" height=\\\"52\\\" rx=\\\"8\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e5e7eb\\\"/>\\n  <line x1=\\\"34\\\" y1=\\\"14\\\" x2=\\\"34\\\" y2=\\\"58\\\" stroke=\\\"#e5e7eb\\\" stroke-width=\\\"0.6\\\"/>\\n  <line x1=\\\"60\\\" y1=\\\"14\\\" x2=\\\"60\\\" y2=\\\"58\\\" stroke=\\\"#e5e7eb\\\" stroke-width=\\\"0.6\\\"/>\\n  <line x1=\\\"86\\\" y1=\\\"14\\\" x2=\\\"86\\\" y2=\\\"58\\\" stroke=\\\"#e5e7eb\\\" stroke-width=\\\"0.6\\\"/>\\n  <!-- highlighted cell (Standard): tinted bg + top strip -->\\n  <rect x=\\\"34\\\" y=\\\"10\\\" width=\\\"26\\\" height=\\\"52\\\" fill=\\\"#fffdf0\\\"/>\\n  <rect x=\\\"34\\\" y=\\\"10\\\" width=\\\"26\\\" height=\\\"6\\\" fill=\\\"#e8f1ff\\\"/>\\n  <text x=\\\"38\\\" y=\\\"14.2\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"3\\\" font-style=\\\"italic\\\" fill=\\\"#1e3a8a\\\" text-decoration=\\\"underline\\\">Best value</text>\\n  <!-- prices (serif) -->\\n  <text x=\\\"14\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$19</text>\\n  <text x=\\\"66\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$49</text>\\n  <text x=\\\"92\\\" y=\\\"34\\\" font-family=\\\"Georgia,serif\\\" font-size=\\\"9\\\" font-weight=\\\"700\\\" fill=\\\"#1c1917\\\">$99</text>\\n  <!-- Mailchimp-yellow CTA pills -->\\n  <rect x=\\\"12\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n  <rect x=\\\"38\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n  <rect x=\\\"90\\\" y=\\\"50\\\" width=\\\"18\\\" height=\\\"6\\\" rx=\\\"3\\\" fill=\\\"#ffe01b\\\" stroke=\\\"#1a1a1a\\\" stroke-width=\\\"0.3\\\"/>\\n</svg>\",\n  tier: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#f5f3ff\\\"/>\\n  <!-- staircase: index 0 lowest, last highest -->\\n  <rect x=\\\"8\\\"  y=\\\"22\\\" width=\\\"24\\\" height=\\\"44\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e0e7ff\\\"/>\\n  <rect x=\\\"36\\\" y=\\\"18\\\" width=\\\"24\\\" height=\\\"48\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e0e7ff\\\"/>\\n  <rect x=\\\"64\\\" y=\\\"14\\\" width=\\\"24\\\" height=\\\"52\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#e0e7ff\\\"/>\\n  <rect x=\\\"92\\\" y=\\\"10\\\" width=\\\"20\\\" height=\\\"56\\\" rx=\\\"5\\\" fill=\\\"#ffffff\\\" stroke=\\\"#c7d2fe\\\" stroke-width=\\\"1.5\\\"/>\\n  <!-- accent chip badges -->\\n  <rect x=\\\"11\\\" y=\\\"25\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n  <rect x=\\\"39\\\" y=\\\"21\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n  <rect x=\\\"67\\\" y=\\\"17\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n  <rect x=\\\"95\\\" y=\\\"13\\\" width=\\\"6\\\" height=\\\"6\\\" rx=\\\"2\\\" fill=\\\"#4f46e530\\\"/>\\n  <!-- prices -->\\n  <text x=\\\"12\\\" y=\\\"46\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$0</text>\\n  <text x=\\\"40\\\" y=\\\"42\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$19</text>\\n  <text x=\\\"68\\\" y=\\\"38\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$49</text>\\n  <text x=\\\"95\\\" y=\\\"34\\\" font-size=\\\"7\\\" font-weight=\\\"800\\\" fill=\\\"#1e1b4b\\\">$99</text>\\n  <!-- indigo CTA -->\\n  <rect x=\\\"12\\\" y=\\\"56\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n  <rect x=\\\"40\\\" y=\\\"56\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n  <rect x=\\\"68\\\" y=\\\"56\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n  <rect x=\\\"94\\\" y=\\\"56\\\" width=\\\"14\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#4f46e5\\\"/>\\n</svg>\",\n  neo: \"\\n<svg viewBox=\\\"0 0 120 72\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n  <defs>\\n    <filter id=\\\"pc-neo-soft\\\" x=\\\"-10%\\\" y=\\\"-10%\\\" width=\\\"120%\\\" height=\\\"120%\\\">\\n      <feGaussianBlur stdDeviation=\\\"1.2\\\"/>\\n    </filter>\\n  </defs>\\n  <rect width=\\\"120\\\" height=\\\"72\\\" fill=\\\"#e9edf3\\\"/>\\n  <!-- soft-shadowed cards \\u2014 approximate neumorphism with layered rects -->\\n  <g>\\n    <rect x=\\\"10\\\"  y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n    <rect x=\\\"10\\\"  y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n    <rect x=\\\"10\\\"  y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n  </g>\\n  <g>\\n    <rect x=\\\"38\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n    <rect x=\\\"38\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n    <rect x=\\\"38\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n  </g>\\n  <g>\\n    <rect x=\\\"66\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n    <rect x=\\\"66\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n    <rect x=\\\"66\\\" y=\\\"12\\\" width=\\\"22\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n  </g>\\n  <g>\\n    <rect x=\\\"94\\\" y=\\\"12\\\" width=\\\"18\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#c7cdd6\\\" opacity=\\\"0.55\\\" transform=\\\"translate(2 2)\\\"/>\\n    <rect x=\\\"94\\\" y=\\\"12\\\" width=\\\"18\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#ffffff\\\" opacity=\\\"0.9\\\" transform=\\\"translate(-2 -2)\\\"/>\\n    <rect x=\\\"94\\\" y=\\\"12\\\" width=\\\"18\\\" height=\\\"48\\\" rx=\\\"6\\\" fill=\\\"#e9edf3\\\"/>\\n  </g>\\n  <!-- prices -->\\n  <text x=\\\"13\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$0</text>\\n  <text x=\\\"41\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$19</text>\\n  <text x=\\\"69\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$49</text>\\n  <text x=\\\"96\\\" y=\\\"32\\\" font-size=\\\"6\\\" font-weight=\\\"800\\\" fill=\\\"#1e293b\\\">$99</text>\\n  <!-- periwinkle buttons with soft look -->\\n  <rect x=\\\"13\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n  <rect x=\\\"41\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n  <rect x=\\\"69\\\" y=\\\"50\\\" width=\\\"16\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n  <rect x=\\\"96\\\" y=\\\"50\\\" width=\\\"12\\\" height=\\\"5\\\" rx=\\\"2.5\\\" fill=\\\"#eef1f6\\\" stroke=\\\"#d6dbe4\\\"/>\\n</svg>\"\n};\nPricingCardsElement.VALID_STYLES = VALID_STYLES;\nPricingCardsElement.DEFAULT_STYLE = DEFAULT_STYLE;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PricingCardsElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PricingCardsElement.js?");

/***/ }),

/***/ "./src/includes/PricingCardsWidget.js":
/*!********************************************!*\
  !*** ./src/includes/PricingCardsWidget.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./PricingCardsElement.js */ \"./src/includes/PricingCardsElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * PricingCardsWidget — the widget-box entry that drops a fully populated\n * PricingCardsElement onto the canvas.\n *\n * Seeds 4 realistic plan cards (Free / Basic / Standard / Premium) using\n * native elements (Heading, PElement for price / period / features,\n * ButtonElement CTA). The Standard card is highlighted with a \"Most Popular\"\n * badge + yellow accent to mirror the dominant pattern on every pricing page\n * (Mailchimp, Stripe, Vercel…). User can change style from `highlighted`\n * default to any of the other 9 presets via the StyleControl.\n *\n * Replaces retired PricingTableWidget.\n */\nvar PricingCardsWidget = /*#__PURE__*/function (_BaseWidget) {\n  function PricingCardsWidget() {\n    var _this;\n    _classCallCheck(this, PricingCardsWidget);\n    _this = _callSuper(this, PricingCardsWidget);\n    var el = new _PricingCardsElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('PricingCards');\n    el.style = 'highlighted';\n    el.cell_gap = 20;\n    el.append(el.newCell({\n      planName: 'Free',\n      planDesc: 'Forever free, no credit card needed.',\n      planPrice: '$0',\n      planPeriod: 'per month',\n      features: ['Up to 500 subscribers', '1 campaign per month', 'Basic templates', 'Community support'],\n      ctaText: 'Start free',\n      ctaUrl: '#free'\n    }));\n    el.append(el.newCell({\n      planName: 'Basic',\n      planDesc: 'For solo creators just starting.',\n      planPrice: '$19',\n      planPeriod: 'per month',\n      features: ['Up to 5,000 subscribers', '10 campaigns per month', 'A/B testing', 'Audience segments', 'Email support'],\n      ctaText: 'Choose Basic',\n      ctaUrl: '#basic'\n    }));\n    var standard = el.newCell({\n      planName: 'Standard',\n      planDesc: 'Most teams pick this one.',\n      planPrice: '$49',\n      planPeriod: 'per month',\n      features: ['Up to 50,000 subscribers', 'Unlimited campaigns', 'Automations & journeys', 'Advanced analytics', 'Priority support'],\n      ctaText: 'Choose Standard',\n      ctaUrl: '#standard'\n    });\n    standard.highlighted = true;\n    standard.badge = 'Most Popular';\n    standard.icon = 'workspace_premium';\n    standard.accent_color = '#ffcc2a';\n    el.append(standard);\n    var premium = el.newCell({\n      planName: 'Premium',\n      planDesc: 'For growing companies & agencies.',\n      planPrice: '$99',\n      planPeriod: 'per month',\n      features: ['Unlimited subscribers', 'Unlimited campaigns', 'Multi-user roles & SSO', 'Dedicated IP & SLA', '24/7 phone support'],\n      ctaText: 'Contact sales',\n      ctaUrl: '#sales'\n    });\n    premium.icon = 'diamond';\n    el.append(premium);\n    _this.block.appendElements([el]);\n    return _this;\n  }\n  _inherits(PricingCardsWidget, _BaseWidget);\n  return _createClass(PricingCardsWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.pricing_cards');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'view_column';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PricingCardsWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/PricingCardsWidget.js?");

/***/ }),

/***/ "./src/includes/RSSControl.js":
/*!************************************!*\
  !*** ./src/includes/RSSControl.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * RSSControl — combined RSS feed editor: URL + fetch, style select,\n * 6 toggle switches, 2 numeric steppers (max items, content length).\n *\n * Consumer: RSSElement (one panel section handles the whole element).\n *\n * 2026-04-18 Phase 2.29 rewrite — replaced the Bootstrap surface\n * (`.form-control form-control-sm` ×3, `.form-select form-select-sm`,\n * `.btn btn-outline-secondary`, `.input-group`, `.builder-checkbox-modern`,\n * `.toggle-label`, `.badge bg-success`, `.py-2 px-3`, `.d-flex`, plus a\n * pile of inline hex colours / pixel widths) with `.bjs-text-input`,\n * `.bjs-btn--primary`, `.bjs-select`, `.bjs-number-input`, `.bjs-toggle`,\n * and `.bjs-info-banner--{success,error,info}` inside new\n * `.bjs-rss-control` / `.bjs-rss-section` scoped classes.\n *\n * Logic upgrades:\n *   - Status area uses `.bjs-info-banner` with `textContent` (no HTML injection\n *     from rssHandler error payloads).\n *   - Number steppers (limit + content_length) are editable — user can type,\n *     blur-clamps to [min,max], arrow keys +/- step.\n *   - Fetch button disables itself during in-flight request; auto-re-enables\n *     in `finally()`.\n *   - `textContent` used everywhere for user/server-supplied strings.\n */\nvar RSSControl = /*#__PURE__*/function () {\n  function RSSControl(label, values, callback) {\n    _classCallCheck(this, RSSControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.callback = callback;\n    this.url = values.url || '';\n    this.limit = values.limit || 5;\n    this.style = values.style || 'classic';\n    this.show_title = values.show_title !== undefined ? values.show_title : true;\n    this.show_desc = values.show_desc !== undefined ? values.show_desc : true;\n    this.show_date = values.show_date !== undefined ? values.show_date : true;\n    this.show_image = values.show_image !== undefined ? values.show_image : true;\n    this.show_link = values.show_link !== undefined ? values.show_link : false;\n    this.show_author = values.show_author !== undefined ? values.show_author : false;\n    this.content_length = values.content_length !== undefined ? values.content_length : 150;\n    this.fetchCount = values.fetchCount;\n    this._fetching = false;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-rss-control');\n    this.render();\n  }\n  return _createClass(RSSControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var toggles = [{\n        key: 'show_title',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_title')\n      }, {\n        key: 'show_desc',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_desc')\n      }, {\n        key: 'show_date',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_date')\n      }, {\n        key: 'show_image',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_image')\n      }, {\n        key: 'show_link',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_link')\n      }, {\n        key: 'show_author',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.show_author')\n      }];\n      var togglesHtml = toggles.map(function (t) {\n        var tid = \"\".concat(_this.id, \"_\").concat(t.key);\n        return \"\\n                <div class=\\\"bjs-rss-row\\\">\\n                    <label class=\\\"bjs-rss-row-label\\\" for=\\\"\".concat(tid, \"\\\">\").concat(_this._escape(t.label), \"</label>\\n                    <label class=\\\"bjs-toggle\\\">\\n                        <input type=\\\"checkbox\\\" id=\\\"\").concat(tid, \"\\\" class=\\\"bjs-toggle-input\\\"\\n                               data-toggle-key=\\\"\").concat(t.key, \"\\\" \").concat(_this[t.key] ? 'checked' : '', \">\\n                        <span class=\\\"bjs-toggle-track\\\"></span>\\n                        <span class=\\\"bjs-toggle-thumb\\\"></span>\\n                    </label>\\n                </div>\\n            \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <section class=\\\"bjs-rss-section\\\">\\n                <div class=\\\"bjs-rss-section-title\\\">\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.rss_feed')), \"</div>\\n\\n                <div class=\\\"bjs-rss-url-row\\\">\\n                    <input type=\\\"text\\\" class=\\\"bjs-text-input\\\" data-control=\\\"url\\\"\\n                           value=\\\"\").concat(this._escape(this.url), \"\\\"\\n                           placeholder=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.enter_url')), \"\\\"\\n                           aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.enter_url')), \"\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-btn bjs-btn--primary\\\" data-control=\\\"fetch\\\">\\n                        <span>\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch')), \"</span>\\n                    </button>\\n                </div>\\n\\n                <div class=\\\"bjs-rss-status\\\" data-control=\\\"status\\\"></div>\\n\\n                <div class=\\\"bjs-rss-row\\\">\\n                    <label class=\\\"bjs-rss-row-label\\\" for=\\\"\").concat(this.id, \"_style\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.style')), \"</label>\\n                    <select id=\\\"\").concat(this.id, \"_style\\\" class=\\\"bjs-select\\\" data-control=\\\"style\\\">\\n                        <option value=\\\"modern\\\" \").concat(this.style === 'modern' ? 'selected' : '', \">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.style_modern')), \"</option>\\n                        <option value=\\\"classic\\\" \").concat(this.style === 'classic' ? 'selected' : '', \">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.style_classic')), \"</option>\\n                    </select>\\n                </div>\\n            </section>\\n\\n            <section class=\\\"bjs-rss-section\\\">\\n                <div class=\\\"bjs-rss-section-title\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.rss_display')), \"</div>\\n\\n                <div class=\\\"bjs-rss-toggles\\\">\\n                    \").concat(togglesHtml, \"\\n                </div>\\n\\n                <div class=\\\"bjs-rss-row\\\">\\n                    <label class=\\\"bjs-rss-row-label\\\" for=\\\"\").concat(this.id, \"_limit\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.max_items')), \"</label>\\n                    <div class=\\\"bjs-number-input\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"limit-dec\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.decrease', 'Decrease')), \"\\\">&minus;</button>\\n                        <input id=\\\"\").concat(this.id, \"_limit\\\" type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n                               data-control=\\\"limit\\\" value=\\\"\").concat(this.limit, \"\\\" min=\\\"1\\\" max=\\\"50\\\" step=\\\"1\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"limit-inc\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.increase', 'Increase')), \"\\\">+</button>\\n                    </div>\\n                </div>\\n\\n                <div class=\\\"bjs-rss-row\\\">\\n                    <label class=\\\"bjs-rss-row-label\\\" for=\\\"\").concat(this.id, \"_cl\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.content_length')), \"</label>\\n                    <div class=\\\"bjs-number-input\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"cl-dec\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.decrease', 'Decrease')), \"\\\">&minus;</button>\\n                        <input id=\\\"\").concat(this.id, \"_cl\\\" type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n                               data-control=\\\"content_length\\\" value=\\\"\").concat(this.content_length, \"\\\" min=\\\"0\\\" max=\\\"1000\\\" step=\\\"10\\\">\\n                        <button type=\\\"button\\\" class=\\\"bjs-number-step\\\" data-control=\\\"cl-inc\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.increase', 'Increase')), \"\\\">+</button>\\n                    </div>\\n                </div>\\n            </section>\\n        \");\n      this._bindEvents();\n      this._renderInitialStatus();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      this._fetchBtn().addEventListener('click', function () {\n        return _this2._handleFetch();\n      });\n      this._urlInput().addEventListener('keydown', function (e) {\n        if (e.key === 'Enter') {\n          e.preventDefault();\n          _this2._handleFetch();\n        }\n      });\n      this.domNode.querySelector('[data-control=\"style\"]').addEventListener('change', function (e) {\n        _this2.style = e.target.value;\n        _this2._autoApply();\n      });\n      this.domNode.querySelectorAll('[data-toggle-key]').forEach(function (el) {\n        el.addEventListener('change', function (e) {\n          _this2[e.target.dataset.toggleKey] = e.target.checked;\n          _this2._autoApply();\n        });\n      });\n      this._bindStepper('limit', {\n        min: 1,\n        max: 50,\n        step: 1\n      });\n      this._bindStepper('content_length', {\n        min: 0,\n        max: 1000,\n        step: 10\n      });\n    }\n  }, {\n    key: \"_bindStepper\",\n    value: function _bindStepper(key, _ref) {\n      var _this3 = this;\n      var min = _ref.min,\n        max = _ref.max,\n        step = _ref.step;\n      var decSel = key === 'limit' ? '[data-control=\"limit-dec\"]' : '[data-control=\"cl-dec\"]';\n      var incSel = key === 'limit' ? '[data-control=\"limit-inc\"]' : '[data-control=\"cl-inc\"]';\n      var input = this.domNode.querySelector(\"[data-control=\\\"\".concat(key, \"\\\"]\"));\n      var dec = this.domNode.querySelector(decSel);\n      var inc = this.domNode.querySelector(incSel);\n      var clamp = function clamp(n) {\n        return Math.max(min, Math.min(max, n));\n      };\n      var write = function write(n) {\n        _this3[key] = clamp(n);\n        input.value = _this3[key];\n        _this3._autoApply();\n      };\n      dec.addEventListener('click', function () {\n        return write(_this3[key] - step);\n      });\n      inc.addEventListener('click', function () {\n        return write(_this3[key] + step);\n      });\n      input.addEventListener('input', function (e) {\n        var raw = e.target.value;\n        if (raw === '') return; /* allow partial typing */\n        var n = parseFloat(raw);\n        if (!isNaN(n)) {\n          _this3[key] = clamp(n);\n          _this3._autoApply();\n        }\n      });\n      input.addEventListener('blur', function (e) {\n        var n = parseFloat(e.target.value);\n        if (isNaN(n)) {\n          _this3[key] = min;\n        } else {\n          _this3[key] = clamp(n);\n        }\n        e.target.value = _this3[key];\n        _this3._autoApply();\n      });\n      input.addEventListener('keydown', function (e) {\n        if (e.key === 'ArrowUp') {\n          e.preventDefault();\n          write(_this3[key] + step);\n        } else if (e.key === 'ArrowDown') {\n          e.preventDefault();\n          write(_this3[key] - step);\n        }\n      });\n    }\n  }, {\n    key: \"_renderInitialStatus\",\n    value: function _renderInitialStatus() {\n      if (this.fetchCount !== null && this.fetchCount !== undefined) {\n        this._showSuccess(this.fetchCount);\n      } else {\n        this._statusArea().innerHTML = '';\n      }\n    }\n  }, {\n    key: \"_urlInput\",\n    value: function _urlInput() {\n      return this.domNode.querySelector('[data-control=\"url\"]');\n    }\n  }, {\n    key: \"_fetchBtn\",\n    value: function _fetchBtn() {\n      return this.domNode.querySelector('[data-control=\"fetch\"]');\n    }\n  }, {\n    key: \"_statusArea\",\n    value: function _statusArea() {\n      return this.domNode.querySelector('[data-control=\"status\"]');\n    }\n  }, {\n    key: \"_showBanner\",\n    value: function _showBanner(variant, iconName, text) {\n      var variantClass = variant ? \" bjs-info-banner--\".concat(variant) : '';\n      var area = this._statusArea();\n      area.innerHTML = \"\\n            <div class=\\\"bjs-info-banner\".concat(variantClass, \"\\\" role=\\\"status\\\">\\n                <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\").concat(iconName, \"</span>\\n                <span class=\\\"bjs-info-banner-text\\\" data-control=\\\"status-text\\\"></span>\\n            </div>\\n        \");\n      area.querySelector('[data-control=\"status-text\"]').textContent = text;\n    }\n  }, {\n    key: \"_showError\",\n    value: function _showError(msg) {\n      this._showBanner('error', 'error', msg);\n    }\n  }, {\n    key: \"_showInfo\",\n    value: function _showInfo(msg) {\n      this._showBanner('', 'sync', msg);\n    }\n  }, {\n    key: \"_showSuccess\",\n    value: function _showSuccess(count) {\n      this.fetchCount = count;\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.items_found', 'items found');\n      this._showBanner('success', 'check_circle', \"\".concat(count, \" \").concat(label));\n    }\n  }, {\n    key: \"_autoApply\",\n    value: function _autoApply() {\n      this.callback.applySettings({\n        url: this.url || null,\n        limit: this.limit,\n        style: this.style,\n        show_title: this.show_title,\n        show_desc: this.show_desc,\n        show_date: this.show_date,\n        show_image: this.show_image,\n        show_link: this.show_link,\n        show_author: this.show_author,\n        content_length: this.content_length\n      });\n    }\n  }, {\n    key: \"_handleFetch\",\n    value: function _handleFetch() {\n      var _this$host$rssHandler,\n        _this$host,\n        _this4 = this;\n      var url = this._urlInput().value.trim();\n      if (!url) {\n        this._showError(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.url_required'));\n        return;\n      }\n      var rssRegex = /^(http|https):\\/\\/[^\\s$.?#].[^\\s]*$/;\n      if (!rssRegex.test(url)) {\n        this._showError(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.invalid_url'));\n        return;\n      }\n      this.url = url;\n      this._fetching = true;\n      var fetchBtn = this._fetchBtn();\n      var labelSpan = fetchBtn.querySelector('span');\n      var originalText = labelSpan ? labelSpan.textContent : fetchBtn.textContent;\n      if (labelSpan) labelSpan.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetching');else fetchBtn.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetching');\n      fetchBtn.disabled = true;\n      this._showInfo(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetching'));\n      var rssHandler = (_this$host$rssHandler = (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.rssHandler) !== null && _this$host$rssHandler !== void 0 ? _this$host$rssHandler : null;\n      if (!rssHandler) {\n        this._showError(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.handler_missing', 'RSS handler not configured.'));\n        if (labelSpan) labelSpan.textContent = originalText;else fetchBtn.textContent = originalText;\n        fetchBtn.disabled = false;\n        this._fetching = false;\n        return;\n      }\n      fetch(\"\".concat(rssHandler, \"?url=\").concat(encodeURIComponent(url))).then(function (response) {\n        if (!response.ok) {\n          return response.json().then(function (data) {\n            throw new Error(data.error || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed'));\n          });\n        }\n        return response.json();\n      }).then(function (data) {\n        if (data.error) throw new Error(data.error);\n        if (!data.items || !Array.isArray(data.items)) {\n          throw new Error(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.invalid_format'));\n        }\n        _this4._showSuccess(data.count || data.items.length);\n        _this4._autoApply();\n      })[\"catch\"](function (error) {\n        _this4._showError(error.message || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed'));\n      })[\"finally\"](function () {\n        _this4._fetching = false;\n        if (labelSpan) labelSpan.textContent = originalText;else fetchBtn.textContent = originalText;\n        fetchBtn.disabled = false;\n      });\n    }\n  }, {\n    key: \"_escape\",\n    value: function _escape(s) {\n      return String(s !== null && s !== void 0 ? s : '').replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RSSControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RSSControl.js?");

/***/ }),

/***/ "./src/includes/RSSElement.js":
/*!************************************!*\
  !*** ./src/includes/RSSElement.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _RSSControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./RSSControl.js */ \"./src/includes/RSSControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\nvar RSSElement = /*#__PURE__*/function (_BaseElement) {\n  function RSSElement(template, url, limit) {\n    var _this;\n    _classCallCheck(this, RSSElement);\n    _this = _callSuper(this, RSSElement);\n    _this.template = template;\n    _this.url = url;\n    _this.limit = limit || 5;\n    _this.domNode = null;\n\n    // Display options\n    _this.style = 'classic'; // 'classic' | 'modern'\n    _this.show_title = true;\n    _this.show_desc = true;\n    _this.show_date = true;\n    _this.show_image = true;\n    _this.show_link = false;\n    _this.show_author = false;\n    _this.content_length = 150; // 0 = no truncation\n\n    // Transient state (not serialized)\n    _this._items = null;\n    _this._error = null;\n    _this._loading = false;\n    _this._fetchingUrl = null;\n    _this._lastFetchedUrl = null;\n    _this._lastFetchedLimit = null;\n\n    // Formatter\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      background_color: null,\n      background_image: null,\n      background_position: null,\n      background_size: null,\n      background_repeat: null,\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      border_radius: null\n    });\n    return _this;\n  }\n  _inherits(RSSElement, _BaseElement);\n  return _createClass(RSSElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.rss');\n    }\n\n    // Helper for description truncation — passed to template\n  }, {\n    key: \"_truncate\",\n    value: function _truncate(text, maxLen) {\n      if (!text) return '';\n      if (!maxLen || maxLen <= 0) return text;\n      return text.length > maxLen ? text.substring(0, maxLen) + '...' : text;\n    }\n  }, {\n    key: \"_renderTemplate\",\n    value: function _renderTemplate() {\n      var _this$url;\n      this.domNode.innerHTML = this.renderTemplate({\n        url: (_this$url = this.url) !== null && _this$url !== void 0 ? _this$url : false,\n        items: this._items,\n        loading: this._loading,\n        error: this._error,\n        style: this.style,\n        show_title: this.show_title,\n        show_desc: this.show_desc,\n        show_date: this.show_date,\n        show_image: this.show_image,\n        show_link: this.show_link,\n        show_author: this.show_author,\n        content_length: this.content_length,\n        truncate: this._truncate.bind(this),\n        I18n: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n        // formatter auto-merged by BaseElement.renderTemplate (W0.2c)\n      });\n    }\n  }, {\n    key: \"_getRssHandler\",\n    value: function _getRssHandler() {\n      var _this$host$rssHandler, _this$host;\n      // Read from injected host (per-instance — multi-instance safe).\n      return (_this$host$rssHandler = (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.rssHandler) !== null && _this$host$rssHandler !== void 0 ? _this$host$rssHandler : null;\n    }\n  }, {\n    key: \"_fetchFeed\",\n    value: function _fetchFeed() {\n      var _this2 = this;\n      var rssHandler = this._getRssHandler();\n      if (!this.url || !rssHandler) return;\n      var fetchUrl = this.url;\n      this._fetchingUrl = fetchUrl;\n      this._loading = true;\n      this._error = null;\n      this._renderTemplate();\n      fetch(\"\".concat(rssHandler, \"?url=\").concat(encodeURIComponent(this.url))).then(function (response) {\n        if (!response.ok) {\n          return response.json().then(function (data) {\n            throw new Error(data.error || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed'));\n          });\n        }\n        return response.json();\n      }).then(function (data) {\n        // Stale response guard\n        if (_this2._fetchingUrl !== fetchUrl) return;\n        if (data.error) {\n          throw new Error(data.error);\n        }\n        if (!data.items || !Array.isArray(data.items)) {\n          throw new Error(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.invalid_format'));\n        }\n        _this2._items = data.items.slice(0, _this2.limit);\n        _this2._error = null;\n        _this2._loading = false;\n        _this2._lastFetchedUrl = fetchUrl;\n        _this2._lastFetchedLimit = _this2.limit;\n        _this2._fetchingUrl = null;\n        _this2._renderTemplate();\n      })[\"catch\"](function (error) {\n        // Stale response guard\n        if (_this2._fetchingUrl !== fetchUrl) return;\n        _this2._items = null;\n        _this2._error = error.message || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rss.fetch_failed');\n        _this2._loading = false;\n        _this2._fetchingUrl = null;\n        _this2._renderTemplate();\n      });\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      if (!this.url) {\n        // No URL — show placeholder\n        this._items = null;\n        this._error = null;\n        this._loading = false;\n        this._renderTemplate();\n      } else if (this._lastFetchedUrl === this.url && this._lastFetchedLimit >= this.limit && this._items) {\n        // Cached items still valid — re-render with possibly updated display options\n        // Trim items if limit decreased\n        var displayItems = this._items.slice(0, this.limit);\n        this._items = displayItems;\n        this._renderTemplate();\n      } else {\n        // Need to fetch (new URL or limit increased)\n        this._fetchFeed();\n      }\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(RSSElement, \"getData\", this, 3)([])), {}, {\n        url: this.url,\n        limit: this.limit,\n        style: this.style,\n        show_title: this.show_title,\n        show_desc: this.show_desc,\n        show_date: this.show_date,\n        show_image: this.show_image,\n        show_link: this.show_link,\n        show_author: this.show_author,\n        content_length: this.content_length\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this3 = this;\n      return [\n      // RSS Feed Control (URL, style, toggles, limit, content_length)\n      new _RSSControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('section.rss_feed'), {\n        url: this.url,\n        limit: this.limit,\n        style: this.style,\n        show_title: this.show_title,\n        show_desc: this.show_desc,\n        show_date: this.show_date,\n        show_image: this.show_image,\n        show_link: this.show_link,\n        show_author: this.show_author,\n        content_length: this.content_length,\n        fetchCount: this._items ? this._items.length : null\n      }, {\n        applySettings: function applySettings(settings) {\n          var urlChanged = settings.url !== _this3.url;\n          var limitIncreased = settings.limit > _this3.limit;\n          _this3.url = settings.url;\n          _this3.limit = settings.limit;\n          _this3.style = settings.style;\n          _this3.show_title = settings.show_title;\n          _this3.show_desc = settings.show_desc;\n          _this3.show_date = settings.show_date;\n          _this3.show_image = settings.show_image;\n          _this3.show_link = settings.show_link;\n          _this3.show_author = settings.show_author;\n          _this3.content_length = settings.content_length;\n          if (urlChanged || limitIncreased) {\n            // Clear cache to force re-fetch\n            _this3._items = null;\n            _this3._lastFetchedUrl = null;\n            _this3._lastFetchedLimit = null;\n          }\n          _this3.render();\n        }\n      }),\n      // W3.8b — PaddingMarginControl removed. RSS items are content\n      // inside a Block; parent Block.padding handles layout spacing.\n\n      // Background\n      new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this3.formatter.setFormat('background_color', values.color);\n          _this3.formatter.setFormat('background_image', values.image);\n          _this3.formatter.setFormat('background_position', values.position);\n          _this3.formatter.setFormat('background_size', values.size);\n          _this3.formatter.setFormat('background_repeat', values.repeat);\n          _this3.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }),\n      // Border\n      new _BorderControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this3.formatter.setFormat('border_top_style', border_top_style);\n          _this3.formatter.setFormat('border_top_width', border_top_width);\n          _this3.formatter.setFormat('border_top_color', border_top_color);\n          _this3.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this3.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this3.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this3.formatter.setFormat('border_left_style', border_left_style);\n          _this3.formatter.setFormat('border_left_width', border_left_width);\n          _this3.formatter.setFormat('border_left_color', border_left_color);\n          _this3.formatter.setFormat('border_right_style', border_right_style);\n          _this3.formatter.setFormat('border_right_width', border_right_width);\n          _this3.formatter.setFormat('border_right_color', border_right_color);\n          _this3.render();\n        }\n      }),\n      // Border Radius\n      new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this3.formatter.setFormat('border_radius', v);\n          _this3.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new RSSElement(data.template, data.url, data.limit);\n\n      // Display options (backward-compatible defaults)\n      e.style = data.style || 'classic';\n      e.show_title = data.show_title !== undefined ? data.show_title : true;\n      e.show_desc = data.show_desc !== undefined ? data.show_desc : true;\n      e.show_date = data.show_date !== undefined ? data.show_date : true;\n      e.show_image = data.show_image !== undefined ? data.show_image : true;\n      e.show_link = data.show_link !== undefined ? data.show_link : false;\n      e.show_author = data.show_author !== undefined ? data.show_author : false;\n      e.content_length = data.content_length !== undefined ? data.content_length : 150;\n\n      // Formatter\n      if (data.formats) {\n        e.formatter.formats = data.formats;\n      }\n      return e;\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RSSElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RSSElement.js?");

/***/ }),

/***/ "./src/includes/RSSWidget.js":
/*!***********************************!*\
  !*** ./src/includes/RSSWidget.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar RSSWidget = /*#__PURE__*/function (_BaseWidget) {\n  function RSSWidget() {\n    var _this;\n    _classCallCheck(this, RSSWidget);\n    _this = _callSuper(this, RSSWidget); // Call the parent class constructor\n\n    // Add a RSSElement to the widget\n    var rssElement = new RSSElement('RSS', null, 5);\n\n    // Append the new element to the block\n    _this.block.appendElements([rssElement]);\n    return _this;\n  }\n  _inherits(RSSWidget, _BaseWidget);\n  return _createClass(RSSWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.rss');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'rss_feed';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RSSWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RSSWidget.js?");

/***/ }),

/***/ "./src/includes/RadioElement.js":
/*!**************************************!*\
  !*** ./src/includes/RadioElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectControl.js */ \"./src/includes/SelectControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar RadioElement = /*#__PURE__*/function (_BaseElement) {\n  function RadioElement(template) {\n    var _this;\n    var inputName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n    var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];\n    _classCallCheck(this, RadioElement);\n    _this = _callSuper(this, RadioElement);\n    _this.template = template;\n    _this.inputName = inputName;\n    _this.items = _this.normalizeItems(items);\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['items'];\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({});\n    return _this;\n  }\n  _inherits(RadioElement, _BaseElement);\n  return _createClass(RadioElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.radio');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        items: this.items,\n        inputName: this.inputName\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(RadioElement, \"getData\", this, 3)([])), {}, {\n        inputName: this.inputName,\n        items: this.items\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [new _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radio_options'), this.items.map(function (item) {\n        return {\n          label: item.label,\n          value: item.value\n        };\n      }), {\n        setItems: function setItems(items) {\n          _this2.items = _this2.normalizeItems(items);\n          _this2.render();\n        },\n        setName: function setName(name) {\n          _this2.inputName = name;\n          _this2.render();\n        }\n      }, this.inputName)];\n    }\n  }, {\n    key: \"normalizeItems\",\n    value: function normalizeItems(items) {\n      return (Array.isArray(items) ? items : []).map(function (item, index) {\n        var _item$label, _item$value;\n        return {\n          label: (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : \"Option \".concat(index + 1),\n          value: (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : \"option_\".concat(index + 1)\n        };\n      });\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.inputName || \"\", data.items || []), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RadioElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RadioElement.js?");

/***/ }),

/***/ "./src/includes/RadioWidget.js":
/*!*************************************!*\
  !*** ./src/includes/RadioWidget.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _RadioElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./RadioElement.js */ \"./src/includes/RadioElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar RadioWidget = /*#__PURE__*/function (_BaseWidget) {\n  function RadioWidget() {\n    var _this;\n    _classCallCheck(this, RadioWidget);\n    _this = _callSuper(this, RadioWidget);\n    _this.block.appendElements([new _RadioElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Radio', 'contact_method', [{\n      label: 'Email',\n      value: 'email'\n    }, {\n      label: 'Phone',\n      value: 'phone'\n    }, {\n      label: 'SMS',\n      value: 'sms'\n    }])]);\n    return _this;\n  }\n  _inherits(RadioWidget, _BaseWidget);\n  return _createClass(RadioWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.radio');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'radio_button_checked';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RadioWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RadioWidget.js?");

/***/ }),

/***/ "./src/includes/RadiosControl.js":
/*!***************************************!*\
  !*** ./src/includes/RadiosControl.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar RadiosControl = /*#__PURE__*/function () {\n  function RadiosControl(label, value, options, callback) {\n    _classCallCheck(this, RadiosControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.value = value; // Initial value of the text input\n    this.options = options; // Options for the radio buttons\n    this.callback = callback; // Callback function to handle input changes\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n  }\n  return _createClass(RadiosControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var radioButtons = '';\n\n      // Create the radio buttons\n      this.options.forEach(function (option, index) {\n        var optionId = \"radio_\".concat(_this.id, \"_\").concat(index);\n        radioButtons += \"\\n        <input type=\\\"radio\\\" class=\\\"btn-check\\\" name=\\\"radioButton_\".concat(_this.id, \"\\\" \\n               id=\\\"\").concat(optionId, \"\\\" value=\\\"\").concat(option.value, \"\\\" \\n               \").concat(_this.value === option.value ? 'checked' : '', \">\\n        <label class=\\\"btn btn-outline-primary py-2 builder-radio-btn builder-radio-option fw-bold\\\" for=\\\"\").concat(optionId, \"\\\">\").concat(option.label, \"</label>\\n      \");\n      });\n      this.domNode.innerHTML = \"\\n      <div class=\\\"py-2 px-3 builder-radio-container\\\">\\n        <label class=\\\"form-label fw-semibold d-block mb-2 builder-radio-label\\\">\".concat(this.label, \"</label>\\n        <div class=\\\"btn-group builder-radio-group\\\" role=\\\"group\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n          \").concat(radioButtons, \"\\n        </div>\\n      </div>\\n    \");\n\n      // Add event listeners to all radio buttons\n      var radioInputs = this.domNode.querySelectorAll(\"input[name=\\\"radioButton_\".concat(this.id, \"\\\"]\"));\n      radioInputs.forEach(function (radio) {\n        radio.addEventListener('change', function (e) {\n          _this.value = e.target.value;\n\n          // Call the callback with the new value if a callback was provided\n          if (typeof _this.callback === 'function') {\n            _this.callback(_this.value);\n          }\n        });\n      });\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      var radio = this.domNode.querySelector(\"input[value=\\\"\".concat(newValue, \"\\\"]\"));\n      if (radio) {\n        radio.checked = true;\n\n        // Trigger the callback\n        if (typeof this.callback === 'function') {\n          this.callback(this.value);\n        }\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RadiosControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RadiosControl.js?");

/***/ }),

/***/ "./src/includes/RangeControl.js":
/*!**************************************!*\
  !*** ./src/includes/RangeControl.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * RangeControl — slider + editable numeric value, with optional quick-preset\n * chips below. Emits `.bjs-slider` (see builder.css §8 + ui-showcase #8).\n *\n * 2026-04-18 audit (§2.12): migrated from Bootstrap `.form-range` + bare\n * value label to `.bjs-slider` primitive (range track with `--pct` progress\n * fill + editable number input + unit span). Adds optional preset chips —\n * GridElement uses [0, 8, 16, 24] for the cell-gap common-case, PageElement\n * keeps its existing flow (no presets) and just benefits from the new look.\n *\n * Failure-state audit: number input is clamped to [min, max] on blur; typed\n * values outside the range flash `.bjs-text-input.is-error` briefly (300ms)\n * via the `is-error` class then auto-correct. Invalid input (non-numeric)\n * resets to last-valid value.\n */\nvar RangeControl = /*#__PURE__*/function () {\n  /**\n   * @param {string}   label\n   * @param {number}   currentValue\n   * @param {number}   min\n   * @param {number}   max\n   * @param {string}   unit\n   * @param {number}   step\n   * @param {function} callback          Receives the numeric value on change (debounced 100ms on slider, immediate on preset/number blur).\n   * @param {object}   [options]\n   * @param {number[]} [options.presets] Quick-apply values shown as chips below the slider.\n   * @param {string}   [options.description] Sub-label text (muted, below title).\n   */\n  function RangeControl(label, currentValue, min, max, unit, step, callback) {\n    var options = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : {};\n    _classCallCheck(this, RangeControl);\n    this.id = '_rng_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.min = min;\n    this.max = max;\n    this.unit = unit || '';\n    this.step = step || 1;\n    this.callback = callback || function () {};\n    this.presets = Array.isArray(options.presets) ? options.presets.slice() : [];\n    this.description = options.description || '';\n    this.value = this._clamp(parseFloat(currentValue));\n    if (isNaN(this.value)) this.value = this.min;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('range-control');\n    this.render();\n    this._bindEvents();\n  }\n  return _createClass(RangeControl, [{\n    key: \"_clamp\",\n    value: function _clamp(v) {\n      if (isNaN(v)) return NaN;\n      if (v < this.min) return this.min;\n      if (v > this.max) return this.max;\n      return v;\n    }\n  }, {\n    key: \"_pct\",\n    value: function _pct() {\n      if (this.max === this.min) return 0;\n      return (this.value - this.min) / (this.max - this.min) * 100;\n    }\n  }, {\n    key: \"_t\",\n    value: function _t(key, fallback) {\n      try {\n        var v = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n        return v && v !== key ? v : fallback;\n      } catch (_e) {\n        return fallback;\n      }\n    }\n\n    /** Programmatic setter — used by sibling controls (e.g. preset chip) to\n     *  force a value without emitting the callback twice. */\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      var emit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n      var clamped = this._clamp(parseFloat(newValue));\n      if (isNaN(clamped)) return;\n      this.value = clamped;\n      this._syncDOM();\n      if (emit) this.callback(this.value);\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }, {\n    key: \"_syncDOM\",\n    value: function _syncDOM() {\n      var range = this.domNode.querySelector('.bjs-slider-track');\n      var numInput = this.domNode.querySelector('.bjs-number-value');\n      if (range) {\n        range.value = this.value;\n        range.style.setProperty('--pct', this._pct() + '%');\n      }\n      if (numInput) numInput.value = this.value;\n      this._syncPresetActive();\n    }\n  }, {\n    key: \"_syncPresetActive\",\n    value: function _syncPresetActive() {\n      var _this = this;\n      this.domNode.querySelectorAll('[data-preset]').forEach(function (btn) {\n        var pv = parseFloat(btn.getAttribute('data-preset'));\n        btn.classList.toggle('is-active', !isNaN(pv) && Math.abs(pv - _this.value) < 0.01);\n      });\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this2 = this;\n      var pct = this._pct();\n      var desc = this.description ? \"<span class=\\\"bjs-control-description\\\">\".concat(this.description, \"</span>\") : '';\n      var presetChips = this.presets.length ? \"<div class=\\\"range-control-presets\\\">\" + this.presets.map(function (p) {\n        var active = Math.abs(p - _this2.value) < 0.01 ? ' is-active' : '';\n        // Unit is already shown on the slider's number input — keep chip\n        // labels to bare values so the row doesn't read \"0px 8px 16px\".\n        return \"<button type=\\\"button\\\" class=\\\"range-control-preset\".concat(active, \"\\\" data-preset=\\\"\").concat(p, \"\\\">\").concat(p, \"</button>\");\n      }).join('') + \"</div>\" : '';\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-stack\\\">\\n        <div class=\\\"bjs-control-label\\\">\\n          <span>\".concat(this.label, \"</span>\\n          \").concat(desc, \"\\n        </div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-slider\\\">\\n            <input type=\\\"range\\\" class=\\\"bjs-slider-track\\\" id=\\\"\").concat(this.id, \"_slider\\\"\\n              min=\\\"\").concat(this.min, \"\\\" max=\\\"\").concat(this.max, \"\\\" step=\\\"\").concat(this.step, \"\\\" value=\\\"\").concat(this.value, \"\\\"\\n              style=\\\"--pct: \").concat(pct, \"%\\\">\\n            <div class=\\\"bjs-slider-value\\\">\\n              <input type=\\\"number\\\" class=\\\"bjs-number-value\\\"\\n                min=\\\"\").concat(this.min, \"\\\" max=\\\"\").concat(this.max, \"\\\" step=\\\"\").concat(this.step, \"\\\" value=\\\"\").concat(this.value, \"\\\"\\n                aria-label=\\\"\").concat(this.label, \"\\\">\\n              \").concat(this.unit ? \"<span class=\\\"bjs-number-unit\\\">\".concat(this.unit, \"</span>\") : '', \"\\n            </div>\\n          </div>\\n          \").concat(presetChips, \"\\n        </div>\\n      </div>\\n    \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this3 = this;\n      var range = this.domNode.querySelector('.bjs-slider-track');\n      var numInput = this.domNode.querySelector('.bjs-number-value');\n      var debounceTimeout = null;\n      var DEBOUNCE_MS = 100;\n      if (range) {\n        range.addEventListener('input', function (e) {\n          _this3.value = parseFloat(e.target.value);\n          range.style.setProperty('--pct', _this3._pct() + '%');\n          if (numInput) numInput.value = _this3.value;\n          _this3._syncPresetActive();\n          if (debounceTimeout) clearTimeout(debounceTimeout);\n          debounceTimeout = setTimeout(function () {\n            return _this3.callback(_this3.value);\n          }, DEBOUNCE_MS);\n        });\n      }\n      if (numInput) {\n        numInput.addEventListener('input', function (e) {\n          var raw = parseFloat(e.target.value);\n          if (isNaN(raw)) return; // wait until user stops typing\n          var clamped = _this3._clamp(raw);\n          _this3.value = clamped;\n          if (range) {\n            range.value = clamped;\n            range.style.setProperty('--pct', _this3._pct() + '%');\n          }\n          _this3._syncPresetActive();\n          if (debounceTimeout) clearTimeout(debounceTimeout);\n          debounceTimeout = setTimeout(function () {\n            return _this3.callback(_this3.value);\n          }, DEBOUNCE_MS);\n        });\n        numInput.addEventListener('blur', function (e) {\n          var raw = parseFloat(e.target.value);\n          if (isNaN(raw)) {\n            // Invalid typed content — restore last valid value\n            numInput.value = _this3.value;\n            return;\n          }\n          var clamped = _this3._clamp(raw);\n          if (clamped !== raw) {\n            // Out-of-range typed input — flash error + auto-correct\n            numInput.classList.add('is-error');\n            setTimeout(function () {\n              return numInput.classList.remove('is-error');\n            }, 300);\n          }\n          _this3.value = clamped;\n          numInput.value = clamped;\n          _this3._syncDOM();\n          _this3.callback(_this3.value);\n        });\n      }\n      this.domNode.querySelectorAll('[data-preset]').forEach(function (btn) {\n        btn.addEventListener('click', function () {\n          var pv = parseFloat(btn.getAttribute('data-preset'));\n          if (!isNaN(pv)) _this3.setValue(pv);\n        });\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RangeControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RangeControl.js?");

/***/ }),

/***/ "./src/includes/RichTextControl.js":
/*!*****************************************!*\
  !*** ./src/includes/RichTextControl.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar RichTextControl = /*#__PURE__*/function () {\n  function RichTextControl(label, value, callback) {\n    var formats = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n    var sourceElement = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n    _classCallCheck(this, RichTextControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n    this.sourceElement = sourceElement;\n    this.domNode = document.createElement(\"div\");\n    this.isEditing = false;\n    this.formats = {};\n    for (var _i = 0, _Object$entries = Object.entries(formats); _i < _Object$entries.length; _i++) {\n      var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n        key = _Object$entries$_i[0],\n        _value = _Object$entries$_i[1];\n      if (_value !== null && _value !== undefined && _value !== \"\") {\n        this.formats[key] = _value;\n      }\n    }\n    if (this.sourceElement) this.extractStylesFromElement();\n    this.render();\n  }\n  return _createClass(RichTextControl, [{\n    key: \"extractStylesFromElement\",\n    value: function extractStylesFromElement() {\n      var _textElement;\n      if (!this.sourceElement) return;\n      var textElement = this.sourceElement.querySelector('[inline-edit=\"text\"]');\n      if (!textElement) {\n        var textTags = [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\", \"p\", \"span\", \"div\", \"td\", \"a\"];\n        for (var _i2 = 0, _textTags = textTags; _i2 < _textTags.length; _i2++) {\n          var tag = _textTags[_i2];\n          textElement = this.sourceElement.querySelector(tag);\n          if (textElement && textElement.textContent.trim()) break;\n        }\n      }\n      if (!textElement) textElement = this.sourceElement;\n      var cs = window.getComputedStyle(textElement);\n      this.formats.font_family = cs.getPropertyValue(\"font-family\");\n      this.formats.font_size = cs.getPropertyValue(\"font-size\");\n      this.formats.font_weight = cs.getPropertyValue(\"font-weight\");\n      this.formats.font_style = cs.getPropertyValue(\"font-style\");\n      this.formats.font_variant = cs.getPropertyValue(\"font-variant\");\n      this.formats.line_height = cs.getPropertyValue(\"line-height\");\n      this.formats.color = cs.getPropertyValue(\"color\");\n      this.formats.text_align = cs.getPropertyValue(\"text-align\");\n      this.formats.text_decoration = cs.getPropertyValue(\"text-decoration\");\n      this.formats.text_transform = cs.getPropertyValue(\"text-transform\");\n      this.formats.letter_spacing = cs.getPropertyValue(\"letter-spacing\");\n      this.formats.word_spacing = cs.getPropertyValue(\"word-spacing\");\n      this.sourceTag = (_textElement = textElement) !== null && _textElement !== void 0 && _textElement.tagName ? textElement.tagName.toLowerCase() : null;\n      for (var i = 0; i < cs.length; i++) {\n        var prop = cs[i];\n        var val = cs.getPropertyValue(prop);\n        if (!val) continue;\n        var key = prop.replace(/-/g, \"_\");\n        if (this.formats[key] !== undefined) continue;\n        this.formats[key] = val;\n      }\n    }\n  }, {\n    key: \"stripTags\",\n    value: function stripTags(html) {\n      var pre = (html || \"\").replace(/<br\\s*\\/?>/gi, \" \\n\").replace(/<\\/(p|div|h[1-6]|li|blockquote|section)>/gi, \" \\n\");\n      var div = document.createElement(\"div\");\n      div.innerHTML = pre;\n      var raw = (div.textContent || div.innerText || \"\").replace(/\\u00A0/g, \" \");\n      return raw.replace(/\\s+/g, \" \").trim();\n    }\n  }, {\n    key: \"toPreview\",\n    value: function toPreview(text) {\n      var max = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 28;\n      var t = (text || \"\").trim();\n      if (t.length <= max) return t;\n      var s = t.slice(0, max);\n      var cut = s.lastIndexOf(\" \");\n      if (cut > 8) s = s.slice(0, cut);\n      return s + \"…\";\n    }\n  }, {\n    key: \"_getWrappedContent\",\n    value: function _getWrappedContent(tag, style) {\n      var _this$value;\n      var safeTag = tag || \"div\";\n      var content = (_this$value = this.value) !== null && _this$value !== void 0 ? _this$value : \"\";\n      var styleAttr = style ? \" style=\\\"\".concat(style, \"\\\"\") : \"\";\n      return \"<\".concat(safeTag).concat(styleAttr, \" contenteditable=\\\"true\\\">\").concat(content, \"</\").concat(safeTag, \">\");\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var plain = this.stripTags(this.value || \"\");\n      var preview = this.toPreview(plain, 500);\n\n      // 2026-04-17 dark-mode pass: swapped hardcoded `#f8f9fa / #111 / #ced4da`\n      // for `.bjs-*` tokens so the preview + edit button track the theme.\n      // The `all: initial` reset only wipes standard property VALUES; custom\n      // properties (CSS variables) still resolve inside it, so var(--bjs-*)\n      // keeps working under the reset. Edit button migrated to\n      // `.bjs-icon-btn` (same 28/32 px surface used elsewhere).\n      this.domNode.innerHTML = \"\\n      <div class=\\\"py-2 px-3 position-relative\\\">\\n        <label class=\\\"form-label fw-semibold\\\">\".concat(this.label, \"</label>\\n        <div class=\\\"richtext-row\\\">\\n          <div class=\\\"richtext-content\\\" style=\\\"width:100% !important; max-width:100% !important;\\\">\\n            <div class=\\\"js-text-preview\\\" style=\\\"\\n              all: initial !important;\\n              box-sizing: border-box !important;\\n              display: -webkit-box !important;\\n              width: 100% !important;\\n              max-width: 100% !important;\\n\\n              padding: 5px!important;\\n              padding-left: 4px !important;\\n\\n              font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif !important;\\n              font-size: 13px !important;\\n              line-height: 1.4 !important;\\n              color: var(--bjs-text) !important;\\n\\n              overflow: hidden !important;\\n              text-overflow: ellipsis !important;\\n\\n              -webkit-line-clamp: 3 !important;\\n              -webkit-box-orient: vertical !important;\\n\\n              white-space: normal !important; /* IMPORTANT */\\n\\n              vertical-align: middle !important;\\n              border: solid 1px var(--bjs-input-border) !important;\\n              border-radius: 4px !important;\\n              background-color: var(--bjs-input-bg) !important;\\n\\n            \\\" title=\\\"\").concat(plain.replace(/\"/g, '&quot;'), \"\\\">\\n              \").concat(preview, \"\\n            </div>\\n          </div>\\n          <div class=\\\"richtext-action\\\">\\n            <a class=\\\"bjs-icon-btn d-inline-flex justify-content-center align-items-center\\\" data-control=\\\"edit\\\" aria-label=\\\"Edit\\\" role=\\\"button\\\" tabindex=\\\"0\\\"><span class=\\\"material-symbols-rounded\\\">edit</span></a>\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this.domNode.querySelector('[data-control=\"edit\"]').addEventListener(\"click\", function () {\n        _this.isEditing = true;\n        _this.renderEditor();\n      });\n    }\n  }, {\n    key: \"renderEditor\",\n    value: function renderEditor() {\n      var _this$value2,\n        _this2 = this;\n      this.domNode.innerHTML = \"\\n      <div class=\\\"py-2 px-3 position-relative\\\">\\n        <label class=\\\"form-label fw-semibold\\\">\".concat(this.label, \"</label>\\n        <div class=\\\"richtext-editor-shell\\\">\\n          <div\\n            id=\\\"\").concat(this.id, \"\\\"\\n            class=\\\"richtext-editor-body\\\"\\n            contenteditable=\\\"true\\\"\\n          >\").concat((_this$value2 = this.value) !== null && _this$value2 !== void 0 ? _this$value2 : \"\", \"</div>\\n          <div class=\\\"richtext-editor-toolbar\\\">\\n            <div class=\\\"richtext-toolbar-row\\\">\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"bold\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.bold'), \"\\\"><strong>B</strong></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"italic\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.italic'), \"\\\"><em>I</em></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"underline\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.underline'), \"\\\"><u>U</u></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"strikeThrough\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.strikethrough'), \"\\\"><s>S</s></button>\\n              <span class=\\\"richtext-tool-sep\\\"></span>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"superscript\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.superscript'), \"\\\"><span style=\\\"font-size:11px\\\">X<sup>2</sup></span></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"subscript\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.subscript'), \"\\\"><span style=\\\"font-size:11px\\\">X<sub>2</sub></span></button>\\n              <span class=\\\"richtext-tool-sep\\\"></span>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn richtext-tool-color\\\" data-command=\\\"foreColor\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.text_color'), \"\\\"><span style=\\\"font-size:14px;font-weight:700\\\">A</span><input type=\\\"color\\\" class=\\\"richtext-color-picker\\\" data-for=\\\"foreColor\\\" value=\\\"#000000\\\"></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn richtext-tool-color\\\" data-command=\\\"hiliteColor\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.highlight'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">ink_highlighter</span><input type=\\\"color\\\" class=\\\"richtext-color-picker\\\" data-for=\\\"hiliteColor\\\" value=\\\"#ffff00\\\"></button>\\n            </div>\\n            <div class=\\\"richtext-toolbar-row\\\">\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"createLink\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">link</span></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"unlink\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.unlink'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">link_off</span></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"insertHorizontalRule\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.horizontal_rule'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">horizontal_rule</span></button>\\n              <span class=\\\"richtext-tool-sep\\\"></span>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"undo\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.undo'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">undo</span></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"redo\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.redo'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">redo</span></button>\\n              <span class=\\\"richtext-tool-sep\\\"></span>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"selectAll\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.select_all'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">checklist</span></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"unselect\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.unselect'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">deselect</span></button>\\n              <button type=\\\"button\\\" class=\\\"richtext-tool-btn\\\" data-command=\\\"removeFormat\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.clear_formatting'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">format_clear</span></button>\\n            </div>\\n          </div>\\n          <div class=\\\"richtext-link-popover\\\" style=\\\"display:none;\\\">\\n            <input type=\\\"text\\\" class=\\\"richtext-link-input\\\" placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link_url_placeholder'), \"\\\">\\n            <select class=\\\"richtext-link-target\\\">\\n              <option value=\\\"\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link.target_self'), \"</option>\\n              <option value=\\\"_blank\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link.target_blank'), \"</option>\\n            </select>\\n            <button type=\\\"button\\\" class=\\\"richtext-link-apply\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link_apply'), \"\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">check</span></button>\\n            <button type=\\\"button\\\" class=\\\"richtext-link-remove\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('richtext.link_remove'), \"\\\" style=\\\"display:none;\\\"><span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px\\\">link_off</span></button>\\n          </div>\\n        </div>\\n        <div class=\\\"d-flex align-items-center mt-2\\\" style=\\\"gap:4px;\\\">\\n          <button class=\\\"btn btn-primary btn-sm ms-auto\\\" data-control=\\\"done\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.save'), \"</button>\\n        </div>\\n      </div>\\n    \");\n      var editor = document.getElementById(this.id);\n\n      // Place cursor at end of content\n      try {\n        var range = document.createRange();\n        range.selectNodeContents(editor);\n        range.collapse(false);\n        var sel = window.getSelection();\n        sel.removeAllRanges();\n        sel.addRange(range);\n      } catch (_unused) {}\n      editor.focus();\n      var simpleCommands = [\"bold\", \"italic\", \"underline\", \"strikeThrough\", \"superscript\", \"subscript\", \"removeFormat\", \"unlink\", \"insertHorizontalRule\", \"undo\", \"redo\", \"selectAll\"];\n      this.domNode.querySelectorAll(\"[data-command]\").forEach(function (control) {\n        var cmd = control.getAttribute(\"data-command\");\n        if (control.tagName !== \"BUTTON\") return;\n        control.addEventListener(\"mousedown\", function (ev) {\n          return ev.preventDefault();\n        });\n        if (simpleCommands.includes(cmd)) {\n          control.addEventListener(\"click\", function (e) {\n            e.preventDefault();\n            document.execCommand(cmd, false, null);\n            editor.focus();\n          });\n        }\n      });\n\n      // Color picker buttons (foreColor, hiliteColor)\n      this.domNode.querySelectorAll('.richtext-color-picker').forEach(function (picker) {\n        var cmd = picker.dataset[\"for\"];\n        picker.addEventListener('input', function () {\n          _this2._restoreSelection();\n          document.execCommand(cmd, false, picker.value);\n          _this2._saveSelection();\n          _this2.value = editor.innerHTML;\n          _this2.callback.setText(_this2.value);\n        });\n        // Save selection before color picker opens\n        picker.closest('.richtext-tool-btn').addEventListener('click', function (e) {\n          if (e.target === picker) return;\n          e.preventDefault();\n          _this2._saveSelection();\n          picker.click();\n        });\n      });\n\n      // Unselect button handler (collapse selection to cursor)\n      var unselectBtn = this.domNode.querySelector('[data-command=\"unselect\"]');\n      if (unselectBtn) {\n        unselectBtn.addEventListener(\"mousedown\", function (ev) {\n          return ev.preventDefault();\n        });\n        unselectBtn.addEventListener(\"click\", function (e) {\n          e.preventDefault();\n          var sel = window.getSelection();\n          if (sel.rangeCount > 0) sel.collapseToEnd();\n          editor.focus();\n        });\n      }\n\n      // Link button handler\n      var linkBtn = this.domNode.querySelector('[data-command=\"createLink\"]');\n      if (linkBtn) {\n        linkBtn.addEventListener(\"mousedown\", function (ev) {\n          return ev.preventDefault();\n        });\n        linkBtn.addEventListener(\"click\", function (e) {\n          e.preventDefault();\n          _this2._handleLinkButton(editor);\n        });\n      }\n\n      // Keyboard shortcut: Ctrl+K / Cmd+K for link\n      // Keyboard shortcuts — stop propagation to prevent builder-level undo/redo\n      editor.addEventListener(\"keydown\", function (e) {\n        if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {\n          e.preventDefault();\n          e.stopPropagation();\n          _this2._handleLinkButton(editor);\n        }\n        // Ctrl+Z / Cmd+Z (undo) and Ctrl+Shift+Z / Cmd+Shift+Z (redo)\n        // Must stay scoped to the editor, not bubble to builder\n        if (e.key === 'z' && (e.ctrlKey || e.metaKey)) {\n          e.stopPropagation();\n        }\n        if (e.key === 'y' && (e.ctrlKey || e.metaKey)) {\n          e.stopPropagation();\n        }\n      });\n      editor.addEventListener(\"input\", function () {\n        _this2.value = editor.innerHTML;\n        _this2.callback.setText(_this2.value);\n      });\n      this.domNode.querySelector('[data-control=\"done\"]').addEventListener(\"click\", function () {\n        _this2.value = editor.innerHTML.trim();\n        _this2.isEditing = false;\n        _this2.callback.setText(_this2.value);\n        _this2.render();\n      });\n\n      // Link popover event listeners\n      var popover = this.domNode.querySelector('.richtext-link-popover');\n      if (popover) {\n        popover.querySelector('.richtext-link-apply').addEventListener('click', function () {\n          _this2._applyLink(editor);\n        });\n        popover.querySelector('.richtext-link-remove').addEventListener('click', function () {\n          _this2._removeLink(editor);\n        });\n        // Stop all keyboard shortcuts from bubbling to builder when in link input\n        popover.addEventListener('keydown', function (e) {\n          e.stopPropagation();\n        });\n        popover.querySelector('.richtext-link-input').addEventListener('keydown', function (e) {\n          if (e.key === 'Enter') {\n            e.preventDefault();\n            _this2._applyLink(editor);\n          }\n          if (e.key === 'Escape') {\n            e.preventDefault();\n            popover.style.display = 'none';\n            _this2._unmarkSelection();\n            _this2._restoreSelection();\n            editor.focus();\n          }\n        });\n      }\n      editor.focus();\n    }\n  }, {\n    key: \"_markSelection\",\n    value: function _markSelection() {\n      this._unmarkSelection();\n      var sel = window.getSelection();\n      if (!sel.rangeCount || sel.isCollapsed) return;\n      var range = sel.getRangeAt(0);\n      var rects = range.getClientRects();\n      var editor = document.getElementById(this.id);\n      if (!editor || !rects.length) return;\n      var editorRect = editor.getBoundingClientRect();\n\n      // Position-based overlay — does NOT modify DOM text, so range stays valid\n      var _iterator = _createForOfIteratorHelper(rects),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var rect = _step.value;\n          var overlay = document.createElement('div');\n          overlay.className = 'richtext-selection-overlay';\n          Object.assign(overlay.style, {\n            position: 'absolute',\n            top: \"\".concat(rect.top - editorRect.top, \"px\"),\n            left: \"\".concat(rect.left - editorRect.left, \"px\"),\n            width: \"\".concat(rect.width, \"px\"),\n            height: \"\".concat(rect.height, \"px\")\n          });\n          editor.appendChild(overlay);\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n    }\n  }, {\n    key: \"_unmarkSelection\",\n    value: function _unmarkSelection() {\n      var editor = document.getElementById(this.id);\n      if (!editor) return;\n      editor.querySelectorAll('.richtext-selection-overlay').forEach(function (el) {\n        return el.remove();\n      });\n    }\n  }, {\n    key: \"_saveSelection\",\n    value: function _saveSelection() {\n      var sel = window.getSelection();\n      if (sel.rangeCount > 0) {\n        this._savedRange = sel.getRangeAt(0).cloneRange();\n      }\n    }\n  }, {\n    key: \"_restoreSelection\",\n    value: function _restoreSelection() {\n      if (!this._savedRange) return;\n      var sel = window.getSelection();\n      sel.removeAllRanges();\n      sel.addRange(this._savedRange);\n    }\n  }, {\n    key: \"_findParentLink\",\n    value: function _findParentLink(node) {\n      while (node && node !== this.domNode) {\n        if (node.tagName === 'A') return node;\n        node = node.parentElement;\n      }\n      return null;\n    }\n  }, {\n    key: \"_handleLinkButton\",\n    value: function _handleLinkButton(editor) {\n      var sel = window.getSelection();\n      var popover = this.domNode.querySelector('.richtext-link-popover');\n      var input = popover.querySelector('.richtext-link-input');\n      var targetSelect = popover.querySelector('.richtext-link-target');\n      var removeBtn = popover.querySelector('.richtext-link-remove');\n\n      // Check if cursor is inside an existing link\n      var existingLink = null;\n      if (sel.anchorNode) {\n        existingLink = this._findParentLink(sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentElement : sel.anchorNode);\n      }\n      if (existingLink) {\n        // Select the entire link text for easy editing\n        var range = document.createRange();\n        range.selectNodeContents(existingLink);\n        sel.removeAllRanges();\n        sel.addRange(range);\n        input.value = existingLink.getAttribute('href') || '';\n        targetSelect.value = existingLink.getAttribute('target') || '';\n        removeBtn.style.display = 'inline-flex';\n      } else if (sel.isCollapsed) {\n        // No text selected and not inside a link - nothing to wrap\n        var linkBtn = this.domNode.querySelector('[data-command=\"createLink\"]');\n        if (linkBtn) {\n          linkBtn.classList.add('richtext-tool-btn-shake');\n          setTimeout(function () {\n            return linkBtn.classList.remove('richtext-tool-btn-shake');\n          }, 400);\n        }\n        return;\n      } else {\n        input.value = '';\n        targetSelect.value = '';\n        removeBtn.style.display = 'none';\n      }\n      this._saveSelection();\n      this._markSelection();\n      popover.style.display = 'flex';\n      input.focus();\n    }\n  }, {\n    key: \"_applyLink\",\n    value: function _applyLink(editor) {\n      var popover = this.domNode.querySelector('.richtext-link-popover');\n      var input = popover.querySelector('.richtext-link-input');\n      var targetSelect = popover.querySelector('.richtext-link-target');\n      var url = input.value.trim();\n      var target = targetSelect.value;\n      this._unmarkSelection();\n      this._restoreSelection();\n      if (url) {\n        // Auto-prepend https:// if no protocol\n        if (!/^https?:\\/\\//i.test(url) && !/^mailto:/i.test(url) && !/^tel:/i.test(url)) {\n          url = 'https://' + url;\n        }\n        document.execCommand('createLink', false, url);\n\n        // Set target attribute on the created link(s)\n        // execCommand doesn't support target, so we set it manually\n        var sel = window.getSelection();\n        if (sel.anchorNode) {\n          var link = this._findParentLink(sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentElement : sel.anchorNode);\n          if (link) {\n            if (target) {\n              link.setAttribute('target', target);\n            } else {\n              link.removeAttribute('target');\n            }\n          }\n        }\n      } else {\n        document.execCommand('unlink');\n      }\n      popover.style.display = 'none';\n      this.value = editor.innerHTML;\n      this.callback.setText(this.value);\n      editor.focus();\n    }\n  }, {\n    key: \"_removeLink\",\n    value: function _removeLink(editor) {\n      var popover = this.domNode.querySelector('.richtext-link-popover');\n      this._unmarkSelection();\n      this._restoreSelection();\n      document.execCommand('unlink');\n      popover.style.display = 'none';\n      this.value = editor.innerHTML;\n      this.callback.setText(this.value);\n      editor.focus();\n    }\n  }, {\n    key: \"getPreviewStyle\",\n    value: function getPreviewStyle() {\n      var keys = [\"font_family\", \"font_size\", \"font_weight\", \"font_style\", \"font_variant\", \"color\", \"line_height\", \"text_align\", \"text_decoration\", \"text_transform\", \"letter_spacing\", \"word_spacing\", \"text_indent\", \"text_shadow\", \"background_color\", \"background_image\", \"background_position\", \"background_size\", \"background_repeat\", \"padding\", \"padding_top\", \"padding_right\", \"padding_bottom\", \"padding_left\", \"margin\", \"margin_top\", \"margin_right\", \"margin_bottom\", \"margin_left\", \"border\", \"border_top\", \"border_right\", \"border_bottom\", \"border_left\", \"border_radius\", \"border_top_left_radius\", \"border_top_right_radius\", \"border_bottom_left_radius\", \"border_bottom_right_radius\", \"width\", \"height\", \"max_width\", \"min_width\", \"display\", \"vertical_align\", \"white_space\", \"word_wrap\", \"word_break\", \"overflow_wrap\"];\n      var styles = [];\n      for (var _i3 = 0, _keys = keys; _i3 < _keys.length; _i3++) {\n        var k = _keys[_i3];\n        if (this.formats[k]) {\n          var p = k.replace(/_/g, \"-\");\n          styles.push(\"\".concat(p, \": \").concat(this.formats[k], \" !important\"));\n        }\n      }\n      return styles.join(\"; \");\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RichTextControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/RichTextControl.js?");

/***/ }),

/***/ "./src/includes/SAlert.js":
/*!********************************!*\
  !*** ./src/includes/SAlert.js ***!
  \********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n\n\n/**\n * SAlert — styled modal dialog for builder notifications.\n *\n * Usage:\n *   SAlert.show('Saved!');                        // info (default)\n *   SAlert.show('Missing {ITEMS}', 'error');      // error\n *   SAlert.show('Upload complete', 'success');    // success\n */\nvar SAlert = {\n  show: function show(message) {\n    var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'info';\n    var wrapper = document.getElementById('alertsWrapper');\n    if (!wrapper) {\n      wrapper = document.createElement('div');\n      wrapper.id = 'alertsWrapper';\n      document.body.appendChild(wrapper);\n    }\n\n    // Remove any existing modal\n    var existing = document.getElementById('SAlertModal');\n    if (existing) existing.remove();\n\n    // Icon + color per type\n    var config = {\n      error: {\n        icon: 'error',\n        color: '#EF4444',\n        bg: '#FEF2F2',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.error') || 'Error'\n      },\n      success: {\n        icon: 'check_circle',\n        color: '#10B981',\n        bg: '#F0FDF4',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.success') || 'Success'\n      },\n      info: {\n        icon: 'info',\n        color: '#3B82F6',\n        bg: '#EFF6FF',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.info') || 'Info'\n      }\n    };\n    var _ref = config[type] || config.info,\n      icon = _ref.icon,\n      color = _ref.color,\n      bg = _ref.bg,\n      label = _ref.label;\n    wrapper.innerHTML = \"\\n            <div class=\\\"modal fade\\\" id=\\\"SAlertModal\\\" tabindex=\\\"-1\\\" aria-labelledby=\\\"SAlertLabel\\\" aria-hidden=\\\"true\\\">\\n                <div class=\\\"modal-dialog modal-dialog-centered\\\" style=\\\"max-width:420px;\\\">\\n                    <div class=\\\"modal-content\\\" style=\\\"border:none;border-radius:12px;overflow:hidden;box-shadow:0 8px 32px rgba(0,0,0,0.18);\\\">\\n                        <div class=\\\"modal-header\\\" style=\\\"background:\".concat(bg, \";border-bottom:none;padding:20px 24px 12px;\\\">\\n                            <div style=\\\"display:flex;align-items:center;gap:10px;\\\">\\n                                <span class=\\\"material-symbols-rounded\\\" style=\\\"color:\").concat(color, \";font-size:24px;flex-shrink:0;\\\">\").concat(icon, \"</span>\\n                                <span style=\\\"font-weight:600;font-size:15px;color:#1E293B;\\\" id=\\\"SAlertLabel\\\">\").concat(label, \"</span>\\n                            </div>\\n                            <button type=\\\"button\\\" class=\\\"btn-close\\\" data-bs-dismiss=\\\"modal\\\" aria-label=\\\"Close\\\" style=\\\"margin:0;opacity:0.5;\\\"></button>\\n                        </div>\\n                        <div class=\\\"modal-body\\\" id=\\\"SAlertModalBody\\\" style=\\\"padding:16px 24px 8px;font-size:14px;color:#475569;line-height:1.6;\\\">\\n                        </div>\\n                        <div class=\\\"modal-footer\\\" style=\\\"border-top:none;padding:8px 24px 20px;justify-content:flex-end;\\\">\\n                            <button type=\\\"button\\\"\\n                                class=\\\"btn btn-primary btn-sm\\\"\\n                                data-bs-dismiss=\\\"modal\\\"\\n                                style=\\\"min-width:72px;\\\">\\n                                \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('dialog.ok') || 'OK', \"\\n                            </button>\\n                        </div>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n    document.getElementById('SAlertModalBody').innerHTML = message;\n    var modal = new bootstrap.Modal(document.getElementById('SAlertModal'));\n    modal.show();\n  }\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SAlert);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SAlert.js?");

/***/ }),

/***/ "./src/includes/SectionGroupControl.js":
/*!*********************************************!*\
  !*** ./src/includes/SectionGroupControl.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * SectionGroupControl — collapsible group wrapper styled like the BORDERS section.\n *\n * Usage:\n *   new SectionGroupControl({\n *     title: 'IMAGE SIZE',\n *     description: 'Adjust width, height and bounds.',\n *     children: [ ctrl1, ctrl2, ... ],\n *     collapsed: false,     // optional, default false\n *   })\n *\n * Children are other Control instances (anything with a `domNode`). They are\n * appended into the group's body on render. Clicking the header toggles the\n * collapsed state. The control is dark-mode safe — all styling lives in\n * `.bjs-group-*` classes in builder.css, resolving through `--bjs-*` tokens.\n */\nvar SectionGroupControl = /*#__PURE__*/function () {\n  function SectionGroupControl() {\n    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n      _ref$title = _ref.title,\n      title = _ref$title === void 0 ? '' : _ref$title,\n      _ref$description = _ref.description,\n      description = _ref$description === void 0 ? '' : _ref$description,\n      _ref$children = _ref.children,\n      children = _ref$children === void 0 ? [] : _ref$children,\n      _ref$collapsed = _ref.collapsed,\n      collapsed = _ref$collapsed === void 0 ? false : _ref$collapsed;\n    _classCallCheck(this, SectionGroupControl);\n    this.id = '_bjsg_' + Math.random().toString(36).substr(2, 9);\n    this.title = title;\n    this.description = description;\n    this.children = Array.isArray(children) ? children : [];\n    this.collapsed = !!collapsed;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-group');\n    if (this.collapsed) this.domNode.classList.add('is-collapsed');\n    this.render();\n    this._bindEvents();\n  }\n  return _createClass(SectionGroupControl, [{\n    key: \"render\",\n    value: function render() {\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-group-header\\\" role=\\\"button\\\" tabindex=\\\"0\\\" aria-expanded=\\\"\".concat(!this.collapsed, \"\\\">\\n                <div>\\n                    <span class=\\\"bjs-group-header-title\\\">\").concat(this.title, \"</span>\\n                    \").concat(this.description ? \"<span class=\\\"bjs-group-header-desc\\\">\".concat(this.description, \"</span>\") : '', \"\\n                </div>\\n                <span class=\\\"material-symbols-rounded bjs-group-header-caret\\\" aria-hidden=\\\"true\\\">keyboard_arrow_down</span>\\n            </div>\\n            <div class=\\\"bjs-group-body\\\"></div>\\n        \");\n      var body = this.domNode.querySelector('.bjs-group-body');\n      this.children.forEach(function (child) {\n        if (child && child.domNode) body.appendChild(child.domNode);\n      });\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      var header = this.domNode.querySelector('.bjs-group-header');\n      if (!header) return;\n      var toggle = function toggle() {\n        _this.collapsed = !_this.collapsed;\n        _this.domNode.classList.toggle('is-collapsed', _this.collapsed);\n        header.setAttribute('aria-expanded', String(!_this.collapsed));\n      };\n      header.addEventListener('click', toggle);\n      header.addEventListener('keydown', function (e) {\n        if (e.key === 'Enter' || e.key === ' ') {\n          e.preventDefault();\n          toggle();\n        }\n      });\n    }\n\n    /** Composite destroy — Builder.renderElementControls only sees the\n     *  outer control list (it doesn't recurse into a section's children).\n     *  Without this, child controls (DimensionControl, etc.) that own\n     *  subscribe disposers would leak listeners every time the sidebar\n     *  rebuilds. Idempotent: safe to call multiple times. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._destroyed) return;\n      this._destroyed = true;\n      var _iterator = _createForOfIteratorHelper(this.children || []),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var child = _step.value;\n          if (child && typeof child.destroy === 'function') {\n            try {\n              child.destroy();\n            } catch (err) {\n              /* eslint-disable-next-line no-console */console.error('[bjs:SectionGroup] child destroy threw:', err);\n            }\n          }\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SectionGroupControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SectionGroupControl.js?");

/***/ }),

/***/ "./src/includes/SectionLabelControl.js":
/*!*********************************************!*\
  !*** ./src/includes/SectionLabelControl.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * SectionLabelControl — a non-interactive section header dropped between\n * control rows (e.g. the \"PAGE SETTINGS\" divider above Page-level block\n * padding in the Block panel).\n *\n * 2026-04-17 audit (§2.12): migrated from `.shadow-sm .text-white\n * .section-label` (Bootstrap, white-on-dark, deprecated) to\n * `.bjs-section-header` — the panel's canonical divider primitive\n * (token-driven, uppercase title, subtle bottom border, dark-mode-safe).\n *\n * Constructor accepts an optional description shown below the title for\n * sections that need one-liner guidance (\"these settings apply to the\n * page, not this block\"). Omit for a bare title.\n */\nvar SectionLabelControl = /*#__PURE__*/function () {\n  function SectionLabelControl(label) {\n    var description = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n    _classCallCheck(this, SectionLabelControl);\n    this.label = label;\n    this.description = description;\n    this.domNode = document.createElement('div');\n    this.render();\n  }\n  return _createClass(SectionLabelControl, [{\n    key: \"render\",\n    value: function render() {\n      var desc = this.description ? \"<span class=\\\"bjs-section-header-desc\\\">\".concat(this.description, \"</span>\") : '';\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-section-header\\\" role=\\\"heading\\\" aria-level=\\\"3\\\">\\n                <div>\\n                    <span class=\\\"bjs-section-header-title\\\">\".concat(this.label, \"</span>\\n                    \").concat(desc, \"\\n                </div>\\n            </div>\\n        \");\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SectionLabelControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SectionLabelControl.js?");

/***/ }),

/***/ "./src/includes/SegmentedTextControl.js":
/*!**********************************************!*\
  !*** ./src/includes/SegmentedTextControl.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * SegmentedTextControl — sibling of AlignControl that renders text\n * labels (XS · SM · MD · LG · XL) instead of material-symbol icons. Uses\n * the canonical `.bjs-control-row` + `.bjs-segmented` shell (Sync Pass\n * 2026-04-19) so it inherits the wrap-capable + breath-room styling all\n * other segmented controls in the panel use.\n *\n * Constructor signature mirrors AlignControl for muscle-memory parity:\n *   new SegmentedTextControl(label, value, callback, options)\n *\n * `options` is an array of either:\n *   - 'xs'                                  → label='xs' (auto-uppercased)\n *   - { value: 'xs', label: 'XS' }          → explicit label\n *   - { value: 'pill', label: 'Pill', tooltip: 'Fully rounded' }\n *\n * `callback` accepts either a fn or an object with `setValue(v)` —\n * matches AlignControl's loose contract so consumers can wire either\n * shape.\n *\n * Public API:\n *   .setValue(v) — programmatic update + fires callback\n *   .getValue()  — current value\n *\n * NOT a BaseControl subclass — this control owns no element-state\n * subscription so there's nothing to dispose. Builder.renderElementControls'\n * destroy guard is `typeof ctrl.destroy === 'function'` so the omission is\n * safe.\n */\nvar SegmentedTextControl = /*#__PURE__*/function () {\n  function SegmentedTextControl(label, value, callback) {\n    var _this = this;\n    var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];\n    var sync = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n    _classCallCheck(this, SegmentedTextControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n    this.options = (options || []).map(function (entry) {\n      if (entry && _typeof(entry) === 'object') {\n        return {\n          value: entry.value,\n          label: entry.label || String(entry.value).toUpperCase(),\n          tooltip: entry.tooltip || null\n        };\n      }\n      return {\n        value: entry,\n        label: String(entry).toUpperCase(),\n        tooltip: null\n      };\n    });\n    this.domNode = document.createElement('div');\n    this.render();\n\n    // Optional sync config — when another surface mutates element state\n    // we re-read the axis via readValue() and silently patch the active\n    // chip so this instance stays in step. No callback fires (silent).\n    //\n    //   sync = { element, readValue: () => axisKeyFromElement }\n    //\n    // Canonical pattern for dual-surface axes (Sidebar + Settings\n    // popover, Sidebar + Preset picker, etc.) — both surfaces pass a\n    // readValue pointing at the SAME element.<axis_key> so state flows\n    // one-way: element → control visual.\n    this._syncDispose = null;\n    if (sync && sync.element && typeof sync.readValue === 'function' && typeof sync.element.addSyncListener === 'function') {\n      this._syncDispose = sync.element.addSyncListener('SegmentedTextControl:' + this.id, function () {\n        try {\n          var next = sync.readValue();\n          if (next != null) _this.syncValue(next);\n        } catch (_) {/* no-op — sync failures must not crash */}\n      });\n    }\n  }\n\n  /**\n   * Destroy hook called by Builder.renderElementControls when the control\n   * tree rebuilds. Releases the sync subscription so we don't leak\n   * listeners across rebuilds.\n   */\n  return _createClass(SegmentedTextControl, [{\n    key: \"destroy\",\n    value: function destroy() {\n      if (typeof this._syncDispose === 'function') {\n        try {\n          this._syncDispose();\n        } catch (_) {/* no-op */}\n        this._syncDispose = null;\n      }\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this2 = this;\n      var escapeAttr = function escapeAttr(s) {\n        return String(s == null ? '' : s).replace(/\"/g, '&quot;');\n      };\n      var escapeText = function escapeText(s) {\n        return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n      };\n      var buttons = this.options.map(function (opt) {\n        var isActive = _this2.value === opt.value;\n        var tip = opt.tooltip ? \" data-tooltip=\\\"\".concat(escapeAttr(opt.tooltip), \"\\\"\") : '';\n        return \"\\n                <button type=\\\"button\\\"\\n                        class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n                        role=\\\"radio\\\"\\n                        aria-checked=\\\"\").concat(isActive, \"\\\"\\n                        data-value=\\\"\").concat(escapeAttr(opt.value), \"\\\"\").concat(tip, \"\\n                        tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n                    \").concat(escapeText(opt.label), \"\\n                </button>\\n            \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <div class=\\\"bjs-control-label\\\"><span>\".concat(escapeText(this.label), \"</span></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(this.label), \"\\\">\\n                        \").concat(buttons, \"\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this3 = this;\n      var group = this.domNode.querySelector('.bjs-segmented');\n      if (!group) return;\n      group.addEventListener('click', function (e) {\n        var btn = e.target.closest('.bjs-segmented-btn');\n        if (!btn || !group.contains(btn)) return;\n        _this3._select(btn.dataset.value, {\n          focus: true\n        });\n      });\n\n      // Keyboard nav matches AlignControl — radio group convention\n      group.addEventListener('keydown', function (e) {\n        if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n        e.preventDefault();\n        var btns = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n        var idx = btns.findIndex(function (b) {\n          return b.classList.contains('is-active');\n        });\n        var next = idx;\n        if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') next = (idx - 1 + btns.length) % btns.length;else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') next = (idx + 1) % btns.length;else if (e.key === 'Home') next = 0;else if (e.key === 'End') next = btns.length - 1;\n        var nb = btns[next];\n        if (nb) _this3._select(nb.dataset.value, {\n          focus: true\n        });\n      });\n    }\n  }, {\n    key: \"_select\",\n    value: function _select(value) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$focus = _ref.focus,\n        focus = _ref$focus === void 0 ? false : _ref$focus;\n      if (value === this.value) return;\n      this.value = value;\n      this._updateActive();\n      if (focus) {\n        var active = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n        if (active) active.focus();\n      }\n      if (typeof this.callback === 'function') this.callback(this.value);else if (this.callback && typeof this.callback.setValue === 'function') this.callback.setValue(this.value);\n    }\n  }, {\n    key: \"_updateActive\",\n    value: function _updateActive() {\n      var _this4 = this;\n      this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var isActive = btn.dataset.value === _this4.value;\n        btn.classList.toggle('is-active', isActive);\n        btn.setAttribute('aria-checked', String(isActive));\n        btn.setAttribute('tabindex', isActive ? '0' : '-1');\n      });\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      if (newValue === this.value) return;\n      this.value = newValue;\n      this._updateActive();\n      if (typeof this.callback === 'function') this.callback(this.value);else if (this.callback && typeof this.callback.setValue === 'function') this.callback.setValue(this.value);\n    }\n\n    /**\n     * Silent value set — updates visual state only, DOES NOT fire callback.\n     * Used by the sync listener so dual-surface mutations (popover +\n     * sidebar) don't bounce back into apply*() and cause a feedback loop.\n     */\n  }, {\n    key: \"syncValue\",\n    value: function syncValue(newValue) {\n      if (newValue === this.value) return;\n      this.value = newValue;\n      this._updateActive();\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SegmentedTextControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SegmentedTextControl.js?");

/***/ }),

/***/ "./src/includes/SelectControl.js":
/*!***************************************!*\
  !*** ./src/includes/SelectControl.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/sortable.js */ \"./src/includes/ui/sortable.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n/**\n * SelectControl — edits a list of {label, value} items plus a field name.\n *\n * Consumer: SelectElement, RadioElement, CheckboxElement form fields.\n * Each item surfaces two `.bjs-text-input` fields (label + value) and a\n * remove `.bjs-icon-btn--danger`. \"Add Item\" is a `.bjs-btn`.\n *\n * 2026-04-18 Phase 2.18 rewrite — drops Bootstrap `.form-control\n * form-control-sm`, `.list-group`, `.btn btn-primary`/`btn-danger`,\n * `.d-flex`, etc. Uses `.bjs-*` primitives end-to-end.\n */\nvar SelectControl = /*#__PURE__*/function () {\n  function SelectControl(label, items, callback) {\n    var inputName = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '';\n    _classCallCheck(this, SelectControl);\n    this.label = label;\n    this.items = items || [];\n    this.callback = callback;\n    this.inputName = inputName;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-select-control');\n    this.render();\n  }\n  return _createClass(SelectControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var id = this._id || (this._id = '_' + Math.random().toString(36).substr(2, 9));\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label><span>\".concat(this.label, \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-select-control-name\\\">\\n                    <label class=\\\"bjs-control-label\\\" for=\\\"\").concat(id, \"_name\\\"><span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.element_name', 'Element Name'), \"</span></label>\\n                    <input id=\\\"\").concat(id, \"_name\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" value=\\\"\").concat(this._escape(this.inputName), \"\\\" data-control=\\\"name-input\\\" placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.element_name_ph', 'field_name'), \"\\\">\\n                </div>\\n                <div class=\\\"bjs-select-control-items\\\" data-control=\\\"items\\\"></div>\\n                <div class=\\\"bjs-select-control-actions\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-btn bjs-btn--primary\\\" data-control=\\\"add-item\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">add</span>\\n                        <span>\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.add_item', 'Add item'), \"</span>\\n                    </button>\\n                </div>\\n            </div>\\n        \");\n      var itemsContainer = this.domNode.querySelector('[data-control=\"items\"]');\n      this.items.forEach(function (item, index) {\n        var row = document.createElement('div');\n        row.className = 'bjs-select-control-item bjs-list-item';\n        row.setAttribute('data-index', String(index));\n        row.innerHTML = \"\\n                <div class=\\\"bjs-select-control-item-head\\\">\\n                    <button type=\\\"button\\\" class=\\\"bjs-list-item-handle\\\" aria-label=\\\"\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.reorder', 'Drag to reorder'), \"\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.reorder', 'Drag to reorder'), \"\\\" tabindex=\\\"0\\\">\\u2261</button>\\n                    <span class=\\\"bjs-select-control-item-index\\\">#\").concat(index + 1, \"</span>\\n                    <button type=\\\"button\\\" class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" data-control=\\\"remove-item\\\" data-index=\\\"\").concat(index, \"\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.remove_item', 'Remove item'), \"\\\">\\n                        <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">delete</span>\\n                    </button>\\n                </div>\\n                <label class=\\\"bjs-select-control-field\\\">\\n                    <span class=\\\"bjs-select-control-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.label', 'Label'), \"</span>\\n                    <input type=\\\"text\\\" class=\\\"bjs-text-input\\\" value=\\\"\").concat(_this._escape(item.label), \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"label\\\">\\n                </label>\\n                <label class=\\\"bjs-select-control-field\\\">\\n                    <span class=\\\"bjs-select-control-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('select.value', 'Value'), \"</span>\\n                    <input type=\\\"text\\\" class=\\\"bjs-text-input\\\" value=\\\"\").concat(_this._escape(item.value), \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"value\\\">\\n                </label>\\n            \");\n        row.querySelectorAll('input[data-field]').forEach(function (inp) {\n          inp.addEventListener('input', function (e) {\n            var _this$callback;\n            var field = e.target.dataset.field;\n            var i = parseInt(e.target.dataset.index, 10);\n            _this.items[i][field] = e.target.value;\n            if ((_this$callback = _this.callback) !== null && _this$callback !== void 0 && _this$callback.setItems) _this.callback.setItems(_this.items);\n          });\n        });\n        row.querySelector('[data-control=\"remove-item\"]').addEventListener('click', function (e) {\n          var _this$callback2;\n          var i = parseInt(e.currentTarget.dataset.index, 10);\n          _this.items.splice(i, 1);\n          _this.render();\n          if ((_this$callback2 = _this.callback) !== null && _this$callback2 !== void 0 && _this$callback2.setItems) _this.callback.setItems(_this.items);\n        });\n        itemsContainer.appendChild(row);\n      });\n      this.domNode.querySelector('[data-control=\"add-item\"]').addEventListener('click', function () {\n        var _this$callback3;\n        _this.items.push({\n          label: '',\n          value: ''\n        });\n        _this.render();\n        if ((_this$callback3 = _this.callback) !== null && _this$callback3 !== void 0 && _this$callback3.setItems) _this.callback.setItems(_this.items);\n      });\n      this.domNode.querySelector('[data-control=\"name-input\"]').addEventListener('input', function (e) {\n        var _this$callback4;\n        _this.inputName = e.target.value;\n        if ((_this$callback4 = _this.callback) !== null && _this$callback4 !== void 0 && _this$callback4.setName) _this.callback.setName(_this.inputName);\n      });\n      this._bindSortable();\n    }\n\n    /** Phase-3 W6.2 — drag-reorder via shared bjsSortable mixin. Items are\n     *  the existing .bjs-select-control-item rows (aliased to .bjs-list-item\n     *  so the shared mixin's default selectors work). */\n  }, {\n    key: \"_bindSortable\",\n    value: function _bindSortable() {\n      var _this2 = this;\n      if (this._sortable && typeof this._sortable.destroy === 'function') {\n        try {\n          this._sortable.destroy();\n        } catch (_e) {}\n      }\n      var container = this.domNode.querySelector('[data-control=\"items\"]');\n      if (!container) return;\n      this._sortable = (0,_ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__.bjsSortable)(container, {\n        itemSelector: '.bjs-list-item',\n        handleSelector: '.bjs-list-item-handle',\n        onReorder: function onReorder(from, to) {\n          var _this2$callback;\n          var _this2$items$splice = _this2.items.splice(from, 1),\n            _this2$items$splice2 = _slicedToArray(_this2$items$splice, 1),\n            moved = _this2$items$splice2[0];\n          var adjusted = to > from ? to - 1 : to;\n          _this2.items.splice(adjusted, 0, moved);\n          _this2.render();\n          if ((_this2$callback = _this2.callback) !== null && _this2$callback !== void 0 && _this2$callback.setItems) _this2.callback.setItems(_this2.items);\n        }\n      });\n    }\n  }, {\n    key: \"_escape\",\n    value: function _escape(s) {\n      return String(s !== null && s !== void 0 ? s : '').replace(/\"/g, '&quot;').replace(/</g, '&lt;');\n    }\n  }, {\n    key: \"getListContainer\",\n    value: function getListContainer() {\n      return this.domNode.querySelector('[data-control=\"items\"]');\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SelectControl.js?");

/***/ }),

/***/ "./src/includes/SelectElement.js":
/*!***************************************!*\
  !*** ./src/includes/SelectElement.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SelectControl.js */ \"./src/includes/SelectControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\nvar SelectElement = /*#__PURE__*/function (_BaseElement) {\n  function SelectElement(template) {\n    var _this;\n    var inputName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : \"\";\n    var items = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];\n    _classCallCheck(this, SelectElement);\n    _this = _callSuper(this, SelectElement);\n    _this.template = template;\n    _this.items = _this.normalizeItems(items);\n    _this.inputName = inputName;\n    _this.domNode = null;\n    _this.requiredTemplateKeys = [\"items\"];\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      background_color: null,\n      background_image: null,\n      background_position: \"center\",\n      background_size: \"100%\",\n      background_repeat: \"no-repeat\",\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      width: null,\n      height: null\n    });\n    return _this;\n  }\n  _inherits(SelectElement, _BaseElement);\n  return _createClass(SelectElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.select');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        items: this.items,\n        inputName: this.inputName\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(SelectElement, \"getData\", this, 3)([])), {}, {\n        inputName: this.inputName,\n        items: this.items\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [new _SelectControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.select_options'), this.items.map(function (item) {\n        return {\n          label: item.label,\n          value: item.value\n        };\n      }), {\n        setItems: function setItems(items) {\n          _this2.items = _this2.normalizeItems(items);\n          _this2.render();\n        },\n        setName: function setName(name) {\n          _this2.inputName = name;\n          _this2.render();\n        }\n      }, this.inputName),\n      // W3.8b — InnerPaddingControl (intrinsic: select input breathing room).\n      new InnerPaddingControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.select_padding'), {\n        top: this.formatter.getFormat(\"padding_top\"),\n        right: this.formatter.getFormat(\"padding_right\"),\n        bottom: this.formatter.getFormat(\"padding_bottom\"),\n        left: this.formatter.getFormat(\"padding_left\")\n      }, {\n        setValues: function setValues(values) {\n          _this2.formatter.setFormat(\"padding_top\", values.top);\n          _this2.formatter.setFormat(\"padding_right\", values.right);\n          _this2.formatter.setFormat(\"padding_bottom\", values.bottom);\n          _this2.formatter.setFormat(\"padding_left\", values.left);\n          _this2.render();\n        }\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), this.formatter.getFormat(\"width\"), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat(\"width\", value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 320,\n        minValue: 80,\n        maxValue: 1600,\n        suffix: \"px\",\n        allowZero: false\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), this.formatter.getFormat(\"height\"), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat(\"height\", value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 44,\n        minValue: 24,\n        maxValue: 400,\n        suffix: \"px\",\n        allowZero: false\n      })];\n    }\n  }, {\n    key: \"normalizeItems\",\n    value: function normalizeItems(items) {\n      return (Array.isArray(items) ? items : []).map(function (item, index) {\n        var _item$label, _item$value;\n        return {\n          label: (_item$label = item === null || item === void 0 ? void 0 : item.label) !== null && _item$label !== void 0 ? _item$label : \"Option \".concat(index + 1),\n          value: (_item$value = item === null || item === void 0 ? void 0 : item.value) !== null && _item$value !== void 0 ? _item$value : \"option_\".concat(index + 1)\n        };\n      });\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.inputName || \"\", data.items || []), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SelectElement.js?");

/***/ }),

/***/ "./src/includes/SelectWidget.js":
/*!**************************************!*\
  !*** ./src/includes/SelectWidget.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _SelectElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SelectElement.js */ \"./src/includes/SelectElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar SelectWidget = /*#__PURE__*/function (_BaseWidget) {\n  function SelectWidget() {\n    var _this;\n    _classCallCheck(this, SelectWidget);\n    _this = _callSuper(this, SelectWidget);\n    _this.block.appendElements([new _SelectElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Select', 'topic', [{\n      label: 'Choose an option',\n      value: ''\n    }, {\n      label: 'Starter',\n      value: 'starter'\n    }, {\n      label: 'Growth',\n      value: 'growth'\n    }, {\n      label: 'Enterprise',\n      value: 'enterprise'\n    }])]);\n    return _this;\n  }\n  _inherits(SelectWidget, _BaseWidget);\n  return _createClass(SelectWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.select');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'arrow_drop_down_circle';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SelectWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SelectWidget.js?");

/***/ }),

/***/ "./src/includes/SeparatorControl.js":
/*!******************************************!*\
  !*** ./src/includes/SeparatorControl.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * SeparatorControl — compact picker for a short divider glyph.\n *\n * Built for MenuElement, but reusable anywhere a user needs to pick\n * a short string separator (list bullets, breadcrumb dividers, etc.).\n *\n * UX: 6-slot segmented (None + 4 common glyphs + Custom). Picking\n * Custom reveals a compact 50%-width .bjs-text-input on its own row.\n *\n * No-flicker rule (2026-04-17 audit pass-4):\n *   - The DOM structure is built ONCE in the constructor.\n *   - The custom-input row stays mounted permanently; visibility is\n *     toggled via `hidden`/display, not by re-stamping innerHTML.\n *   - Clicks, keystrokes, and value changes only mutate\n *     classList / aria-checked / input.value — never rebuild the HTML.\n *   This keeps the text input's focus + caret position stable across\n *   every interaction, including typing, and stops the preset clicks\n *   from feeling twitchy.\n *\n * Value contract: `null`/`''` means \"no separator\". Any other string\n * is the raw glyph(s) to render between items.\n */\nvar SeparatorControl = /*#__PURE__*/function () {\n  function SeparatorControl(label, value, callback) {\n    _classCallCheck(this, SeparatorControl);\n    this.label = label;\n    this.value = value || null;\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    // Custom mode is a UX flag, not value-derived. Picking Custom with\n    // an empty string must still reveal the input; only clicking None /\n    // a preset turns custom mode off. Initial state: infer from value\n    // (non-preset non-null means we came in as custom).\n    this._customMode = !!this.value && !this._isPreset(this.value);\n    this._buildDom();\n    this._bindEvents();\n    this._syncDom();\n  }\n  return _createClass(SeparatorControl, [{\n    key: \"_isPreset\",\n    value: function _isPreset(v) {\n      if (v == null || v === '') return false;\n      return SeparatorControl.PRESETS.some(function (p) {\n        return p.value === v;\n      });\n    }\n  }, {\n    key: \"_buildDom\",\n    value: function _buildDom() {\n      var presetBtns = SeparatorControl.PRESETS.map(function (p) {\n        return \"<button class=\\\"bjs-segmented-btn\\\" type=\\\"button\\\" data-preset=\\\"\".concat(p.value, \"\\\" aria-label=\\\"\").concat(p.label, \"\\\" aria-checked=\\\"false\\\" role=\\\"radio\\\">\").concat(p.label, \"</button>\");\n      }).join('');\n\n      // Structure stays constant. Only classList/aria/input value/hidden\n      // attr change on subsequent interactions.\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <label class=\\\"bjs-control-label\\\">\".concat(this.label, \"</label>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n                        <button class=\\\"bjs-segmented-btn\\\" type=\\\"button\\\" data-action=\\\"none\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.none'), \"\\\" aria-checked=\\\"false\\\" role=\\\"radio\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.none'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">block</span>\\n                        </button>\\n                        \").concat(presetBtns, \"\\n                        <button class=\\\"bjs-segmented-btn\\\" type=\\\"button\\\" data-action=\\\"custom\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.custom'), \"\\\" aria-checked=\\\"false\\\" role=\\\"radio\\\" data-tooltip=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.custom'), \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">edit</span>\\n                        </button>\\n                    </div>\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-separator-custom-row\\\" hidden>\\n                <input\\n                    type=\\\"text\\\"\\n                    class=\\\"bjs-text-input bjs-separator-custom-input\\\"\\n                    data-control=\\\"custom-input\\\"\\n                    maxlength=\\\"8\\\"\\n                    placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.placeholder'), \"\\\"\\n                    aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('separator.custom'), \"\\\"\\n                />\\n            </div>\\n        \");\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      // Events bound ONCE on the mounted structure. Interactions mutate\n      // state + call _syncDom() — no innerHTML rewriting, no rebinding.\n      this.domNode.querySelectorAll('[data-preset]').forEach(function (btn) {\n        btn.addEventListener('click', function () {\n          _this._customMode = false;\n          _this.value = btn.dataset.preset;\n          _this._emit();\n          _this._syncDom();\n        });\n      });\n      var noneBtn = this.domNode.querySelector('[data-action=\"none\"]');\n      if (noneBtn) {\n        noneBtn.addEventListener('click', function () {\n          _this._customMode = false;\n          _this.value = null;\n          _this._emit();\n          _this._syncDom();\n        });\n      }\n      var customBtn = this.domNode.querySelector('[data-action=\"custom\"]');\n      if (customBtn) {\n        customBtn.addEventListener('click', function () {\n          _this._customMode = true;\n          if (_this._isPreset(_this.value)) _this.value = null;\n          // Intentionally NO _emit() here — clicking Custom is a\n          // UX mode switch, not a value change. The first keystroke\n          // in the input will emit the real value.\n          _this._syncDom();\n          var input = _this.domNode.querySelector('[data-control=\"custom-input\"]');\n          if (input) input.focus();\n        });\n      }\n      var customInput = this.domNode.querySelector('[data-control=\"custom-input\"]');\n      if (customInput) {\n        customInput.addEventListener('input', function (e) {\n          _this._customMode = true;\n          _this.value = e.target.value || null;\n          _this._emit();\n          // DO NOT touch the input's .value here (would reset caret).\n          // Only sync the active-chip state.\n          _this._syncActiveChip();\n        });\n      }\n    }\n\n    /** Full DOM sync — used on structural state changes (preset pick, None,\n     * Custom mode toggle). Does NOT rebuild HTML; only flips attributes /\n     * classes / hidden. Safe to call mid-focus. */\n  }, {\n    key: \"_syncDom\",\n    value: function _syncDom() {\n      this._syncActiveChip();\n      var customRow = this.domNode.querySelector('.bjs-separator-custom-row');\n      var customInput = this.domNode.querySelector('[data-control=\"custom-input\"]');\n      if (customRow) {\n        if (this._customMode) customRow.removeAttribute('hidden');else customRow.setAttribute('hidden', '');\n      }\n      if (customInput) {\n        // Only write back to input when we're NOT in an in-flight edit.\n        // Reading document.activeElement lets us skip the write while\n        // the user is actively typing; the input event keeps value and\n        // state in sync anyway.\n        if (document.activeElement !== customInput) {\n          var desired = this._customMode && typeof this.value === 'string' ? this.value : '';\n          if (customInput.value !== desired) customInput.value = desired;\n        }\n      }\n    }\n  }, {\n    key: \"_syncActiveChip\",\n    value: function _syncActiveChip() {\n      var val = this.value;\n      var customActive = this._customMode;\n      var presetActive = !customActive && this._isPreset(val);\n      this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        btn.classList.remove('is-active');\n        btn.setAttribute('aria-checked', 'false');\n      });\n      var activeBtn = customActive ? this.domNode.querySelector('[data-action=\"custom\"]') : presetActive ? this.domNode.querySelector(\"[data-preset=\\\"\".concat(CSS.escape(val), \"\\\"]\")) : this.domNode.querySelector('[data-action=\"none\"]');\n      if (activeBtn) {\n        activeBtn.classList.add('is-active');\n        activeBtn.setAttribute('aria-checked', 'true');\n      }\n    }\n  }, {\n    key: \"_emit\",\n    value: function _emit() {\n      if (this.callback && this.callback.setText) {\n        this.callback.setText(this.value);\n      }\n    }\n  }]);\n}();\n_defineProperty(SeparatorControl, \"PRESETS\", [{\n  value: '|',\n  label: '|'\n}, {\n  value: \"\\u2022\",\n  label: \"\\u2022\"\n},\n// •\n{\n  value: \"\\u2014\",\n  label: \"\\u2014\"\n},\n// —\n{\n  value: '/',\n  label: '/'\n}]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SeparatorControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SeparatorControl.js?");

/***/ }),

/***/ "./src/includes/SettingsTabManager.js":
/*!********************************************!*\
  !*** ./src/includes/SettingsTabManager.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ejs-browser */ \"./node_modules/ejs-browser/lib/ejs.js\");\n/* harmony import */ var ejs_browser__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ejs_browser__WEBPACK_IMPORTED_MODULE_0__);\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar SettingsTabManager = /*#__PURE__*/function () {\n  function SettingsTabManager(container) {\n    _classCallCheck(this, SettingsTabManager);\n    this.container = container;\n    this.tabs = [];\n  }\n  return _createClass(SettingsTabManager, [{\n    key: \"addTab\",\n    value: function addTab(name, label, icon) {\n      this.tabs.push({\n        name: name,\n        label: label,\n        icon: icon\n      });\n    }\n  }, {\n    key: \"openTab\",\n    value: function openTab(tabName) {\n      var _this = this;\n      this.tabs.forEach(function (tab) {\n        if (tab.name === tabName) {\n          _this.container.querySelector('[data-tab=\"' + tab.name + '\"]').classList.add('active');\n          _this.container.querySelector('[data-tab-container=\"' + tab.name + '\"]').style.display = 'block';\n        } else {\n          _this.container.querySelector('[data-tab=\"' + tab.name + '\"]').classList.remove('active');\n          _this.container.querySelector('[data-tab-container=\"' + tab.name + '\"]').style.display = 'none';\n        }\n      });\n    }\n  }, {\n    key: \"getTab\",\n    value: function getTab(tabName) {\n      var tab = this.tabs.find(function (t) {\n        return t.name === tabName;\n      });\n      return {\n        name: tab.name,\n        label: tab.label,\n        icon: tab.icon,\n        container: this.container.querySelector('[data-tab-container=\"' + tab.name + '\"]'),\n        button: this.container.querySelector('[data-tab=\"' + tab.name + '\"]')\n      };\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this2 = this;\n      this.container.innerHTML = \"\\n            <div class=\\\"builder-sidebar-tabs px-3 py-2 rounded-0 d-flex bg-light border-bottom\\\">\\n                \".concat(this.tabs.map(function (tab, idx) {\n        return \"\\n                    <div class=\\\"tab-item\\\" data-tab=\\\"\".concat(tab.name, \"\\\">\\n                        <span class=\\\"material-symbols-rounded\\\">\").concat(tab.icon, \"</span>\\n                        <!-- <span>\").concat(tab.label, \"</span> -->\\n                    </div>\\n                \");\n      }).join(''), \"\\n            </div>\\n            <div>\\n                \").concat(this.tabs.map(function (tab, idx) {\n        return \"\\n                    <div data-tab-container=\\\"\".concat(tab.name, \"\\\" style=\\\"display: none;\\\">\\n                    </div>\\n                \");\n      }).join(''), \"\\n            </div>\\n        \");\n\n      // \n      this.tabs.forEach(function (tab) {\n        _this2.getTab(tab.name).button.addEventListener('click', function () {\n          _this2.openTab(tab.name);\n        });\n      });\n\n      // @todo\n      document.querySelector('[data-tab=\"styles\"]').addEventListener('click', function () {\n        if (window.smenu) {\n          window.smenu.openTab(document.querySelector('[data-smenu=\"themes\"]'));\n        }\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SettingsTabManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SettingsTabManager.js?");

/***/ }),

/***/ "./src/includes/SocialIconsControl.js":
/*!********************************************!*\
  !*** ./src/includes/SocialIconsControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ui/sortable.js */ \"./src/includes/ui/sortable.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\nvar SocialIconsControl = /*#__PURE__*/function () {\n  function SocialIconsControl(label, items, iconPacks, callback) {\n    _classCallCheck(this, SocialIconsControl);\n    this.label = label;\n    this.items = items; // [{ image_url, label, url }]\n    this.iconPacks = iconPacks;\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this.render();\n  }\n  return _createClass(SocialIconsControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var platformOrder = ['facebook', 'instagram', 'linkedin', 'twitter', 'youtube', 'tiktok', 'pinterest'];\n      var allPresets = this.getPresets();\n\n      // Quick-add dropdown items\n      var dropdownItems = platformOrder.map(function (key) {\n        var p = allPresets[key];\n        if (!p) return '';\n        var icon = p.image_url ? \"<img src=\\\"\".concat(p.image_url, \"\\\" alt=\\\"\").concat(p.label, \"\\\">\") : '';\n        return \"<button class=\\\"bjs-list-dropdown-item\\\" type=\\\"button\\\" data-network=\\\"\".concat(key, \"\\\">\").concat(icon, \"<span>\").concat(p.label, \"</span></button>\");\n      }).join('');\n\n      // List items\n      var itemsHtml = this.items.map(function (item, index) {\n        var thumb = item.image_url ? \"<img src=\\\"\".concat(item.image_url, \"\\\" alt=\\\"\").concat(item.label || '', \"\\\">\") : \"<span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;color:var(--bjs-text-muted)\\\">image</span>\";\n        var displayName = _this.getDisplayName(item) || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.social_item');\n\n        // Platform chooser buttons\n        var platformsHtml = platformOrder.map(function (key) {\n          var p = allPresets[key];\n          if (!p) return '';\n          var icon = p.image_url ? \"<img src=\\\"\".concat(p.image_url, \"\\\" alt=\\\"\").concat(p.label, \"\\\">\") : '';\n          return \"<button class=\\\"bjs-list-platform-btn\\\" type=\\\"button\\\" data-platform=\\\"\".concat(key, \"\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(icon, \"<span>\").concat(p.label, \"</span></button>\");\n        }).join('');\n        var safeLabel = (item.label || '').replace(/\"/g, '&quot;');\n        var safeUrl = (item.url || '').replace(/\"/g, '&quot;');\n        return \"\\n                <li class=\\\"bjs-list-item\\\" data-index=\\\"\".concat(index, \"\\\" aria-expanded=\\\"false\\\">\\n                    <button class=\\\"bjs-list-item-handle\\\" aria-label=\\\"Drag to reorder\\\" type=\\\"button\\\" tabindex=\\\"0\\\">\\u2261</button>\\n                    <span class=\\\"bjs-list-item-thumb\\\" data-control=\\\"thumb\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(thumb, \"</span>\\n                    <span class=\\\"bjs-list-item-label\\\" data-control=\\\"display-label\\\" data-index=\\\"\").concat(index, \"\\\">\").concat(displayName, \"</span>\\n                    <div class=\\\"bjs-list-item-actions\\\">\\n                        <button class=\\\"bjs-icon-btn bjs-list-item-expand\\\" aria-label=\\\"Edit\\\" data-control=\\\"expand\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n                        </button>\\n                        <button class=\\\"bjs-icon-btn\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.move_up'), \"\\\" data-control=\\\"move-up\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">arrow_upward</span>\\n                        </button>\\n                        <button class=\\\"bjs-icon-btn\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.move_down'), \"\\\" data-control=\\\"move-down\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">arrow_downward</span>\\n                        </button>\\n                        <button class=\\\"bjs-icon-btn bjs-icon-btn--danger\\\" aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.delete_item'), \"\\\" data-control=\\\"remove-item\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            <span class=\\\"material-symbols-rounded\\\">delete</span>\\n                        </button>\\n                    </div>\\n                    <section class=\\\"bjs-list-item-body\\\">\\n                        <div class=\\\"bjs-list-platforms\\\" data-control=\\\"platforms\\\" data-index=\\\"\").concat(index, \"\\\">\\n                            \").concat(platformsHtml, \"\\n                        </div>\\n                        <div class=\\\"bjs-list-field\\\">\\n                            <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.label'), \"</label>\\n                            <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" placeholder=\\\"Facebook\\\" value=\\\"\").concat(safeLabel, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"label\\\">\\n                        </div>\\n                        <div class=\\\"bjs-list-field\\\">\\n                            <label class=\\\"bjs-list-field-label\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.url_label'), \"</label>\\n                            <input type=\\\"text\\\" class=\\\"bjs-list-field-input\\\" placeholder=\\\"https://facebook.com/yourpage\\\" value=\\\"\").concat(safeUrl, \"\\\" data-index=\\\"\").concat(index, \"\\\" data-field=\\\"url\\\">\\n                        </div>\\n                    </section>\\n                </li>\\n            \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-list bjs-list--social\\\">\\n                <header class=\\\"bjs-list-header\\\">\\n                    <span class=\\\"bjs-list-title\\\">\".concat(this.label, \"</span>\\n                    <div class=\\\"bjs-list-add\\\">\\n                        <button class=\\\"bjs-btn\\\" type=\\\"button\\\" data-control=\\\"add-item\\\">\\n                            <span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;margin-right:2px\\\">add</span> \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.add'), \"\\n                        </button>\\n                        <div class=\\\"bjs-list-dropdown\\\">\\n                            <button class=\\\"bjs-btn bjs-btn-caret\\\" type=\\\"button\\\" data-control=\\\"dropdown-toggle\\\" aria-label=\\\"Quick add presets\\\">\\n                                <span class=\\\"material-symbols-rounded\\\">expand_more</span>\\n                            </button>\\n                            <div class=\\\"bjs-list-dropdown-menu\\\" data-control=\\\"dropdown-menu\\\">\\n                                \").concat(dropdownItems, \"\\n                            </div>\\n                        </div>\\n                    </div>\\n                </header>\\n                <ol class=\\\"bjs-list-items\\\">\\n                    \").concat(itemsHtml, \"\\n                </ol>\\n            </div>\\n        \");\n      this._autoFixPresets();\n      this._bindEvents();\n      this._bindSortable();\n    }\n\n    /** Phase-3 W6.2 — drag-reorder via shared bjsSortable mixin. The\n     *  per-item up/down buttons stay as an a11y fallback (keyboard-first)\n     *  but pointer users get a proper drag-and-drop. */\n  }, {\n    key: \"_bindSortable\",\n    value: function _bindSortable() {\n      var _this2 = this;\n      if (this._sortable && typeof this._sortable.destroy === 'function') {\n        try {\n          this._sortable.destroy();\n        } catch (_e) {}\n      }\n      var ol = this.domNode.querySelector('.bjs-list-items');\n      if (!ol) return;\n      this._sortable = (0,_ui_sortable_js__WEBPACK_IMPORTED_MODULE_1__.bjsSortable)(ol, {\n        itemSelector: '.bjs-list-item',\n        handleSelector: '.bjs-list-item-handle',\n        onReorder: function onReorder(from, to) {\n          var _this2$items$splice = _this2.items.splice(from, 1),\n            _this2$items$splice2 = _slicedToArray(_this2$items$splice, 1),\n            moved = _this2$items$splice2[0];\n          var adjusted = to > from ? to - 1 : to;\n          _this2.items.splice(adjusted, 0, moved);\n          _this2.render();\n          _this2.callback && _this2.callback.setItems(_this2.items);\n        }\n      });\n    }\n  }, {\n    key: \"_autoFixPresets\",\n    value: function _autoFixPresets() {\n      var _this3 = this;\n      var mutated = false;\n      this.items.forEach(function (item) {\n        try {\n          var preset = _this3.getPresetByUrl(item.url || '') || _this3.getPresetByLabel(item.label || '') || _this3.getPresetByImageUrl(item.image_url || '');\n          if (preset) {\n            if (!item.image_url || _this3.isDefaultThemeIconUrl(item.image_url)) {\n              item.image_url = preset.image_url;\n              mutated = true;\n            }\n            if (!item.label) {\n              item.label = preset.label;\n              mutated = true;\n            }\n          }\n        } catch (_) {}\n      });\n      if (mutated) {\n        this.callback && this.callback.setItems(this.items);\n      }\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this4 = this;\n      // Add item\n      var addBtn = this.domNode.querySelector('[data-control=\"add-item\"]');\n      if (addBtn) {\n        addBtn.addEventListener('click', function () {\n          _this4.items.push({\n            image_url: '',\n            label: '',\n            url: ''\n          });\n          _this4.render();\n          _this4.callback && _this4.callback.setItems(_this4.items);\n        });\n      }\n\n      // Dropdown toggle\n      var dropdownToggle = this.domNode.querySelector('[data-control=\"dropdown-toggle\"]');\n      var dropdownMenu = this.domNode.querySelector('[data-control=\"dropdown-menu\"]');\n      if (dropdownToggle && dropdownMenu) {\n        dropdownToggle.addEventListener('click', function (e) {\n          e.stopPropagation();\n          dropdownMenu.classList.toggle('is-open');\n        });\n        // Close on outside click\n        var closeDropdown = function closeDropdown(e) {\n          if (!dropdownMenu.contains(e.target) && e.target !== dropdownToggle) {\n            dropdownMenu.classList.remove('is-open');\n          }\n        };\n        document.addEventListener('click', closeDropdown);\n        // Store cleanup ref\n        this._cleanupDropdown = function () {\n          return document.removeEventListener('click', closeDropdown);\n        };\n      }\n\n      // Quick-add presets from dropdown\n      this.domNode.querySelectorAll('.bjs-list-dropdown-item[data-network]').forEach(function (btn) {\n        btn.addEventListener('click', function (e) {\n          var network = e.currentTarget.dataset.network;\n          var p = _this4.getPresets()[network];\n          if (!p) return;\n          _this4.items.push({\n            image_url: p.image_url,\n            label: p.label,\n            url: p.url\n          });\n          dropdownMenu && dropdownMenu.classList.remove('is-open');\n          _this4.render();\n          _this4.callback && _this4.callback.setItems(_this4.items);\n        });\n      });\n\n      // Per-item events\n      this.domNode.querySelectorAll('.bjs-list-item').forEach(function (li) {\n        var _li$querySelector, _li$querySelector2, _li$querySelector3;\n        var index = parseInt(li.dataset.index, 10);\n\n        // Expand/collapse\n        var expandBtn = li.querySelector('[data-control=\"expand\"]');\n        if (expandBtn) {\n          expandBtn.addEventListener('click', function (e) {\n            e.preventDefault();\n            var isExpanded = li.getAttribute('aria-expanded') === 'true';\n            // Collapse all others\n            _this4.domNode.querySelectorAll('.bjs-list-item').forEach(function (other) {\n              other.setAttribute('aria-expanded', 'false');\n            });\n            if (!isExpanded) {\n              li.setAttribute('aria-expanded', 'true');\n            }\n          });\n        }\n\n        // Remove\n        (_li$querySelector = li.querySelector('[data-control=\"remove-item\"]')) === null || _li$querySelector === void 0 || _li$querySelector.addEventListener('click', function (e) {\n          e.preventDefault();\n          _this4.items.splice(index, 1);\n          _this4.render();\n          _this4.callback && _this4.callback.setItems(_this4.items);\n        });\n\n        // Move up\n        (_li$querySelector2 = li.querySelector('[data-control=\"move-up\"]')) === null || _li$querySelector2 === void 0 || _li$querySelector2.addEventListener('click', function (e) {\n          e.preventDefault();\n          if (index > 0) {\n            var _ref = [_this4.items[index], _this4.items[index - 1]];\n            _this4.items[index - 1] = _ref[0];\n            _this4.items[index] = _ref[1];\n            _this4.render();\n            _this4.callback && _this4.callback.setItems(_this4.items);\n          }\n        });\n\n        // Move down\n        (_li$querySelector3 = li.querySelector('[data-control=\"move-down\"]')) === null || _li$querySelector3 === void 0 || _li$querySelector3.addEventListener('click', function (e) {\n          e.preventDefault();\n          if (index < _this4.items.length - 1) {\n            var _ref2 = [_this4.items[index], _this4.items[index + 1]];\n            _this4.items[index + 1] = _ref2[0];\n            _this4.items[index] = _ref2[1];\n            _this4.render();\n            _this4.callback && _this4.callback.setItems(_this4.items);\n          }\n        });\n\n        // Platform quick-apply buttons\n        li.querySelectorAll('.bjs-list-platform-btn[data-platform]').forEach(function (btn) {\n          btn.addEventListener('click', function (e) {\n            var key = e.currentTarget.dataset.platform;\n            var p = _this4.getPresets()[key];\n            if (!p) return;\n            _this4.items[index].label = p.label;\n            _this4.items[index].url = p.url;\n            _this4.items[index].image_url = p.image_url;\n            // Update in-place without full re-render\n            _this4._updateItemDisplay(li, index);\n            _this4.callback && _this4.callback.setItems(_this4.items);\n          });\n        });\n\n        // Text input live updates\n        li.querySelectorAll('input[data-field]').forEach(function (input) {\n          input.addEventListener('input', function (e) {\n            var field = e.target.dataset.field;\n            _this4.items[index][field] = e.target.value;\n            _this4._updateDisplayLabel(li, index);\n            _this4.callback && _this4.callback.setItems(_this4.items);\n          });\n\n          // URL blur: normalize + infer preset\n          if (input.dataset.field === 'url') {\n            input.addEventListener('blur', function (e) {\n              var url = (e.target.value || '').trim();\n              var changed = false;\n              if (url && !/^https?:\\/\\//i.test(url)) {\n                url = 'https://' + url;\n                e.target.value = url;\n                _this4.items[index].url = url;\n                changed = true;\n              }\n              var preset = _this4.getPresetByUrl(url);\n              if (preset) {\n                if (!_this4.items[index].image_url || _this4.isDefaultThemeIconUrl(_this4.items[index].image_url)) {\n                  _this4.items[index].image_url = preset.image_url;\n                  changed = true;\n                }\n                if (!_this4.items[index].label) {\n                  _this4.items[index].label = preset.label;\n                  var labelInput = li.querySelector('input[data-field=\"label\"]');\n                  if (labelInput) labelInput.value = preset.label;\n                  changed = true;\n                }\n              }\n              if (changed) {\n                _this4._updateItemDisplay(li, index);\n                _this4.callback && _this4.callback.setItems(_this4.items);\n              }\n            });\n          }\n        });\n      });\n    }\n  }, {\n    key: \"_updateItemDisplay\",\n    value: function _updateItemDisplay(li, index) {\n      var item = this.items[index];\n      // Update thumb\n      var thumbEl = li.querySelector('[data-control=\"thumb\"]');\n      if (thumbEl) {\n        thumbEl.innerHTML = item.image_url ? \"<img src=\\\"\".concat(item.image_url, \"\\\" alt=\\\"\").concat(item.label || '', \"\\\">\") : \"<span class=\\\"material-symbols-rounded\\\" style=\\\"font-size:16px;color:var(--bjs-text-muted)\\\">image</span>\";\n      }\n      // Update label\n      this._updateDisplayLabel(li, index);\n      // Update form inputs\n      var labelInput = li.querySelector('input[data-field=\"label\"]');\n      if (labelInput && labelInput.value !== item.label) labelInput.value = item.label || '';\n      var urlInput = li.querySelector('input[data-field=\"url\"]');\n      if (urlInput && urlInput.value !== item.url) urlInput.value = item.url || '';\n    }\n  }, {\n    key: \"_updateDisplayLabel\",\n    value: function _updateDisplayLabel(li, index) {\n      var item = this.items[index];\n      var labelEl = li.querySelector('[data-control=\"display-label\"]');\n      if (labelEl) {\n        labelEl.textContent = this.getDisplayName(item) || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('social.social_item');\n      }\n    }\n\n    // Derive a friendly name for the item based on label or URL\n  }, {\n    key: \"getDisplayName\",\n    value: function getDisplayName(item) {\n      var label = (item.label || '').trim();\n      if (label) return label;\n      var url = (item.url || '').trim().toLowerCase();\n      if (!url) return '';\n      try {\n        var u = new URL(url.startsWith('http') ? url : \"https://\".concat(url));\n        var host = u.hostname.replace('www.', '');\n        var map = {\n          'facebook.com': 'Facebook',\n          'fb.com': 'Facebook',\n          'instagram.com': 'Instagram',\n          'twitter.com': 'Twitter',\n          'x.com': 'X',\n          'linkedin.com': 'LinkedIn',\n          'youtube.com': 'YouTube',\n          'tiktok.com': 'TikTok',\n          'pinterest.com': 'Pinterest',\n          'threads.net': 'Threads',\n          'snapchat.com': 'Snapchat',\n          'whatsapp.com': 'WhatsApp',\n          'telegram.me': 'Telegram',\n          't.me': 'Telegram'\n        };\n        return map[host] || host;\n      } catch (_) {\n        return '';\n      }\n    }\n  }, {\n    key: \"getPresets\",\n    value: function getPresets() {\n      return this.iconPacks;\n    }\n  }, {\n    key: \"isDefaultThemeIconUrl\",\n    value: function isDefaultThemeIconUrl(url) {\n      if (!url) return false;\n      return /image\\/(BurgerCraft_theme|social_theme)\\/.*(facebook|twitter|linkedin|instagram|pinterest|youtube|tiktok).*\\.(png|jpg|jpeg|gif)$/i.test(url);\n    }\n  }, {\n    key: \"getPresetByLabel\",\n    value: function getPresetByLabel(label) {\n      if (!label) return null;\n      var key = label.trim().toLowerCase();\n      var map = {\n        facebook: 'facebook',\n        instagram: 'instagram',\n        linkedin: 'linkedin',\n        twitter: 'twitter',\n        x: 'twitter',\n        'twitter / x': 'twitter',\n        youtube: 'youtube',\n        tiktok: 'tiktok',\n        pinterest: 'pinterest'\n      };\n      var k = map[key];\n      return k ? this.getPresets()[k] || null : null;\n    }\n  }, {\n    key: \"getPresetByImageUrl\",\n    value: function getPresetByImageUrl(imageUrl) {\n      if (!imageUrl) return null;\n      var lower = imageUrl.toLowerCase();\n      var pairs = [['facebook', 'facebook'], ['instagram', 'instagram'], ['linkedin', 'linkedin'], ['twitter', 'twitter'], ['/x.', 'twitter'], ['-x.', 'twitter'], ['youtube', 'youtube'], ['youtu', 'youtube'], ['tiktok', 'tiktok'], ['pinterest', 'pinterest']];\n      for (var _i = 0, _pairs = pairs; _i < _pairs.length; _i++) {\n        var _pairs$_i = _slicedToArray(_pairs[_i], 2),\n          needle = _pairs$_i[0],\n          key = _pairs$_i[1];\n        if (lower.includes(needle)) return this.getPresets()[key] || null;\n      }\n      return null;\n    }\n  }, {\n    key: \"getPresetByUrl\",\n    value: function getPresetByUrl(url) {\n      if (!url) return null;\n      try {\n        var u = new URL(url.startsWith('http') ? url : \"https://\".concat(url));\n        var host = u.hostname.replace(/^www\\./i, '');\n        var map = {\n          'facebook.com': 'facebook',\n          'fb.com': 'facebook',\n          'instagram.com': 'instagram',\n          'linkedin.com': 'linkedin',\n          'twitter.com': 'twitter',\n          'x.com': 'twitter',\n          'youtube.com': 'youtube',\n          'youtu.be': 'youtube',\n          'tiktok.com': 'tiktok',\n          'pinterest.com': 'pinterest'\n        };\n        var key = map[host];\n        return key ? this.getPresets()[key] || null : null;\n      } catch (_) {\n        return null;\n      }\n    }\n  }, {\n    key: \"browserAndUpload\",\n    value: function browserAndUpload(itemIndex) {\n      var _this5 = this;\n      var input = document.createElement('input');\n      input.type = 'file';\n      input.accept = 'image/*';\n      input.addEventListener('change', /*#__PURE__*/function () {\n        var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {\n          var file, formData, response, result;\n          return _regeneratorRuntime().wrap(function _callee$(_context) {\n            while (1) switch (_context.prev = _context.next) {\n              case 0:\n                file = event.target.files[0];\n                if (file) {\n                  _context.next = 3;\n                  break;\n                }\n                return _context.abrupt(\"return\");\n              case 3:\n                formData = new FormData();\n                formData.append('file', file);\n                _context.prev = 5;\n                _context.next = 8;\n                return fetch(_this5.host.assetUploadHandler, {\n                  method: 'POST',\n                  body: formData\n                });\n              case 8:\n                response = _context.sent;\n                if (!response.ok) {\n                  _context.next = 14;\n                  break;\n                }\n                _context.next = 12;\n                return response.json();\n              case 12:\n                result = _context.sent;\n                if (result.url) {\n                  _this5.items[itemIndex].image_url = result.url;\n                  _this5.render();\n                  _this5.callback && _this5.callback.setItems(_this5.items);\n                }\n              case 14:\n                _context.next = 19;\n                break;\n              case 16:\n                _context.prev = 16;\n                _context.t0 = _context[\"catch\"](5);\n                console.error('Error uploading file:', _context.t0);\n              case 19:\n              case \"end\":\n                return _context.stop();\n            }\n          }, _callee, null, [[5, 16]]);\n        }));\n        return function (_x) {\n          return _ref3.apply(this, arguments);\n        };\n      }());\n      input.click();\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SocialIconsControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SocialIconsControl.js?");

/***/ }),

/***/ "./src/includes/SocialIconsElement.js":
/*!********************************************!*\
  !*** ./src/includes/SocialIconsElement.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\n/* harmony import */ var _SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./SocialIconsControl.js */ \"./src/includes/SocialIconsControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\nvar SocialIconsElement = /*#__PURE__*/function (_BaseElement) {\n  function SocialIconsElement(template, items) {\n    var _this2;\n    _classCallCheck(this, SocialIconsElement);\n    // [{image_LINK: '', link: '', label: '' }, ]\n    _this2 = _callSuper(this, SocialIconsElement); // Call the parent class constructor\n    _this2.template = template;\n    _this2.items = items;\n\n    // required keys for the element template\n    _this2.requiredTemplateKeys = ['items'];\n\n    // Formatter\n    _this2.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n      background_color: null,\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      // padding\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null\n    });\n\n    // more settings\n    _this2.size = 30;\n    _this2.gap = 10;\n    _this2.align = 'center';\n    return _this2;\n  }\n  _inherits(SocialIconsElement, _BaseElement);\n  return _createClass(SocialIconsElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.social_icons');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c). Resolve relative image URLs to absolute.\n      var _this = this;\n      this.domNode.innerHTML = this.renderTemplate({\n        items: this.items.map(function (item) {\n          return _objectSpread(_objectSpread({}, item), {}, {\n            image_url: _this.transferMediaAbsUrl(item.image_url)\n          });\n        }),\n        size: this.size,\n        gap: this.gap,\n        align: this.align\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(SocialIconsElement, \"getData\", this, 3)([])), {}, {\n        items: this.items,\n        size: this.size,\n        gap: this.gap,\n        align: this.align\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this3 = this;\n      var _this = this;\n      return [new _SocialIconsControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](\n      // \n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.icons_items_list'),\n      // current items\n      this.items.map(function (item) {\n        return {\n          image_url: _this.transferMediaAbsUrl(item.image_url),\n          // transform relative url to absolutes one\n          label: item.label,\n          url: item.link\n          // description: null\n        };\n      }),\n      // icons packs — getControls() runs post-mount, so this.host is\n      // guaranteed set; transferMediaAbsUrl resolves relative theme\n      // asset paths to per-instance absolute URLs.\n      {\n        facebook: {\n          label: 'Facebook',\n          url: 'https://facebook.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/facebook.png')\n        },\n        twitter: {\n          label: 'Twitter',\n          url: 'https://twitter.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/twitter.png')\n        },\n        instagram: {\n          label: 'Instagram',\n          url: 'https://instagram.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/instagram.png')\n        },\n        linkedin: {\n          label: 'LinkedIn',\n          url: 'https://linkedin.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/linkedin.png')\n        },\n        youtube: {\n          label: 'YouTube',\n          url: 'https://youtube.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/youtube.png')\n        },\n        pinterest: {\n          label: 'Pinterest',\n          url: 'https://pinterest.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/pinterest.png')\n        },\n        tiktok: {\n          label: 'TikTok',\n          url: 'https://tiktok.com',\n          image_url: _this.transferMediaAbsUrl('master/assets/image/icons/tiktok.png')\n        }\n      },\n      // callback\n      {\n        setItems: function setItems(items) {\n          _this.items = items.map(function (item) {\n            return {\n              image_url: item.image_url,\n              label: item.label,\n              link: item.url\n            };\n          });\n          _this.render();\n        } // more callbacks\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.align, {\n        setValue: function setValue(value) {\n          _this3.align = value;\n          _this3.render();\n        }\n      }, ['left', 'center', 'right']), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.icon_gap'), this.gap, {\n        setValue: function setValue(value) {\n          _this3.gap = value;\n          _this3.render();\n        }\n      }, {\n        defaultValue: 16,\n        minValue: 0,\n        maxValue: 200,\n        suffix: 'px',\n        allowZero: false\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.icon_size'), this.size, {\n        setValue: function setValue(value) {\n          _this3.size = value;\n          _this3.render();\n        }\n      }, {\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 200,\n        suffix: 'px',\n        allowZero: false\n      })\n\n      // W3.8b — PaddingMarginControl removed. Social icons are\n      // content inside a Block; parent Block.padding handles layout.\n      ];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var items = Array.isArray(data.items) ? data.items : [];\n      var el = new SocialIconsElement(data.template, items);\n      el.size = data.size || 30;\n      el.gap = data.gap || 10;\n      el.align = data.align || 'center';\n      return this.parseFormats(el, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SocialIconsElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SocialIconsElement.js?");

/***/ }),

/***/ "./src/includes/StyleControl.js":
/*!**************************************!*\
  !*** ./src/includes/StyleControl.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * StyleControl — compact trigger button + popover with thumbnail tiles.\n *\n * The panel row shows a current-style button (label + mini thumb + chevron).\n * Click opens a popover with all available styles rendered in a 3-column\n * grid of small (~80px) thumbnail tiles. Selecting a tile closes the popover.\n *\n * Keyboard: Enter/Space opens the dropdown, Arrow keys navigate tiles, Enter\n * selects and closes, Esc closes. ARIA: trigger=button w/ aria-haspopup,\n * popover=radiogroup with aria-checked on the current tile.\n *\n * Used by: PricingCardsElement (10 style presets). Reusable for any \"pick a\n * visual variant\" situation where compact panel space matters.\n */\nvar StyleControl = /*#__PURE__*/function () {\n  function StyleControl(label, value, options, callback) {\n    var config = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n    _classCallCheck(this, StyleControl);\n    this.label = label;\n    this.value = value;\n    this.options = Array.isArray(options) ? options : [];\n    this.callback = callback;\n    this.isOpen = false;\n    this.id = '_' + Math.random().toString(36).slice(2, 9);\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-style-control');\n    this._documentClickHandler = null;\n    this._documentKeydownHandler = null;\n    this.render();\n  }\n  return _createClass(StyleControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var current = this._currentOption();\n      var currentLabel = current ? current.label : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('pricing.style_label');\n      var currentThumb = current ? current.thumb : '';\n\n      // Inline caret SVG — avoids Material Symbols font dependency\n      var caretSvg = '<svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" aria-hidden=\"true\" style=\"display:block\"><path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>';\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row\\\">\\n                <label class=\\\"bjs-control-label\\\">\".concat(this._esc(this.label), \"</label>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <button\\n                        type=\\\"button\\\"\\n                        class=\\\"bjs-style-trigger\\\"\\n                        aria-haspopup=\\\"listbox\\\"\\n                        aria-expanded=\\\"\").concat(this.isOpen ? 'true' : 'false', \"\\\"\\n                        data-control=\\\"style-trigger\\\"\\n                        id=\\\"style-trigger-\").concat(this.id, \"\\\"\\n                    >\\n                        <span class=\\\"bjs-style-trigger-thumb\\\" aria-hidden=\\\"true\\\">\").concat(currentThumb, \"</span>\\n                        <span class=\\\"bjs-style-trigger-label\\\">\").concat(this._esc(currentLabel), \"</span>\\n                        <span class=\\\"bjs-style-trigger-caret\\\" aria-hidden=\\\"true\\\">\").concat(caretSvg, \"</span>\\n                    </button>\\n                </div>\\n            </div>\\n            <div\\n                class=\\\"bjs-style-popover\").concat(this.isOpen ? ' is-open' : '', \"\\\"\\n                role=\\\"radiogroup\\\"\\n                aria-labelledby=\\\"style-trigger-\").concat(this.id, \"\\\"\\n                data-control=\\\"style-popover\\\"\\n            >\\n                \").concat(this.options.map(function (opt) {\n        var checked = opt.key === _this.value ? 'true' : 'false';\n        return \"\\n                        <button\\n                            type=\\\"button\\\"\\n                            class=\\\"bjs-style-tile\\\"\\n                            role=\\\"radio\\\"\\n                            aria-checked=\\\"\".concat(checked, \"\\\"\\n                            data-key=\\\"\").concat(_this._esc(opt.key), \"\\\"\\n                            tabindex=\\\"\").concat(checked === 'true' ? '0' : '-1', \"\\\"\\n                        >\\n                            <span class=\\\"bjs-style-tile-thumb\\\" aria-hidden=\\\"true\\\">\").concat(opt.thumb || '', \"</span>\\n                            <span class=\\\"bjs-style-tile-label\\\">\").concat(_this._esc(opt.label), \"</span>\\n                        </button>\\n                    \");\n      }).join(''), \"\\n            </div>\\n        \");\n      this._bind();\n    }\n  }, {\n    key: \"_currentOption\",\n    value: function _currentOption() {\n      var _this2 = this;\n      return this.options.find(function (o) {\n        return o.key === _this2.value;\n      }) || this.options[0] || null;\n    }\n  }, {\n    key: \"_bind\",\n    value: function _bind() {\n      var _this3 = this;\n      var trigger = this.domNode.querySelector('[data-control=\"style-trigger\"]');\n      var popover = this.domNode.querySelector('[data-control=\"style-popover\"]');\n      if (!trigger || !popover) return;\n      trigger.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this3._toggle();\n      });\n      var tiles = Array.from(popover.querySelectorAll('.bjs-style-tile'));\n      tiles.forEach(function (tile, idx) {\n        tile.addEventListener('click', function (e) {\n          e.preventDefault();\n          _this3._select(tile.dataset.key);\n          _this3._close();\n        });\n        tile.addEventListener('keydown', function (e) {\n          var cols = 3;\n          var target = null;\n          if (e.key === 'ArrowRight') target = tiles[(idx + 1) % tiles.length];else if (e.key === 'ArrowLeft') target = tiles[(idx - 1 + tiles.length) % tiles.length];else if (e.key === 'ArrowDown') target = tiles[Math.min(idx + cols, tiles.length - 1)];else if (e.key === 'ArrowUp') target = tiles[Math.max(idx - cols, 0)];else if (e.key === 'Enter' || e.key === ' ') {\n            _this3._select(tile.dataset.key);\n            _this3._close();\n            e.preventDefault();\n            return;\n          } else if (e.key === 'Escape') {\n            _this3._close();\n            trigger.focus();\n            e.preventDefault();\n            return;\n          }\n          if (target) {\n            e.preventDefault();\n            target.focus();\n          }\n        });\n      });\n    }\n  }, {\n    key: \"_toggle\",\n    value: function _toggle() {\n      if (this.isOpen) this._close();else this._open();\n    }\n  }, {\n    key: \"_open\",\n    value: function _open() {\n      var _this4 = this;\n      this.isOpen = true;\n      this.render();\n      // Focus current tile for keyboard users\n      var active = this.domNode.querySelector('.bjs-style-tile[aria-checked=\"true\"]') || this.domNode.querySelector('.bjs-style-tile');\n      if (active) active.focus();\n\n      // Outside click / Esc to close\n      this._documentClickHandler = function (e) {\n        if (!_this4.domNode.contains(e.target)) _this4._close();\n      };\n      this._documentKeydownHandler = function (e) {\n        if (e.key === 'Escape') _this4._close();\n      };\n      document.addEventListener('click', this._documentClickHandler);\n      document.addEventListener('keydown', this._documentKeydownHandler);\n    }\n  }, {\n    key: \"_close\",\n    value: function _close() {\n      if (!this.isOpen) return;\n      this.isOpen = false;\n      this.render();\n      if (this._documentClickHandler) document.removeEventListener('click', this._documentClickHandler);\n      if (this._documentKeydownHandler) document.removeEventListener('keydown', this._documentKeydownHandler);\n      this._documentClickHandler = null;\n      this._documentKeydownHandler = null;\n    }\n  }, {\n    key: \"_select\",\n    value: function _select(key) {\n      if (this.value === key) return;\n      this.value = key;\n      this.callback && this.callback.setValue && this.callback.setValue(key);\n      // Trigger + tiles will be fresh on next render (invoked by _close)\n    }\n  }, {\n    key: \"setValue\",\n    value: function setValue(value) {\n      this.value = value;\n      this.render();\n    }\n  }, {\n    key: \"_esc\",\n    value: function _esc(s) {\n      return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StyleControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/StyleControl.js?");

/***/ }),

/***/ "./src/includes/StylePickerControl.js":
/*!********************************************!*\
  !*** ./src/includes/StylePickerControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseControl_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BaseControl.js */ \"./src/includes/BaseControl.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * StylePickerControl — compound sidebar control rendering a \"Style\"\n * preview card (preset thumbnail + name + category + Change button).\n * The Change button enters the element's 'style-picker' edit mode so\n * `ButtonPresetPickerOverlay` mounts as an anchored popover next to\n * the (newly stashed) anchor rect.\n *\n * Sits in the FIRST slot of `ButtonElement.getControls()` so the user\n * sees a one-click identity swap before the granular size / radius /\n * shadow / hover / icon / width modifier rows. The click anchor is the\n * Change button itself — `_lastActionAnchorRect` stash mirrors how\n * `ButtonActionsOverlay._openLinkEditor` anchors the LinkPopover.\n *\n * Dual-view sync (SA I13)\n * ───────────────────────\n *   The element's `notifySyncListeners()` fires whenever preset_id /\n *   size_key / shadow / hover_effect / icon mutate (from the picker\n *   overlay, programmatic loads, etc.). We subscribe via the standard\n *   capability-token pattern so the summary card stays consistent\n *   without a full `renderElementControls()` rebuild.\n *\n * Destroy\n * ───────\n *   Extends BaseControl → addDisposer registers the subscribe-token\n *   teardown. `Builder.renderElementControls` calls destroy() on every\n *   outgoing control before rebuilding, so the listener auto-cleans\n *   when the user selects a different element.\n */\n\n\n\n\n\nvar StylePickerControl = /*#__PURE__*/function (_BaseControl) {\n  function StylePickerControl(element) {\n    var _this;\n    _classCallCheck(this, StylePickerControl);\n    _this = _callSuper(this, StylePickerControl);\n    _this.id = '_' + Math.random().toString(36).substr(2, 9);\n    _this.element = element;\n    _this.domNode = document.createElement('div');\n    _this.render();\n\n    // Re-render on element-side preset / size / shadow / hover / icon mutations\n    // so the summary card always reflects current state.\n    _this.bindSyncListener(element, 'StylePickerControl:' + _this.id, function () {\n      _this._refresh();\n    });\n    return _this;\n  }\n\n  /* ─── Public API ─── */\n  _inherits(StylePickerControl, _BaseControl);\n  return _createClass(StylePickerControl, [{\n    key: \"setValue\",\n    value: function setValue() {/* no-op — this control reads off the element directly */}\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.element ? this.element.preset_id : null;\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    /* ─── Internals ─── */\n  }, {\n    key: \"_currentPreset\",\n    value: function _currentPreset() {\n      var id = this.element && this.element.preset_id;\n      return (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.findPreset)(id);\n    }\n  }, {\n    key: \"_categoryLabel\",\n    value: function _categoryLabel(catId) {\n      var cat = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.CATEGORIES.find(function (c) {\n        return c.id === catId;\n      });\n      return cat ? cat.label : catId;\n    }\n  }, {\n    key: \"_summaryLine\",\n    value: function _summaryLine(preset) {\n      if (!preset) {\n        // No preset applied — element is on raw formatter values\n        return _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.custom_summary', 'Custom · advanced');\n      }\n      var cat = this._categoryLabel(preset.category);\n      var size = this.element && this.element.size_key || 'md';\n      // Compact format — keeps the truncation ellipsis at bay in the\n      // narrow .bp-style-meta column. \"Solid · LG\" reads cleaner than\n      // \"Solid · LG size\" once truncated.\n      return \"\".concat(cat, \" \\xB7 \").concat(size.toUpperCase());\n    }\n  }, {\n    key: \"_name\",\n    value: function _name(preset) {\n      if (!preset) return _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.custom_name', 'Custom');\n      return preset.label;\n    }\n\n    /**\n     * Render the live preview thumbnail for the Style summary card.\n     *\n     * IMPORTANT: reads from `element.formatter.formats` (LIVE state),\n     * NOT from `preset.formats` (preset's original snapshot). This way\n     * any per-button customisation (custom border, hand-tuned color,\n     * Advanced-section override, picking an already-customised button on\n     * the page, etc.) is faithfully reflected in the sidebar preview.\n     * The preset object is only consulted for icon/iconPosition + name —\n     * the actual paint always tracks the live formatter.\n     *\n     * Edge case (`preset == null`) — element has no preset_id (raw / fully\n     * custom). We STILL use the live formatter, just label it \"Custom\" via\n     * the meta line. The thumbnail stays accurate.\n     */\n  }, {\n    key: \"_renderThumb\",\n    value: function _renderThumb(preset) {\n      var text = this.element && this.element.text || 'Click Me';\n      var f = this.element && this.element.formatter && this.element.formatter.formats || {};\n      var icon = this.element && this.element.icon || preset && preset.icon || null;\n      var iconPosition = this.element && this.element.icon_position || preset && preset.iconPosition || 'none';\n      var styleParts = [f.background_image ? \"background:\".concat(f.background_image) : \"background:\".concat(f.background_color || '#2563eb'), f.background_color ? \"background-color:\".concat(f.background_color) : '', \"color:\".concat(f.text_color || '#fff'), f.border_top_color ? \"border:\".concat(f.border_top_width || '1px', \" \").concat(f.border_top_style || 'solid', \" \").concat(f.border_top_color) : 'border:0', \"border-radius:\".concat(f.border_radius || '6px'), f.box_shadow ? \"box-shadow:\".concat(f.box_shadow) : '', f.font_weight ? \"font-weight:\".concat(f.font_weight) : 'font-weight:500', 'font-size:12px', 'padding:4px 10px', 'text-decoration:none', 'display:inline-block', 'line-height:1.4', 'max-width:100%', 'overflow:hidden', 'text-overflow:ellipsis', 'white-space:nowrap'].filter(Boolean).join(';');\n\n      // Icon side-margin picks `margin-left` for right-position and\n      // `margin-right` for left-position so text always has breathing\n      // room on the icon side. 8px matches the picker-cell spacing.\n      var iconLeftHtml = icon ? \"<span class=\\\"bp-thumb-icon\\\" aria-hidden=\\\"true\\\" style=\\\"display:inline-flex;vertical-align:middle;margin-right:8px\\\">\".concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(icon, {\n        size: 14,\n        color: 'currentColor'\n      }), \"</span>\") : '';\n      var iconRightHtml = icon ? \"<span class=\\\"bp-thumb-icon\\\" aria-hidden=\\\"true\\\" style=\\\"display:inline-flex;vertical-align:middle;margin-left:8px\\\">\".concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(icon, {\n        size: 14,\n        color: 'currentColor'\n      }), \"</span>\") : '';\n      var iconOnlyHtml = icon ? \"<span class=\\\"bp-thumb-icon\\\" aria-hidden=\\\"true\\\" style=\\\"display:inline-flex;vertical-align:middle\\\">\".concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(icon, {\n        size: 14,\n        color: 'currentColor'\n      }), \"</span>\") : '';\n\n      // `text` is passed through innerHTML (not escaped) so HTML entities\n      // like &nbsp; and user-authored inline markup match the rendered\n      // <a> in the iframe. EJS <%- text %> in Button.template.html is\n      // ALSO raw HTML → identical parsing here keeps picker/sidebar\n      // WYSIWYG-accurate.\n      var labelHtml;\n      if (icon && iconPosition === 'only') {\n        labelHtml = iconOnlyHtml;\n      } else if (icon && iconPosition === 'right') {\n        labelHtml = \"\".concat(text).concat(iconRightHtml);\n      } else if (icon && iconPosition === 'left') {\n        labelHtml = \"\".concat(iconLeftHtml).concat(text);\n      } else {\n        labelHtml = text;\n      }\n      return \"<a class=\\\"bp-thumb-spec\\\" style=\\\"\".concat(styleParts, \"\\\">\").concat(labelHtml, \"</a>\");\n    }\n  }, {\n    key: \"_escape\",\n    value: function _escape(s) {\n      return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this2 = this;\n      var preset = this._currentPreset();\n      var tooltip = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.change_tooltip', 'Browse all styles');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-row bjs-control-row--wide\\\">\\n                <div class=\\\"bjs-control-label\\\"><span>\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.style.label', 'Style'), \"</span></div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bp-style-summary\\\" data-bjs-style-summary>\\n                        <div class=\\\"bp-style-thumb\\\" data-bjs-style-thumb>\").concat(this._renderThumb(preset), \"</div>\\n                        <div class=\\\"bp-style-meta\\\">\\n                            <div class=\\\"bp-style-name\\\" data-bjs-style-name>\").concat(this._escape(this._name(preset)), \"</div>\\n                            <div class=\\\"bp-style-cat\\\"  data-bjs-style-cat >\").concat(this._escape(this._summaryLine(preset)), \"</div>\\n                        </div>\\n                        <button type=\\\"button\\\" class=\\\"bp-style-change\\\" data-bjs-style-change\\n                                data-tooltip=\\\"\").concat(this._escape(tooltip), \"\\\" aria-label=\\\"\").concat(this._escape(tooltip), \"\\\">\\n                            <span class=\\\"bp-style-change-icon\\\" aria-hidden=\\\"true\\\">\").concat(_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('palette', {\n        size: 18,\n        color: 'currentColor'\n      }), \"</span>\\n                        </button>\\n                    </div>\\n                </div>\\n            </div>\\n        \");\n      var changeBtn = this.domNode.querySelector('[data-bjs-style-change]');\n      if (changeBtn) {\n        changeBtn.addEventListener('click', function (e) {\n          e.preventDefault();\n          e.stopPropagation();\n          _this2._openPicker(e);\n        });\n      }\n    }\n  }, {\n    key: \"_refresh\",\n    value: function _refresh() {\n      // Cheap path: patch only the thumb / name / category text so the\n      // Change button + its anchor don't churn (any in-flight click\n      // animation stays intact).\n      var preset = this._currentPreset();\n      var thumb = this.domNode.querySelector('[data-bjs-style-thumb]');\n      var name = this.domNode.querySelector('[data-bjs-style-name]');\n      var cat = this.domNode.querySelector('[data-bjs-style-cat]');\n      if (thumb) thumb.innerHTML = this._renderThumb(preset);\n      if (name) name.textContent = this._name(preset);\n      if (cat) cat.textContent = this._summaryLine(preset);\n    }\n  }, {\n    key: \"_openPicker\",\n    value: function _openPicker(e) {\n      if (!this.element) return;\n      // Stash the click rect — ButtonPresetPickerOverlay reads\n      // `_lastActionAnchorRect` to anchor next to whichever surface\n      // opened it (sidebar Change button OR action-bar palette pill).\n      var target = e.currentTarget;\n      if (target && typeof target.getBoundingClientRect === 'function') {\n        this.element._lastActionAnchorRect = target.getBoundingClientRect();\n      } else {\n        this.element._lastActionAnchorRect = null;\n      }\n      if (typeof this.element.enterEditMode === 'function') {\n        this.element.enterEditMode('style-picker');\n      }\n    }\n  }]);\n}(_BaseControl_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StylePickerControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/StylePickerControl.js?");

/***/ }),

/***/ "./src/includes/SubmitButtonElement.js":
/*!*********************************************!*\
  !*** ./src/includes/SubmitButtonElement.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar SubmitButtonElement = /*#__PURE__*/function (_BaseElement) {\n  function SubmitButtonElement(template, text) {\n    var _this;\n    _classCallCheck(this, SubmitButtonElement);\n    _this = _callSuper(this, SubmitButtonElement);\n    _this.template = template;\n    _this.text = text;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['text'];\n\n    // Inline edit\n    // Inline edit (W0.2b — auto-wired by BaseElement.afterRender)\n    _this.registerInlineEdit('text');\n\n    // Formatter - Bootstrap button default styles\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_14__[\"default\"]({\n      // align\n      align: 'left',\n      // text styles\n      font_family: \"inherit\",\n      font_weight: \"400\",\n      font_size: \"16px\",\n      text_color: \"#ffffff\",\n      link_color: \"#ffffff\",\n      paragraph_spacing: null,\n      text_align: 'center',\n      // left, center, right,\n      line_height: \"1.5\",\n      letter_spacing: null,\n      text_direction: \"ltr\",\n      // ltr, rtl\n\n      // background - Bootstrap primary button\n      background_color: \"#0d6efd\",\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      // spacing - Bootstrap button padding\n      padding_top: 6,\n      padding_right: 12,\n      padding_bottom: 6,\n      padding_left: 12,\n      // border - Bootstrap button border\n      border_top_style: \"solid\",\n      border_top_width: \"1px\",\n      border_top_color: \"#0d6efd\",\n      border_right_style: \"solid\",\n      border_right_width: \"1px\",\n      border_right_color: \"#0d6efd\",\n      border_bottom_style: \"solid\",\n      border_bottom_width: \"1px\",\n      border_bottom_color: \"#0d6efd\",\n      border_left_width: \"1px\",\n      border_left_style: \"solid\",\n      border_left_color: \"#0d6efd\",\n      // border radius - Bootstrap button radius\n      border_radius: \"0.375rem\",\n      // sizing\n      width: null,\n      max_width: null,\n      min_width: null\n    });\n    return _this;\n  }\n  _inherits(SubmitButtonElement, _BaseElement);\n  return _createClass(SubmitButtonElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.submit_button');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter + text auto-merged (W0.2c); inline-edit auto-wires (W0.2b)\n      this.domNode.innerHTML = this.renderTemplate({});\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(SubmitButtonElement, \"getData\", this, 3)([])), {}, {\n        text: this.text\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      // W3.1 — bus wiring for dual-view sync with FontPopoverOverlay.\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [\n      // TextControl\n      new _TextControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text'), this.text, {\n        setText: function setText(text) {\n          _this2.text = text;\n          _this2.render();\n        }\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('align', value);\n          _this2.render();\n        }\n      }, ['left', 'center', 'right']), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_family', value);\n          _this2.render();\n        }\n      }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_weight', value);\n          _this2.render();\n        }\n      }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('font_size', value);\n          _this2.render();\n        }\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_color', value);\n          _this2.render();\n        }\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('link_color', value);\n          _this2.render();\n        }\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_align', value);\n          _this2.render();\n        }\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.paragraph_spacing'), this.formatter.getFormat('paragraph_spacing'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('paragraph_spacing', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: 0,\n        maxValue: 50,\n        suffix: 'px',\n        allowZero: true\n      }), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('line_height', value);\n          _this2.render();\n        }\n      }), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.letter_spacing'), this.formatter.getFormat('letter_spacing'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('letter_spacing', value);\n          _this2.render();\n        }\n      }, {\n        defaultValue: 0,\n        minValue: -5,\n        maxValue: 10,\n        step: 0.1,\n        suffix: 'px',\n        allowZero: true,\n        allowNegative: true\n      }), new _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_direction'), this.formatter.getFormat('text_direction'), {\n        setValue: function setValue(value) {\n          _this2.formatter.setFormat('text_direction', value);\n          _this2.render();\n        }\n      }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this2.formatter.setFormat('background_color', values.color);\n          _this2.formatter.setFormat('background_image', values.image);\n          _this2.formatter.setFormat('background_position', values.position);\n          _this2.formatter.setFormat('background_size', values.size);\n          _this2.formatter.setFormat('background_repeat', values.repeat);\n          _this2.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this2.formatter.setFormat('border_top_style', border_top_style);\n          _this2.formatter.setFormat('border_top_width', border_top_width);\n          _this2.formatter.setFormat('border_top_color', border_top_color);\n          _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this2.formatter.setFormat('border_left_style', border_left_style);\n          _this2.formatter.setFormat('border_left_width', border_left_width);\n          _this2.formatter.setFormat('border_left_color', border_left_color);\n          _this2.formatter.setFormat('border_right_style', border_right_style);\n          _this2.formatter.setFormat('border_right_width', border_right_width);\n          _this2.formatter.setFormat('border_right_color', border_right_color);\n\n          // re-render\n          _this2.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this2.formatter.setFormat('border_radius', v);\n          _this2.render();\n        }\n      }),\n      // W3.8b — InnerPaddingControl (intrinsic shape).\n      new InnerPaddingControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.button_padding'),\n      // value\n      {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      },\n      // callback\n      {\n        setValues: function setValues(values) {\n          _this2.formatter.setFormat('padding_top', values.top);\n          _this2.formatter.setFormat('padding_right', values.right);\n          _this2.formatter.setFormat('padding_bottom', values.bottom);\n          _this2.formatter.setFormat('padding_left', values.left);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.text), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SubmitButtonElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/SubmitButtonElement.js?");

/***/ }),

/***/ "./src/includes/TabsManager.js":
/*!*************************************!*\
  !*** ./src/includes/TabsManager.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar TabsManager = /*#__PURE__*/function () {\n  function TabsManager() {\n    _classCallCheck(this, TabsManager);\n    this.groups = [];\n  }\n  return _createClass(TabsManager, [{\n    key: \"addTab\",\n    value: function addTab(tab, container) {\n      var _this = this;\n      this.groups.push({\n        tab: tab,\n        container: container\n      });\n\n      // event\n      tab.addEventListener('click', function () {\n        _this.openTab(tab);\n      });\n    }\n  }, {\n    key: \"openTab\",\n    value: function openTab(tab) {\n      this.groups.forEach(function (group) {\n        if (group.tab === tab) {\n          group.tab.classList.add('active');\n          group.container.style.display = 'block';\n        } else {\n          group.tab.classList.remove('active');\n          group.container.style.display = 'none';\n        }\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TabsManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TabsManager.js?");

/***/ }),

/***/ "./src/includes/TermsConfigControl.js":
/*!********************************************!*\
  !*** ./src/includes/TermsConfigControl.js ***!
  \********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * TermsConfigControl — dedicated rich control for TermsOfServiceElement.\n *\n * Bundles every compliance-shaping knob (terms body via inline edit, checkbox\n * label, required toggle, checkbox position, custom validation message) into\n * one panel section so the gate-defining UX is visually grouped and stands\n * apart from the generic styling stack underneath.\n *\n * Conditional UI:\n *   • When checkboxPosition is `inline_left` / `inline_right` the checkbox\n *     sits next to the terms text and uses the text itself as its label —\n *     the dedicated \"Checkbox label\" input is hidden in that mode (its\n *     value is preserved on the model so toggling back to below/above\n *     restores it).\n *\n * Callback contract:\n *   callback.setValues({ termsText?, checkboxLabel?, required?,\n *                        checkboxPosition?, errorMessage? })\n *   The element merges + re-renders; only present keys are applied.\n */\nvar TermsConfigControl = /*#__PURE__*/function () {\n  function TermsConfigControl(label, value, callback) {\n    _classCallCheck(this, TermsConfigControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = {\n      termsText: value && value.termsText != null ? String(value.termsText) : '',\n      checkboxLabel: value && value.checkboxLabel != null ? String(value.checkboxLabel) : '',\n      required: !!(value && value.required),\n      checkboxPosition: TermsConfigControl.POSITIONS.includes(value && value.checkboxPosition) ? value.checkboxPosition : 'below',\n      errorMessage: value && typeof value.errorMessage === 'string' ? value.errorMessage : ''\n    };\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-terms-config-control');\n    this._labelDebounce = null;\n    this._errorDebounce = null;\n    this.render();\n  }\n  return _createClass(TermsConfigControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this$value$checkboxL, _this$value$errorMess;\n      var escapeAttr = function escapeAttr(s) {\n        return String(s == null ? '' : s).replace(/\"/g, '&quot;');\n      };\n      var escapeText = function escapeText(s) {\n        return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n      };\n      var presets = TermsConfigControl.getPresets();\n      var presetButtons = presets.map(function (p) {\n        return \"\\n            <button type=\\\"button\\\"\\n                    class=\\\"bjs-segmented-btn\\\"\\n                    data-preset=\\\"\".concat(escapeAttr(p.id), \"\\\"\\n                    role=\\\"radio\\\"\\n                    aria-checked=\\\"false\\\"\\n                    tabindex=\\\"-1\\\">\\n                \").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(p.labelKey)), \"\\n            </button>\\n        \");\n      }).join('');\n      var positions = TermsConfigControl.getPositions();\n      var positionButtons = positions.map(function (p) {\n        return \"\\n            <button type=\\\"button\\\"\\n                    class=\\\"bjs-segmented-btn\\\"\\n                    data-position=\\\"\".concat(escapeAttr(p.id), \"\\\"\\n                    role=\\\"radio\\\"\\n                    aria-checked=\\\"false\\\"\\n                    tabindex=\\\"-1\\\">\\n                \").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(p.labelKey)), \"\\n            </button>\\n        \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack bjs-terms-config-control__head\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label><span>\".concat(escapeText(this.label), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_settings_help')), \"</span>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-terms-config-control__preset\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_preset_label')), \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-segmented\\\" data-group=\\\"preset\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_preset_label')), \"\\\">\\n                        \").concat(presetButtons, \"\\n                    </div>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-terms-config-control__position\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_position_label')), \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-segmented\\\" data-group=\\\"position\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_position_label')), \"\\\">\\n                        \").concat(positionButtons, \"\\n                    </div>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-terms-config-control__label-row\\\" data-row=\\\"checkbox-label\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"terms_label_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.checkbox_label')), \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"terms_label_\").concat(this.id, \"\\\" type=\\\"text\\\" class=\\\"bjs-text-input\\\" />\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-row bjs-terms-config-control__required-row\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"terms_required_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_required')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_required_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <label class=\\\"bjs-toggle\\\">\\n                        <input id=\\\"terms_required_\").concat(this.id, \"\\\" type=\\\"checkbox\\\" class=\\\"bjs-toggle-input\\\" />\\n                        <span class=\\\"bjs-toggle-track\\\"><span class=\\\"bjs-toggle-thumb\\\"></span></span>\\n                    </label>\\n                </div>\\n            </div>\\n\\n            <div class=\\\"bjs-control-stack bjs-terms-config-control__error-row\\\" data-row=\\\"error-message\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"terms_error_\").concat(this.id, \"\\\"><span>\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_error_message')), \"</span></label>\\n                    <span class=\\\"bjs-control-description\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_error_message_help')), \"</span>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <input id=\\\"terms_error_\").concat(this.id, \"\\\"\\n                           type=\\\"text\\\"\\n                           class=\\\"bjs-text-input\\\"\\n                           placeholder=\\\"\").concat(escapeAttr(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_error_message_placeholder')), \"\\\" />\\n                </div>\\n            </div>\\n\\n            <p class=\\\"bjs-terms-config-control__hint\\\">\").concat(escapeText(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_inline_hint')), \"</p>\\n        \");\n\n      // Hydrate inputs from current value\n      this._labelInput().value = (_this$value$checkboxL = this.value.checkboxLabel) !== null && _this$value$checkboxL !== void 0 ? _this$value$checkboxL : '';\n      this._requiredInput().checked = !!this.value.required;\n      this._errorInput().value = (_this$value$errorMess = this.value.errorMessage) !== null && _this$value$errorMess !== void 0 ? _this$value$errorMess : '';\n      this._syncPresetActive();\n      this._syncPositionActive();\n      this._syncConditionalRows();\n      this._bindEvents();\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this = this;\n      // Preset segmented buttons\n      var presetGroup = this.domNode.querySelector('.bjs-segmented[data-group=\"preset\"]');\n      if (presetGroup) {\n        presetGroup.addEventListener('click', function (e) {\n          var btn = e.target.closest('.bjs-segmented-btn');\n          if (!btn || !presetGroup.contains(btn)) return;\n          _this._applyPreset(btn.dataset.preset);\n        });\n      }\n\n      // Position segmented buttons\n      var positionGroup = this.domNode.querySelector('.bjs-segmented[data-group=\"position\"]');\n      if (positionGroup) {\n        positionGroup.addEventListener('click', function (e) {\n          var btn = e.target.closest('.bjs-segmented-btn');\n          if (!btn || !positionGroup.contains(btn)) return;\n          _this._applyPosition(btn.dataset.position);\n        });\n      }\n\n      // Checkbox-label input — debounced 200ms\n      this._labelInput().addEventListener('input', function () {\n        if (_this._labelDebounce) clearTimeout(_this._labelDebounce);\n        _this._labelDebounce = setTimeout(function () {\n          _this.value.checkboxLabel = _this._labelInput().value;\n          _this._emit({\n            checkboxLabel: _this.value.checkboxLabel\n          });\n        }, 200);\n      });\n\n      // Required toggle\n      this._requiredInput().addEventListener('change', function (e) {\n        _this.value.required = !!e.target.checked;\n        _this._emit({\n          required: _this.value.required\n        });\n      });\n\n      // Custom error-message input — debounced 200ms\n      this._errorInput().addEventListener('input', function () {\n        if (_this._errorDebounce) clearTimeout(_this._errorDebounce);\n        _this._errorDebounce = setTimeout(function () {\n          _this.value.errorMessage = _this._errorInput().value;\n          _this._emit({\n            errorMessage: _this.value.errorMessage\n          });\n        }, 200);\n      });\n    }\n  }, {\n    key: \"_applyPreset\",\n    value: function _applyPreset(presetId) {\n      var preset = TermsConfigControl.getPresets().find(function (p) {\n        return p.id === presetId;\n      });\n      if (!preset) return;\n      var patch = {\n        termsText: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(preset.textKey),\n        checkboxLabel: _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(preset.agreeKey),\n        required: preset.required\n      };\n      // Reflect locally so subsequent re-renders show the new state\n      this.value = _objectSpread(_objectSpread({}, this.value), patch);\n      this._labelInput().value = patch.checkboxLabel;\n      this._requiredInput().checked = patch.required;\n      this._syncPresetActive(presetId);\n      this._emit(patch);\n    }\n  }, {\n    key: \"_applyPosition\",\n    value: function _applyPosition(positionId) {\n      if (!TermsConfigControl.POSITIONS.includes(positionId)) return;\n      if (this.value.checkboxPosition === positionId) return;\n      this.value.checkboxPosition = positionId;\n      this._syncPositionActive();\n      this._syncConditionalRows();\n      this._emit({\n        checkboxPosition: positionId\n      });\n    }\n  }, {\n    key: \"_syncPresetActive\",\n    value: function _syncPresetActive() {\n      var _this2 = this;\n      var forcedId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n      var group = this.domNode.querySelector('.bjs-segmented[data-group=\"preset\"]');\n      if (!group) return;\n      var presets = TermsConfigControl.getPresets();\n      var matchId = forcedId;\n      if (!matchId) {\n        matchId = (presets.find(function (p) {\n          return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(p.textKey) === _this2.value.termsText;\n        }) || {}).id || null;\n      }\n      group.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var isActive = btn.dataset.preset === matchId;\n        btn.classList.toggle('is-active', isActive);\n        btn.setAttribute('aria-checked', isActive ? 'true' : 'false');\n        btn.setAttribute('tabindex', isActive ? '0' : '-1');\n      });\n    }\n  }, {\n    key: \"_syncPositionActive\",\n    value: function _syncPositionActive() {\n      var group = this.domNode.querySelector('.bjs-segmented[data-group=\"position\"]');\n      if (!group) return;\n      var current = this.value.checkboxPosition;\n      group.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var isActive = btn.dataset.position === current;\n        btn.classList.toggle('is-active', isActive);\n        btn.setAttribute('aria-checked', isActive ? 'true' : 'false');\n        btn.setAttribute('tabindex', isActive ? '0' : '-1');\n      });\n    }\n\n    /**\n     * Hide the checkbox-label row when the checkbox is inline with the terms\n     * text — there's no separate label in that layout. Toggle visibility, do\n     * NOT remove from DOM, so the value survives a position toggle round-trip.\n     */\n  }, {\n    key: \"_syncConditionalRows\",\n    value: function _syncConditionalRows() {\n      var labelRow = this.domNode.querySelector('[data-row=\"checkbox-label\"]');\n      if (!labelRow) return;\n      var isInline = this.value.checkboxPosition === 'inline_left' || this.value.checkboxPosition === 'inline_right';\n      labelRow.classList.toggle('is-hidden', isInline);\n    }\n  }, {\n    key: \"_emit\",\n    value: function _emit(patch) {\n      if (this.callback && typeof this.callback.setValues === 'function') {\n        this.callback.setValues(patch);\n      }\n    }\n  }, {\n    key: \"_labelInput\",\n    value: function _labelInput() {\n      return this.domNode.querySelector(\"#terms_label_\".concat(this.id));\n    }\n  }, {\n    key: \"_requiredInput\",\n    value: function _requiredInput() {\n      return this.domNode.querySelector(\"#terms_required_\".concat(this.id));\n    }\n  }, {\n    key: \"_errorInput\",\n    value: function _errorInput() {\n      return this.domNode.querySelector(\"#terms_error_\".concat(this.id));\n    }\n  }], [{\n    key: \"getPresets\",\n    value:\n    /**\n     * Preset boilerplate. Each preset replaces termsText + checkboxLabel and\n     * sets the required flag. i18n keys are looked up at apply-time so locale\n     * switches reseed correctly.\n     */\n    function getPresets() {\n      return [{\n        id: 'tos',\n        labelKey: 'controls.terms_preset_tos',\n        textKey: 'elements.terms_preset_tos_text',\n        agreeKey: 'elements.terms_preset_tos_label',\n        required: true\n      }, {\n        id: 'privacy',\n        labelKey: 'controls.terms_preset_privacy',\n        textKey: 'elements.terms_preset_privacy_text',\n        agreeKey: 'elements.terms_preset_privacy_label',\n        required: true\n      }, {\n        id: 'marketing',\n        labelKey: 'controls.terms_preset_marketing',\n        textKey: 'elements.terms_preset_marketing_text',\n        agreeKey: 'elements.terms_preset_marketing_label',\n        required: false\n      }, {\n        id: 'gdpr',\n        labelKey: 'controls.terms_preset_gdpr',\n        textKey: 'elements.terms_preset_gdpr_text',\n        agreeKey: 'elements.terms_preset_gdpr_label',\n        required: true\n      }];\n    }\n  }, {\n    key: \"getPositions\",\n    value: function getPositions() {\n      return [{\n        id: 'below',\n        labelKey: 'controls.terms_position_below'\n      }, {\n        id: 'above',\n        labelKey: 'controls.terms_position_above'\n      }, {\n        id: 'inline_left',\n        labelKey: 'controls.terms_position_inline_left'\n      }, {\n        id: 'inline_right',\n        labelKey: 'controls.terms_position_inline_right'\n      }];\n    }\n  }]);\n}();\n_defineProperty(TermsConfigControl, \"POSITIONS\", ['below', 'above', 'inline_left', 'inline_right']);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TermsConfigControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TermsConfigControl.js?");

/***/ }),

/***/ "./src/includes/TermsOfServiceElement.js":
/*!***********************************************!*\
  !*** ./src/includes/TermsOfServiceElement.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TermsConfigControl.js */ \"./src/includes/TermsConfigControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./InnerPaddingControl.js */ \"./src/includes/InnerPaddingControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * TermsOfServiceElement — compliance-gate widget for forms.\n *\n * Renders a block of legal/policy text + an \"I agree\" checkbox below it.\n * If `required` is true and the visitor submits without checking the box,\n * the host server (its form-controller + terms-acceptance rule set)\n * rejects the POST with a localized validation error.\n *\n * Singleton (v1): exactly one widget per form, fixed input name\n * `ACM_TERMS_ACCEPT`. Save-time validator (SaveFormBuilderRequest Rule 6)\n * rejects forms with >1 instance.\n */\nvar TermsOfServiceElement = /*#__PURE__*/function (_BaseElement) {\n  function TermsOfServiceElement(template) {\n    var _this;\n    var termsText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';\n    var checkboxLabel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';\n    var required = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n    var checkboxPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'below';\n    var errorMessage = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '';\n    _classCallCheck(this, TermsOfServiceElement);\n    _this = _callSuper(this, TermsOfServiceElement);\n    _this.template = template;\n    _this.termsText = termsText;\n    _this.checkboxLabel = checkboxLabel;\n    _this.required = required;\n    _this.checkboxPosition = TermsOfServiceElement.CHECKBOX_POSITIONS.includes(checkboxPosition) ? checkboxPosition : 'below';\n    // Custom validation message shown on the visitor-side jQuery validate\n    // gate. Empty → fall through to jquery_validate_locale's default\n    // (\"This field is required.\") which is already locale-aware.\n    _this.errorMessage = errorMessage || '';\n    // v1: reserved fixed name; the host server-side walker keys off this.\n    _this.inputName = 'ACM_TERMS_ACCEPT';\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['termsText', 'checkboxLabel', 'inputName', 'checkboxPosition'];\n\n    // Inline rich-text editing on the terms body — visitors can be linked\n    // to the actual ToS URL via the inline link toolbar.\n    _this.registerInlineEdit('termsText');\n\n    // null defaults — let the page CSS cascade win, mirroring PElement.\n    // This keeps dark themes legible without per-instance overrides.\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      link_color: null,\n      text_align: null,\n      line_height: null,\n      letter_spacing: null,\n      background_color: null,\n      background_image: null,\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      border_radius: null\n    });\n    return _this;\n  }\n\n  // Webpack mangling guard — registry + JSON `name` field must be stable.\n  _inherits(TermsOfServiceElement, _BaseElement);\n  return _createClass(TermsOfServiceElement, [{\n    key: \"getClassName\",\n    value: function getClassName() {\n      return 'TermsOfServiceElement';\n    }\n  }, {\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.terms_of_service');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      this.domNode.innerHTML = this.renderTemplate({\n        termsText: this.termsText,\n        checkboxLabel: this.checkboxLabel,\n        inputName: this.inputName,\n        required: this.required,\n        checkboxPosition: this.checkboxPosition,\n        errorMessage: this.errorMessage\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(TermsOfServiceElement, \"getData\", this, 3)([])), {}, {\n        termsText: this.termsText,\n        checkboxLabel: this.checkboxLabel,\n        inputName: this.inputName,\n        required: this.required,\n        checkboxPosition: this.checkboxPosition,\n        errorMessage: this.errorMessage\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this,\n        _this$host;\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          _this2.formatter.setFormat(key, value);\n          _this2.render();\n        };\n      };\n      var busOpts = function busOpts(key) {\n        var _this2$host;\n        return {\n          bus: (_this2$host = _this2.host) === null || _this2$host === void 0 ? void 0 : _this2$host.events,\n          elementUid: _this2.id,\n          formatterKey: key\n        };\n      };\n      return [new _TermsConfigControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.terms_settings'), {\n        termsText: this.termsText,\n        checkboxLabel: this.checkboxLabel,\n        required: this.required,\n        checkboxPosition: this.checkboxPosition,\n        errorMessage: this.errorMessage\n      }, {\n        setValues: function setValues(patch) {\n          if ('termsText' in patch) _this2.termsText = patch.termsText;\n          if ('checkboxLabel' in patch) _this2.checkboxLabel = patch.checkboxLabel;\n          if ('required' in patch) _this2.required = !!patch.required;\n          if ('checkboxPosition' in patch && TermsOfServiceElement.CHECKBOX_POSITIONS.includes(patch.checkboxPosition)) {\n            _this2.checkboxPosition = patch.checkboxPosition;\n          }\n          if ('errorMessage' in patch) _this2.errorMessage = patch.errorMessage || '';\n          _this2.render();\n        }\n      }), new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), this.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }, busOpts('font_family')), new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), this.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }, busOpts('font_weight')), new _NumberControl_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), this.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, _objectSpread({\n        defaultValue: 14,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size'))), new _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.line_height'), this.formatter.getFormat('line_height'), {\n        setValue: setFmt('line_height')\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_color'), this.formatter.getFormat('text_color'), {\n        setValue: setFmt('text_color')\n      }), new _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.link_color'), this.formatter.getFormat('link_color'), {\n        setValue: setFmt('link_color')\n      }), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_9__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.text_alignment'), this.formatter.getFormat('text_align'), {\n        setValue: setFmt('text_align')\n      }, ['left', 'justify', 'center', 'right'], {\n        bus: (_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events,\n        elementUid: this.id,\n        formatterKey: 'text_align'\n      }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_10__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color'),\n        image: this.formatter.getFormat('background_image'),\n        position: this.formatter.getFormat('background_position'),\n        size: this.formatter.getFormat('background_size'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this2.formatter.setFormat('background_color', values.color);\n          _this2.formatter.setFormat('background_image', values.image);\n          _this2.formatter.setFormat('background_position', values.position);\n          _this2.formatter.setFormat('background_size', values.size);\n          _this2.formatter.setFormat('background_repeat', values.repeat);\n          _this2.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this2.formatter.setFormat('border_top_style', border_top_style);\n          _this2.formatter.setFormat('border_top_width', border_top_width);\n          _this2.formatter.setFormat('border_top_color', border_top_color);\n          _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this2.formatter.setFormat('border_left_style', border_left_style);\n          _this2.formatter.setFormat('border_left_width', border_left_width);\n          _this2.formatter.setFormat('border_left_color', border_left_color);\n          _this2.formatter.setFormat('border_right_style', border_right_style);\n          _this2.formatter.setFormat('border_right_width', border_right_width);\n          _this2.formatter.setFormat('border_right_color', border_right_color);\n          _this2.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this2.formatter.setFormat('border_radius', v);\n          _this2.render();\n        }\n      }), new _InnerPaddingControl_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.padding'), {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      }, {\n        setValues: function setValues(values) {\n          _this2.formatter.setFormat('padding_top', values.top);\n          _this2.formatter.setFormat('padding_right', values.right);\n          _this2.formatter.setFormat('padding_bottom', values.bottom);\n          _this2.formatter.setFormat('padding_left', values.left);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var instance = new this(data.template, data.termsText || '', data.checkboxLabel || '', data.required !== undefined ? !!data.required : true, data.checkboxPosition || 'below', typeof data.errorMessage === 'string' ? data.errorMessage : '');\n      // inputName always reset to the reserved value, ignoring any saved\n      // legacy/override (singleton invariant).\n      instance.inputName = 'ACM_TERMS_ACCEPT';\n      return this.parseFormats(instance, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/**\n * Valid checkbox-position values. Any other string falls back to 'below'\n * via parse(), so legacy JSON written before this field shipped renders\n * identically.\n */\n_defineProperty(TermsOfServiceElement, \"CHECKBOX_POSITIONS\", ['below', 'above', 'inline_left', 'inline_right']);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TermsOfServiceElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TermsOfServiceElement.js?");

/***/ }),

/***/ "./src/includes/TermsOfServiceWidget.js":
/*!**********************************************!*\
  !*** ./src/includes/TermsOfServiceWidget.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TermsOfServiceElement.js */ \"./src/includes/TermsOfServiceElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar TermsOfServiceWidget = /*#__PURE__*/function (_BaseWidget) {\n  function TermsOfServiceWidget() {\n    var _this;\n    _classCallCheck(this, TermsOfServiceWidget);\n    _this = _callSuper(this, TermsOfServiceWidget);\n\n    // Match form-field widgets' default block padding (top + bottom 15px)\n    // so a freshly-dropped Terms widget sits flush with the field stack\n    // above + the Submit button below. Mirror set on both axes — the\n    // legal text often gets reasonable breathing room from the surrounding\n    // form fields.\n    _this.block.formatter.setFormat('padding_top', '15');\n    _this.block.formatter.setFormat('padding_bottom', '15');\n\n    // Sample seed: short policy line + an explicit <a> so users see the\n    // link semantic immediately and can re-target via inline-edit.\n    var sampleTerms = 'By submitting this form, you agree to our ' + '<a href=\"#\">Terms of Service</a> and ' + '<a href=\"#\">Privacy Policy</a>.';\n    var sampleAgreeLabel = 'I agree to the terms above.';\n    _this.block.appendElements([new _TermsOfServiceElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('TermsOfService', sampleTerms, sampleAgreeLabel, true, 'below', '')]);\n    return _this;\n  }\n  _inherits(TermsOfServiceWidget, _BaseWidget);\n  return _createClass(TermsOfServiceWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.terms_of_service');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'gavel';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TermsOfServiceWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TermsOfServiceWidget.js?");

/***/ }),

/***/ "./src/includes/TextCenterWidget.js":
/*!******************************************!*\
  !*** ./src/includes/TextCenterWidget.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar TextCenterWidget = /*#__PURE__*/function (_BaseWidget) {\n  function TextCenterWidget() {\n    var _this;\n    _classCallCheck(this, TextCenterWidget);\n    _this = _callSuper(this, TextCenterWidget); // Call the parent class constructor\n\n    //\n    var heading = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    heading.formatter.parseFormats({\n      \"padding_bottom\": 12,\n      \"text_align\": \"center\"\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17,\n      \"text_align\": \"center\"\n    });\n\n    //\n    _this.block.appendElements([heading, p]);\n    return _this;\n  }\n  _inherits(TextCenterWidget, _BaseWidget);\n  return _createClass(TextCenterWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.text_center');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 72'%3E%0A  %3Crect width='180' height='72' fill='%23F7F7F7'/%3E%0A  %3Crect x='58' y='14' width='64' height='8' rx='4' fill='%23C0C0C0'/%3E%0A  %3Crect x='24' y='30' width='132' height='6' rx='3' fill='%23DEDEDE'/%3E%0A  %3Crect x='40' y='42' width='100' height='6' rx='3' fill='%23DEDEDE'/%3E%0A  %3Crect x='68' y='56' width='44' height='12' rx='3.5' fill='%23404040'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextCenterWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextCenterWidget.js?");

/***/ }),

/***/ "./src/includes/TextColorControl.js":
/*!******************************************!*\
  !*** ./src/includes/TextColorControl.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar TextColorControl = /*#__PURE__*/function () {\n  function TextColorControl(label, value, callback) {\n    _classCallCheck(this, TextColorControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    // Initialize properties\n    this.label = label; // Label for the text control\n    this.value = value; // Initial color value (can be null)\n    this.callback = callback; // Callback function to handle input changes\n\n    // Create the main container element\n    this.domNode = document.createElement(\"div\");\n\n    //\n    this.render(); // Call the render method to create the UI\n  }\n  return _createClass(TextColorControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var displayValue = this.value || \"#000000\"; // Default color for color input\n      var hexDisplayValue = this.value || \"not set\"; // Text for hex input when null\n\n      this.domNode.innerHTML = \"<div class=\\\"py-2 ps-3 pe-3 w-100 d-flex align-items-center justify-content-between\\\">\\n      <label for=\\\"\".concat(this.id, \"\\\" class=\\\"form-label fw-semibold mb-0 me-3 small\\\">\").concat(this.label, \"</label>\\n\\n        <div class=\\\"d-flex align-items-center border rounded p-1 ps-2 border-default\\\" style=\\\"gap:4px;min-width:140px; max-width:140px; max-height: 32px;\\\">\\n          <div id=\\\"\").concat(this.id, \"_color_container\\\" class=\\\"position-relative\\\" style=\\\"width: 20px; height: 20px;\\\">\\n            <input id=\\\"\").concat(this.id, \"_color\\\" type=\\\"color\\\" value=\\\"\").concat(displayValue, \"\\\" class=\\\"form-control rounded form-control-color position-absolute\\\" style=\\\"opacity: \").concat(this.value ? 1 : 0, \";\\\">\\n            <div id=\\\"\").concat(this.id, \"_transparency\\\" class=\\\"position-absolute h-100 rounded pe-none\\\" style=\\\"width: 20px; background: repeating-conic-gradient(#ccc 0% 25%, white 0% 50%) 50% / 8px 8px; display: \").concat(this.value ? 'none' : 'block', \";\\\"></div>\\n          </div>\\n          <input id=\\\"\").concat(this.id, \"_hex\\\" type=\\\"text\\\" value=\\\"\").concat(hexDisplayValue, \"\\\" class=\\\"form-control border-none text-center small\\\" style=\\\"height: 28px;font-size:0.875em !important;\\\" />\\n        </div>\\n    </div>\\n    <style>\\n      #\").concat(this.id, \"_color {\\n        border: none;\\n        padding: 0;\\n        width: 20px;\\n        height: 20px;\\n      }\\n      #\").concat(this.id, \"_hex {\\n        border: none;\\n        text-align: center;\\n      }\\n    </style>\\n    \");\n\n      // nodes\n      this.colorInput = this.domNode.querySelector(\"#\".concat(this.id, \"_color\"));\n      this.hexInput = this.domNode.querySelector(\"#\".concat(this.id, \"_hex\"));\n      this.transparencyDiv = this.domNode.querySelector(\"#\".concat(this.id, \"_transparency\"));\n\n      // sync handlers\n      var notify = function notify(val) {\n        _this.value = val;\n        // Update transparency indicator visibility\n        if (_this.transparencyDiv && _this.colorInput) {\n          if (val === null || val === undefined) {\n            _this.transparencyDiv.style.display = 'block';\n            _this.colorInput.style.opacity = '0';\n          } else {\n            _this.transparencyDiv.style.display = 'none';\n            _this.colorInput.style.opacity = '1';\n          }\n        }\n        if (typeof _this.callback === \"function\") {\n          _this.callback(val);\n        } else if (_this.callback && typeof _this.callback.setValue === \"function\") {\n          _this.callback.setValue(val);\n        }\n      };\n      this.colorInput.addEventListener(\"input\", function (e) {\n        var v = e.target.value;\n        _this.hexInput.value = v;\n        notify(v);\n      });\n      this.hexInput.addEventListener(\"focus\", function (e) {\n        // Clear \"not set\" text when user focuses on the input\n        if (e.target.value === \"not set\") {\n          e.target.value = \"\";\n        }\n      });\n      this.hexInput.addEventListener(\"blur\", function (e) {\n        // If user leaves the input empty, show \"not set\" and set value to null\n        if (e.target.value.trim() === \"\") {\n          e.target.value = \"not set\";\n          _this.value = null;\n          notify(null);\n        }\n      });\n      this.hexInput.addEventListener(\"change\", function (e) {\n        var v = e.target.value.trim();\n\n        // If empty or \"not set\", set to null\n        if (v === \"\" || v === \"not set\") {\n          _this.value = null;\n          _this.hexInput.value = \"not set\";\n          notify(null);\n          return;\n        }\n        if (!v.startsWith(\"#\")) v = \"#\" + v;\n        // basic validation to 3/6 hex chars\n        if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(v)) {\n          _this.colorInput.value = v;\n          _this.hexInput.value = v;\n          notify(v);\n        } else {\n          // revert to last known good\n          _this.hexInput.value = _this.value || \"not set\";\n        }\n      });\n\n      // keep UI in sync if value was set programmatically before render\n      // this.setValue(this.value);\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n\n    // Method to set value programmatically\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      if (this.colorInput && this.hexInput) {\n        if (newValue === null || newValue === undefined) {\n          this.colorInput.value = \"#000000\"; // Default color for color input\n          this.colorInput.style.opacity = '0';\n          this.hexInput.value = \"not set\";\n          if (this.transparencyDiv) {\n            this.transparencyDiv.style.display = 'block';\n          }\n        } else {\n          this.colorInput.value = newValue;\n          this.colorInput.style.opacity = '1';\n          this.hexInput.value = newValue;\n          if (this.transparencyDiv) {\n            this.transparencyDiv.style.display = 'none';\n          }\n        }\n      }\n\n      // Support both function and object with setValue\n      if (typeof this.callback === \"function\") {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === \"function\") {\n        this.callback.setValue(this.value);\n      }\n    }\n\n    // Method to get current value\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextColorControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextColorControl.js?");

/***/ }),

/***/ "./src/includes/TextControl.js":
/*!*************************************!*\
  !*** ./src/includes/TextControl.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextControl — multi-line textarea bound to a single string.\n *\n * 2026-04-18 (Phase 2.22) rewrite — drops Bootstrap `.form-control`,\n * `.form-label`, `.py-2 px-3` utility classes. Uses `.bjs-control-stack`\n * + `.bjs-textarea` primitive. Debounces the setText callback 200ms so\n * the canvas doesn't churn on every keystroke (Lesson 19 no-flicker).\n */\nvar TextControl = /*#__PURE__*/function () {\n  function TextControl(label, value, callback) {\n    _classCallCheck(this, TextControl);\n    this.id = '_' + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n    this.domNode = document.createElement('div');\n    this.domNode.classList.add('bjs-text-control');\n    this.render();\n  }\n  return _createClass(TextControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this$value,\n        _this = this;\n      this.domNode.innerHTML = \"\\n            <div class=\\\"bjs-control-stack\\\">\\n                <div class=\\\"bjs-control-label\\\">\\n                    <label for=\\\"\".concat(this.id, \"\\\"><span>\").concat(this.label, \"</span></label>\\n                </div>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <textarea id=\\\"\").concat(this.id, \"\\\" class=\\\"bjs-textarea\\\" name=\\\"text\\\" rows=\\\"3\\\"></textarea>\\n                </div>\\n            </div>\\n        \");\n      this.getTextInput().value = (_this$value = this.value) !== null && _this$value !== void 0 ? _this$value : '';\n      var t = null;\n      this.getTextInput().addEventListener('input', function () {\n        if (t) clearTimeout(t);\n        t = setTimeout(function () {\n          return _this.callback.setText(_this.getText());\n        }, 200);\n      });\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"getTextInput\",\n    value: function getTextInput() {\n      return this.domNode.querySelector('textarea[name=\"text\"]');\n    }\n  }, {\n    key: \"getText\",\n    value: function getText() {\n      return this.getTextInput().value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextControl.js?");

/***/ }),

/***/ "./src/includes/TextDirectionControl.js":
/*!**********************************************!*\
  !*** ./src/includes/TextDirectionControl.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nvar TextDirectionControl = /*#__PURE__*/function () {\n  function TextDirectionControl(label, value, callback) {\n    _classCallCheck(this, TextDirectionControl);\n    this.id = \"_\" + Math.random().toString(36).substr(2, 9);\n    this.label = label;\n    this.value = value;\n    this.callback = callback;\n    this.options = [{\n      icon: \"format_textdirection_l_to_r\",\n      value: \"ltr\"\n    }, {\n      icon: \"format_textdirection_r_to_l\",\n      value: \"rtl\"\n    }];\n    this.domNode = document.createElement(\"div\");\n    this.render();\n  }\n  return _createClass(TextDirectionControl, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      var buttons = this.options.map(function (option) {\n        var isActive = _this.value === option.value;\n        return \"\\n        <button type=\\\"button\\\"\\n                class=\\\"bjs-segmented-btn\".concat(isActive ? ' is-active' : '', \"\\\"\\n                role=\\\"radio\\\"\\n                aria-checked=\\\"\").concat(isActive, \"\\\"\\n                data-value=\\\"\").concat(option.value, \"\\\"\\n                data-tooltip=\\\"\").concat(option.value, \"\\\"\\n                aria-label=\\\"\").concat(option.value, \"\\\"\\n                tabindex=\\\"\").concat(isActive ? '0' : '-1', \"\\\">\\n          <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\").concat(option.icon, \"</span>\\n        </button>\\n      \");\n      }).join('');\n      this.domNode.innerHTML = \"\\n      <div class=\\\"bjs-control-row\\\">\\n        <div class=\\\"bjs-control-label\\\"><span>\".concat(this.label, \"</span></div>\\n        <div class=\\\"bjs-control-input\\\">\\n          <div class=\\\"bjs-segmented\\\" role=\\\"radiogroup\\\" aria-label=\\\"\").concat(this.label, \"\\\">\\n            \").concat(buttons, \"\\n          </div>\\n        </div>\\n      </div>\\n    \");\n      this._bindEvents();\n    }\n  }, {\n    key: \"_bindEvents\",\n    value: function _bindEvents() {\n      var _this2 = this;\n      var group = this.domNode.querySelector('.bjs-segmented');\n      if (!group) return;\n      group.addEventListener('click', function (e) {\n        var btn = e.target.closest('.bjs-segmented-btn');\n        if (!btn || !group.contains(btn)) return;\n        _this2._selectValue(btn.dataset.value, {\n          focus: true\n        });\n      });\n      group.addEventListener('keydown', function (e) {\n        if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.key)) return;\n        e.preventDefault();\n        var buttons = Array.from(group.querySelectorAll('.bjs-segmented-btn'));\n        var currentIndex = buttons.findIndex(function (b) {\n          return b.classList.contains('is-active');\n        });\n        var nextIndex = currentIndex;\n        if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n          nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;\n        } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n          nextIndex = (currentIndex + 1) % buttons.length;\n        } else if (e.key === 'Home') {\n          nextIndex = 0;\n        } else if (e.key === 'End') {\n          nextIndex = buttons.length - 1;\n        }\n        var nextBtn = buttons[nextIndex];\n        if (nextBtn) _this2._selectValue(nextBtn.dataset.value, {\n          focus: true\n        });\n      });\n    }\n  }, {\n    key: \"_selectValue\",\n    value: function _selectValue(value) {\n      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},\n        _ref$focus = _ref.focus,\n        focus = _ref$focus === void 0 ? false : _ref$focus;\n      if (value === this.value) return;\n      this.value = value;\n      this._updateActiveState();\n      this._fireCallback();\n      if (focus) {\n        var activeBtn = this.domNode.querySelector('.bjs-segmented-btn.is-active');\n        if (activeBtn) try {\n          activeBtn.focus();\n        } catch (e) {}\n      }\n    }\n  }, {\n    key: \"_updateActiveState\",\n    value: function _updateActiveState() {\n      var _this3 = this;\n      this.domNode.querySelectorAll('.bjs-segmented-btn').forEach(function (btn) {\n        var active = btn.dataset.value === _this3.value;\n        btn.classList.toggle('is-active', active);\n        btn.setAttribute('aria-checked', active);\n        btn.setAttribute('tabindex', active ? '0' : '-1');\n      });\n    }\n  }, {\n    key: \"_fireCallback\",\n    value: function _fireCallback() {\n      if (typeof this.callback === 'function') {\n        this.callback(this.value);\n      } else if (this.callback && typeof this.callback.setValue === 'function') {\n        this.callback.setValue(this.value);\n      }\n    }\n  }, {\n    key: \"afterRender\",\n    value: function afterRender() {}\n  }, {\n    key: \"setValue\",\n    value: function setValue(newValue) {\n      this.value = newValue;\n      this._updateActiveState();\n      this._fireCallback();\n    }\n  }, {\n    key: \"getValue\",\n    value: function getValue() {\n      return this.value;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextDirectionControl);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextDirectionControl.js?");

/***/ }),

/***/ "./src/includes/TextDoubleWidget.js":
/*!******************************************!*\
  !*** ./src/includes/TextDoubleWidget.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar TextDoubleWidget = /*#__PURE__*/function (_BaseWidget) {\n  function TextDoubleWidget() {\n    var _this;\n    _classCallCheck(this, TextDoubleWidget);\n    _this = _callSuper(this, TextDoubleWidget); // Call the parent class constructor\n\n    //\n    var grid = new GridElement('Grid');\n    grid.cell_gap = 20;\n    var cell1 = new CellElement('Cell');\n    cell1.formatter.setFormat('width', 50);\n    var cell2 = new CellElement('Cell');\n    cell2.formatter.setFormat('width', 50);\n    grid.appendCells([cell1, cell2]);\n    _this.block.appendElements([grid]);\n\n    //\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n\n    //\n    var p_2 = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p_2.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n\n    //\n    var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block1.appendElements([p]);\n    var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block2.appendElements([p_2]);\n\n    //\n    cell1.appendBlock(block1);\n    cell2.appendBlock(block2);\n    return _this;\n  }\n  _inherits(TextDoubleWidget, _BaseWidget);\n  return _createClass(TextDoubleWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.text_double');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 72'%3E%0A  %3Crect width='200' height='72' fill='%23F7F7F7'/%3E%0A  %3Crect x='14' y='14' width='56' height='8' rx='4' fill='%23C0C0C0'/%3E%0A  %3Crect x='14' y='28' width='80' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='38' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='52' width='36' height='10' rx='3' fill='%23404040'/%3E%0A  %3Crect x='108' y='14' width='56' height='8' rx='4' fill='%23C0C0C0'/%3E%0A  %3Crect x='108' y='28' width='80' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='108' y='38' width='68' height='5' rx='2.5' fill='%23DEDEDE'/%3E%0A  %3Crect x='108' y='52' width='36' height='10' rx='3' fill='%23404040'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextDoubleWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextDoubleWidget.js?");

/***/ }),

/***/ "./src/includes/TextInlineKeyboardShortcuts.js":
/*!*****************************************************!*\
  !*** ./src/includes/TextInlineKeyboardShortcuts.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextInlineKeyboardShortcuts — W6.3 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * Keyboard shortcut dispatcher scoped to inline-text hosts. Fires only\n * when the iframe's `activeElement` is inside a `[data-bjs-inline-text]`\n * ancestor AND is not a nested native input. Captures on the iframe\n * document so we run BEFORE the browser's native handler — most\n * shortcuts prevent-default and route through the canonical toolbar\n * pipeline (`_applyExecCommand` / formatter / sanitizer) so rich\n * formatting stays deterministic across engines.\n *\n * Shortcuts shipped (13):\n *\n *   ⌘B  / Ctrl+B   bold\n *   ⌘I  / Ctrl+I   italic\n *   ⌘U  / Ctrl+U   underline\n *   ⌘⇧X / Ctrl+⇧X  strikethrough\n *   ⌘K  / Ctrl+K   open Link popover (requires selection + toolbar)\n *   ⌘⇧K / Ctrl+⇧K  unlink (remove link)\n *   ⌘⌥C / Ctrl+⌥C  copy format (stash computed style on builder._formatClipboard)\n *   ⌘⌥V / Ctrl+⌥V  paste format (wrap selection in <span style>)\n *   ⌘\\  / Ctrl+\\   clear format (execCommand removeFormat)\n *   ⌘⇧L / Ctrl+⇧L  align left\n *   ⌘⇧E / Ctrl+⇧E  align center\n *   ⌘⇧R / Ctrl+⇧R  align right\n *   ⌘⇧J / Ctrl+⇧J  justify\n *\n * Deferred to W2.3 (needs `ElementFactory.retype()`):\n *   ⌘⌥0     paragraph (P)\n *   ⌘⌥1-6   heading H1-H6\n *   ⌘⌥Q     quote (→ BlockquoteElement)\n *\n * Coexistence with ⌘Z undo (PLAN_UNDO_REDO): the history handler in\n * `Builder._historyInit` EXPLICITLY skips contenteditable targets, so\n * undo/redo inside inline text is handled by the browser's native\n * contenteditable undo stack — we intentionally do NOT bind ⌘Z here.\n *\n * Scope check (HARD RULE T1 consequence): target must be a descendant\n * of a `[data-bjs-inline-text]` host AND not inside a nested input.\n * Typing ⌘B in the sidebar does nothing here; typing ⌘B in a P\n * inline-edit toggles bold.\n *\n * Dispatcher design: capture-phase listener on the iframe document so\n * a shortcut's preventDefault runs BEFORE the browser's contenteditable\n * default would. This avoids the \"⌘B toggled twice\" bug that happens\n * when both our handler and the native execCommand fire.\n */\n\n\n\nvar TextInlineKeyboardShortcuts = /*#__PURE__*/function () {\n  function TextInlineKeyboardShortcuts(builder) {\n    _classCallCheck(this, TextInlineKeyboardShortcuts);\n    if (!builder) {\n      throw new Error('TextInlineKeyboardShortcuts: builder required');\n    }\n    this._builder = builder;\n    this._doc = null;\n    this._handler = this._onKeyDown.bind(this);\n    this._attached = false;\n  }\n  return _createClass(TextInlineKeyboardShortcuts, [{\n    key: \"attach\",\n    value: function attach() {\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) return;\n      if (this._attached && this._doc === idoc) return;\n      // Detach from a previous doc if the iframe was recreated.\n      if (this._attached && this._doc && this._doc !== idoc) {\n        this._doc.removeEventListener('keydown', this._handler, true);\n      }\n      this._doc = idoc;\n      idoc.addEventListener('keydown', this._handler, true);\n      this._attached = true;\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-kbd', 'attached');\n    }\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (!this._attached || !this._doc) return;\n      this._doc.removeEventListener('keydown', this._handler, true);\n      this._attached = false;\n      this._doc = null;\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-kbd', 'destroyed');\n    }\n\n    /* ── dispatcher ──────────────────────────────────────────── */\n  }, {\n    key: \"_onKeyDown\",\n    value: function _onKeyDown(e) {\n      var mod = e.metaKey || e.ctrlKey;\n      if (!mod) return;\n\n      // Scope check — target must be inside an inline-text host AND\n      // not a nested native input (which owns its own key semantics).\n      var target = e.target;\n      if (!target || target.nodeType !== 1) return;\n      var host = typeof target.closest === 'function' ? target.closest('[data-bjs-inline-text]') : null;\n      if (!host) return;\n      var tag = target.tagName && target.tagName.toLowerCase();\n      if (tag === 'input' || tag === 'textarea' || tag === 'select') return;\n      var key = (e.key || '').toLowerCase();\n      var shift = e.shiftKey;\n      var alt = e.altKey;\n\n      // Dispatch matrix. Every captured shortcut prevents default +\n      // stops propagation so the browser's native handler (or a\n      // higher-level listener) doesn't double-fire.\n      var handled = false;\n      if (!shift && !alt) {\n        // Plain ⌘/Ctrl + single key.\n        switch (key) {\n          case 'b':\n            handled = this._execCommand('bold', null);\n            break;\n          case 'i':\n            handled = this._execCommand('italic', null);\n            break;\n          case 'u':\n            handled = this._execCommand('underline', null);\n            break;\n          case 'k':\n            handled = this._openLinkPopover();\n            break;\n          case '\\\\':\n            handled = this._execCommand('removeFormat', null);\n            break;\n        }\n      } else if (shift && !alt) {\n        switch (key) {\n          case 'x':\n            handled = this._execCommand('strikeThrough', null);\n            break;\n          case 'k':\n            handled = this._removeLink();\n            break;\n          case 'l':\n            handled = this._applyAlign('left');\n            break;\n          case 'e':\n            handled = this._applyAlign('center');\n            break;\n          case 'r':\n            handled = this._applyAlign('right');\n            break;\n          case 'j':\n            handled = this._applyAlign('justify');\n            break;\n        }\n      } else if (alt && !shift) {\n        switch (key) {\n          case 'c':\n            handled = this._copyFormat();\n            break;\n          case 'v':\n            handled = this._pasteFormat();\n            break;\n          // ⌘⌥1-6, ⌘⌥0, ⌘⌥Q deferred — see W2.3 (ElementFactory.retype).\n        }\n      }\n      if (handled) {\n        e.preventDefault();\n        e.stopPropagation();\n      }\n    }\n\n    /* ── action routes ──────────────────────────────────────── */\n\n    /**\n     * Route through `iframeDoc.execCommand` then `InlineSanitizer.normalize`\n     * on the inline-text host so `<b>/<i>/<font>` divergent browser\n     * outputs canonicalise to `<strong>/<em>/<span style>`. Mirrors the\n     * toolbar's `_applyExecCommand` shape but without the char-offset\n     * save/restore (the shortcut fires from a keydown inside the\n     * contenteditable — the browser's own input event handles the\n     * rest of the setText → innerHTML rewrite + selection restore).\n     */\n  }, {\n    key: \"_execCommand\",\n    value: function _execCommand(cmd, value) {\n      var idoc = this._doc;\n      if (!idoc) return false;\n      var ok = false;\n      try {\n        ok = idoc.execCommand(cmd, false, value);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:execCommand:' + cmd, err);\n        return false;\n      }\n      if (ok) this._normalizeActiveHost();\n      this._refreshTracker();\n      return true; // we preventDefault regardless so browser doesn't double-fire\n    }\n  }, {\n    key: \"_applyAlign\",\n    value: function _applyAlign(side) {\n      var element = this._resolveActiveElement();\n      if (!element || !element.formatter || typeof element.formatter.setFormat !== 'function') {\n        return false;\n      }\n      try {\n        element.formatter.setFormat('text_align', side);\n        if (typeof element.applyFormatStyles === 'function') {\n          element.applyFormatStyles();\n        } else if (typeof element.render === 'function') {\n          element.render();\n        }\n        if (this._builder.events && typeof this._builder.events.emit === 'function') {\n          this._builder.events.emit('formatter:change', {\n            elementUid: element.id,\n            key: 'text_align',\n            value: side,\n            source: 'text-inline-kbd'\n          });\n        }\n        this._refreshTracker();\n        return true;\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:align:' + side, err);\n        return false;\n      }\n    }\n  }, {\n    key: \"_openLinkPopover\",\n    value: function _openLinkPopover() {\n      var toolbar = this._builder._textInlineToolbar;\n      if (!toolbar || !toolbar._mounted) return false;\n      // Toolbar's own click handler is the canonical path — reuse the\n      // Link button so the single-popover invariant the toolbar owns\n      // stays intact (closes color/font/more/AI siblings before opening).\n      var btn = toolbar.domNode && toolbar.domNode.querySelector('[data-link-btn]');\n      if (!btn) return false;\n      try {\n        if (typeof toolbar._toggleLinkPopover === 'function') {\n          toolbar._toggleLinkPopover(btn);\n          return true;\n        }\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:link-popover', err);\n      }\n      return false;\n    }\n  }, {\n    key: \"_removeLink\",\n    value: function _removeLink() {\n      // `unlink` strips an anchor whose selection covers it. Same\n      // path the More menu's Remove Link item uses, but without the\n      // pre-dispatch disabled-state check (the browser's execCommand\n      // is a no-op when selection has no <a>, so we don't have to\n      // pre-check — false return from execCommand is silent).\n      return this._execCommand('unlink', null);\n    }\n\n    /**\n     * Snapshot the selection's computed style onto `builder._formatClipboard`\n     * — same shape as `TextInlineToolbarOverlay._doCopyFormat`. No toolbar\n     * dependency (uses activeElement's iframe host + getComputedStyle).\n     */\n  }, {\n    key: \"_copyFormat\",\n    value: function _copyFormat() {\n      var idoc = this._doc;\n      var iwin = idoc && idoc.defaultView;\n      if (!idoc || !iwin) return false;\n      var sel = iwin.getSelection();\n      if (!sel || sel.rangeCount === 0) return false;\n      var range = sel.getRangeAt(0);\n      var ac = range.commonAncestorContainer;\n      var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n      if (!el) return false;\n      var cs;\n      try {\n        cs = iwin.getComputedStyle(el);\n      } catch (_) {\n        return false;\n      }\n      if (!cs) return false;\n      this._builder._formatClipboard = {\n        fontFamily: cs.fontFamily || '',\n        fontWeight: cs.fontWeight || '',\n        fontStyle: cs.fontStyle || '',\n        fontSize: cs.fontSize || '',\n        color: cs.color || '',\n        backgroundColor: cs.backgroundColor || '',\n        textDecorationLine: cs.textDecorationLine || cs.textDecoration || '',\n        letterSpacing: cs.letterSpacing || '',\n        lineHeight: cs.lineHeight || ''\n      };\n      return true;\n    }\n\n    /**\n     * Wrap the current selection in a `<span style>` carrying the\n     * snapshotted clipboard. No-ops if clipboard empty — a fresh\n     * ⌘⌥C Copy Format primes it.\n     */\n  }, {\n    key: \"_pasteFormat\",\n    value: function _pasteFormat() {\n      var snap = this._builder._formatClipboard;\n      if (!snap) return false;\n      var idoc = this._doc;\n      var iwin = idoc && idoc.defaultView;\n      if (!idoc || !iwin) return false;\n      var sel = iwin.getSelection();\n      if (!sel || sel.rangeCount === 0) return false;\n      var range = sel.getRangeAt(0);\n      if (range.collapsed) return false;\n      var css = this._cssFromFormat(snap);\n      if (!css) return false;\n      var innerHtml = '';\n      try {\n        var frag = range.cloneContents();\n        var tmp = idoc.createElement('div');\n        tmp.appendChild(frag);\n        innerHtml = tmp.innerHTML;\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:paste-format:clone', err);\n        return false;\n      }\n      if (!innerHtml) return false;\n      var wrapped = \"<span style=\\\"\".concat(css, \"\\\">\").concat(innerHtml, \"</span>\");\n      try {\n        idoc.execCommand('insertHTML', false, wrapped);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:paste-format:insert', err);\n        return false;\n      }\n      this._normalizeActiveHost();\n      this._refreshTracker();\n      return true;\n    }\n\n    /* ── helpers ─────────────────────────────────────────────── */\n  }, {\n    key: \"_cssFromFormat\",\n    value: function _cssFromFormat(snap) {\n      if (!snap) return '';\n      var isDefaultDecoration = function isDefaultDecoration(v) {\n        return !v || v === 'none' || v === 'initial' || v === 'inherit';\n      };\n      var isTransparent = function isTransparent(v) {\n        return !v || v === 'rgba(0, 0, 0, 0)' || v === 'transparent';\n      };\n      var isAutoOrNormal = function isAutoOrNormal(v) {\n        return !v || v === 'normal' || v === 'auto';\n      };\n      var parts = [];\n      if (snap.fontFamily && snap.fontFamily !== 'inherit') parts.push(\"font-family: \".concat(snap.fontFamily));\n      if (snap.fontWeight && snap.fontWeight !== '400' && snap.fontWeight !== 'normal') parts.push(\"font-weight: \".concat(snap.fontWeight));\n      if (snap.fontStyle && snap.fontStyle !== 'normal') parts.push(\"font-style: \".concat(snap.fontStyle));\n      if (snap.fontSize) parts.push(\"font-size: \".concat(snap.fontSize));\n      if (snap.color) parts.push(\"color: \".concat(snap.color));\n      if (!isTransparent(snap.backgroundColor)) parts.push(\"background-color: \".concat(snap.backgroundColor));\n      if (!isDefaultDecoration(snap.textDecorationLine)) parts.push(\"text-decoration: \".concat(snap.textDecorationLine));\n      if (!isAutoOrNormal(snap.letterSpacing)) parts.push(\"letter-spacing: \".concat(snap.letterSpacing));\n      if (!isAutoOrNormal(snap.lineHeight)) parts.push(\"line-height: \".concat(snap.lineHeight));\n      return parts.join('; ');\n    }\n\n    /**\n     * Find the inline-text host that currently owns the iframe's active\n     * selection + normalize its markup in place. Same rationale as\n     * `TextInlineToolbarOverlay._normalizeHost` — after any execCommand,\n     * the browser's markup (Safari/Firefox/Chromium) is canonicalised\n     * so round-trip invariants hold.\n     */\n  }, {\n    key: \"_normalizeActiveHost\",\n    value: function _normalizeActiveHost() {\n      var idoc = this._doc;\n      if (!idoc) return;\n      var active = idoc.activeElement;\n      var host = active && typeof active.closest === 'function' ? active.closest('[data-bjs-inline-text]') : null;\n      if (!host) return;\n      try {\n        _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].normalize(host);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-kbd:normalize', err);\n      }\n    }\n  }, {\n    key: \"_refreshTracker\",\n    value: function _refreshTracker() {\n      var tracker = this._builder.textSelectionTracker;\n      if (tracker && typeof tracker.refresh === 'function') {\n        try {\n          tracker.refresh();\n        } catch (_) {}\n      }\n    }\n\n    /**\n     * Resolve the element instance for the currently-focused inline-text\n     * host. Uses the marker's `data-bjs-inline-text` uid (W0.2b) +\n     * `builder.uiManager.elements` registry — same shape as the toolbar's\n     * `_resolveCurrentElement` but independent of toolbar mount state.\n     */\n  }, {\n    key: \"_resolveActiveElement\",\n    value: function _resolveActiveElement() {\n      var idoc = this._doc;\n      if (!idoc) return null;\n      var active = idoc.activeElement;\n      if (!active || typeof active.closest !== 'function') return null;\n      var host = active.closest('[data-bjs-inline-text]');\n      if (!host) return null;\n      var uid = host.getAttribute('data-bjs-inline-text');\n      if (!uid) return null;\n      var uiMgr = this._builder && this._builder.uiManager;\n      if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n      return uiMgr.elements.find(function (el) {\n        return el && el.id === uid;\n      }) || null;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextInlineKeyboardShortcuts);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextInlineKeyboardShortcuts.js?");

/***/ }),

/***/ "./src/includes/TextInputElement.js":
/*!******************************************!*\
  !*** ./src/includes/TextInputElement.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _TextControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextControl.js */ \"./src/includes/TextControl.js\");\n/* harmony import */ var _Formatter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Formatter.js */ \"./src/includes/Formatter.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _ColorPickerControl_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./ColorPickerControl.js */ \"./src/includes/ColorPickerControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _LineHeightControl_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./LineHeightControl.js */ \"./src/includes/LineHeightControl.js\");\n/* harmony import */ var _TextDirectionControl_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./TextDirectionControl.js */ \"./src/includes/TextDirectionControl.js\");\n/* harmony import */ var _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./BackgroundControl.js */ \"./src/includes/BackgroundControl.js\");\n/* harmony import */ var _BorderControl_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./BorderControl.js */ \"./src/includes/BorderControl.js\");\n/* harmony import */ var _CheckboxControl_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./CheckboxControl.js */ \"./src/includes/CheckboxControl.js\");\n/* harmony import */ var _PaddingMarginControl_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./PaddingMarginControl.js */ \"./src/includes/PaddingMarginControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar TextInputElement = /*#__PURE__*/function (_BaseElement) {\n  function TextInputElement(template, inputName, inputValue, placeholder) {\n    var _this;\n    _classCallCheck(this, TextInputElement);\n    _this = _callSuper(this, TextInputElement); // Call the parent class constructor\n    _this.template = template;\n    _this.inputName = inputName;\n    _this.inputValue = inputValue;\n    _this.placeholder = placeholder;\n    _this.required = false;\n    _this.type = 'text';\n    _this.domNode = null;\n    _this.formatter = new _Formatter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]({\n      align: null,\n      font_family: null,\n      font_weight: null,\n      font_size: null,\n      text_color: null,\n      text_align: null,\n      line_height: null,\n      letter_spacing: null,\n      background_color: null,\n      background_image: null,\n      background_position: null,\n      background_size: null,\n      background_repeat: null,\n      padding_top: null,\n      padding_right: null,\n      padding_bottom: null,\n      padding_left: null,\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      border_radius: null,\n      width: null,\n      max_width: null,\n      min_width: null\n    });\n    return _this;\n  }\n  _inherits(TextInputElement, _BaseElement);\n  return _createClass(TextInputElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.text_input');\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        name: this.inputName,\n        value: this.inputValue,\n        placeholder: this.placeholder,\n        required: this.required,\n        type: this.type\n      });\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(TextInputElement, \"getData\", this, 3)([])), {}, {\n        inputName: this.inputName,\n        inputValue: this.inputValue,\n        placeholder: this.placeholder,\n        type: this.type || 'text',\n        required: this.required || false\n      });\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this2 = this;\n      return [\n      // TextControl\n      new _TextControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.name'),\n      // value\n      this.inputName,\n      // callback\n      {\n        // set name\n        setText: function setText(inputName) {\n          _this2.inputName = inputName;\n          _this2.render();\n        }\n      }),\n      // TextControl\n      new _TextControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.value'),\n      // value\n      this.inputValue,\n      // callback\n      {\n        // set value\n        setText: function setText(inputValue) {\n          _this2.inputValue = inputValue;\n          _this2.render();\n        }\n      }),\n      // TextControl\n      new _TextControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.placeholder'),\n      // value\n      this.placeholder,\n      // callback\n      {\n        // set text\n        setText: function setText(placeholder) {\n          _this2.placeholder = placeholder;\n          _this2.render();\n        }\n      }), new _BackgroundControl_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.background_settings'), {\n        color: this.formatter.getFormat('background_color', '#ffffff'),\n        image: this.formatter.getFormat('background_image', ''),\n        position: this.formatter.getFormat('background_position', 'center'),\n        size: this.formatter.getFormat('background_size', '100'),\n        repeat: this.formatter.getFormat('background_repeat', 'no-repeat')\n      }, {\n        setBackground: function setBackground(values) {\n          _this2.formatter.setFormat('background_color', values.color);\n          _this2.formatter.setFormat('background_image', values.image);\n          _this2.formatter.setFormat('background_position', values.position);\n          _this2.formatter.setFormat('background_size', values.size);\n          _this2.formatter.setFormat('background_repeat', values.repeat);\n          _this2.render();\n        }\n      }, {\n        features: ['color', 'image', 'size', 'repeat', 'gradient']\n      }), new _BorderControl_js__WEBPACK_IMPORTED_MODULE_13__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style'),\n        border_top_width: this.formatter.getFormat('border_top_width'),\n        border_top_color: this.formatter.getFormat('border_top_color'),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style'),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width'),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color'),\n        border_left_style: this.formatter.getFormat('border_left_style'),\n        border_left_width: this.formatter.getFormat('border_left_width'),\n        border_left_color: this.formatter.getFormat('border_left_color'),\n        border_right_style: this.formatter.getFormat('border_right_style'),\n        border_right_width: this.formatter.getFormat('border_right_width'),\n        border_right_color: this.formatter.getFormat('border_right_color')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this2.formatter.setFormat('border_top_style', border_top_style);\n          _this2.formatter.setFormat('border_top_width', border_top_width);\n          _this2.formatter.setFormat('border_top_color', border_top_color);\n          _this2.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this2.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this2.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this2.formatter.setFormat('border_left_style', border_left_style);\n          _this2.formatter.setFormat('border_left_width', border_left_width);\n          _this2.formatter.setFormat('border_left_color', border_left_color);\n          _this2.formatter.setFormat('border_right_style', border_right_style);\n          _this2.formatter.setFormat('border_right_width', border_right_width);\n          _this2.formatter.setFormat('border_right_color', border_right_color);\n\n          // re-render\n          _this2.render();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius'), {\n        setRadius: function setRadius(v) {\n          _this2.formatter.setFormat('border_radius', v);\n          _this2.render();\n        }\n      }),\n      // W3.8b — InnerPaddingControl (intrinsic: input breathing room).\n      new InnerPaddingControl(\n      // label\n      _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.padding'),\n      // value\n      {\n        top: this.formatter.getFormat('padding_top'),\n        right: this.formatter.getFormat('padding_right'),\n        bottom: this.formatter.getFormat('padding_bottom'),\n        left: this.formatter.getFormat('padding_left')\n      },\n      // callback\n      {\n        setValues: function setValues(values) {\n          _this2.formatter.setFormat('padding_top', values.top);\n          _this2.formatter.setFormat('padding_right', values.right);\n          _this2.formatter.setFormat('padding_bottom', values.bottom);\n          _this2.formatter.setFormat('padding_left', values.left);\n          _this2.render();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      var e = new this(data.template, data.inputName, data.inputValue, data.placeholder);\n      e.required = data.required || false;\n      e.type = data.type || 'text';\n      return this.parseFormats(e, data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextInputElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextInputElement.js?");

/***/ }),

/***/ "./src/includes/TextLeftWidget.js":
/*!****************************************!*\
  !*** ./src/includes/TextLeftWidget.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\nvar TextLeftWidget = /*#__PURE__*/function (_BaseWidget) {\n  function TextLeftWidget() {\n    var _this;\n    _classCallCheck(this, TextLeftWidget);\n    _this = _callSuper(this, TextLeftWidget); // Call the parent class constructor\n\n    //\n    var grid = new GridElement('Grid');\n    grid.cell_gap = 20;\n    var cell1 = new CellElement('Cell');\n    cell1.formatter.setFormat('width', 50);\n    var cell2 = new CellElement('Cell');\n    cell2.formatter.setFormat('width', 50);\n    grid.appendCells([cell1, cell2]);\n    _this.block.appendElements([grid]);\n\n    //\n    var heading = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h2', 'Talk up your brand.');\n    heading.formatter.parseFormats({\n      \"padding_bottom\": 12\n    });\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'Use this space to add more details about your brand, a customer quote, or to talk about important news.');\n    p.formatter.parseFormats({\n      \"padding_bottom\": 17\n    });\n\n    //\n    var block1 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block1.appendElements([heading]);\n    var block2 = new _BlockElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('Block');\n    block2.appendElements([p]);\n\n    //\n    cell1.appendBlock(block1);\n    cell2.appendBlock(block2);\n    return _this;\n  }\n  _inherits(TextLeftWidget, _BaseWidget);\n  return _createClass(TextLeftWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.text_left');\n    }\n  }, {\n    key: \"getImageUrl\",\n    value: function getImageUrl() {\n      return \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 72'%3E%0A  %3Crect width='180' height='72' fill='%23F7F7F7'/%3E%0A  %3Crect x='14' y='14' width='64' height='8' rx='4' fill='%23C0C0C0'/%3E%0A  %3Crect x='14' y='30' width='152' height='6' rx='3' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='42' width='120' height='6' rx='3' fill='%23DEDEDE'/%3E%0A  %3Crect x='14' y='56' width='44' height='12' rx='3.5' fill='%23404040'/%3E%0A%3C/svg%3E\";\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextLeftWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextLeftWidget.js?");

/***/ }),

/***/ "./src/includes/TextSelectionTracker.js":
/*!**********************************************!*\
  !*** ./src/includes/TextSelectionTracker.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   SelectionGuard: () => (/* binding */ SelectionGuard),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BJS.js */ \"./src/includes/BJS.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\n/**\n * TextSelectionTracker — single source of truth for \"what text range is the\n * user currently selecting on the canvas?\".\n *\n * Per TEXT_INLINE_PLAN W0.3 + HARD RULE T1, every selection-aware overlay\n * (floating toolbar, color popover, link-on-selection popover, font popover,\n * advanced popover, AI rewrite, slash menu) mounts from `text-selection:*`\n * bus events and nothing else — never from element click, never from body\n * event. Centralising the listener chain here (one pair of selectionchange\n * + mouseup handlers on the iframe doc) keeps that invariant from drifting.\n *\n * Scope — only tracks selections whose anchor AND focus nodes are inside a\n * `[data-bjs-inline-text]` ancestor (marker stamped by\n * `BaseElement._wireInlineEdit()`, TEXT_INLINE_PLAN W0.2b). Anything else\n * — selection outside an inline text surface, collapsed caret, or a cross-\n * surface selection (anchor in one paragraph, focus in a different one) —\n * emits `text-selection:clear` so subscribers tear down cleanly.\n *\n * Emits on `builder.events` (CanvasHighlightBus):\n *   'text-selection:change' { elementUid, range, rect, text, formats }\n *   'text-selection:clear'  { elementUid }\n *\n * `elementUid` uses `BaseElement.id` per HARD RULE E (never `.uid`).\n *\n * `formats` is introspection-only; write paths (bold, italic, link, etc.)\n * live in the toolbar overlays that ship in later waves. Keys covered:\n * bold / italic / underline / strikeThrough (from `queryCommandState`) +\n * link / linkHref / linkTarget (ancestor `<a>` walk inside the host) +\n * align / fontFamily / fontSize / fontWeight / color (computed style of\n * the range's common ancestor). A selection-aware subscriber should treat\n * any missing key as \"unknown, render `.is-mixed`\".\n *\n * Event timing:\n *   - `selectionchange` fires MANY times during a drag-select; coalesced\n *     into one emit via `debounceMs` (default 50ms — UIManager Lesson I1).\n *   - `mouseup` fast-paths an emit without debounce so the toolbar paints\n *     on the release frame.\n *   - `_emitClear()` is idempotent — after the first clear, re-clears are\n *     no-ops until a non-empty selection fires next.\n */\nvar TextSelectionTracker = /*#__PURE__*/function () {\n  /**\n   * @param {Object} opts\n   * @param {Document} opts.doc           — iframe contentDocument (the builder canvas).\n   * @param {Object}   opts.bus           — `builder.events` CanvasHighlightBus.\n   * @param {number}  [opts.debounceMs=50] — selectionchange coalesce window.\n   */\n  function TextSelectionTracker() {\n    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n      doc = _ref.doc,\n      bus = _ref.bus,\n      _ref$debounceMs = _ref.debounceMs,\n      debounceMs = _ref$debounceMs === void 0 ? 50 : _ref$debounceMs;\n    _classCallCheck(this, TextSelectionTracker);\n    if (!doc) {\n      throw new Error('TextSelectionTracker: `doc` is required (pass iframe.contentDocument).');\n    }\n    if (!bus || typeof bus.emit !== 'function') {\n      throw new Error('TextSelectionTracker: `bus` must expose .emit() (pass builder.events).');\n    }\n    this._doc = doc;\n    this._bus = bus;\n    this._debounceMs = Math.max(0, debounceMs | 0);\n    this._timer = null;\n    this._attached = false;\n\n    // Last emitted payload — null when cleared. Drives `getCurrent()`\n    // + idempotent `_emitClear()` (second clear is a no-op; if we\n    // emit clear without previous state, subscribers like the\n    // toolbar would tear down a mount that never happened).\n    this._lastPayload = null;\n    this._onSelectionChange = this._onSelectionChange.bind(this);\n    this._onMouseUp = this._onMouseUp.bind(this);\n  }\n\n  /** Start listening. Idempotent. */\n  return _createClass(TextSelectionTracker, [{\n    key: \"attach\",\n    value: function attach() {\n      if (this._attached) return;\n      this._doc.addEventListener('selectionchange', this._onSelectionChange);\n      this._doc.addEventListener('mouseup', this._onMouseUp, true);\n      this._attached = true;\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-selection-tracker', 'attached');\n    }\n\n    /** Stop listening; clear any pending timer + emit a final clear. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (!this._attached) return;\n      this._doc.removeEventListener('selectionchange', this._onSelectionChange);\n      this._doc.removeEventListener('mouseup', this._onMouseUp, true);\n      if (this._timer) {\n        clearTimeout(this._timer);\n        this._timer = null;\n      }\n      this._emitClear();\n      this._attached = false;\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-selection-tracker', 'destroyed');\n    }\n\n    /** Most recently emitted payload (or null if currently cleared). */\n  }, {\n    key: \"getCurrent\",\n    value: function getCurrent() {\n      return this._lastPayload;\n    }\n\n    /**\n     * Force a synchronous recompute + emit. Use after programmatic DOM\n     * mutations that do NOT fire selectionchange (e.g. toolbar format\n     * apply that re-reads its buttons' `.is-active` state).\n     */\n  }, {\n    key: \"refresh\",\n    value: function refresh() {\n      if (this._timer) {\n        clearTimeout(this._timer);\n        this._timer = null;\n      }\n      this._recompute();\n    }\n\n    /* ── Private ─────────────────────────────────────────────────── */\n  }, {\n    key: \"_onSelectionChange\",\n    value: function _onSelectionChange() {\n      var _this = this;\n      if (this._timer) clearTimeout(this._timer);\n      this._timer = setTimeout(function () {\n        _this._timer = null;\n        _this._recompute();\n      }, this._debounceMs);\n    }\n  }, {\n    key: \"_onMouseUp\",\n    value: function _onMouseUp() {\n      // Emit immediately on release — the 50ms debounce swallows the\n      // last selectionchange otherwise, which produces a visible lag\n      // before the floating toolbar appears.\n      if (this._timer) {\n        clearTimeout(this._timer);\n        this._timer = null;\n      }\n      this._recompute();\n    }\n  }, {\n    key: \"_recompute\",\n    value: function _recompute() {\n      var win = this._doc.defaultView;\n      if (!win) return;\n      var sel = win.getSelection();\n      if (!sel || sel.rangeCount === 0) return this._emitClear();\n      var range = sel.getRangeAt(0);\n      if (range.collapsed) return this._emitClear();\n      var anchorHost = this._closestInlineHost(sel.anchorNode);\n      var focusHost = this._closestInlineHost(sel.focusNode);\n\n      // Both ends must be inside the SAME inline-text surface — cross-\n      // surface ranges have no single `elementUid` (HARD RULE E) and no\n      // single-element toolbar can own them.\n      if (!anchorHost || !focusHost || anchorHost !== focusHost) {\n        return this._emitClear();\n      }\n      var elementUid = anchorHost.getAttribute('data-bjs-inline-text');\n      if (!elementUid) return this._emitClear();\n      var payload = {\n        elementUid: elementUid,\n        range: range.cloneRange(),\n        rect: range.getBoundingClientRect(),\n        text: range.toString(),\n        formats: this._introspectFormats(anchorHost, range)\n      };\n      this._lastPayload = payload;\n      this._bus.emit('text-selection:change', payload);\n    }\n  }, {\n    key: \"_emitClear\",\n    value: function _emitClear() {\n      var prev = this._lastPayload;\n      if (!prev) return; // idempotent — nothing to tear down\n      this._lastPayload = null;\n      this._bus.emit('text-selection:clear', {\n        elementUid: prev.elementUid\n      });\n    }\n  }, {\n    key: \"_closestInlineHost\",\n    value: function _closestInlineHost(node) {\n      if (!node) return null;\n      var el = node.nodeType === 1 /* ELEMENT_NODE */ ? node : node.parentElement;\n      if (!el || typeof el.closest !== 'function') return null;\n      return el.closest('[data-bjs-inline-text]');\n    }\n  }, {\n    key: \"_introspectFormats\",\n    value: function _introspectFormats(host, range) {\n      var doc = this._doc;\n      var win = doc.defaultView;\n      var safe = function safe(cmd) {\n        try {\n          return !!doc.queryCommandState(cmd);\n        } catch (_) {\n          return false;\n        }\n      };\n      var container = range.commonAncestorContainer;\n      var anchorEl = container.nodeType === 1 ? container : container.parentElement;\n      var style = anchorEl && win ? win.getComputedStyle(anchorEl) : null;\n\n      // Link detection — walk ancestors up to but not past the inline\n      // host. We never look outside the text surface; an <a> that wraps\n      // the whole element (LinkElement's root) counts — that's valid\n      // because the selection is still \"inside a link\".\n      var linkHref = null;\n      var linkTarget = null;\n      var cursor = anchorEl;\n      while (cursor && cursor !== host) {\n        if (cursor.tagName === 'A') {\n          linkHref = cursor.getAttribute('href') || null;\n          linkTarget = cursor.getAttribute('target') || null;\n          break;\n        }\n        cursor = cursor.parentElement;\n      }\n      // Edge case: host itself is the <a> (LinkElement.template.html is\n      // `<a><%- text %></a>`). Recognise link state even though the walk\n      // above stops at host.\n      if (!linkHref && host.tagName === 'A') {\n        linkHref = host.getAttribute('href') || null;\n        linkTarget = host.getAttribute('target') || null;\n      }\n      return {\n        bold: safe('bold'),\n        italic: safe('italic'),\n        underline: safe('underline'),\n        strikeThrough: safe('strikeThrough'),\n        link: !!linkHref,\n        linkHref: linkHref,\n        linkTarget: linkTarget,\n        align: style ? style.textAlign : null,\n        fontFamily: style ? style.fontFamily : null,\n        fontSize: style ? style.fontSize : null,\n        fontWeight: style ? style.fontWeight : null,\n        color: style ? style.color : null\n      };\n    }\n  }]);\n}();\n/**\n * SelectionGuard — W5.2 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * Save + restore the iframe's text selection across popover mount /\n * interaction cycles so the user's highlight survives clicking into\n * popover inputs. Addresses the UX regression where opening a\n * FontPopoverOverlay / ColorPopoverOverlay / LinkOnSelectionPopoverOverlay\n * shifts focus to the popover's own inputs (selects, number steppers,\n * URL fields), which — on some Chromium builds — collapses the iframe\n * selection the user painted.\n *\n * Save/restore strategy: character offsets against the inline-text host,\n * not Range references. Rationale (same as W1.1 `_saveSelectionOffsets`\n * precedent):\n *   - Range objects hold node references; after `setText → innerHTML =`\n *     rebuilds those nodes, the Range points to detached nodes.\n *   - Char offsets are invariant under any innerHTML rewrite (text\n *     content survives, only the node chunks change).\n *   - TreeWalker(SHOW_TEXT) resolves offsets back to live nodes after\n *     the rebuild.\n *\n * API:\n *   SelectionGuard.save(builder)     → snapshot | null\n *   SelectionGuard.restore(builder, snapshot)\n *   SelectionGuard.run(builder, fn)  → fn() wrapped in save/restore\n *                                       (supports async fn via finally)\n *\n * Consumers call `SelectionGuard.save(this._builder)` on popover open,\n * stash the snapshot, and call `.restore(this._builder, snapshot)` on\n * popover close. Alternatively, wrap a single apply handler with `.run()`\n * when the guard's scope is just one operation.\n *\n * Retirement plan: when W5.1 refactors every inline-text element to\n * `applyFormatStyles()` (no innerHTML rebuild on format apply), the\n * char-offset shim becomes unnecessary — Range references will survive\n * the format write, and Selection APIs can track the live range without\n * manual save/restore. SelectionGuard will slim to a thin range-clone\n * pattern or retire entirely. Keep the API stable so the transition\n * is transparent to callers.\n */\nvar SelectionGuard = /*#__PURE__*/function () {\n  function SelectionGuard() {\n    _classCallCheck(this, SelectionGuard);\n  }\n  return _createClass(SelectionGuard, null, [{\n    key: \"save\",\n    value:\n    /**\n     * Snapshot the current selection's char offsets within its inline-text\n     * host. Returns `null` when no iframe selection is live OR the\n     * selection is outside any `[data-bjs-inline-text]` surface.\n     *\n     * @param {Builder} owner\n     * @returns {{elementUid: string, start: number, end: number} | null}\n     */\n    function save(owner) {\n      if (!owner) return null;\n      var idoc = owner.iframe && owner.iframe.contentDocument;\n      var iwin = idoc && idoc.defaultView;\n      if (!idoc || !iwin) return null;\n\n      // Prefer the tracker's last payload (non-collapsed, inline-scoped).\n      // Fall back to the live iframe selection so callers without a\n      // toolbar-sourced payload still get coverage.\n      var range = null;\n      var inlineHostEl = null;\n      var tracker = owner.textSelectionTracker;\n      if (tracker && typeof tracker.getCurrent === 'function') {\n        var payload = tracker.getCurrent();\n        if (payload && payload.range) {\n          range = payload.range;\n          inlineHostEl = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n        }\n      }\n      if (!range) {\n        var sel = iwin.getSelection();\n        if (!sel || sel.rangeCount === 0) return null;\n        var live = sel.getRangeAt(0);\n        if (live.collapsed) return null;\n        var ac = live.commonAncestorContainer;\n        var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n        inlineHostEl = el && typeof el.closest === 'function' ? el.closest('[data-bjs-inline-text]') : null;\n        if (!inlineHostEl) return null;\n        range = live;\n      }\n      if (!inlineHostEl) return null;\n      var uid = inlineHostEl.getAttribute('data-bjs-inline-text');\n      if (!uid) return null;\n      try {\n        var pre = idoc.createRange();\n        pre.selectNodeContents(inlineHostEl);\n        pre.setEnd(range.startContainer, range.startOffset);\n        var start = pre.toString().length;\n        var end = start + range.toString().length;\n        return {\n          elementUid: uid,\n          start: start,\n          end: end\n        };\n      } catch (_) {\n        return null;\n      }\n    }\n\n    /**\n     * Restore a previously-saved snapshot. Idempotent + defensive:\n     * silently skips when the host vanished from the DOM (element\n     * deleted) or the offsets no longer map to valid text nodes\n     * (content shorter after apply). Notifies the tracker so any\n     * subscribers re-read state.\n     *\n     * Skips if the tracker was EXPLICITLY cleared between save + restore\n     * — covers the \"selection-clear cascade closes a popover that had\n     * a saved snapshot\" case. Reviving the selection there would re-\n     * mount the toolbar the user just dismissed (e.g. by clicking on\n     * canvas outside the inline-text host).\n     */\n  }, {\n    key: \"restore\",\n    value: function restore(owner, snapshot) {\n      if (!owner || !snapshot) return;\n      // If the tracker has no current payload AND was non-null when we\n      // saved (i.e. someone deliberately cleared it via\n      // `text-selection:clear`), the user's intent is \"selection gone\"\n      // — don't revive it. The save() path only produces a snapshot\n      // when a selection was live, so a null tracker at restore time\n      // means clear happened between the two.\n      var trackerRef = owner.textSelectionTracker;\n      if (trackerRef && typeof trackerRef.getCurrent === 'function' && trackerRef.getCurrent() === null) {\n        return;\n      }\n      var idoc = owner.iframe && owner.iframe.contentDocument;\n      var iwin = idoc && idoc.defaultView;\n      if (!idoc || !iwin) return;\n      var inlineHostEl = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(snapshot.elementUid, \"\\\"]\"));\n      if (!inlineHostEl) return;\n\n      // TreeWalker resolves char offsets → live text nodes after any\n      // intervening innerHTML rebuild. NodeFilter.SHOW_TEXT = 4.\n      var walker = idoc.createTreeWalker(inlineHostEl, 4, null, false);\n      var count = 0;\n      var startNode = null,\n        startOffset = 0;\n      var endNode = null,\n        endOffset = 0;\n      var node;\n      while (node = walker.nextNode()) {\n        var len = node.textContent.length;\n        var nextCount = count + len;\n        if (!startNode && nextCount >= snapshot.start) {\n          startNode = node;\n          startOffset = snapshot.start - count;\n        }\n        if (!endNode && nextCount >= snapshot.end) {\n          endNode = node;\n          endOffset = snapshot.end - count;\n          break;\n        }\n        count = nextCount;\n      }\n      // Clamp to host extents — prefer a collapsed caret over a throw.\n      if (!startNode) {\n        startNode = inlineHostEl;\n        startOffset = 0;\n      }\n      if (!endNode) {\n        endNode = startNode;\n        endOffset = Math.min(startOffset, (startNode.textContent || '').length);\n      }\n      try {\n        var range = idoc.createRange();\n        range.setStart(startNode, startOffset);\n        range.setEnd(endNode, endOffset);\n        var sel = iwin.getSelection();\n        sel.removeAllRanges();\n        sel.addRange(range);\n      } catch (_) {\n        return;\n      }\n\n      // Refresh the tracker so subscribers see the restored range in\n      // the next tick. The tracker's debounce may coalesce this with\n      // any in-flight selectionchange — `refresh()` bypasses the\n      // debounce synchronously.\n      var tracker = owner.textSelectionTracker;\n      if (tracker && typeof tracker.refresh === 'function') {\n        try {\n          tracker.refresh();\n        } catch (_) {}\n      }\n    }\n\n    /**\n     * Wrap a function with save/restore. Handles both sync and async\n     * callbacks — for async, restore fires on `.finally()` so errors\n     * don't leak selection state. Returns the callback's result.\n     */\n  }, {\n    key: \"run\",\n    value: function run(owner, fn) {\n      var snap = SelectionGuard.save(owner);\n      var result;\n      try {\n        result = fn();\n      } catch (err) {\n        SelectionGuard.restore(owner, snap);\n        throw err;\n      }\n      if (result && typeof result.then === 'function') {\n        return result.then(function (v) {\n          SelectionGuard.restore(owner, snap);\n          return v;\n        }, function (err) {\n          SelectionGuard.restore(owner, snap);\n          throw err;\n        });\n      }\n      SelectionGuard.restore(owner, snap);\n      return result;\n    }\n  }]);\n}();\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextSelectionTracker);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TextSelectionTracker.js?");

/***/ }),

/***/ "./src/includes/ToolbarPositioner.js":
/*!*******************************************!*\
  !*** ./src/includes/ToolbarPositioner.js ***!
  \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * ToolbarPositioner — geometry + attachment utility for floating toolbars.\n *\n * Has two faces:\n *\n *   (1) **Pure** `compute({ anchor | elementRect, toolbar, ... })` — returns\n *       `{ top, left, side, didFlip, didClamp }` in viewport (fixed) coords.\n *       Zero DOM access, zero side effects. Callers that already have a\n *       rect in hand stay on this path (BaseElement's actions-box + image\n *       toolbar paths — both pre-date the W0.4 anchor extension).\n *\n *   (2) **Stateful** `attach({ anchor, target, ... })` — mounts a floating\n *       toolbar DOM node on top of an anchor (Range, DOMRect, or HTMLElement)\n *       and keeps it pinned through `window scroll` (capture) + `resize` +\n *       `ResizeObserver` (Element anchors only). Returns a handle with\n *       `{ dispose, reposition, getLast }`. Every selection-aware overlay\n *       in W1-W4 mounts via this path.\n *\n * History:\n *   - PLAN_EFFECT W0.3 (2026-04-19) — shipped `compute()` with `elementRect`.\n *   - TEXT_INLINE_PLAN W0.4 (2026-04-20) — extends `compute()` to accept\n *     `anchor: Range | DOMRect | HTMLElement`, adds `offset` / `flip` /\n *     `collisionPadding` input aliases, adds `attach()` stateful helper.\n *     Backward-compatible — `elementRect` + `gap` + `margin` callers keep\n *     working unchanged.\n *\n * Iframe note:\n *   Both `compute` and `attach` expect anchors already in the viewport\n *   coordinate space of the window that holds the `target`. Callers whose\n *   anchor lives inside an iframe MUST pre-shift the anchor's rect by the\n *   iframe's `getBoundingClientRect()` — there is no one-size-fits-all\n *   iframe math (e.g. the builder canvas iframe offsets differ from the\n *   showcase page's inline anchors). Keeping the utility window-agnostic\n *   makes iframe math a caller decision, not a hidden assumption.\n *\n * Algorithm (unchanged from W0.3):\n *   1. Resolve preferred side. If fits, keep. If not AND flip=true, try\n *      the other side. If neither fits, pick the roomier side.\n *   2. Clamp horizontal into [margin, viewport.width - toolbar.width -\n *      margin]. Toolbar wider than viewport-2m → snap to margin (caller\n *      owns truncation).\n *   3. top = above → element.top - toolbar.height - gap;\n *      below → element.top + element.height + gap.\n *\n * NOT for:\n *   - Positioning of `.selected-box` — that hugs element geometry via\n *     `matchingDomNode` (no flip needed).\n *   - Anchored popovers with arrow pointers — use `AnchoredPopoverOverlay`\n *     which owns arrow math. This utility stays arrow-agnostic.\n */\nvar ToolbarPositioner = /*#__PURE__*/function () {\n  function ToolbarPositioner() {\n    _classCallCheck(this, ToolbarPositioner);\n  }\n  return _createClass(ToolbarPositioner, null, [{\n    key: \"DEFAULTS\",\n    get:\n    /**\n     * Default input values. Exposed for test introspection + consumer\n     * discoverability. Callers can merge partial input over these.\n     */\n    function get() {\n      return {\n        gap: 3,\n        margin: 8,\n        preferredSide: 'above',\n        flip: true\n      };\n    }\n\n    /**\n     * Resolve an `anchor: Range | DOMRect | HTMLElement` into a plain\n     * `{ top, left, width, height }` rect in viewport coordinates. Returned\n     * values are numbers the positioner's math can consume directly.\n     *\n     * @param {Range|DOMRect|HTMLElement|{top,left,width,height}} anchor\n     * @returns {{top:number,left:number,width:number,height:number}}\n     */\n  }, {\n    key: \"rectFromAnchor\",\n    value: function rectFromAnchor(anchor) {\n      if (!anchor) {\n        throw new Error('ToolbarPositioner.rectFromAnchor: anchor is required');\n      }\n\n      // Plain rect-shape passthrough — covers legacy `elementRect` callers\n      // + DOMRect instances in older engines that expose { top, left, width,\n      // height } but not the full Geometry interface.\n      if (Number.isFinite(anchor.top) && Number.isFinite(anchor.left) && Number.isFinite(anchor.width) && Number.isFinite(anchor.height)) {\n        return {\n          top: anchor.top,\n          left: anchor.left,\n          width: anchor.width,\n          height: anchor.height\n        };\n      }\n\n      // Range / Element — `getBoundingClientRect` returns viewport coords\n      // in the window where the node lives. If node is inside an iframe,\n      // caller must translate; see the iframe-note in the class header.\n      if (typeof anchor.getBoundingClientRect === 'function') {\n        var r = anchor.getBoundingClientRect();\n        return {\n          top: r.top,\n          left: r.left,\n          width: r.width,\n          height: r.height\n        };\n      }\n      throw new Error('ToolbarPositioner.rectFromAnchor: anchor must be Range, DOMRect, ' + 'HTMLElement, or {top,left,width,height}. Got: ' + Object.prototype.toString.call(anchor));\n    }\n\n    /**\n     * Compute a flipped + clamped toolbar position.\n     *\n     * @param {Object}   input\n     * @param {Range|DOMRect|HTMLElement} [input.anchor]\n     *     Preferred — any kind of anchor. Resolved via `rectFromAnchor()`.\n     * @param {{top:number,left:number,width:number,height:number}} [input.elementRect]\n     *     Legacy — used when `anchor` is absent. Kept verbatim for\n     *     backward compatibility with W0.3 callers.\n     * @param {{width:number,height:number}} input.toolbar\n     *     Desired toolbar outer dimensions in px.\n     * @param {{width:number,height:number}} [input.viewport]\n     *     Viewport bounds. Falls back to `window.innerWidth/innerHeight`.\n     * @param {number} [input.gap=3] / [input.offset]\n     *     Gap between element edge and toolbar. `offset` is a W0.4 alias.\n     * @param {number} [input.margin=8] / [input.collisionPadding]\n     *     Minimum distance from viewport edge. `collisionPadding` is a W0.4 alias.\n     * @param {'above'|'below'} [input.preferredSide='above']\n     * @param {boolean} [input.flip=true]\n     *     When false, the positioner keeps `preferredSide` even if the toolbar\n     *     would overflow. `didFlip` is always false in that case. Useful for\n     *     tooltips/popovers that need a stable side (arrow direction).\n     *\n     * @returns {{\n     *     top: number,\n     *     left: number,\n     *     side: 'above'|'below',\n     *     didFlip: boolean,\n     *     didClamp: boolean,\n     * }}\n     *\n     * @throws {Error} if required inputs are malformed — caller bug, not a\n     * runtime condition the positioner should silently swallow.\n     */\n  }, {\n    key: \"compute\",\n    value: function compute(input) {\n      if (!input || _typeof(input) !== 'object') {\n        throw new Error('ToolbarPositioner.compute: input object required');\n      }\n\n      // Resolve rect — `anchor` wins over `elementRect` when both given.\n      var elementRect;\n      if (input.anchor !== undefined && input.anchor !== null) {\n        elementRect = ToolbarPositioner.rectFromAnchor(input.anchor);\n      } else if (input.elementRect) {\n        elementRect = input.elementRect;\n      } else {\n        throw new Error('ToolbarPositioner.compute: anchor or elementRect required');\n      }\n      var toolbar = input.toolbar;\n      if (!toolbar) {\n        throw new Error('ToolbarPositioner.compute: toolbar required');\n      }\n      for (var _i = 0, _arr = ['top', 'left', 'width', 'height']; _i < _arr.length; _i++) {\n        var k = _arr[_i];\n        if (!Number.isFinite(elementRect[k])) {\n          throw new Error(\"ToolbarPositioner.compute: elementRect.\".concat(k, \" must be finite number\"));\n        }\n      }\n      for (var _i2 = 0, _arr2 = ['width', 'height']; _i2 < _arr2.length; _i2++) {\n        var _k = _arr2[_i2];\n        if (!Number.isFinite(toolbar[_k]) || toolbar[_k] < 0) {\n          throw new Error(\"ToolbarPositioner.compute: toolbar.\".concat(_k, \" must be finite non-negative number\"));\n        }\n      }\n\n      // Input aliases — `offset` → `gap`, `collisionPadding` → `margin`.\n      // Legacy `gap` / `margin` still win when both are passed (explicit\n      // old-world caller intent).\n      var gap = Number.isFinite(input.gap) ? input.gap : Number.isFinite(input.offset) ? input.offset : ToolbarPositioner.DEFAULTS.gap;\n      var margin = Number.isFinite(input.margin) ? input.margin : Number.isFinite(input.collisionPadding) ? input.collisionPadding : ToolbarPositioner.DEFAULTS.margin;\n      var preferredSide = input.preferredSide === 'below' ? 'below' : ToolbarPositioner.DEFAULTS.preferredSide;\n      var flipEnabled = input.flip === undefined ? ToolbarPositioner.DEFAULTS.flip : !!input.flip;\n      var viewport = input.viewport || {\n        // Fall back to window dims; tests should pass explicit viewport.\n        width: typeof window !== 'undefined' ? window.innerWidth : 0,\n        height: typeof window !== 'undefined' ? window.innerHeight : 0\n      };\n      if (!Number.isFinite(viewport.width) || !Number.isFinite(viewport.height)) {\n        throw new Error('ToolbarPositioner.compute: viewport.width/height must be finite numbers');\n      }\n\n      // Space available on each side of the element.\n      var spaceAbove = elementRect.top - gap;\n      var spaceBelow = viewport.height - (elementRect.top + elementRect.height) - gap;\n      var fitsAbove = spaceAbove >= toolbar.height;\n      var fitsBelow = spaceBelow >= toolbar.height;\n      var side;\n      var didFlip = false;\n      if (!flipEnabled) {\n        // Flip disabled — honor preferredSide unconditionally.\n        side = preferredSide;\n      } else if (preferredSide === 'above') {\n        if (fitsAbove) {\n          side = 'above';\n        } else if (fitsBelow) {\n          side = 'below';\n          didFlip = true;\n        } else {\n          // Neither fits. Pick the roomier side — lesser evil.\n          side = spaceBelow > spaceAbove ? 'below' : 'above';\n          didFlip = side !== preferredSide;\n        }\n      } else {\n        // preferredSide === 'below'\n        if (fitsBelow) {\n          side = 'below';\n        } else if (fitsAbove) {\n          side = 'above';\n          didFlip = true;\n        } else {\n          side = spaceAbove > spaceBelow ? 'above' : 'below';\n          didFlip = side !== preferredSide;\n        }\n      }\n      var top = side === 'above' ? elementRect.top - toolbar.height - gap : elementRect.top + elementRect.height + gap;\n\n      // Horizontal clamp. Raw left = element's left edge (toolbar\n      // anchored to the start of the element). Callers that want a\n      // centered / right-aligned anchor can pre-shift elementRect or\n      // anchor before calling — keeps the utility anchor-agnostic.\n      var rawLeft = elementRect.left;\n      var maxLeft = Math.max(margin, viewport.width - toolbar.width - margin);\n      var minLeft = margin;\n      var left;\n      var didClamp = false;\n      if (rawLeft < minLeft) {\n        left = minLeft;\n        didClamp = true;\n      } else if (rawLeft > maxLeft) {\n        left = maxLeft;\n        didClamp = true;\n      } else {\n        left = rawLeft;\n      }\n      return {\n        top: top,\n        left: left,\n        side: side,\n        didFlip: didFlip,\n        didClamp: didClamp\n      };\n    }\n\n    /**\n     * Mount a floating toolbar `target` on top of `anchor` and keep it\n     * pinned through viewport scroll / resize / anchor resize.\n     *\n     * Side effects on `target`:\n     *   - Sets `position: fixed` + computed `top` / `left`.\n     *   - Adds `data-side` / `data-did-flip` / `data-did-clamp` diagnostic\n     *     attributes mirroring the last compute result (CSS can tint on\n     *     non-preferred side).\n     *   - Does NOT touch display / visibility / z-index — caller owns\n     *     those (we'd overwrite a host's own style discipline otherwise).\n     *\n     * Listeners installed:\n     *   - `window.scroll` on capture phase — catches nested scroll\n     *     containers without re-attaching per container.\n     *   - `window.resize`.\n     *   - `ResizeObserver` on `anchor` when anchor is an HTMLElement.\n     *     Range and DOMRect anchors have no observable size source — the\n     *     caller must `handle.reposition()` after DOM mutations that\n     *     change the range's rect (selectionchange covers most).\n     *\n     * @param {Object} input\n     * @param {Range|DOMRect|HTMLElement|Function} input.anchor\n     *     A live Range / Element whose rect the toolbar follows, a fixed\n     *     DOMRect, or a `() => rectShape | Range | DOMRect | Element`\n     *     callback the positioner invokes on every reposition (useful\n     *     when the anchor is derived, e.g. \"last selection range\").\n     * @param {HTMLElement} input.target\n     *     The DOM node to position. Must already be attached to the\n     *     document (the positioner does not append it).\n     * @param {{width:number,height:number}} [input.viewport]\n     *     Override viewport dims (tests + iframe contexts).\n     * @param {number} [input.offset]         Alias for gap.\n     * @param {number} [input.gap]\n     * @param {number} [input.collisionPadding] Alias for margin.\n     * @param {number} [input.margin]\n     * @param {'above'|'below'} [input.preferredSide]\n     * @param {boolean} [input.flip]\n     * @param {Function} [input.onUpdate]     Called after every reposition with the compute result.\n     *\n     * @returns {{\n     *     dispose: () => void,\n     *     reposition: () => void,\n     *     getLast: () => Object | null,\n     * }}\n     */\n  }, {\n    key: \"attach\",\n    value: function attach(input) {\n      if (!input || _typeof(input) !== 'object') {\n        throw new Error('ToolbarPositioner.attach: input object required');\n      }\n      var anchor = input.anchor,\n        target = input.target,\n        onUpdate = input.onUpdate;\n      if (!anchor) {\n        throw new Error('ToolbarPositioner.attach: anchor is required');\n      }\n      if (!target || typeof target.getBoundingClientRect !== 'function') {\n        throw new Error('ToolbarPositioner.attach: target must be an HTMLElement');\n      }\n      var resolveAnchor = typeof anchor === 'function' ? anchor : function () {\n        return anchor;\n      };\n      var last = null;\n      var disposed = false;\n      var reposition = function reposition() {\n        if (disposed) return;\n\n        // Resolve anchor afresh — for Range anchors the caller-held\n        // range may have shifted; for callback anchors we call every\n        // reposition.\n        var resolved;\n        try {\n          resolved = resolveAnchor();\n        } catch (err) {\n          // Anchor resolution failure (detached range, null target) is\n          // a runtime condition — skip this frame, keep listening. No\n          // swallowed silent failure: surface via console.warn so a\n          // developer investigating a stuck toolbar sees it (HARD\n          // RULE T6).\n          // eslint-disable-next-line no-console\n          if (typeof console !== 'undefined') console.warn('[bjs] ToolbarPositioner.attach anchor resolver threw:', err);\n          return;\n        }\n        if (!resolved) return;\n\n        // Toolbar size comes from the target's own rect — callers don't\n        // have to feed dimensions in. Measured pre-position to avoid\n        // reading a post-position rect (which would depend on the last\n        // compute's output and drift).\n        var toolbarRect = target.getBoundingClientRect();\n        var toolbar = {\n          width: toolbarRect.width,\n          height: toolbarRect.height\n        };\n        var pos;\n        try {\n          pos = ToolbarPositioner.compute({\n            anchor: resolved,\n            toolbar: toolbar,\n            viewport: input.viewport,\n            gap: input.gap,\n            offset: input.offset,\n            margin: input.margin,\n            collisionPadding: input.collisionPadding,\n            preferredSide: input.preferredSide,\n            flip: input.flip\n          });\n        } catch (err) {\n          // eslint-disable-next-line no-console\n          if (typeof console !== 'undefined') console.warn('[bjs] ToolbarPositioner.attach compute threw:', err);\n          return;\n        }\n        last = pos;\n        target.style.position = 'fixed';\n        target.style.top = pos.top + 'px';\n        target.style.left = pos.left + 'px';\n        target.dataset.side = pos.side;\n        target.dataset.didFlip = String(pos.didFlip);\n        target.dataset.didClamp = String(pos.didClamp);\n        if (typeof onUpdate === 'function') {\n          try {\n            onUpdate(pos);\n          } catch (err) {\n            // eslint-disable-next-line no-console\n            if (typeof console !== 'undefined') console.warn('[bjs] ToolbarPositioner.attach onUpdate threw:', err);\n          }\n        }\n      };\n\n      // Scroll listener in capture phase — catches nested scroll\n      // containers (sidebar, panel) without needing per-container\n      // re-wiring. Resize on window. Element anchors add a\n      // ResizeObserver so the toolbar follows element size changes\n      // (e.g. image resize popups).\n      var win = typeof window !== 'undefined' ? window : null;\n      if (win) {\n        win.addEventListener('scroll', reposition, true);\n        win.addEventListener('resize', reposition);\n      }\n      var resizeObserver = null;\n      if (anchor && anchor.nodeType === 1 /* ELEMENT_NODE */ && typeof ResizeObserver !== 'undefined') {\n        resizeObserver = new ResizeObserver(reposition);\n        resizeObserver.observe(anchor);\n      }\n\n      // Initial position.\n      reposition();\n      return {\n        dispose: function dispose() {\n          if (disposed) return;\n          disposed = true;\n          if (win) {\n            win.removeEventListener('scroll', reposition, true);\n            win.removeEventListener('resize', reposition);\n          }\n          if (resizeObserver) {\n            resizeObserver.disconnect();\n            resizeObserver = null;\n          }\n        },\n        reposition: reposition,\n        getLast: function getLast() {\n          return last;\n        }\n      };\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ToolbarPositioner);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ToolbarPositioner.js?");

/***/ }),

/***/ "./src/includes/TooltipManager.js":
/*!****************************************!*\
  !*** ./src/includes/TooltipManager.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */   getTooltipManager: () => (/* binding */ getTooltipManager)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * TooltipManager — singleton DOM tooltip for BuilderJS.\n *\n * Why a JS manager instead of pure CSS `::after` pseudo-elements:\n *   CSS pseudo-elements CAN'T escape an ancestor that clips overflow\n *   (sidebars, scrollable panels, popovers). The tooltip gets visually\n *   truncated at the clipping edge — exactly the \"Enable CSS crop &\n *   fo…\" bug the user reported 2026-04-19. Portalling the tooltip into\n *   `<body>` with `position: fixed` bypasses every ancestor's clip.\n *\n * Attributes honoured:\n *   - data-tooltip=\"Text\"                             (required)\n *   - data-tooltip-placement=\"top|bottom|left|right\"  (default \"top\")\n *   - data-tooltip-align=\"start|center|end\"           (default \"center\")\n *   - data-tooltip-disabled                           (hides tooltip)\n *\n * Arrow points at the trigger's center regardless of alignment — the\n * whole reason callers opt into `align=end` is that the tooltip body\n * should slide sideways but the arrow must still unambiguously\n * identify which button it belongs to.\n *\n * Showcase docs: demo/ui-showcase.html — \"Tooltips\" section.\n */\n\nvar PLACEMENTS = ['top', 'bottom', 'left', 'right'];\nvar ALIGNS = ['start', 'center', 'end'];\nvar GAP = 8; // px between trigger edge and tooltip\nvar ARROW_SIZE = 5; // matches CSS ::before triangle border width\nvar VIEWPORT_PADDING = 4; // keep tooltip this far from viewport edges\nvar TooltipManager = /*#__PURE__*/function () {\n  function TooltipManager() {\n    _classCallCheck(this, TooltipManager);\n    this._tip = null;\n    this._arrow = null;\n    this._target = null;\n    this._rafId = null;\n\n    // Bound handlers so add/removeEventListener pair up.\n    this._onPointerOver = this._onPointerOver.bind(this);\n    this._onPointerOut = this._onPointerOut.bind(this);\n    this._onFocusIn = this._onFocusIn.bind(this);\n    this._onFocusOut = this._onFocusOut.bind(this);\n    this._onReposition = this._onReposition.bind(this);\n\n    // Delegated, capture-phase so we catch events regardless of\n    // which subtree the trigger lives in (sidebar, iframe wrapper,\n    // canvas overlay, etc.).\n    document.addEventListener('pointerover', this._onPointerOver, true);\n    document.addEventListener('pointerout', this._onPointerOut, true);\n    document.addEventListener('focusin', this._onFocusIn, true);\n    document.addEventListener('focusout', this._onFocusOut, true);\n  }\n\n  /** Find the closest [data-tooltip] ancestor of `node`, honoring\n   *  Shadow DOM via composedPath when the event provides one. */\n  return _createClass(TooltipManager, [{\n    key: \"_resolveTrigger\",\n    value: function _resolveTrigger(node) {\n      if (!node || typeof node.closest !== 'function') return null;\n      var t = node.closest('[data-tooltip]');\n      if (!t) return null;\n      if (t.hasAttribute('data-tooltip-disabled')) return null;\n      if (!t.getAttribute('data-tooltip')) return null;\n      return t;\n    }\n  }, {\n    key: \"_onPointerOver\",\n    value: function _onPointerOver(e) {\n      var t = this._resolveTrigger(e.target);\n      if (!t || t === this._target) return;\n      this._show(t);\n    }\n  }, {\n    key: \"_onPointerOut\",\n    value: function _onPointerOut(e) {\n      if (!this._target) return;\n      // Treat as \"left the trigger\" only when relatedTarget sits OUTSIDE\n      // the current trigger. Moving between children of the trigger\n      // should keep the tooltip open.\n      if (e.relatedTarget && this._target.contains(e.relatedTarget)) return;\n      this._hide();\n    }\n  }, {\n    key: \"_onFocusIn\",\n    value: function _onFocusIn(e) {\n      var t = this._resolveTrigger(e.target);\n      if (!t) return;\n      this._show(t);\n    }\n  }, {\n    key: \"_onFocusOut\",\n    value: function _onFocusOut() {\n      // Keyboard focus moved away — always hide. Hover handlers will\n      // re-show on the next pointerover if the pointer still sits on\n      // the original trigger.\n      this._hide();\n    }\n  }, {\n    key: \"_onReposition\",\n    value: function _onReposition() {\n      var _this = this;\n      if (!this._target || !document.body.contains(this._target)) {\n        this._hide();\n        return;\n      }\n      // Coalesce scroll/resize storms into one rAF frame.\n      if (this._rafId) return;\n      this._rafId = requestAnimationFrame(function () {\n        _this._rafId = null;\n        _this._position();\n      });\n    }\n  }, {\n    key: \"_ensureTip\",\n    value: function _ensureTip() {\n      if (this._tip) return;\n      this._tip = document.createElement('div');\n      this._tip.className = 'bjs-tooltip';\n      this._tip.setAttribute('role', 'tooltip');\n      this._arrow = document.createElement('div');\n      this._arrow.className = 'bjs-tooltip-arrow';\n      this._tip.appendChild(this._arrow);\n      this._label = document.createElement('span');\n      this._label.className = 'bjs-tooltip-label';\n      this._tip.appendChild(this._label);\n      document.body.appendChild(this._tip);\n    }\n  }, {\n    key: \"_show\",\n    value: function _show(target) {\n      this._ensureTip();\n      var text = target.getAttribute('data-tooltip') || '';\n      var placement = PLACEMENTS.includes(target.getAttribute('data-tooltip-placement')) ? target.getAttribute('data-tooltip-placement') : 'top';\n      var align = ALIGNS.includes(target.getAttribute('data-tooltip-align')) ? target.getAttribute('data-tooltip-align') : 'center';\n      this._target = target;\n      this._label.textContent = text;\n      this._tip.dataset.placement = placement;\n      this._tip.dataset.align = align;\n      this._tip.classList.add('is-visible');\n      this._position();\n\n      // Reposition only while visible. Capture-phase so we catch\n      // scrolls inside the sidebar + iframe + main doc.\n      window.addEventListener('scroll', this._onReposition, true);\n      window.addEventListener('resize', this._onReposition, true);\n    }\n  }, {\n    key: \"_hide\",\n    value: function _hide() {\n      if (!this._tip) return;\n      this._tip.classList.remove('is-visible');\n      this._target = null;\n      if (this._rafId) {\n        cancelAnimationFrame(this._rafId);\n        this._rafId = null;\n      }\n      window.removeEventListener('scroll', this._onReposition, true);\n      window.removeEventListener('resize', this._onReposition, true);\n    }\n  }, {\n    key: \"_position\",\n    value: function _position() {\n      if (!this._tip || !this._target) return;\n\n      // Hide while measuring so the tip's own rect doesn't reflect an\n      // off-screen position that shifted the document. `visibility:\n      // hidden` keeps it measurable without showing a flash.\n      var prev = this._tip.style.visibility;\n      this._tip.style.visibility = 'hidden';\n      this._tip.style.top = '0px';\n      this._tip.style.left = '0px';\n      var tr = this._target.getBoundingClientRect();\n      var size = this._tip.getBoundingClientRect();\n      var placement = this._tip.dataset.placement || 'top';\n      var align = this._tip.dataset.align || 'center';\n      var top = 0;\n      var left = 0;\n\n      // 1. Axis-of-placement: distance from the trigger edge.\n      if (placement === 'top') top = tr.top - size.height - GAP;else if (placement === 'bottom') top = tr.bottom + GAP;else if (placement === 'left') left = tr.left - size.width - GAP;else left = tr.right + GAP;\n\n      // 2. Axis-of-alignment: where along the trigger edge we anchor.\n      if (placement === 'top' || placement === 'bottom') {\n        if (align === 'start') left = tr.left;else if (align === 'end') left = tr.right - size.width;else left = tr.left + (tr.width - size.width) / 2;\n      } else {\n        if (align === 'start') top = tr.top;else if (align === 'end') top = tr.bottom - size.height;else top = tr.top + (tr.height - size.height) / 2;\n      }\n\n      // 3. Viewport clamp — safety net so a `center`-aligned tooltip\n      //    near the right rail still stays on-screen. Caller can still\n      //    flip `align=end` to avoid the clamp arrow/body mismatch.\n      var maxLeft = window.innerWidth - size.width - VIEWPORT_PADDING;\n      var maxTop = window.innerHeight - size.height - VIEWPORT_PADDING;\n      left = Math.max(VIEWPORT_PADDING, Math.min(left, maxLeft));\n      top = Math.max(VIEWPORT_PADDING, Math.min(top, maxTop));\n      this._tip.style.left = left + 'px';\n      this._tip.style.top = top + 'px';\n\n      // 4. Arrow stays pointed at the trigger's center. After body\n      //    clamping, the offset between trigger-center and tip-edge\n      //    can shift, so recompute arrow offset each time.\n      this._positionArrow(tr, size, left, top, placement);\n      this._tip.style.visibility = prev || '';\n    }\n  }, {\n    key: \"_positionArrow\",\n    value: function _positionArrow(triggerRect, tipSize, tipLeft, tipTop, placement) {\n      if (!this._arrow) return;\n      var arrow = this._arrow;\n      // Reset\n      arrow.style.top = arrow.style.left = arrow.style.right = arrow.style.bottom = '';\n      if (placement === 'top' || placement === 'bottom') {\n        var triggerCenterX = triggerRect.left + triggerRect.width / 2;\n        var offsetX = Math.max(ARROW_SIZE * 2, Math.min(triggerCenterX - tipLeft, tipSize.width - ARROW_SIZE * 2));\n        arrow.style.left = offsetX + 'px';\n      } else {\n        var triggerCenterY = triggerRect.top + triggerRect.height / 2;\n        var offsetY = Math.max(ARROW_SIZE * 2, Math.min(triggerCenterY - tipTop, tipSize.height - ARROW_SIZE * 2));\n        arrow.style.top = offsetY + 'px';\n      }\n    }\n\n    /** Force-refresh position. Callers that move/resize a trigger\n     *  synchronously while the tooltip is up (rare — most state flips\n     *  come from clicks that already trigger pointerout → hide) can\n     *  call this to avoid a stale frame. */\n  }, {\n    key: \"refresh\",\n    value: function refresh() {\n      if (this._target) this._position();\n    }\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      this._hide();\n      document.removeEventListener('pointerover', this._onPointerOver, true);\n      document.removeEventListener('pointerout', this._onPointerOut, true);\n      document.removeEventListener('focusin', this._onFocusIn, true);\n      document.removeEventListener('focusout', this._onFocusOut, true);\n      if (this._tip && this._tip.parentNode) this._tip.parentNode.removeChild(this._tip);\n      this._tip = this._arrow = this._label = this._target = null;\n    }\n  }]);\n}(); // Singleton — constructor side-effects install the delegated listeners.\n// Callers just import this file; no `new` needed at use sites.\nvar _instance = null;\nfunction getTooltipManager() {\n  if (!_instance && typeof document !== 'undefined') {\n    _instance = new TooltipManager();\n  }\n  return _instance;\n}\n\n// Auto-activate on module load. The constructor only attaches passive\n// document listeners — zero work happens until a `[data-tooltip]`\n// element is hovered. This lets pages that load `dist/builder.js`\n// (e.g. ui-showcase.html) benefit from tooltips without needing to\n// construct a full Builder instance.\nif (typeof document !== 'undefined') {\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', function () {\n      return getTooltipManager();\n    }, {\n      once: true\n    });\n  } else {\n    getTooltipManager();\n  }\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TooltipManager);\n\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/TooltipManager.js?");

/***/ }),

/***/ "./src/includes/UIManager.js":
/*!***********************************!*\
  !*** ./src/includes/UIManager.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BlockElement_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./BlockElement.js */ \"./src/includes/BlockElement.js\");\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\n\nvar UIManager = /*#__PURE__*/function () {\n  function UIManager(builder) {\n    _classCallCheck(this, UIManager);\n    this.builder = builder;\n    this.elements = [];\n    this.hoveringElements = [];\n    this.dragOveringElements = [];\n    this.draggableItems = [];\n    this.draggingItem = null;\n  }\n  return _createClass(UIManager, [{\n    key: \"init\",\n    value: function init() {\n      var _this = this;\n      // clear drag over elements\n      this.elements = [];\n      this.hoveringElements = [];\n      this.dragOveringElements = [];\n      this.draggableItems = [];\n      this.draggingItem = null;\n\n      // remove effects\n      this.elements.forEach(function (el) {\n        el.removeHoverHightlight();\n        el.removeDropHighlight();\n        el.removeContainerHightlight();\n        el.removeContainerDropHightlight();\n      });\n\n      // ─────────────────────────────────────────────────────────────────\n      // CLEAR-HOVER-ON-LEAVE-CANVAS\n      // ─────────────────────────────────────────────────────────────────\n      //\n      // Hover highlights, container highlights and the drag-anchor live\n      // inside the builder iframe. Their show/hide is driven by mouseover\n      // / mouseout listeners attached to elements *inside* that iframe\n      // (see handleElementEvents). Those listeners are scoped to the\n      // iframe document, so once the mouse crosses the iframe boundary\n      // into the parent document (sidebar, toolbar, gray canvas around\n      // the iframe, anywhere) the iframe stops receiving mouse events\n      // and the hover state can get \"stuck\" — the last hovered block\n      // keeps its highlight and the \"Block\" tag stays floating even\n      // though the cursor is now over the WidgetsBox or the toolbar.\n      //\n      // Fix: listen for mouseover on the parent document. Anything that\n      // is NOT the iframe element itself means the mouse is somewhere in\n      // the parent doc — i.e. it has left the canvas — so we wipe all\n      // hover state. The previous implementation only fired when the\n      // target was exactly `mainContainer` (the gray grid wrapper around\n      // the iframe), which left every other parent-doc region (sidebar,\n      // toolbar, anywhere outside #MainContainer) as dead zones where\n      // the hover state never got cleared.\n      //\n      // Why `e.target !== this.builder.iframe` is the right test:\n      //   • Mouse over iframe area → e.target == iframe → DON'T clear\n      //     (mouse is back on the canvas; iframe-internal listeners\n      //      take over the hover state).\n      //   • Mouse over any other parent-doc element → CLEAR.\n      //   • Mouse moving inside the iframe contents → no parent-doc\n      //     mouseover at all (separate document), so this handler is\n      //     not invoked and the iframe-internal listeners run instead.\n      //\n      // Regression: e2e/hover-clear-on-leave-canvas.spec.js\n      // ─────────────────────────────────────────────────────────────────\n      document.addEventListener('mouseover', function (e) {\n        if (e.target === _this.builder.iframe) {\n          // Mouse is back over the canvas — let iframe-internal\n          // listeners handle the hover state.\n          return;\n        }\n\n        // ─────────────────────────────────────────────────────────\n        // EXEMPT DRAG ANCHORS — CRITICAL for Chrome + Safari\n        // ─────────────────────────────────────────────────────────\n        // Drag anchors (the floating \"hand\" handles) live in the\n        // MAIN document (document.body), so any mouseover on them\n        // is a parent-doc event. Without this exemption, the\n        // clear-on-leave-iframe logic below would treat hovering\n        // the hand icon as \"mouse has left the canvas\", wipe the\n        // hover state, and hide the anchor — producing a rapid\n        // flicker loop and making the hand impossible to grab\n        // (especially bad on Safari where the anchor vanishes\n        // between repaints).\n        //\n        // Skip the clear for anything that IS a drag-anchor or\n        // sits INSIDE one, plus the element settings toolbar\n        // (mc-element-controls) which also lives outside the\n        // iframe and must not nuke hover state.\n        // ─────────────────────────────────────────────────────────\n        if (e.target && typeof e.target.closest === 'function') {\n          if (e.target.closest('.drag-anchor')) {\n            return;\n          }\n          if (e.target.closest('[data-element-controls]')) {\n            return;\n          }\n          // ─────────────────────────────────────────────────────\n          // Phase 1.1 (§4.I6): canvas overlays live in parent doc\n          // same as drag anchors. Without this exemption, hovering\n          // any `.bjs-ovl` node would wipe hover state → overlay\n          // unmounts → cursor back on iframe → overlay re-mounts\n          // → flicker loop. BaseOverlay.mount() always adds the\n          // class. See docs/archived/OVERLAY_PLAN.md §4.I6.\n          // ─────────────────────────────────────────────────────\n          if (e.target.closest('.bjs-ovl')) {\n            // Phase 1.6 — additionally cancel any pending 50 ms\n            // unmount timer. Cursor left the iframe block (mouseout\n            // fired + scheduled the timeout) and crossed onto the\n            // parent-doc overlay. Without this cancel, the timeout\n            // still fires and unmounts the overlay out from under\n            // the cursor (the `.bjs-ovl` exemption above only\n            // prevents the PARENT-DOC hover-clear from also wiping\n            // state — it doesn't touch the iframe-mouseout timer).\n            // Legacy `.drag-anchor` worked because hideDragAnchor\n            // was `display:none`; the DOM stayed alive for re-entry.\n            // Overlay path destroys the DOM, so we must keep the\n            // overlay ALIVE while the cursor is on it.\n            // See docs/core/OVERLAY.md §7.4 + OVERLAY_PLAN.md §5 D53.\n            if (_this._hideTimeout) {\n              clearTimeout(_this._hideTimeout);\n              _this._hideTimeout = null;\n            }\n            return;\n          }\n        }\n\n        // Mouse is somewhere in the parent document outside the iframe\n        // (sidebar, toolbar, anywhere). Wipe all hover state so nothing\n        // stays \"stuck\" on a block the user is no longer pointing at.\n        _this.elements.forEach(function (el) {\n          el.removeHoverHightlight();\n          if (el.container) {\n            el.container.removeContainerHightlight();\n          }\n          if (el.getDragAnchor) {\n            el.hideDragAnchor();\n          }\n\n          // Phase 1.6 — unmount 'hover'-trigger overlays too. Legacy\n          // `hideDragAnchor()` is enough for widgets (keeps their DOM\n          // but toggles display). Blocks moved to the overlay path —\n          // their anchor DOM must be destroyed when cursor leaves\n          // the canvas entirely (sidebar / toolbar / anywhere outside\n          // iframe + outside `.bjs-ovl`). Without this, the block\n          // drag anchor stays mounted in parent doc after the cursor\n          // has left — next canvas hover would create a duplicate.\n          el.unmountOverlays('hover');\n        });\n        _this.hoveringElements = [];\n        // Also cancel any pending mouseout 50 ms timeout — the parent-doc\n        // wipe above is the authoritative \"mouse is no longer on any\n        // canvas element\" signal; any scheduled cleanup from an earlier\n        // iframe-block mouseout is redundant + would race against the\n        // next mouseover if the user comes back.\n        if (_this._hideTimeout) {\n          clearTimeout(_this._hideTimeout);\n          _this._hideTimeout = null;\n        }\n      });\n    }\n  }, {\n    key: \"addElement\",\n    value: function addElement(element) {\n      // Idempotent. Pre-fix this push was unguarded — every cascade\n      // re-render of a Block called addElement() on each child again,\n      // accumulating duplicates in `this.elements` and re-triggering\n      // hover-listener teardown on every mouseover (the forEach at\n      // line ~251 iterates the array). With the new surgical\n      // structural mutations (BlockElement / PageElement /\n      // CellElement removeElement + addBlock*) duplicate pushes\n      // should no longer happen, but the guard freezes the invariant.\n      // `handleElementEvents` already had its own `eventHandled` guard\n      // so the DOM-listener leak was self-limited; the array bloat\n      // wasn't.\n      if (this.elements.indexOf(element) !== -1) return;\n      this.elements.push(element);\n      this.handleElementEvents(element);\n    }\n  }, {\n    key: \"handleElementEvents\",\n    value: function handleElementEvents(element) {\n      var _this2 = this;\n      if (!element.eventHandled) {\n        element.domNode.addEventListener('mouseover', function (e) {\n          e.preventDefault();\n          _this2.mouseover(element);\n        });\n        element.domNode.addEventListener('mouseout', function (e) {\n          e.preventDefault();\n          _this2.mouseout(element, e);\n        });\n\n        // Droppable elements\n        if (element.isDroppable()) {\n          // dragover event\n          element.domNode.addEventListener('dragover', function (e) {\n            e.preventDefault();\n            _this2.dragOver(element, e);\n          });\n\n          // dragleave event\n          element.domNode.addEventListener('dragleave', function () {\n            _this2.dragLeave(element);\n          });\n\n          // Drop draggable element\n          element.domNode.addEventListener('drop', function (e) {\n            e.preventDefault();\n            _this2.drop(element, e);\n          });\n        }\n\n        // Select element\n        element.domNode.addEventListener('click', function (e) {\n          e.preventDefault();\n          var topElement = _this2.getTopHoveringElement();\n\n          // only click on top element\n          if (topElement != element) {\n            return;\n          }\n\n          //\n          _this2.builder.selectElement(topElement);\n        });\n        element.eventHandled = true;\n      }\n    }\n  }, {\n    key: \"mouseover\",\n    value: function mouseover(element) {\n      var _this3 = this;\n      // Phase 1.1 (§4.I7 placement): active-drag guard MUST go FIRST, before\n      // the isHoverable short-circuit. During any pointer-driven drag, freeze\n      // hover recompute entirely — otherwise element.domNode mouseover events\n      // fire under the captured pointer and churn state beneath the drag.\n      // See docs/core/OVERLAY.md §10 + docs/archived/OVERLAY_PLAN.md §4.I7.\n      if (_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasActive()) return;\n\n      // Container-only elements (Grid, Cell) are not hoverable from the canvas.\n      // They can still be selected via breadcrumb or builder.selectElement().\n      if (!element.isHoverable()) {\n        return;\n      }\n\n      // Cancel any pending mouseout hide (prevents flicker when drag anchor overlaps iframe)\n      if (this._hideTimeout) {\n        clearTimeout(this._hideTimeout);\n        this._hideTimeout = null;\n      }\n      this.addHoveringElement(element);\n\n      // MOUSEOUT ALL\n      this.elements.forEach(function (el) {\n        // remove hover highlight\n        el.removeHoverHightlight();\n\n        // remove container hover highlight\n        if (el.container) {\n          // Remove hover highlight to its container\n          el.container.removeContainerHightlight();\n        }\n\n        // hide drag anchor\n        if (el.getDragAnchor) {\n          el.hideDragAnchor();\n        }\n\n        // Phase 1.1: tear down any 'hover'-trigger overlays. Idempotent\n        // if no overlays are live (default getOverlays() returns []).\n        // See docs/core/OVERLAY.md §3 mount/unmount contract.\n        el.unmountOverlays('hover');\n      });\n\n      // Only add a hover highlight to the last nested element.\n      this.hoveringElements.forEach(function (el) {\n        if (el == _this3.getTopHoveringElement()) {\n          el.addHoverHightlight();\n\n          // PLAN_EFFECT W2.1b — when the hovered element is the\n          // currently-selected one, skip the container padding-\n          // region highlight too. Its 4-box dashed/striped pattern\n          // duplicates the selection identity + user feedback\n          // 2026-04-19 \"container highlight leak on selection\"\n          // wants it gone in this case.\n          if (el.container && _this3.builder.getSelectedElement() !== el) {\n            el.container.addContainerHightlight(el);\n          } else if (el.container) {\n            el.container.removeContainerHightlight();\n          }\n        } else {\n          el.removeHoverHightlight();\n        }\n      });\n\n      // Phase 1.6 — mount the 'hover'-trigger overlay on the NEAREST\n      // ancestor in the hover chain that declares a `'hover'`-trigger\n      // overlay. `hoveringElements` is ordered deepest→root\n      // (getTopHoveringElement() returns [0]), so walking forward from 0\n      // gives the closest-to-cursor element.\n      //\n      // Why \"nearest\" not \"top-only\" or \"all ancestors\":\n      //   - top-only (Phase 1.1 original) breaks the block drag-anchor UX —\n      //     hovering a button inside a block would never mount the block's\n      //     anchor.\n      //   - all-ancestors (legacy `showDragAnchor()` semantic) stacks\n      //     multiple block anchors when blocks are nested (e.g. BlockA →\n      //     Grid → Cell → BlockB). The user sees two hand icons at once —\n      //     visually noisy + ambiguous for the drag target.\n      //   - nearest (this) — exactly one anchor per hover, on the closest\n      //     block to the cursor. Matches Webflow / Notion. Future 'hover'\n      //     overlays get the same single-mount contract.\n      //\n      // Critical: filter by `getTrigger() === 'hover'`, not just\n      // `getOverlays().length > 0`. Elements with only `'select'`-trigger\n      // overlays (e.g. ImageElement's 6 actions/corners/crop overlays)\n      // MUST NOT short-circuit the walk — otherwise a block wrapping an\n      // image would never mount its hover overlay because the Image\n      // stops the walk at index 0.\n      //\n      // Idempotent via mountOverlays guard (D9); zero overhead for elements\n      // that don't opt in (default getOverlays() returns []).\n      // See docs/core/OVERLAY.md §3 + §7.4 + §5 Phase 1.6 D47.\n      for (var i = 0; i < this.hoveringElements.length; i++) {\n        var ee = this.hoveringElements[i];\n        if (typeof ee.getOverlays !== 'function') continue;\n        var hoverOverlays = ee.getOverlays().some(function (o) {\n          return typeof o.getTrigger === 'function' && o.getTrigger() === 'hover';\n        });\n        if (hoverOverlays) {\n          ee.mountOverlays('hover');\n          break;\n        }\n      }\n    }\n  }, {\n    key: \"mouseout\",\n    value: function mouseout(element, e) {\n      var _this4 = this;\n      // Phase 1.1 (§4.I7 placement): active-drag guard. During a captured\n      // pointer drag, skip mouseout cleanup entirely — the drag is authoritative\n      // and the deferred 50ms hide below would race with pointerup.\n      // The 50ms debounce stays (§4.I1 — idle-hover fix, independent concern).\n      // See docs/core/OVERLAY.md §10.\n      if (_PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasActive()) return;\n      this.removeHoveringElement(element);\n\n      // ─────────────────────────────────────────────────────────────────\n      // CRITICAL: 50ms delay — NEVER remove this\n      // ─────────────────────────────────────────────────────────────────\n      // Drag anchor (hand icon) is fixed-positioned in the MAIN document\n      // and overlaps the iframe boundary. When the cursor crosses from\n      // the block (inside iframe) onto the drag anchor (outside iframe),\n      // both Chrome and Safari fire a rapid mouseout→mouseover loop:\n      //\n      //   iframe-block.mouseout  →  hideDragAnchor  →  anchor disappears\n      //      ↓ cursor now over empty gap, re-enters iframe\n      //   iframe-block.mouseover →  showDragAnchor  →  anchor reappears\n      //      ↓ cursor now over anchor again\n      //   iframe-block.mouseout  → ... (LOOP = flicker + ungrab-able)\n      //\n      // Safari makes it worse: with 0ms debounce it never even renders\n      // the hand icon because the mouseout fires between paints.\n      //\n      // The 50ms deferred hide gives the re-entering mouseover enough\n      // time to cancel the pending hide, stabilising the anchor while\n      // the cursor is parked over it. See commit 4b8f46ec for the\n      // original Chrome fix — this block restores its 50ms delay that\n      // was silently dropped in a later refactor.\n      // ─────────────────────────────────────────────────────────────────\n      if (this._hideTimeout) {\n        clearTimeout(this._hideTimeout);\n      }\n      this._hideTimeout = setTimeout(function () {\n        _this4._hideTimeout = null;\n\n        // Skip if element was re-added to hovering list (mouseover fired before this timeout)\n        if (_this4.hoveringElements.includes(element)) {\n          return;\n        }\n\n        // Remove hover highlight from the element that the mouse left\n        element.removeHoverHightlight();\n\n        // Remove container highlight\n        if (element.container) {\n          element.container.removeContainerHightlight();\n        }\n\n        // Hide drag anchor\n        if (element.getDragAnchor) {\n          element.hideDragAnchor();\n        }\n\n        // Phase 1.1: tear down 'hover'-trigger overlays. Default\n        // getOverlays() returns [] → no-op for non-opt-in elements.\n        element.unmountOverlays('hover');\n\n        // Phase 1.6 — sweep 'hover' overlays off any element that's no\n        // longer in the hovering chain. The per-element unmount above\n        // only catches the LAST-out element's overlays (because the\n        // debounce timeout is shared, so intermediate mouseouts get\n        // their timers cancelled and never reach this body). Without\n        // this sweep, an overlay mounted on an ancestor via the\n        // nearest-mount rule in mouseover gets orphaned when the\n        // cursor leaves its subtree via a descendant's mouseout.\n        _this4.elements.forEach(function (el) {\n          if (el !== element && !_this4.hoveringElements.includes(el)) {\n            el.unmountOverlays('hover');\n          }\n        });\n\n        // If there are still hovering elements, re-highlight the new top element\n        if (_this4.hoveringElements.length > 0) {\n          var topElement = _this4.getTopHoveringElement();\n          if (topElement) {\n            topElement.addHoverHightlight();\n            if (topElement.container) {\n              topElement.container.addContainerHightlight(topElement);\n            }\n            if (topElement.getDragAnchor) {\n              topElement.showDragAnchor();\n            }\n          }\n        }\n      }, 50);\n    }\n  }, {\n    key: \"addHoveringElement\",\n    value: function addHoveringElement(element) {\n      this.hoveringElements.push(element);\n    }\n  }, {\n    key: \"removeHoveringElement\",\n    value: function removeHoveringElement(element) {\n      this.hoveringElements = this.hoveringElements.filter(function (e) {\n        return e !== element;\n      });\n    }\n  }, {\n    key: \"getTopHoveringElement\",\n    value: function getTopHoveringElement() {\n      return this.hoveringElements[0];\n    }\n  }, {\n    key: \"getTopHDraggableElement\",\n    value: function getTopHDraggableElement() {\n      return this.draggableItems[0];\n    }\n  }, {\n    key: \"getDroppableElements\",\n    value: function getDroppableElements() {\n      return this.elements.filter(function (element) {\n        return element.isDroppable();\n      });\n    }\n  }, {\n    key: \"addDragOveringElement\",\n    value: function addDragOveringElement(element) {\n      this.dragOveringElements.push(element);\n    }\n  }, {\n    key: \"removeDragOveringElement\",\n    value: function removeDragOveringElement(element) {\n      this.dragOveringElements = this.dragOveringElements.filter(function (e) {\n        return e !== element;\n      });\n    }\n  }, {\n    key: \"dragOver\",\n    value: function dragOver(element, e) {\n      var draggableItem = this.draggingItem;\n      this.addDragOveringElement(element);\n\n      // Get top drag overing element\n      var topElement = this.getTopDragOveringElement(draggableItem);\n\n      // return if no valid drop target or not the triggering element\n      if (!topElement || element != topElement && !this._isDescendantOf(element, topElement)) {\n        return;\n      }\n\n      // ─────────────────────────────────────────────────────────────────\n      // DROP-TARGET BRANCHING — order matters, read carefully.\n      // ─────────────────────────────────────────────────────────────────\n      //\n      // 1. canDropBefore / canDropAfter (BlockElement)\n      //      The user is hovering an existing block. Highlight ABOVE or\n      //      BELOW the block depending on cursor Y. This is the primary\n      //      placement affordance once the page/cell has any content.\n      //\n      // 2. canDropInside (PageElement / CellElement, EMPTY only)\n      //      Only reached when the user is NOT hovering a block. Lights\n      //      up the whole container. By contract this branch only fires\n      //      when the container is empty — see PageElement.canDropInside\n      //      and CellElement.canDropInside. Once a container has any\n      //      block, drop-inside is disabled and this branch becomes a\n      //      no-op for that container, forcing the user to hover an\n      //      actual block instead. That guarantees the highlight always\n      //      matches the real landing position (no \"whole page lights up\n      //      but block silently lands at the bottom\" bug).\n      //\n      // The else-if (NOT a separate if) is what makes blocks win over\n      // their parent container when both are valid drop targets.\n      // ─────────────────────────────────────────────────────────────────\n\n      // check if the element can drop before or after\n      if (topElement.canDropAfter() || topElement.canDropBefore()) {\n        if (topElement.checkIfThePositionIsBefore(e.clientX, e.clientY)) {\n          if (topElement.canDropBefore()) {\n            // Cursor is in the top half of the hovered block\n            topElement.addDropBeforeHighlight();\n          }\n        } else {\n          if (topElement.canDropAfter()) {\n            // Cursor is in the bottom half of the hovered block\n            topElement.addDropAfterHighlight();\n          }\n        }\n\n        //\n        if (element.container) {\n          // Add hover highlight to its container\n          element.container.addContainerDropHightlight();\n          if (element.container.container) {\n            // Add hover highlight to its container\n            element.container.container.addContainerDropHightlight();\n          }\n        }\n      }\n\n      // Check if the element can drop inside\n      // (only true for EMPTY PageElement / CellElement — see comment above)\n      else if (topElement.canDropInside()) {\n        topElement.addDropInsideHighlight();\n\n        //\n        if (element.container) {\n          // Add hover highlight to its container\n          element.container.addContainerDropHightlight();\n          if (element.container.container) {\n            // Add hover highlight to its container\n            element.container.container.addContainerDropHightlight();\n          }\n        }\n      }\n    }\n  }, {\n    key: \"drop\",\n    value: function drop(element, e) {\n      var _this5 = this;\n      var draggableItem = this.draggingItem;\n      if (!draggableItem) {\n        console.warn('No draggable item to drop');\n        return;\n      }\n      var topElement = this.getTopDragOveringElement(draggableItem);\n\n      // release the dragging item\n      this.draggingItem = null;\n      if (!topElement) {\n        return;\n      }\n\n      // ─── PLAN_UNDO_REDO — drag-drop reorder = ONE entry ────────────\n      //\n      // When an EXISTING block is dragged to a new position, the drop\n      // flow fires TWO structural mutations:\n      //   1. addBlockAfter/Before/Inside  → structure:add commit\n      //   2. draggableItem.remove()       → structure:remove commit\n      //      (async — fires after 300 ms fadeOut)\n      //\n      // Without a transaction, history sees 2 entries (\"Add Block\" +\n      // \"Delete Block\"). Semantically it's ONE user intent: move. So\n      // we wrap both commits in a transaction labelled structure:move.\n      // Both individual commits get silenced inside the tx; a single\n      // \"Move <Type>\" entry is pushed at endTransaction.\n      //\n      // Widget drop from sidebar → removeAfterDrop() === false → no tx\n      // (a single \"Add <Type>\" entry is the correct semantics).\n      //\n      // The endTransaction is scheduled after the fadeOut duration so\n      // it always fires AFTER remove()'s commit attempt. 400 ms = 300\n      // fadeOut + 100 buffer. autoCloseTxMs (5000) is a safety net if\n      // the setTimeout is dropped.\n      var isReorder = typeof draggableItem.removeAfterDrop === 'function' && draggableItem.removeAfterDrop();\n      if (isReorder && this.builder.history) {\n        this.builder.history.beginTransaction('history.structure_move', {\n          change: 'structure:move',\n          elementType: typeof draggableItem.getName === 'function' ? draggableItem.getName() : undefined,\n          source: 'drag-drop'\n        });\n      }\n\n      // remove dropover highlight\n      topElement.removeDropHighlight();\n\n      // return if current element is not the top one (or a descendant of it)\n      if (topElement != element && !this._isDescendantOf(element, topElement)) {\n        return;\n      }\n\n      // Mirrors the dragOver() branching — same precedence rules apply:\n      //   1. drop above/below an existing block (canDropBefore/After)\n      //   2. drop inside an EMPTY container (canDropInside)\n      // If the user is hovering the page background of a non-empty page,\n      // both branches are false here and the drop is a no-op (intentional).\n      // check if the element can drop before or after\n      if (topElement.canDropAfter() || topElement.canDropBefore()) {\n        if (topElement.checkIfThePositionIsBefore(e.clientX, e.clientY)) {\n          if (topElement.canDropBefore()) {\n            // Cursor is in the top half of the hovered block\n            this.addBlockBefore(topElement.container, topElement, draggableItem.renderBlock());\n          }\n        } else {\n          if (topElement.canDropAfter()) {\n            // Cursor is in the bottom half of the hovered block\n            this.addBlockAfter(topElement.container, topElement, draggableItem.renderBlock());\n          }\n        }\n\n        //\n        if (topElement.container) {\n          // Add hover highlight to its container\n          topElement.container.removeContainerDropHightlight();\n          if (topElement.container.container) {\n            // Add hover highlight to its container\n            topElement.container.container.removeContainerDropHightlight();\n          }\n        }\n\n        // remove current element\n        if (draggableItem.removeAfterDrop()) {\n          // remove \n          draggableItem.remove();\n        }\n      }\n\n      // Check if the element can drop inside\n      else if (topElement.canDropInside()) {\n        this.addBlockInside(topElement, draggableItem.renderBlock());\n\n        //\n        if (topElement.container) {\n          // Add hover highlight to its container\n          topElement.container.removeContainerDropHightlight();\n          if (topElement.container.container) {\n            // Add hover highlight to its container\n            topElement.container.container.removeContainerDropHightlight();\n          }\n        }\n\n        // remove current element\n        if (draggableItem.removeAfterDrop()) {\n          // remove\n          draggableItem.remove();\n        }\n      }\n\n      // cleanup effects\n      this.elements.forEach(function (el) {\n        el.removeSelectedHighlight();\n        el.removeDropHighlight();\n        el.removeContainerHightlight();\n        el.removeContainerDropHightlight();\n        el.removeHoverHightlight();\n        // hide drag anchor\n        if (el.getDragAnchor) {\n          el.hideDragAnchor();\n        }\n      });\n\n      // PLAN_UNDO_REDO — close the move transaction AFTER remove()'s\n      // fadeOut (300 ms) + its trailing commit. 400 ms gives 100 ms\n      // buffer. endTransaction pushes ONE entry via the label we set\n      // at begin ('history.structure_move'). If the drop was not a\n      // reorder (widget from sidebar), no tx was opened → this is a\n      // no-op.\n      if (isReorder && this.builder.history) {\n        setTimeout(function () {\n          _this5.builder.history.endTransaction();\n        }, 400);\n      }\n    }\n  }, {\n    key: \"addBlockAfter\",\n    value: function addBlockAfter(container, referenceBlock, block) {\n      // Host injection — block came from BaseWidget.renderBlock() →\n      // BlockElement.parse() and has not yet been adopted. Adopt\n      // BEFORE the container mounts it so its overlays + control\n      // emissions can reach `this.host` from the very first render().\n      if (this.builder && typeof this.builder._adopt === 'function') {\n        this.builder._adopt(block);\n      }\n\n      // Surgical insert — container.addBlockAfter now does BOTH the\n      // array splice AND the DOM mount + UIManager registration (see\n      // PageElement / CellElement). The pre-fix `container.render()`\n      // here triggered a page-wide cascade re-render that round-\n      // tripped every sibling's text through the HTML5 fragment\n      // parser — see BlockElement.removeElement notes for the\n      // customer-visible data-loss bug that caused.\n      container.addBlockAfter(block, referenceBlock);\n      block.fadeIn();\n      this._commitStructureAdd(block);\n    }\n  }, {\n    key: \"addBlockBefore\",\n    value: function addBlockBefore(container, referenceBlock, block) {\n      if (this.builder && typeof this.builder._adopt === 'function') {\n        this.builder._adopt(block);\n      }\n      container.addBlockBefore(block, referenceBlock);\n      block.fadeIn();\n      this._commitStructureAdd(block);\n    }\n  }, {\n    key: \"addBlockInside\",\n    value: function addBlockInside(topElement, block) {\n      if (this.builder && typeof this.builder._adopt === 'function') {\n        this.builder._adopt(block);\n      }\n      // Append block inside. `appendBlock` now both pushes to the\n      // container's `blocks`/`elements` array AND mounts the DOM\n      // (PageElement._mountBlockDom / CellElement._mountChildBlockDom).\n      topElement.appendBlock(block);\n      block.fadeIn();\n      this._commitStructureAdd(block);\n    }\n\n    /** PLAN_UNDO_REDO — shared helper for the 3 addBlock* drop paths.\n     *  Use getName() for the display name (subclass override) — not the\n     *  raw class name — so the history dropdown shows \"Add Block\" not\n     *  \"Add BlockElement\". */\n  }, {\n    key: \"_commitStructureAdd\",\n    value: function _commitStructureAdd(block) {\n      if (!this.builder.history) return;\n      var elementType = typeof (block === null || block === void 0 ? void 0 : block.getName) === 'function' ? block.getName() : undefined;\n      this.builder.history.commit('history.structure_add', {\n        change: 'structure:add',\n        elementUid: block === null || block === void 0 ? void 0 : block.id,\n        elementType: elementType,\n        source: 'drag-drop'\n      });\n\n      // CD-3 (AIBuilder Wave 4) — emit element:added at the structure-mutation\n      // chokepoint, NOT through HistoryManager (which dedupes identical-data\n      // commits). A Layers tree subscriber (Wave 14) needs to see every add\n      // even if undo/redo brings the JSON back to a byte-equal prior state.\n      if (this.builder.events && (block === null || block === void 0 ? void 0 : block.id) != null) {\n        var _window$Builder$EVENT, _window$Builder;\n        this.builder.events.emit((_window$Builder$EVENT = (_window$Builder = window.Builder) === null || _window$Builder === void 0 || (_window$Builder = _window$Builder.EVENTS) === null || _window$Builder === void 0 ? void 0 : _window$Builder.ELEMENT_ADDED) !== null && _window$Builder$EVENT !== void 0 ? _window$Builder$EVENT : 'element:added', {\n          elementUid: block.id,\n          elementType: elementType\n        });\n      }\n    }\n  }, {\n    key: \"dragLeave\",\n    value: function dragLeave(element) {\n      this.removeDragOveringElement(element);\n\n      // just remove the drop highlight\n      element.removeDropHighlight();\n\n      //\n      if (element.container) {\n        // Add hover highlight to its container\n        element.container.removeContainerDropHightlight();\n        if (element.container.container) {\n          // Add hover highlight to its container\n          element.container.container.removeContainerDropHightlight();\n        }\n      }\n    }\n  }, {\n    key: \"getTopDragOveringElement\",\n    value: function getTopDragOveringElement(draggableItem) {\n      var top = this.dragOveringElements[0];\n      if (!top) return null;\n      if (draggableItem && typeof draggableItem.canDropOn === 'function') {\n        // First try the directly hovered elements\n        var direct = this.dragOveringElements.find(function (e) {\n          return draggableItem.canDropOn(e);\n        });\n        if (direct) return direct;\n\n        // Walk up the container chain from the top element to find a valid drop target\n        var current = top.container;\n        while (current) {\n          if (draggableItem.canDropOn(current)) {\n            return current;\n          }\n          current = current.container;\n        }\n        return null;\n      }\n      return top;\n    }\n  }, {\n    key: \"addDraggableItem\",\n    value: function addDraggableItem(draggableItem) {\n      var _this6 = this;\n      this.draggableItems.push(draggableItem);\n\n      // Phase 1.6 — elements with a Canvas Overlay-backed drag anchor\n      // (BlockElement via BlockDragAnchorOverlay) wire their OWN dragstart\n      // inside the overlay's onDragStart hook, which then hands off to\n      // `uiManager.dragStart(block)`. Skip the legacy anchor-wiring path\n      // entirely so the element's hover-triggered overlay is authoritative.\n      //\n      // Widgets (BaseWidget subclasses) do NOT implement usesOverlayDragAnchor,\n      // so they stay on the legacy path below — their `domNode` itself is\n      // the draggable source.\n      //\n      // See docs/core/OVERLAY.md §7.4 + docs/archived/OVERLAY_PLAN.md §3.7 + §4.I2 (pointer\n      // events ⊥ HTML5 DnD — NativeDragHandleOverlay handles the ghost\n      // workaround for Safari independently).\n      if (typeof draggableItem.usesOverlayDragAnchor === 'function' && draggableItem.usesOverlayDragAnchor()) {\n        return;\n      }\n\n      //\n      // draggableItem.getDragAnchor().setAttribute('draggable', true);\n\n      //\n      draggableItem.addDragAnchor();\n\n      // handle dragstart event\n      draggableItem.getDragAnchor().addEventListener('dragstart', function (e) {\n        if (_this6.draggingItem != null) {\n          return;\n        }\n\n        // ─────────────────────────────────────────────────────────────\n        // DRAG GHOST — Chrome vs Safari paths\n        // ─────────────────────────────────────────────────────────────\n        // Chrome/Firefox/Edge: default drag image capture works fine\n        //   → just set dataTransfer.setData + effectAllowed. DO NOT\n        //     touch setDragImage on Chrome — user confirmed it works.\n        //\n        // Safari: automatic drag image capture SILENTLY FAILS when\n        //   the draggable element is clipped by an ancestor's\n        //   `overflow: hidden` or `overflow-y: scroll`. Both apply\n        //   to `.widget-item`:\n        //     .widgets-box     { overflow: hidden }\n        //       .widget-items  { overflow-y: scroll }\n        //         .widget-item { overflow: hidden; position: static }\n        //   So Safari gets an empty ghost.\n        //\n        //   Known workaround: clone the draggable element into\n        //   document.body (off-screen but rendered) and pass the\n        //   clone to setDragImage. Since the clone is a direct\n        //   child of body with no clipping ancestor, Safari can\n        //   snapshot it cleanly. Remove the clone on next tick —\n        //   Safari has already captured it.\n        //\n        // We gate the clone workaround on Safari-only user-agent\n        // detection so we do not risk regressing Chrome's path.\n        //\n        // See docs/BUILDER.md → Design Lessons 11 + 12.\n        // ─────────────────────────────────────────────────────────────\n        if (e.dataTransfer) {\n          try {\n            e.dataTransfer.setData('text/plain', '');\n            e.dataTransfer.effectAllowed = 'all';\n\n            // Safari-only: clone workaround for scroll-container bug.\n            var ua = typeof navigator !== 'undefined' && navigator.userAgent || '';\n            var isSafari = /safari/i.test(ua) && !/chrome|chromium|crios|android/i.test(ua);\n            if (isSafari && typeof e.dataTransfer.setDragImage === 'function') {\n              var anchor = draggableItem.getDragAnchor();\n              if (anchor) {\n                var rect = anchor.getBoundingClientRect();\n                if (rect.width > 0 && rect.height > 0) {\n                  var clone = anchor.cloneNode(true);\n                  var computed = getComputedStyle(anchor);\n                  Object.assign(clone.style, {\n                    position: 'fixed',\n                    top: '0',\n                    // Render off-screen (negative left) but\n                    // NOT display:none — Safari needs a real\n                    // rendered element for the snapshot.\n                    left: '-10000px',\n                    width: rect.width + 'px',\n                    height: rect.height + 'px',\n                    margin: '0',\n                    padding: computed.padding,\n                    background: computed.backgroundColor || '#ffffff',\n                    color: computed.color,\n                    fontFamily: computed.fontFamily,\n                    fontSize: computed.fontSize,\n                    border: computed.border,\n                    borderRadius: computed.borderRadius,\n                    boxShadow: '0 8px 24px rgba(0,0,0,0.18)',\n                    pointerEvents: 'none',\n                    opacity: '0.95',\n                    zIndex: '-1'\n                  });\n                  document.body.appendChild(clone);\n                  e.dataTransfer.setDragImage(clone, rect.width / 2, rect.height / 2);\n                  // Remove on next microtask — Safari has\n                  // already captured the snapshot by then.\n                  setTimeout(function () {\n                    if (clone.parentNode) {\n                      clone.parentNode.removeChild(clone);\n                    }\n                  }, 0);\n                }\n              }\n            }\n            // Chrome path: do NOT call setDragImage — default\n            // capture works and user explicitly confirmed it.\n          } catch (_) {\n            // Non-fatal — fall through to browser default\n          }\n        }\n        _this6.dragStart(draggableItem);\n      });\n    }\n  }, {\n    key: \"removeDraggableItem\",\n    value: function removeDraggableItem(object) {\n      this.draggableItems = this.draggableItems.filter(function (e) {\n        return e !== object;\n      });\n    }\n  }, {\n    key: \"getDraggableItemByIndex\",\n    value: function getDraggableItemByIndex(index) {\n      return this.draggableItems[index];\n    }\n  }, {\n    key: \"dragStart\",\n    value: function dragStart(draggableItem) {\n      this.draggingItem = draggableItem;\n\n      // clear drag over elements\n      this.dragOveringElements = [];\n\n      // remove hover effects\n      this.elements.forEach(function (el) {\n        el.removeHoverHightlight();\n        el.removeDropHighlight();\n        el.removeContainerHightlight();\n        el.removeContainerDropHightlight();\n      });\n\n      // Legacy drag-source (widgets): hide the anchor 100 ms after dragstart.\n      // Overlay drag-source (blocks via BlockDragAnchorOverlay): the overlay\n      // self-destroys in its own onDragStart hook (identical 100 ms timer),\n      // so `hideDragAnchor` is intentionally missing on the element — guard\n      // here preserves the contract without try/catch pollution.\n      setTimeout(function () {\n        if (typeof draggableItem.hideDragAnchor === 'function') {\n          draggableItem.hideDragAnchor();\n        }\n      }, 100);\n    }\n  }, {\n    key: \"removeElement\",\n    value: function removeElement(element) {\n      this.elements = this.elements.filter(function (e) {\n        return e !== element;\n      });\n      this.removeDragOveringElement(element);\n      this.removeHoveringElement(element);\n      this.removeDraggableItem(element);\n    }\n  }, {\n    key: \"_isDescendantOf\",\n    value: function _isDescendantOf(element, ancestor) {\n      var current = element.container;\n      while (current) {\n        if (current === ancestor) return true;\n        current = current.container;\n      }\n      return false;\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (UIManager);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/UIManager.js?");

/***/ }),

/***/ "./src/includes/VideoElement.js":
/*!**************************************!*\
  !*** ./src/includes/VideoElement.js ***!
  \**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n/**\n * Style keys the template consumes via `formatter.toStyleStringAll(...)`.\n * Kept in sync with `Video.template.html` so the cheap in-place style update\n * matches exactly what a full render would emit.\n */\nvar CSS_KEYS = ['width', 'height', 'border_top_style', 'border_top_width', 'border_top_color', 'border_right_style', 'border_right_width', 'border_right_color', 'border_bottom_style', 'border_bottom_width', 'border_bottom_color', 'border_left_style', 'border_left_width', 'border_left_color', 'border_radius'];\nvar VideoElement = /*#__PURE__*/function (_BaseElement) {\n  function VideoElement(template, src) {\n    var _this;\n    _classCallCheck(this, VideoElement);\n    _this = _callSuper(this, VideoElement);\n    _this.template = template;\n    _this.src = src;\n    _this.domNode = null;\n\n    // required keys for the element template\n    _this.requiredTemplateKeys = ['src'];\n    _this.formatter = new Formatter({\n      width: null,\n      height: null,\n      align: 'center',\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      border_radius: 0\n    });\n    return _this;\n  }\n  _inherits(VideoElement, _BaseElement);\n  return _createClass(VideoElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.video');\n    }\n\n    /**\n     * Full render — rebuilds the iframe DOM from the template. Used only when\n     * structure changes (empty-state ↔ video, initial mount). For format-only\n     * changes call `applyFormatStyles()` instead — it keeps the existing\n     * `<video>` element alive so canvas selection/hover overlays, loaded media,\n     * and listeners don't churn.\n     *\n     * W0.2a: scaffold + return migrated to BaseElement.render() lifecycle.\n     */\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        src: this.src ? this.transferMediaAbsUrl(this.src) : ''\n      });\n\n      // Re-wire canvas listeners since `<video>` is a fresh element.\n      this._wireCanvasVideoListeners();\n    }\n\n    /**\n     * Cheap, structure-preserving update. Reads CSS keys from the formatter\n     * and patches the existing `<video>` / placeholder `style` attribute +\n     * the wrapper's `justify-content` for align. No innerHTML swap → no\n     * listener re-registration, no selection-overlay flicker.\n     *\n     * Falls back to full `render()` only when the domNode hasn't been mounted\n     * yet (first paint).\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      if (!this.domNode || !this.domNode.firstElementChild) {\n        this.render();\n        return;\n      }\n\n      // Outer flex wrapper — controls alignment.\n      var wrapper = this.domNode.firstElementChild;\n      var align = this.formatter.getFormat('align', 'center');\n      wrapper.style.justifyContent = align;\n\n      // Inner visible node: the real <video> when src is set, else the\n      // `.bjs-video-placeholder` empty-state box. Both accept the same CSS\n      // so they use the same style string.\n      var target = this.domNode.querySelector('video, .bjs-video-placeholder');\n      if (!target) return;\n\n      // Rewrite only the formatter-driven portion of the style attribute,\n      // preserving any static declarations the template put in front\n      // (display, max-width, box-shadow, border color overlays, etc.).\n      var dynamic = this.formatter.toStyleStringAll(CSS_KEYS);\n      target.setAttribute('data-bjs-dyn-style', dynamic);\n      this._rebuildStyle(target);\n    }\n\n    /**\n     * The template's inline `style` has two halves:\n     *   (1) a static prefix authored in the .html template (layout + chrome)\n     *   (2) a dynamic suffix computed from the formatter\n     * On first paint we capture (1) into `data-bjs-static-style` so later\n     * `applyFormatStyles()` calls can rewrite (2) without touching (1).\n     */\n  }, {\n    key: \"_rebuildStyle\",\n    value: function _rebuildStyle(target) {\n      var staticPart = target.getAttribute('data-bjs-static-style');\n      if (staticPart === null) {\n        // Capture once: everything currently in `style` that ISN'T a\n        // formatter key. We approximate by stripping the dynamic half\n        // (safe because we control the template ordering — dynamic is\n        // appended after ` max-width: 100%; `).\n        staticPart = target.getAttribute('style') || '';\n        target.setAttribute('data-bjs-static-style', staticPart);\n      }\n      var dynamic = target.getAttribute('data-bjs-dyn-style') || '';\n      target.setAttribute('style', \"\".concat(staticPart, \" \").concat(dynamic));\n    }\n  }, {\n    key: \"_wireCanvasVideoListeners\",\n    value: function _wireCanvasVideoListeners() {\n      var _this2 = this;\n      var videoEl = this.domNode && this.domNode.querySelector('video');\n      if (!videoEl || !this.src) {\n        this._setStatus('idle');\n        return;\n      }\n      this._setStatus('loading');\n      videoEl.addEventListener('loadedmetadata', function () {\n        return _this2._setStatus('success');\n      }, {\n        once: true\n      });\n      videoEl.addEventListener('error', function () {\n        var err = videoEl.error;\n        _this2._setStatus('error', err && err.code);\n      }, {\n        once: true\n      });\n    }\n  }, {\n    key: \"_setStatus\",\n    value: function _setStatus(kind, errorCode) {\n      var node = this._statusNode;\n      if (!node || !node.isConnected) return;\n      if (kind === 'idle') {\n        node.hidden = true;\n        node.className = 'bjs-video-status';\n        node.innerHTML = '';\n        return;\n      }\n      var variant = 'info';\n      var icon = 'hourglass_empty';\n      var key = 'video.load_pending';\n      if (kind === 'success') {\n        variant = 'success';\n        icon = 'check_circle';\n        key = 'video.load_ok';\n      } else if (kind === 'error') {\n        variant = 'error';\n        icon = 'error';\n        switch (errorCode) {\n          case 1:\n            key = 'video.err_aborted';\n            break;\n          case 2:\n            key = 'video.err_network';\n            break;\n          case 3:\n            key = 'video.err_decode';\n            break;\n          case 4:\n            key = 'video.err_src_unsupported';\n            break;\n          default:\n            key = 'video.load_error';\n        }\n      }\n      node.hidden = false;\n      node.className = \"bjs-info-banner bjs-info-banner--\".concat(variant, \" bjs-video-status\");\n      node.innerHTML = \"\\n            <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\".concat(icon, \"</span>\\n            <span class=\\\"bjs-info-banner-text\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key), \"</span>\\n        \");\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(VideoElement, \"getData\", this, 3)([])), {}, {\n        src: this.src\n      });\n    }\n  }, {\n    key: \"buildDimensionControl\",\n    value: function buildDimensionControl(label, key) {\n      var _this3 = this;\n      return new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](label, this.formatter.getFormat(key), {\n        units: ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'],\n        onChange: function onChange(serialized) {\n          _this3.formatter.setFormat(key, serialized);\n          // Structure-preserving: keep the same <video> element so\n          // loading/selection state survives a width/height tweak.\n          _this3.applyFormatStyles();\n        }\n      });\n    }\n  }, {\n    key: \"buildUrlControl\",\n    value: function buildUrlControl() {\n      var _this4 = this;\n      var node = document.createElement('div');\n      node.innerHTML = \"\\n            <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n                <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n                <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.url_banner'), \"</span>\\n            </div>\\n            <div class=\\\"bjs-control-stack\\\">\\n                <label class=\\\"bjs-control-label\\\" for=\\\"video-url-input\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.video_url'), \"</label>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-link-input\\\">\\n                        <input type=\\\"url\\\"\\n                            id=\\\"video-url-input\\\"\\n                            name=\\\"video-url\\\"\\n                            class=\\\"bjs-text-input\\\"\\n                            placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.url_placeholder'), \"\\\"\\n                            value=\\\"\").concat((this.src || '').replace(/\"/g, '&quot;'), \"\\\"\\n                            autocomplete=\\\"url\\\">\\n                        <button type=\\\"button\\\"\\n                            class=\\\"bjs-icon-btn\\\"\\n                            data-control=\\\"clear\\\"\\n                            aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.clear'), \"\\\"\\n                            \").concat(this.src ? '' : 'hidden', \">\\n                            <span class=\\\"material-symbols-rounded\\\">close</span>\\n                        </button>\\n                    </div>\\n                    <span class=\\\"bjs-link-error\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-video-status\\\" role=\\\"status\\\" aria-live=\\\"polite\\\" hidden></div>\\n        \");\n      var input = node.querySelector('input');\n      var clearBtn = node.querySelector('[data-control=\"clear\"]');\n      var errorSpan = node.querySelector('.bjs-link-error');\n      this._statusNode = node.querySelector('.bjs-video-status');\n      var isSyntacticallyValid = function isSyntacticallyValid(v) {\n        if (!v) return true;\n        return /^(https?:\\/\\/|\\/|\\.{0,2}\\/|blob:|data:)/i.test(v.trim());\n      };\n      var debounceId = null;\n      var commit = function commit() {\n        var v = input.value.trim();\n        var prevHadSrc = !!_this4.src;\n        _this4.src = v;\n        clearBtn.hidden = !v;\n        if (!isSyntacticallyValid(v)) {\n          input.classList.add('is-error');\n          errorSpan.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('video.invalid_url');\n          _this4._setStatus('idle');\n          return;\n        }\n        input.classList.remove('is-error');\n        errorSpan.textContent = '';\n\n        // Src change = structure change (empty-state ↔ <video>, or swap\n        // in a new video resource) → full render is the right path.\n        // Dimension/border/align changes go through applyFormatStyles().\n        var structureChanged = prevHadSrc !== !!v || prevHadSrc;\n        if (structureChanged) {\n          _this4.render();\n        } else {\n          _this4.applyFormatStyles();\n        }\n      };\n      input.addEventListener('input', function () {\n        if (debounceId) clearTimeout(debounceId);\n        clearBtn.hidden = !input.value.trim();\n        input.classList.remove('is-error');\n        errorSpan.textContent = '';\n        debounceId = setTimeout(commit, 350);\n      });\n      input.addEventListener('blur', function () {\n        if (debounceId) {\n          clearTimeout(debounceId);\n          debounceId = null;\n        }\n        commit();\n      });\n      clearBtn.addEventListener('click', function () {\n        input.value = '';\n        commit();\n        input.focus();\n      });\n      if (this.src) this._wireCanvasVideoListeners();\n      return {\n        domNode: node\n      };\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this5 = this;\n      return [this.buildUrlControl(), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), 'width'), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), 'height'), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n        setValue: function setValue(value) {\n          _this5.formatter.setFormat('align', value);\n          _this5.applyFormatStyles();\n        }\n      }, ['left', 'center', 'right']), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style', ''),\n        border_top_width: this.formatter.getFormat('border_top_width', ''),\n        border_top_color: this.formatter.getFormat('border_top_color', ''),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style', ''),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width', ''),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color', ''),\n        border_left_style: this.formatter.getFormat('border_left_style', ''),\n        border_left_width: this.formatter.getFormat('border_left_width', ''),\n        border_left_color: this.formatter.getFormat('border_left_color', ''),\n        border_right_style: this.formatter.getFormat('border_right_style', ''),\n        border_right_width: this.formatter.getFormat('border_right_width', ''),\n        border_right_color: this.formatter.getFormat('border_right_color', '')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this5.formatter.setFormat('border_top_style', border_top_style);\n          _this5.formatter.setFormat('border_top_width', border_top_width);\n          _this5.formatter.setFormat('border_top_color', border_top_color);\n          _this5.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this5.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this5.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this5.formatter.setFormat('border_left_style', border_left_style);\n          _this5.formatter.setFormat('border_left_width', border_left_width);\n          _this5.formatter.setFormat('border_left_color', border_left_color);\n          _this5.formatter.setFormat('border_right_style', border_right_style);\n          _this5.formatter.setFormat('border_right_width', border_right_width);\n          _this5.formatter.setFormat('border_right_color', border_right_color);\n          _this5.applyFormatStyles();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius', 0), {\n        setRadius: function setRadius(v) {\n          _this5.formatter.setFormat('border_radius', v);\n          _this5.applyFormatStyles();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.src), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VideoElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/VideoElement.js?");

/***/ }),

/***/ "./src/includes/VideoWidget.js":
/*!*************************************!*\
  !*** ./src/includes/VideoWidget.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _VideoElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VideoElement.js */ \"./src/includes/VideoElement.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar VideoWidget = /*#__PURE__*/function (_BaseWidget) {\n  function VideoWidget() {\n    var _this;\n    _classCallCheck(this, VideoWidget);\n    _this = _callSuper(this, VideoWidget); // Call the parent class constructor\n\n    // Add a VideoElement to the widget.\n    // No default URL: the upstream demo link (media.w3.org/2010/.../trailer.mp4)\n    // is dead, and showing a broken video on first drop is worse than an empty\n    // state. The empty-state template renders an illustration + \"paste a URL\"\n    // hint, which is also the better onboarding.\n    var video = new _VideoElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('Video', '');\n\n    // Append the new element to the block\n    _this.block.appendElements([video]);\n    return _this;\n  }\n  _inherits(VideoWidget, _BaseWidget);\n  return _createClass(VideoWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.video');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'videocam';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VideoWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/VideoWidget.js?");

/***/ }),

/***/ "./src/includes/WelcomeWidget.js":
/*!***************************************!*\
  !*** ./src/includes/WelcomeWidget.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\nvar WelcomeWidget = /*#__PURE__*/function (_BaseWidget) {\n  function WelcomeWidget() {\n    var _this;\n    _classCallCheck(this, WelcomeWidget);\n    _this = _callSuper(this, WelcomeWidget); // Call the parent class constructor\n\n    // Add elements to the widget\n    var h1 = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h1', 'Welcome!');\n    var p = new _PElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]('P', 'This is a welcome message!');\n    p.formatter.setFormat('text_align', 'center');\n\n    // Append the new elements to the block\n    _this.block.appendElements([h1, p]);\n    return _this;\n  }\n  _inherits(WelcomeWidget, _BaseWidget);\n  return _createClass(WelcomeWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.welcome');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'history_edu';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (WelcomeWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/WelcomeWidget.js?");

/***/ }),

/***/ "./src/includes/WidgetsBox.js":
/*!************************************!*\
  !*** ./src/includes/WidgetsBox.js ***!
  \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar WidgetsBox = /*#__PURE__*/function () {\n  // host-injection: Builder passes itself so widget drag-registration\n  // can route through the per-instance UIManager instead of a bare-\n  // builder global. Multi-instance safe.\n  function WidgetsBox(container) {\n    var host = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n    _classCallCheck(this, WidgetsBox);\n    this.container = container;\n    this.host = host;\n    this.widgetGroups = {};\n    this.groupHeaders = {};\n    this.widgetItemsContainer;\n  }\n\n  /**\n   * Attach a custom banner to a group, rendered between the group title\n   * and the widget grid. Useful for showing context (e.g. info card).\n   *\n   * @param {string} group   Group name (must match the one used in addWidget).\n   * @param {string|HTMLElement|Function} content\n   *        - string:      raw HTML\n   *        - HTMLElement: appended as-is\n   *        - function:    called at render time, must return string or HTMLElement\n   */\n  return _createClass(WidgetsBox, [{\n    key: \"setGroupHeader\",\n    value: function setGroupHeader(group, content) {\n      this.groupHeaders[group] = content;\n    }\n  }, {\n    key: \"addWidget\",\n    value: function addWidget(widget) {\n      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n      // group\n      if (typeof options.group === 'undefined') {\n        options.group = 'Basic';\n      }\n\n      // display type\n      if (typeof options.type === 'undefined') {\n        widget.type = 'icon';\n      } else {\n        widget.type = options.type;\n      }\n      if (typeof this.widgetGroups[options.group] === 'undefined') {\n        this.widgetGroups[options.group] = [];\n      }\n      if (typeof options.index === 'number' && options.index >= 0 && options.index <= this.widgetGroups[options.group].length) {\n        this.widgetGroups[options.group].splice(options.index, 0, widget);\n      } else {\n        this.widgetGroups[options.group].push(widget);\n      }\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      if (!this.widgetItemsContainer) {\n        var wrapper = document.createElement('div');\n        wrapper.innerHTML = \"\\n                <div class=\\\"widgets-box shadow-sm rounded-0 bg-white\\\">\\n                    <div class=\\\"widget-header w-100 p-3\\\">\\n                        <div class=\\\"alert alert-light fst-italic rounded-2 bg-light border-0 mb-0\\\">\\n                            \\u2728 \".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets_box.drag_hint'), \"\\n                        </div>\\n                    </div>\\n                    <div class=\\\"widget-items\\\"></div>\\n                </div>\\n            \");\n        this.widgetItemsContainer = wrapper.querySelector('.widget-items');\n        this.container.appendChild(wrapper);\n      }\n\n      //\n      this.widgetItemsContainer.innerHTML = ''; // Clear previous content\n\n      Object.entries(this.widgetGroups).forEach(function (_ref) {\n        var _ref2 = _slicedToArray(_ref, 2),\n          key = _ref2[0],\n          widgets = _ref2[1];\n        var groupDom = document.createElement('div');\n        groupDom.innerHTML = \"\\n                <div class=\\\"widgets-group\\\">\\n                    <div class=\\\"widget-group-header w-100 px-3 d-flex justify-content-between align-items-center cursor-pointer\\\">\\n                        <h6 class=\\\"widget-group-title mb-0 text-nowrap\\\">\".concat(key, \"</h6>\\n                        <hr class=\\\"mx-3 w-100\\\">\\n                        <span class=\\\"material-symbols-rounded toggle-icon\\\" style=\\\"cursor:pointer;\\\">expand_more</span>\\n                    </div>\\n                    <div class=\\\"widget-items-container\\\"><div class=\\\"widget-group-items\\\"></div></div>\\n                </div>\\n            \");\n        var header = groupDom.querySelector('.widget-group-header');\n        var toggleIcon = groupDom.querySelector('.toggle-icon');\n        var groupContent = groupDom.querySelector('.widget-group-items');\n        var groupContainer = groupDom.querySelector('.widget-items-container');\n\n        // Optional banner above the widget grid\n        var headerContent = _this.groupHeaders[key];\n        if (headerContent) {\n          var banner = document.createElement('div');\n          banner.className = 'widget-group-banner';\n          var resolved = headerContent;\n          if (typeof resolved === 'function') {\n            resolved = resolved();\n          }\n          if (resolved instanceof HTMLElement) {\n            banner.appendChild(resolved);\n          } else if (typeof resolved === 'string') {\n            banner.innerHTML = resolved;\n          }\n          groupContainer.insertBefore(banner, groupContent);\n        }\n\n        // Initially collapsed\n        // groupContainer.style.display = 'none';\n\n        // Toggle functionality\n        header.addEventListener('click', function () {\n          var isCollapsed = groupContainer.style.display === 'none';\n          if (isCollapsed) {\n            groupContainer.style.display = 'block';\n            toggleIcon.textContent = 'expand_less';\n            // Smooth scroll to this group\n            groupDom.scrollIntoView({\n              behavior: 'smooth',\n              block: 'start'\n            });\n          } else {\n            groupContainer.style.display = 'none';\n            toggleIcon.textContent = 'expand_more';\n          }\n        });\n        widgets.forEach(function (widget) {\n          groupContent.appendChild(widget.render(widget.type));\n          _this.host.uiManager.addDraggableItem(widget);\n        });\n        _this.widgetItemsContainer.appendChild(groupDom);\n      });\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (WidgetsBox);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/WidgetsBox.js?");

/***/ }),

/***/ "./src/includes/YoutubeElement.js":
/*!****************************************!*\
  !*** ./src/includes/YoutubeElement.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseElement_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./BaseElement.js */ \"./src/includes/BaseElement.js\");\n/* harmony import */ var _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BorderRadiusControl.js */ \"./src/includes/BorderRadiusControl.js\");\n/* harmony import */ var _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AlignControl.js */ \"./src/includes/AlignControl.js\");\n/* harmony import */ var _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./DimensionControl.js */ \"./src/includes/DimensionControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n/**\n * Keys that map to CSS on the <iframe> / placeholder. Kept in sync with\n * `Youtube.template.html`; the cheap in-place `applyFormatStyles()` path\n * rewrites only these. See PHASE_2_PLAN §2.8 rule E.\n */\nvar CSS_KEYS = ['width', 'height', 'border_top_style', 'border_top_width', 'border_top_color', 'border_right_style', 'border_right_width', 'border_right_color', 'border_bottom_style', 'border_bottom_width', 'border_bottom_color', 'border_left_style', 'border_left_width', 'border_left_color', 'border_radius'];\nvar YoutubeElement = /*#__PURE__*/function (_BaseElement) {\n  function YoutubeElement(template, url) {\n    var _this;\n    _classCallCheck(this, YoutubeElement);\n    _this = _callSuper(this, YoutubeElement);\n    _this.template = template;\n    _this.url = url;\n    _this.domNode = null;\n    _this.requiredTemplateKeys = ['url'];\n    _this.formatter = new Formatter({\n      width: null,\n      height: null,\n      align: 'center',\n      border_top_style: null,\n      border_top_width: null,\n      border_top_color: null,\n      border_right_style: null,\n      border_right_width: null,\n      border_right_color: null,\n      border_bottom_style: null,\n      border_bottom_width: null,\n      border_bottom_color: null,\n      border_left_style: null,\n      border_left_width: null,\n      border_left_color: null,\n      border_radius: 0\n    });\n    return _this;\n  }\n  _inherits(YoutubeElement, _BaseElement);\n  return _createClass(YoutubeElement, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.youtube');\n    }\n\n    /**\n     * Extract the YouTube video ID from a URL. Supports:\n     *  - https://www.youtube.com/watch?v=ID\n     *  - https://youtu.be/ID\n     *  - https://www.youtube.com/embed/ID\n     *  - https://www.youtube.com/shorts/ID\n     * Returns null when the URL is missing / malformed / not a YouTube URL.\n     */\n  }, {\n    key: \"getYouTubeVideoId\",\n    value: function getYouTubeVideoId() {\n      if (!this.url) return null;\n      try {\n        var parsedUrl = new URL(this.url);\n        if (parsedUrl.hostname === 'youtu.be') {\n          return parsedUrl.pathname.slice(1) || null;\n        }\n        if (parsedUrl.hostname.includes('youtube.com')) {\n          if (parsedUrl.pathname.startsWith('/embed/')) {\n            return parsedUrl.pathname.slice('/embed/'.length) || null;\n          }\n          if (parsedUrl.pathname.startsWith('/shorts/')) {\n            return parsedUrl.pathname.slice('/shorts/'.length) || null;\n          }\n          return parsedUrl.searchParams.get('v') || null;\n        }\n        return null;\n      } catch (e) {\n        return null;\n      }\n    }\n  }, {\n    key: \"_doRender\",\n    value: function _doRender() {\n      var _this$getYouTubeVideo;\n      // formatter auto-merged (W0.2c)\n      this.domNode.innerHTML = this.renderTemplate({\n        youtubeID: (_this$getYouTubeVideo = this.getYouTubeVideoId()) !== null && _this$getYouTubeVideo !== void 0 ? _this$getYouTubeVideo : false\n      });\n    }\n\n    /**\n     * Cheap, structure-preserving update for format-only changes (dimension,\n     * align, border, radius). Keeps the existing <iframe>/placeholder DOM\n     * alive so selection/hover overlays don't churn. See PHASE_2_PLAN §2.8 E.\n     */\n  }, {\n    key: \"applyFormatStyles\",\n    value: function applyFormatStyles() {\n      var _target$dataset, _target$dataset$bjsSt;\n      if (!this.domNode || !this.domNode.firstElementChild) {\n        this.render();\n        return;\n      }\n      // Outer flex wrapper — alignment\n      var wrapper = this.domNode.firstElementChild;\n      wrapper.style.justifyContent = this.formatter.getFormat('align', 'center');\n\n      // Inner styled element: <iframe> when embed works, else placeholder\n      var target = this.domNode.querySelector('iframe, .bjs-video-placeholder');\n      if (!target) return;\n      var staticPrefix = (_target$dataset$bjsSt = (_target$dataset = target.dataset).bjsStaticStyle) !== null && _target$dataset$bjsSt !== void 0 ? _target$dataset$bjsSt : _target$dataset.bjsStaticStyle = target.getAttribute('style') || '';\n      target.setAttribute('style', \"\".concat(staticPrefix, \" \").concat(this.formatter.toStyleStringAll(CSS_KEYS)));\n    }\n  }, {\n    key: \"getData\",\n    value: function getData() {\n      return _objectSpread(_objectSpread({}, _superPropGet(YoutubeElement, \"getData\", this, 3)([])), {}, {\n        url: this.url\n      });\n    }\n  }, {\n    key: \"buildDimensionControl\",\n    value: function buildDimensionControl(label, key) {\n      var _this2 = this;\n      return new _DimensionControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](label, this.formatter.getFormat(key), {\n        units: ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'],\n        onChange: function onChange(serialized) {\n          _this2.formatter.setFormat(key, serialized);\n          _this2.applyFormatStyles();\n        }\n      });\n    }\n\n    /**\n     * URL control — `.bjs-text-input` + clear button + 350ms debounce +\n     * synchronous YouTube-ID extraction. No async probe needed (YouTube\n     * embed's error events don't cross the iframe boundary reliably —\n     * see PHASE_2_PLAN §2.8 D). Status comes from the URL's parse result:\n     * - Empty URL → idle (empty-state rendered on canvas).\n     * - URL parses + ID extracted → `.bjs-info-banner--success` with the ID.\n     * - URL set but ID extraction fails → `.bjs-info-banner--error` with\n     *   \"This doesn't look like a YouTube URL — use youtube.com/watch?v=… or youtu.be/…\".\n     */\n  }, {\n    key: \"buildUrlControl\",\n    value: function buildUrlControl() {\n      var _this3 = this;\n      var node = document.createElement('div');\n      node.innerHTML = \"\\n            <div class=\\\"bjs-info-banner\\\" role=\\\"note\\\">\\n                <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">info</span>\\n                <span class=\\\"bjs-info-banner-text\\\">\".concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.url_banner'), \"</span>\\n            </div>\\n            <div class=\\\"bjs-control-stack\\\">\\n                <label class=\\\"bjs-control-label\\\" for=\\\"youtube-url-input\\\">\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.youtube_url'), \"</label>\\n                <div class=\\\"bjs-control-input\\\">\\n                    <div class=\\\"bjs-link-input\\\">\\n                        <input type=\\\"url\\\"\\n                            id=\\\"youtube-url-input\\\"\\n                            name=\\\"youtube-url\\\"\\n                            class=\\\"bjs-text-input\\\"\\n                            placeholder=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.url_placeholder'), \"\\\"\\n                            value=\\\"\").concat((this.url || '').replace(/\"/g, '&quot;'), \"\\\"\\n                            autocomplete=\\\"url\\\">\\n                        <button type=\\\"button\\\"\\n                            class=\\\"bjs-icon-btn\\\"\\n                            data-control=\\\"clear\\\"\\n                            aria-label=\\\"\").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.clear'), \"\\\"\\n                            \").concat(this.url ? '' : 'hidden', \">\\n                            <span class=\\\"material-symbols-rounded\\\">close</span>\\n                        </button>\\n                    </div>\\n                    <span class=\\\"bjs-link-error\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"></span>\\n                </div>\\n            </div>\\n            <div class=\\\"bjs-video-status\\\" role=\\\"status\\\" aria-live=\\\"polite\\\" hidden></div>\\n        \");\n      var input = node.querySelector('input');\n      var clearBtn = node.querySelector('[data-control=\"clear\"]');\n      var errorSpan = node.querySelector('.bjs-link-error');\n      this._statusNode = node.querySelector('.bjs-video-status');\n      var isSyntacticallyValid = function isSyntacticallyValid(v) {\n        if (!v) return true;\n        return /^(https?:\\/\\/|\\/|\\.{0,2}\\/)/i.test(v.trim());\n      };\n      var debounceId = null;\n      var commit = function commit() {\n        var v = input.value.trim();\n        var prevUrl = _this3.url;\n        _this3.url = v;\n        clearBtn.hidden = !v;\n        if (v && !isSyntacticallyValid(v)) {\n          input.classList.add('is-error');\n          errorSpan.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('youtube.invalid_url');\n          _this3._setStatus('idle');\n          return;\n        }\n        input.classList.remove('is-error');\n        errorSpan.textContent = '';\n\n        // Re-render whenever the URL flips between empty/non-empty OR the\n        // extracted video ID changes (src swap). Otherwise structure is\n        // the same — applyFormatStyles would suffice but URL change IS a\n        // structure change for YT, so always render().\n        var structureChanged = !!prevUrl !== !!v || _this3._lastVideoId !== _this3.getYouTubeVideoId();\n        if (structureChanged) _this3.render();\n\n        // Status\n        if (!v) {\n          _this3._setStatus('idle');\n        } else if (_this3.getYouTubeVideoId()) {\n          _this3._setStatus('success');\n          _this3._lastVideoId = _this3.getYouTubeVideoId();\n        } else {\n          _this3._setStatus('error');\n        }\n      };\n      input.addEventListener('input', function () {\n        if (debounceId) clearTimeout(debounceId);\n        clearBtn.hidden = !input.value.trim();\n        input.classList.remove('is-error');\n        errorSpan.textContent = '';\n        debounceId = setTimeout(commit, 350);\n      });\n      input.addEventListener('blur', function () {\n        if (debounceId) {\n          clearTimeout(debounceId);\n          debounceId = null;\n        }\n        commit();\n      });\n      clearBtn.addEventListener('click', function () {\n        input.value = '';\n        commit();\n        input.focus();\n      });\n\n      // Initial status — deferred to `afterRender()` because the status\n      // node isn't in the DOM yet at this point (Builder appends the\n      // control's domNode AFTER getControls() returns, then calls\n      // afterRender — so `_setStatus` would early-out on !isConnected).\n      var initialStatus = this.url ? this.getYouTubeVideoId() ? 'success' : 'error' : 'idle';\n      return {\n        domNode: node,\n        afterRender: function afterRender() {\n          _this3._setStatus(initialStatus);\n        }\n      };\n    }\n  }, {\n    key: \"_setStatus\",\n    value: function _setStatus(kind) {\n      var node = this._statusNode;\n      if (!node || !node.isConnected) return;\n      if (kind === 'idle') {\n        node.hidden = true;\n        node.className = 'bjs-video-status';\n        node.innerHTML = '';\n        return;\n      }\n      var variant, icon, textKey;\n      if (kind === 'success') {\n        variant = 'success';\n        icon = 'check_circle';\n        textKey = 'youtube.extract_ok';\n      } else {\n        variant = 'error';\n        icon = 'error';\n        textKey = 'youtube.extract_failed';\n      }\n      var text = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(textKey);\n      node.hidden = false;\n      node.className = \"bjs-info-banner bjs-info-banner--\".concat(variant, \" bjs-video-status\");\n      node.innerHTML = \"\\n            <span class=\\\"material-symbols-rounded bjs-info-banner-icon\\\" aria-hidden=\\\"true\\\">\".concat(icon, \"</span>\\n            <span class=\\\"bjs-info-banner-text\\\">\").concat(text, \"</span>\\n        \");\n    }\n  }, {\n    key: \"getControls\",\n    value: function getControls() {\n      var _this4 = this;\n      return [this.buildUrlControl(), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.width'), 'width'), this.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.height'), 'height'), new _AlignControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.alignment'), this.formatter.getFormat('align'), {\n        setValue: function setValue(value) {\n          _this4.formatter.setFormat('align', value);\n          _this4.applyFormatStyles();\n        }\n      }, ['left', 'center', 'right']), new BorderControl(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.border_settings'), {\n        border_top_style: this.formatter.getFormat('border_top_style', ''),\n        border_top_width: this.formatter.getFormat('border_top_width', ''),\n        border_top_color: this.formatter.getFormat('border_top_color', ''),\n        border_bottom_style: this.formatter.getFormat('border_bottom_style', ''),\n        border_bottom_width: this.formatter.getFormat('border_bottom_width', ''),\n        border_bottom_color: this.formatter.getFormat('border_bottom_color', ''),\n        border_left_style: this.formatter.getFormat('border_left_style', ''),\n        border_left_width: this.formatter.getFormat('border_left_width', ''),\n        border_left_color: this.formatter.getFormat('border_left_color', ''),\n        border_right_style: this.formatter.getFormat('border_right_style', ''),\n        border_right_width: this.formatter.getFormat('border_right_width', ''),\n        border_right_color: this.formatter.getFormat('border_right_color', '')\n      }, {\n        setBorder: function setBorder(border_top_style, border_top_width, border_top_color, border_bottom_style, border_bottom_width, border_bottom_color, border_left_style, border_left_width, border_left_color, border_right_style, border_right_width, border_right_color) {\n          _this4.formatter.setFormat('border_top_style', border_top_style);\n          _this4.formatter.setFormat('border_top_width', border_top_width);\n          _this4.formatter.setFormat('border_top_color', border_top_color);\n          _this4.formatter.setFormat('border_bottom_style', border_bottom_style);\n          _this4.formatter.setFormat('border_bottom_width', border_bottom_width);\n          _this4.formatter.setFormat('border_bottom_color', border_bottom_color);\n          _this4.formatter.setFormat('border_left_style', border_left_style);\n          _this4.formatter.setFormat('border_left_width', border_left_width);\n          _this4.formatter.setFormat('border_left_color', border_left_color);\n          _this4.formatter.setFormat('border_right_style', border_right_style);\n          _this4.formatter.setFormat('border_right_width', border_right_width);\n          _this4.formatter.setFormat('border_right_color', border_right_color);\n          _this4.applyFormatStyles();\n        }\n      }), new _BorderRadiusControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.radius'), this.formatter.getFormat('border_radius', 0), {\n        setRadius: function setRadius(v) {\n          _this4.formatter.setFormat('border_radius', v);\n          _this4.applyFormatStyles();\n        }\n      })];\n    }\n  }], [{\n    key: \"parse\",\n    value: function parse(data) {\n      return this.parseFormats(new this(data.template, data.url), data);\n    }\n  }]);\n}(_BaseElement_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (YoutubeElement);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/YoutubeElement.js?");

/***/ }),

/***/ "./src/includes/YoutubeWidget.js":
/*!***************************************!*\
  !*** ./src/includes/YoutubeWidget.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ElementFactory_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ElementFactory.js */ \"./src/includes/ElementFactory.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./BaseWidget.js */ \"./src/includes/BaseWidget.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\nvar YoutubeWidget = /*#__PURE__*/function (_BaseWidget) {\n  function YoutubeWidget() {\n    var _this;\n    _classCallCheck(this, YoutubeWidget);\n    _this = _callSuper(this, YoutubeWidget); // Call the parent class constructor\n\n    // Add a RSSElement to the widget\n    var rssElement = new YoutubeElement('Youtube', null);\n\n    // Append the new element to the block\n    _this.block.appendElements([rssElement]);\n    return _this;\n  }\n  _inherits(YoutubeWidget, _BaseWidget);\n  return _createClass(YoutubeWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.youtube');\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'youtube_activity';\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (YoutubeWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/YoutubeWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdCTAWidget.js":
/*!*****************************************!*\
  !*** ./src/includes/ads/AdCTAWidget.js ***!
  \*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ButtonElement.js */ \"./src/includes/ButtonElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Call-to-Action widget — a button that maps to platform CTA dictionaries.\n *\n * Unlike a freeform button, ad CTAs are constrained to a fixed set of platform\n * enums. The UI exposes all options as plain text, but the exporter maps them\n * to the matching platform enum (e.g. \"Learn More\" → SHOP_NOW_WITHOUT_PRICE\n * depending on target). The host server keeps the canonical CTA dict.\n *\n * Allowed CTAs (shared across platforms):\n *   learn_more, shop_now, sign_up, contact_us, download, get_quote, book_now, apply_now\n */\nvar AdCTAWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdCTAWidget() {\n    var _this;\n    _classCallCheck(this, AdCTAWidget);\n    _this = _callSuper(this, AdCTAWidget);\n    _this.elements = [];\n    var cta = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Button', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_cta_default') || 'Learn More', '#');\n\n    // Ad CTA button styling: teal fill, bold, comfortable padding\n    cta.formatter.parseFormats({\n      align: 'left',\n      font_family: 'inherit',\n      font_weight: '600',\n      font_size: '15px',\n      text_color: '#FFFFFF',\n      link_color: '#FFFFFF',\n      text_align: 'center',\n      line_height: '1.2',\n      background_color: '#0891B2',\n      background_position: 'center',\n      background_size: '100%',\n      background_repeat: 'no-repeat',\n      padding_top: 12,\n      padding_right: 24,\n      padding_bottom: 12,\n      padding_left: 24,\n      border_top_style: 'solid',\n      border_top_width: '0',\n      border_top_color: '#0891B2',\n      border_right_style: 'solid',\n      border_right_width: '0',\n      border_right_color: '#0891B2',\n      border_bottom_style: 'solid',\n      border_bottom_width: '0',\n      border_bottom_color: '#0891B2',\n      border_left_width: '0',\n      border_left_style: 'solid',\n      border_left_color: '#0891B2',\n      border_radius: '6px'\n    });\n    _this.block.appendElements([cta]);\n    return _this;\n  }\n  _inherits(AdCTAWidget, _BaseWidget);\n  return _createClass(AdCTAWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_cta') || 'Call to Action';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'ads_click';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'cta';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        allowedValues: ['learn_more', 'shop_now', 'sign_up', 'contact_us', 'download', 'get_quote', 'book_now', 'apply_now'],\n        defaultValue: 'learn_more',\n        exportField: 'call_to_action'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdCTAWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdCTAWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdCarouselCardWidget.js":
/*!**************************************************!*\
  !*** ./src/includes/ads/AdCarouselCardWidget.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ImageElement.js */ \"./src/includes/ImageElement.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../HeadingElement.js */ \"./src/includes/HeadingElement.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../PElement.js */ \"./src/includes/PElement.js\");\n/* harmony import */ var _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../ButtonElement.js */ \"./src/includes/ButtonElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n\n\n\n/**\n * Ad Carousel Card widget — a composite card with image + headline +\n * description + CTA, repeatable 2-10 times for Meta / TikTok carousel ads.\n *\n * Exporter extracts each BlockElement containing this structure as one\n * element of the carousel_cards[] array.\n */\nvar AdCarouselCardWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdCarouselCardWidget() {\n    var _this;\n    _classCallCheck(this, AdCarouselCardWidget);\n    _this = _callSuper(this, AdCarouselCardWidget);\n    _this.elements = [];\n\n    // Image (top)\n    var image = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Image');\n    image.formatter.parseFormats({\n      width: '100%',\n      align: 'center',\n      border_radius: '8px',\n      padding_top: 0,\n      padding_bottom: 0,\n      padding_left: 0,\n      padding_right: 0\n    });\n\n    // Headline (middle)\n    var headline = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"]('Heading', 'h3', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_carousel_headline_default') || 'Card headline');\n    headline.formatter.parseFormats({\n      font_weight: '700',\n      font_size: '16px',\n      text_color: '#111827',\n      text_align: 'left',\n      line_height: '1.25',\n      padding_top: 10,\n      padding_bottom: 4,\n      padding_left: 12,\n      padding_right: 12\n    });\n\n    // Description (below headline)\n    var desc = new _PElement_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"]('P', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_carousel_desc_default') || 'Short sub-text');\n    desc.formatter.parseFormats({\n      font_size: '13px',\n      text_color: '#6B7280',\n      line_height: '1.4',\n      padding_top: 0,\n      padding_bottom: 10,\n      padding_left: 12,\n      padding_right: 12\n    });\n\n    // CTA (bottom)\n    var cta = new _ButtonElement_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"]('Button', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_cta_default') || 'Learn More', '#');\n    cta.formatter.parseFormats({\n      align: 'left',\n      font_weight: '600',\n      font_size: '14px',\n      text_color: '#0891B2',\n      link_color: '#0891B2',\n      text_align: 'center',\n      line_height: '1.2',\n      background_color: '#FFFFFF',\n      padding_top: 10,\n      padding_right: 18,\n      padding_bottom: 10,\n      padding_left: 18,\n      border_top_style: 'solid',\n      border_top_width: '1px',\n      border_top_color: '#0891B2',\n      border_right_style: 'solid',\n      border_right_width: '1px',\n      border_right_color: '#0891B2',\n      border_bottom_style: 'solid',\n      border_bottom_width: '1px',\n      border_bottom_color: '#0891B2',\n      border_left_width: '1px',\n      border_left_style: 'solid',\n      border_left_color: '#0891B2',\n      border_radius: '6px'\n    });\n\n    // Block styling: card-like with border + radius\n    _this.block.formatter.parseFormats({\n      background_color: '#FFFFFF',\n      padding_top: 0,\n      padding_bottom: 16,\n      padding_left: 0,\n      padding_right: 0,\n      border_top_style: 'solid',\n      border_top_width: '1px',\n      border_top_color: '#E5E7EB',\n      border_right_style: 'solid',\n      border_right_width: '1px',\n      border_right_color: '#E5E7EB',\n      border_bottom_style: 'solid',\n      border_bottom_width: '1px',\n      border_bottom_color: '#E5E7EB',\n      border_left_width: '1px',\n      border_left_style: 'solid',\n      border_left_color: '#E5E7EB',\n      border_radius: '10px'\n    });\n    _this.block.appendElements([image, headline, desc, cta]);\n    return _this;\n  }\n  _inherits(AdCarouselCardWidget, _BaseWidget);\n  return _createClass(AdCarouselCardWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_carousel_card') || 'Carousel Card';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'view_carousel';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'carousel_card';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        imageAspectRatio: '1:1',\n        headlineMaxLength: 40,\n        descriptionMaxLength: 20,\n        minCards: 2,\n        maxCards: 10,\n        exportField: 'carousel_cards'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdCarouselCardWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdCarouselCardWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdDescriptionWidget.js":
/*!*************************************************!*\
  !*** ./src/includes/ads/AdDescriptionWidget.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../PElement.js */ \"./src/includes/PElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Description widget — a short sub-line below the headline.\n *\n * On Meta this maps to the \"description\" field (newsfeed card byline).\n * On Google Responsive Display it's descriptions[1+]. It's shorter and\n * more direct than primary text.\n *\n * Platform constraints:\n *   - Meta:      max 30 chars (link description)\n *   - Google:    max 90 chars (as description asset)\n *   - TikTok:    N/A (merged with primary text)\n *   - LinkedIn:  max 70 chars (headline variant)\n */\nvar AdDescriptionWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdDescriptionWidget() {\n    var _this;\n    _classCallCheck(this, AdDescriptionWidget);\n    _this = _callSuper(this, AdDescriptionWidget);\n    _this.elements = [];\n    var desc = new _PElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('P', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_description_default') || 'One-line sub-text');\n    desc.formatter.parseFormats({\n      font_size: '13px',\n      text_color: '#6B7280',\n      line_height: '1.4',\n      padding_top: 0,\n      padding_bottom: 8,\n      padding_left: 16,\n      padding_right: 16\n    });\n    _this.block.appendElements([desc]);\n    return _this;\n  }\n  _inherits(AdDescriptionWidget, _BaseWidget);\n  return _createClass(AdDescriptionWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_description') || 'Description';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'short_text';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'description';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        maxLength: 30,\n        platforms: {\n          meta: {\n            maxLength: 30\n          },\n          google: {\n            maxLength: 90\n          },\n          linkedin: {\n            maxLength: 70\n          }\n        },\n        exportField: 'description'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdDescriptionWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdDescriptionWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdHeadlineWidget.js":
/*!**********************************************!*\
  !*** ./src/includes/ads/AdHeadlineWidget.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../HeadingElement.js */ \"./src/includes/HeadingElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Headline widget — short, bold, attention-grabbing text.\n *\n * Uses a standard HeadingElement under the hood so the exporter can find\n * \"first HeadingElement in the page\" and map it to the headline field\n * of platform API payloads (Meta body.name, Google Ads headlines[0], etc).\n *\n * Platform constraints (informational — enforced by the PHP exporter + UI):\n *   - Meta:      max 40 chars, 1 line\n *   - Google:    max 30 chars per headline (Responsive Display allows 5)\n *   - TikTok:    max 40 chars\n *   - LinkedIn:  max 70 chars\n */\nvar AdHeadlineWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdHeadlineWidget() {\n    var _this;\n    _classCallCheck(this, AdHeadlineWidget);\n    _this = _callSuper(this, AdHeadlineWidget);\n    _this.elements = [];\n\n    // h2 matches typical Meta feed card headline sizing\n    var headline = new _HeadingElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Heading', 'h2', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_headline_default') || 'Your attention-grabbing headline');\n\n    // Default style: bold, dark, centered — reads like an ad headline\n    headline.formatter.parseFormats({\n      font_weight: '700',\n      font_size: '22px',\n      text_color: '#111827',\n      text_align: 'left',\n      line_height: '1.2',\n      padding_top: 8,\n      padding_bottom: 8,\n      padding_left: 16,\n      padding_right: 16\n    });\n    _this.block.appendElements([headline]);\n    return _this;\n  }\n  _inherits(AdHeadlineWidget, _BaseWidget);\n  return _createClass(AdHeadlineWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_headline') || 'Ad Headline';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'title';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'headline';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        maxLength: 40,\n        singleLine: true,\n        platforms: {\n          meta: {\n            maxLength: 40\n          },\n          google: {\n            maxLength: 30\n          },\n          tiktok: {\n            maxLength: 40\n          },\n          linkedin: {\n            maxLength: 70\n          }\n        },\n        exportField: 'headline'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdHeadlineWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdHeadlineWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdImageSlotWidget.js":
/*!***********************************************!*\
  !*** ./src/includes/ads/AdImageSlotWidget.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ImageElement.js */ \"./src/includes/ImageElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Image Slot widget — the main creative image.\n *\n * Platform aspect ratios (what the user should upload):\n *   - Meta Feed:       1:1 (1080x1080) or 1.91:1 (1200x628)\n *   - Meta Story:      9:16 (1080x1920)\n *   - Google Display:  various (300x250, 728x90, 160x600, 1200x628)\n *   - TikTok Video:    9:16 (cover image, same ratio)\n *   - LinkedIn Feed:   1.91:1 (1200x627)\n *\n * Exporter picks first ImageElement in the page → image_url / image_hash.\n */\nvar AdImageSlotWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdImageSlotWidget() {\n    var _this;\n    _classCallCheck(this, AdImageSlotWidget);\n    _this = _callSuper(this, AdImageSlotWidget);\n    _this.elements = [];\n    var image = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Image');\n    image.formatter.parseFormats({\n      width: '100%',\n      align: 'center',\n      border_radius: '0',\n      padding_top: 0,\n      padding_bottom: 0,\n      padding_left: 0,\n      padding_right: 0\n    });\n    _this.block.appendElements([image]);\n    return _this;\n  }\n  _inherits(AdImageSlotWidget, _BaseWidget);\n  return _createClass(AdImageSlotWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_image') || 'Ad Image';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'image';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'image';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        aspectRatios: {\n          meta_feed: '1:1',\n          meta_story: '9:16',\n          google_display: '1.91:1',\n          tiktok: '9:16',\n          linkedin: '1.91:1'\n        },\n        minWidth: 600,\n        recommendedWidth: 1200,\n        exportField: 'image_url'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdImageSlotWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdImageSlotWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdLogoSlotWidget.js":
/*!**********************************************!*\
  !*** ./src/includes/ads/AdLogoSlotWidget.js ***!
  \**********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ImageElement.js */ \"./src/includes/ImageElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Logo Slot widget — the brand logo shown alongside the creative.\n *\n * On Meta this maps to the page profile image (already set at page level),\n * but some placements support a dedicated brand asset (e.g. Carousel cards).\n * On Google Responsive Display this maps to logoImages[].\n *\n * Exporter picks first ImageElement with adRole=logo, or the SECOND\n * ImageElement in a page (after the main image slot).\n */\nvar AdLogoSlotWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdLogoSlotWidget() {\n    var _this;\n    _classCallCheck(this, AdLogoSlotWidget);\n    _this = _callSuper(this, AdLogoSlotWidget);\n    _this.elements = [];\n    var logo = new _ImageElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('Image');\n    logo.formatter.parseFormats({\n      width: '80px',\n      max_width: '80px',\n      align: 'left',\n      border_radius: '50%',\n      padding_top: 8,\n      padding_bottom: 8,\n      padding_left: 16,\n      padding_right: 0\n    });\n    _this.block.appendElements([logo]);\n    return _this;\n  }\n  _inherits(AdLogoSlotWidget, _BaseWidget);\n  return _createClass(AdLogoSlotWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_logo') || 'Brand Logo';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'verified';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'logo';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        aspectRatio: '1:1',\n        minWidth: 128,\n        recommendedWidth: 512,\n        exportField: 'brand_logo_url'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdLogoSlotWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdLogoSlotWidget.js?");

/***/ }),

/***/ "./src/includes/ads/AdPrimaryTextWidget.js":
/*!*************************************************!*\
  !*** ./src/includes/ads/AdPrimaryTextWidget.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BaseWidget.js */ \"./src/includes/BaseWidget.js\");\n/* harmony import */ var _PElement_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../PElement.js */ \"./src/includes/PElement.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n\n\n\n\n/**\n * Ad Primary Text widget — the main body copy above/below the creative.\n *\n * On Meta this is the \"primary_text\" that shows above the image. On Google\n * Responsive Display this maps to descriptions[0]. The exporter extracts\n * \"first PElement with adRole=primary_text (via widget-class)\" or falls back\n * to \"first PElement in the page\".\n *\n * Platform constraints:\n *   - Meta:      max 125 chars (recommended)\n *   - Google:    max 90 chars per description\n *   - TikTok:    max 100 chars\n *   - LinkedIn:  max 600 chars (but recommends < 150)\n */\nvar AdPrimaryTextWidget = /*#__PURE__*/function (_BaseWidget) {\n  function AdPrimaryTextWidget() {\n    var _this;\n    _classCallCheck(this, AdPrimaryTextWidget);\n    _this = _callSuper(this, AdPrimaryTextWidget);\n    _this.elements = [];\n    var text = new _PElement_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]('P', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('elements.ad_primary_text_default') || 'Your body copy here. Keep it short, clear, and actionable — under 125 characters works best on most platforms.');\n    text.formatter.parseFormats({\n      font_size: '15px',\n      text_color: '#374151',\n      line_height: '1.5',\n      padding_top: 4,\n      padding_bottom: 12,\n      padding_left: 16,\n      padding_right: 16\n    });\n    _this.block.appendElements([text]);\n    return _this;\n  }\n  _inherits(AdPrimaryTextWidget, _BaseWidget);\n  return _createClass(AdPrimaryTextWidget, [{\n    key: \"getName\",\n    value: function getName() {\n      return _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('widgets.ad_primary_text') || 'Primary Text';\n    }\n  }, {\n    key: \"getIcon\",\n    value: function getIcon() {\n      return 'notes';\n    }\n  }], [{\n    key: \"adRole\",\n    get: function get() {\n      return 'primary_text';\n    }\n  }, {\n    key: \"constraints\",\n    get: function get() {\n      return {\n        maxLength: 125,\n        platforms: {\n          meta: {\n            maxLength: 125\n          },\n          google: {\n            maxLength: 90\n          },\n          tiktok: {\n            maxLength: 100\n          },\n          linkedin: {\n            maxLength: 600,\n            recommended: 150\n          }\n        },\n        exportField: 'primary_text'\n      };\n    }\n  }]);\n}(_BaseWidget_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AdPrimaryTextWidget);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ads/AdPrimaryTextWidget.js?");

/***/ }),

/***/ "./src/includes/buttonPresets.js":
/*!***************************************!*\
  !*** ./src/includes/buttonPresets.js ***!
  \***************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   CATEGORIES: () => (/* binding */ CATEGORIES),\n/* harmony export */   HOVER_EFFECT_KEYS: () => (/* binding */ HOVER_EFFECT_KEYS),\n/* harmony export */   PRESETS: () => (/* binding */ PRESETS),\n/* harmony export */   SHADOW_KEYS: () => (/* binding */ SHADOW_KEYS),\n/* harmony export */   SHADOW_SCALE: () => (/* binding */ SHADOW_SCALE),\n/* harmony export */   SIZE_KEYS: () => (/* binding */ SIZE_KEYS),\n/* harmony export */   SIZE_SCALE: () => (/* binding */ SIZE_SCALE),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */   findPreset: () => (/* binding */ findPreset),\n/* harmony export */   presetsByCategory: () => (/* binding */ presetsByCategory)\n/* harmony export */ });\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/*\n * buttonPresets.js — curated library of ~210 button style presets for\n * ButtonElement. Each preset is a Formatter snapshot + metadata; the\n * user picks one and the element's applyPreset() writes the snapshot\n * into its formatter in a single pass.\n *\n * Architecture\n * ────────────\n *\n *   PALETTE          — reusable base color tokens (~16 color families ×\n *                      {solid / strong / soft / tone / toneText}). Every\n *                      generator function reads from here so a one-line\n *                      palette tweak updates dozens of presets at once.\n *\n *   SIZE_SCALE       — xs · sm · md · lg · xl (5 entries). Each entry is a\n *                      partial formatter snapshot patching only\n *                      font_size + padding_{top,right,bottom,left}. Size\n *                      is an orthogonal axis to preset identity; switching\n *                      preset does NOT change size, switching size does\n *                      NOT change color/border/radius/shadow identity.\n *\n *   SHADOW_SCALE     — 6 named box-shadow values (none / sm / md / lg /\n *                      xl / inner). Page-mode only — email exporters\n *                      strip box-shadow.\n *\n *   HOVER_EFFECTS    — 6 data-bjs-hover-fx values (none / lift / glow /\n *                      scale / sweep / push). Actual animation CSS lives\n *                      in src/builder.css alongside the other overlay\n *                      chrome. Page-mode only — no `:hover` in email.\n *\n *   PRESETS          — array of preset objects. Order within the array\n *                      drives display order within each category tab.\n *\n *   CATEGORIES       — display metadata (label, order, mode). Drives the\n *                      picker's tab row + sidebar category filter.\n *\n * Preset shape\n * ────────────\n *\n *   {\n *     id: 'solid-indigo',              // stable serialization key\n *     category: 'solid',               // matches CATEGORIES key\n *     label: 'Indigo',                 // i18n key if starts with 'i18n:'\n *     flags: {\n *       emailSafe:    true,            // false → show ⚠ warn badge in email mode\n *       requiresVML:  false,           // true → auto-wrap <table>+VML on export\n *       pageOnly:     false,           // true → label \"Page only\" in email mode\n *     },\n *     formats: {                       // partial formatter snapshot\n *       background_color: '#2563eb',\n *       text_color:       '#ffffff',\n *       // …every CSS_KEY the preset owns…\n *     },\n *     icon:          null,             // null OR a material-symbols name\n *     iconPosition:  'none',           // 'left' | 'right' | 'only' | 'none'\n *   }\n *\n * Non-obvious rules\n * ────────────────\n *\n *   1. Generators (makeSolid / makeOutline / makeTonal) mix a per-color\n *      object into a shared DEFAULT_MD skeleton so every preset covers\n *      the full CSS_KEYS set. Partial snapshots would leak the previous\n *      preset's values into the new one on apply.\n *\n *   2. `border_radius` baseline is 6px (matches current ButtonElement\n *      default). Radius is a separate axis — presets don't touch it\n *      unless the preset's IDENTITY demands it (pill-* ships 999px,\n *      brutalist-* ships 0px).\n *\n *   3. Gradient presets write `background_image` (not background_color);\n *      background_color becomes the FALLBACK color emitted first so\n *      Outlook-strip-gradient degrades to flat color, not transparent.\n *\n *   4. Glass / glow presets USE box_shadow + backdrop-filter. backdrop-\n *      filter is NOT in the formatter's CSS_KEYS → it gets attached via\n *      the element's extraInlineStyles() passthrough (new method).\n *\n *   5. Icon presets carry a non-null `icon` + non-'none' iconPosition.\n *      Non-icon presets carry null + 'none'. Applying a preset RESETS\n *      both fields to the preset's values (icon choice follows the\n *      preset identity — switching to a non-icon preset removes the\n *      icon).\n */\n\n// ─── SIZE SCALE ────────────────────────────────────────────────────────────\n\nvar SIZE_SCALE = {\n  xs: {\n    font_size: '11px',\n    padding_top: 4,\n    padding_right: 8,\n    padding_bottom: 4,\n    padding_left: 8\n  },\n  sm: {\n    font_size: '13px',\n    padding_top: 6,\n    padding_right: 12,\n    padding_bottom: 6,\n    padding_left: 12\n  },\n  md: {\n    font_size: '14px',\n    padding_top: 10,\n    padding_right: 20,\n    padding_bottom: 10,\n    padding_left: 20\n  },\n  lg: {\n    font_size: '16px',\n    padding_top: 12,\n    padding_right: 28,\n    padding_bottom: 12,\n    padding_left: 28\n  },\n  xl: {\n    font_size: '18px',\n    padding_top: 16,\n    padding_right: 36,\n    padding_bottom: 16,\n    padding_left: 36\n  }\n};\nvar SIZE_KEYS = ['xs', 'sm', 'md', 'lg', 'xl'];\n\n// ─── SHADOW SCALE (page-mode only — email strips box-shadow) ───────────────\n\nvar SHADOW_SCALE = {\n  none: '',\n  sm: '0 1px 2px rgba(0,0,0,0.08)',\n  md: '0 4px 8px -2px rgba(0,0,0,0.16)',\n  lg: '0 10px 18px -6px rgba(0,0,0,0.22)',\n  xl: '0 18px 32px -10px rgba(0,0,0,0.28)',\n  inner: 'inset 0 2px 4px rgba(0,0,0,0.25)'\n};\nvar SHADOW_KEYS = ['none', 'sm', 'md', 'lg', 'xl', 'inner'];\n\n// ─── HOVER EFFECTS (page-mode only — no :hover reliability in email) ──────\n// Values match data-bjs-hover-fx attribute. CSS rules live in\n// src/builder.css under `[data-bjs-hover-fx=\"<key>\"]:hover { … }`.\n\nvar HOVER_EFFECT_KEYS = ['none', 'lift', 'glow', 'scale', 'sweep', 'push'];\n\n// ─── PALETTE (shared color tokens) ─────────────────────────────────────────\n\nvar PAL = {\n  indigo: {\n    solid: '#2563eb',\n    strong: '#1d4ed8',\n    soft: '#93c5fd',\n    onSolid: '#ffffff',\n    tone: '#dbeafe',\n    toneText: '#1d4ed8'\n  },\n  indigoDeep: {\n    solid: '#3730a3',\n    strong: '#1e1b4b',\n    soft: '#a5b4fc',\n    onSolid: '#ffffff',\n    tone: '#e0e7ff',\n    toneText: '#3730a3'\n  },\n  slate: {\n    solid: '#64748b',\n    strong: '#334155',\n    soft: '#cbd5e1',\n    onSolid: '#ffffff',\n    tone: '#f1f5f9',\n    toneText: '#334155'\n  },\n  ink: {\n    solid: '#111827',\n    strong: '#030712',\n    soft: '#6b7280',\n    onSolid: '#ffffff',\n    tone: '#f3f4f6',\n    toneText: '#111827'\n  },\n  charcoal: {\n    solid: '#1f2937',\n    strong: '#030712',\n    soft: '#9ca3af',\n    onSolid: '#f3f4f6',\n    tone: '#e5e7eb',\n    toneText: '#111827'\n  },\n  paper: {\n    solid: '#f9fafb',\n    strong: '#f3f4f6',\n    soft: '#ffffff',\n    onSolid: '#111827',\n    tone: '#ffffff',\n    toneText: '#111827',\n    border: '#d1d5db'\n  },\n  emerald: {\n    solid: '#16a34a',\n    strong: '#14532d',\n    soft: '#86efac',\n    onSolid: '#ffffff',\n    tone: '#dcfce7',\n    toneText: '#15803d'\n  },\n  amber: {\n    solid: '#f59e0b',\n    strong: '#b45309',\n    soft: '#fcd34d',\n    onSolid: '#1f2937',\n    tone: '#fef3c7',\n    toneText: '#b45309'\n  },\n  crimson: {\n    solid: '#dc2626',\n    strong: '#7f1d1d',\n    soft: '#fca5a5',\n    onSolid: '#ffffff',\n    tone: '#fee2e2',\n    toneText: '#b91c1c'\n  },\n  cyan: {\n    solid: '#06b6d4',\n    strong: '#0e7490',\n    soft: '#67e8f9',\n    onSolid: '#ffffff',\n    tone: '#cffafe',\n    toneText: '#0e7490'\n  },\n  violet: {\n    solid: '#7c3aed',\n    strong: '#4c1d95',\n    soft: '#c4b5fd',\n    onSolid: '#ffffff',\n    tone: '#ede9fe',\n    toneText: '#6d28d9'\n  },\n  rose: {\n    solid: '#e11d48',\n    strong: '#881337',\n    soft: '#fda4af',\n    onSolid: '#ffffff',\n    tone: '#ffe4e6',\n    toneText: '#be123c'\n  },\n  orange: {\n    solid: '#ea580c',\n    strong: '#9a3412',\n    soft: '#fdba74',\n    onSolid: '#ffffff',\n    tone: '#ffedd5',\n    toneText: '#c2410c'\n  },\n  teal: {\n    solid: '#0d9488',\n    strong: '#134e4a',\n    soft: '#99f6e4',\n    onSolid: '#ffffff',\n    tone: '#ccfbf1',\n    toneText: '#115e59'\n  },\n  lime: {\n    solid: '#65a30d',\n    strong: '#365314',\n    soft: '#bef264',\n    onSolid: '#1f2937',\n    tone: '#ecfccb',\n    toneText: '#3f6212'\n  },\n  pink: {\n    solid: '#db2777',\n    strong: '#831843',\n    soft: '#f9a8d4',\n    onSolid: '#ffffff',\n    tone: '#fce7f3',\n    toneText: '#9d174d'\n  },\n  sky: {\n    solid: '#0284c7',\n    strong: '#075985',\n    soft: '#7dd3fc',\n    onSolid: '#ffffff',\n    tone: '#e0f2fe',\n    toneText: '#0369a1'\n  },\n  mint: {\n    solid: '#5eead4',\n    strong: '#14b8a6',\n    soft: '#99f6e4',\n    onSolid: '#134e4a',\n    tone: '#f0fdfa',\n    toneText: '#134e4a'\n  },\n  plum: {\n    solid: '#9333ea',\n    strong: '#581c87',\n    soft: '#d8b4fe',\n    onSolid: '#ffffff',\n    tone: '#f3e8ff',\n    toneText: '#7e22ce'\n  },\n  sand: {\n    solid: '#d6cfbe',\n    strong: '#a8a29e',\n    soft: '#f5f5f4',\n    onSolid: '#1c1917',\n    tone: '#f5f5f4',\n    toneText: '#44403c'\n  },\n  sage: {\n    solid: '#84cc16',\n    strong: '#3f6212',\n    soft: '#d9f99d',\n    onSolid: '#1c1917',\n    tone: '#f7fee7',\n    toneText: '#4d7c0f'\n  },\n  graphite: {\n    solid: '#374151',\n    strong: '#0f172a',\n    soft: '#9ca3af',\n    onSolid: '#ffffff',\n    tone: '#e5e7eb',\n    toneText: '#1f2937'\n  }\n};\n\n// ─── DEFAULT SKELETON ─────────────────────────────────────────────────────\n// Every generator mixes into this so every preset emits a FULL snapshot.\n// Without this, applying preset B after preset A would leak A's values.\n\nvar DEFAULT_MD = {\n  font_family: 'inherit',\n  font_weight: '500',\n  font_size: '14px',\n  text_color: '#ffffff',\n  link_color: '#ffffff',\n  text_align: 'center',\n  line_height: '1.5',\n  letter_spacing: null,\n  text_direction: 'ltr',\n  paragraph_spacing: null,\n  background_color: '#2563eb',\n  background_image: null,\n  background_position: 'center',\n  background_size: '100%',\n  background_repeat: 'no-repeat',\n  padding_top: 10,\n  padding_right: 20,\n  padding_bottom: 10,\n  padding_left: 20,\n  border_top_style: 'solid',\n  border_top_width: '1px',\n  border_top_color: '#2563eb',\n  border_right_style: 'solid',\n  border_right_width: '1px',\n  border_right_color: '#2563eb',\n  border_bottom_style: 'solid',\n  border_bottom_width: '1px',\n  border_bottom_color: '#2563eb',\n  border_left_style: 'solid',\n  border_left_width: '1px',\n  border_left_color: '#2563eb',\n  border_radius: '6px',\n  box_shadow: '',\n  width: null,\n  max_width: null,\n  min_width: null\n};\n\n// Apply a single color uniformly to all 4 border sides.\nfunction borderColor(color) {\n  return {\n    border_top_color: color,\n    border_right_color: color,\n    border_bottom_color: color,\n    border_left_color: color\n  };\n}\nfunction borderWidth(width) {\n  return {\n    border_top_width: width,\n    border_right_width: width,\n    border_bottom_width: width,\n    border_left_width: width\n  };\n}\nfunction borderStyle(style) {\n  return {\n    border_top_style: style,\n    border_right_style: style,\n    border_bottom_style: style,\n    border_left_style: style\n  };\n}\nvar SAFE = {\n  emailSafe: true,\n  requiresVML: false,\n  pageOnly: false\n};\nvar WARN = {\n  emailSafe: false,\n  requiresVML: true,\n  pageOnly: false\n};\nvar PAGE = {\n  emailSafe: false,\n  requiresVML: false,\n  pageOnly: true\n};\n\n// ─── SOLID (~30) ──────────────────────────────────────────────────────────\n\nfunction makeSolid(id, label, color) {\n  var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n  var bg = opts.bg || color.solid;\n  var fg = opts.fg || color.onSolid;\n  var bd = opts.border || bg;\n  return {\n    id: \"solid-\".concat(id),\n    category: 'solid',\n    label: label,\n    flags: SAFE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n      background_color: bg,\n      text_color: fg,\n      link_color: fg\n    }, borderColor(bd))),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// For soft variant we need dark text on soft bg — color.toneText or custom.\nfunction makeSolidSoft(id, label, color) {\n  return {\n    id: \"solid-\".concat(id, \"-soft\"),\n    category: 'solid',\n    label: \"\".concat(label, \" \\xB7 soft\"),\n    flags: SAFE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n      background_color: color.soft,\n      text_color: color.toneText,\n      link_color: color.toneText\n    }, borderColor(color.soft))),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── OUTLINE (~22) ────────────────────────────────────────────────────────\n\nfunction makeOutline(id, label, color) {\n  var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n  var bd = opts.border || color.solid;\n  var fg = opts.text || color.solid;\n  return {\n    id: \"outline-\".concat(id),\n    category: 'outline',\n    label: label,\n    flags: SAFE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n      background_color: 'transparent',\n      text_color: fg,\n      link_color: fg\n    }, borderColor(bd)), borderWidth('1px')), borderStyle('solid'))),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── TONAL (~22) ──────────────────────────────────────────────────────────\n\nfunction makeTonal(id, label, color) {\n  return {\n    id: \"tonal-\".concat(id),\n    category: 'tonal',\n    label: label,\n    flags: SAFE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n      background_color: color.tone,\n      text_color: color.toneText,\n      link_color: color.toneText\n    }, borderColor(color.tone))),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── GHOST (~14) ──────────────────────────────────────────────────────────\n\nfunction makeGhost(id, label, color) {\n  var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};\n  var fg = opts.text || color.solid;\n  var extra = opts.extra || {};\n  return {\n    id: \"ghost-\".concat(id),\n    category: 'ghost',\n    label: label,\n    flags: SAFE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n      background_color: 'transparent',\n      text_color: fg,\n      link_color: fg\n    }, borderColor('transparent')), extra)),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── GRADIENT (~32) ───────────────────────────────────────────────────────\n\nfunction makeGradient(id, label, gradient, fallback) {\n  var text = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '#ffffff';\n  var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};\n  return {\n    id: \"gradient-\".concat(id),\n    category: 'gradient',\n    label: label,\n    flags: opts.flags || WARN,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n      background_color: fallback,\n      background_image: gradient,\n      text_color: text,\n      link_color: text\n    }, borderColor(fallback)), opts.formats || {})),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── ELEVATED (~18, page-only) ───────────────────────────────────────────\nfunction makeElevated(id, label, base, shadow) {\n  var opts = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n  var fg = opts.fg || base.onSolid;\n  return {\n    id: \"elevated-\".concat(id),\n    category: 'elevated',\n    label: label,\n    flags: PAGE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n      background_color: base.solid,\n      text_color: fg,\n      link_color: fg\n    }, borderColor(base.solid)), {}, {\n      box_shadow: shadow\n    }, opts.formats || {})),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── GLASS & GLOW (~16, page-only) ───────────────────────────────────────\nfunction makeGlow(id, label, base, glow) {\n  var opts = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};\n  return {\n    id: \"glass-\".concat(id),\n    category: 'glass',\n    label: label,\n    flags: PAGE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n      background_color: base.solid,\n      text_color: base.onSolid,\n      link_color: base.onSolid\n    }, borderColor(base.solid)), borderWidth('0px')), {}, {\n      box_shadow: glow\n    }, opts.formats || {})),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── BRUTALIST (~14) ─────────────────────────────────────────────────────\nfunction makeBrutalist(id, label, bg, fg) {\n  var shadowColor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '#111827';\n  var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};\n  return {\n    id: \"brutalist-\".concat(id),\n    category: 'brutalist',\n    label: label,\n    flags: SAFE,\n    formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread(_objectSpread({\n      background_color: bg,\n      text_color: fg,\n      link_color: fg,\n      font_weight: '700'\n    }, borderColor(shadowColor)), borderWidth('2px')), borderStyle('solid')), {}, {\n      border_radius: '0px',\n      box_shadow: \"4px 4px 0 \".concat(shadowColor)\n    }, opts.formats || {})),\n    icon: null,\n    iconPosition: 'none'\n  };\n}\n\n// ─── SOLID (~30) ──────────────────────────────────────────────────────────\n\nvar SOLID = [makeSolid('indigo', 'Indigo', PAL.indigo), makeSolid('indigo-strong', 'Indigo · strong', PAL.indigo, {\n  bg: PAL.indigo.strong,\n  border: PAL.indigo.strong\n}), makeSolidSoft('indigo', 'Indigo', PAL.indigo), makeSolid('indigo-deep', 'Indigo · deep', PAL.indigoDeep), makeSolid('slate', 'Slate', PAL.slate), makeSolid('ink', 'Ink · black', PAL.ink), makeSolid('paper', 'Paper · white', PAL.paper, {\n  bg: PAL.paper.solid,\n  fg: '#111827',\n  border: PAL.paper.border\n}), makeSolid('charcoal', 'Charcoal', PAL.charcoal), makeSolid('emerald', 'Emerald', PAL.emerald), makeSolid('emerald-strong', 'Emerald · strong', PAL.emerald, {\n  bg: PAL.emerald.strong,\n  border: PAL.emerald.strong\n}), makeSolidSoft('emerald', 'Emerald', PAL.emerald), makeSolid('amber', 'Amber', PAL.amber), makeSolid('amber-strong', 'Amber · strong', PAL.amber, {\n  bg: PAL.amber.strong,\n  fg: '#fff',\n  border: PAL.amber.strong\n}), makeSolidSoft('amber', 'Amber', PAL.amber), makeSolid('crimson', 'Crimson', PAL.crimson), makeSolid('crimson-strong', 'Crimson · deep', PAL.crimson, {\n  bg: PAL.crimson.strong,\n  border: PAL.crimson.strong\n}), makeSolid('cyan', 'Cyan', PAL.cyan), makeSolid('cyan-strong', 'Cyan · deep', PAL.cyan, {\n  bg: PAL.cyan.strong,\n  border: PAL.cyan.strong\n}), makeSolid('violet', 'Violet', PAL.violet), makeSolid('violet-strong', 'Violet · deep', PAL.violet, {\n  bg: PAL.violet.strong,\n  border: PAL.violet.strong\n}), makeSolid('rose', 'Rose', PAL.rose), makeSolid('rose-strong', 'Rose · deep', PAL.rose, {\n  bg: PAL.rose.strong,\n  border: PAL.rose.strong\n}), makeSolid('orange', 'Orange', PAL.orange), makeSolid('teal', 'Teal', PAL.teal), makeSolid('lime', 'Lime', PAL.lime), makeSolid('pink', 'Pink', PAL.pink), makeSolid('sky', 'Sky', PAL.sky), makeSolid('mint', 'Mint', PAL.mint), makeSolid('plum', 'Plum', PAL.plum), makeSolid('graphite', 'Graphite', PAL.graphite)];\n\n// ─── OUTLINE (~22) ────────────────────────────────────────────────────────\n\nvar OUTLINE = [makeOutline('indigo', 'Indigo', PAL.indigo), makeOutline('ink', 'Ink', PAL.ink), makeOutline('paper', 'Paper', PAL.paper, {\n  border: '#ffffff',\n  text: '#ffffff'\n}),\n// for dark backgrounds\nmakeOutline('slate', 'Slate', PAL.slate), makeOutline('emerald', 'Emerald', PAL.emerald), makeOutline('amber', 'Amber', PAL.amber, {\n  text: PAL.amber.strong\n}), makeOutline('crimson', 'Crimson', PAL.crimson), makeOutline('cyan', 'Cyan', PAL.cyan, {\n  text: PAL.cyan.strong\n}), makeOutline('violet', 'Violet', PAL.violet), makeOutline('rose', 'Rose', PAL.rose), makeOutline('orange', 'Orange', PAL.orange, {\n  text: PAL.orange.strong\n}), makeOutline('teal', 'Teal', PAL.teal), makeOutline('lime', 'Lime', PAL.lime, {\n  text: PAL.lime.strong\n}), makeOutline('pink', 'Pink', PAL.pink), makeOutline('sky', 'Sky', PAL.sky),\n// Thick-2px variants\n{\n  id: 'outline-indigo-thick',\n  category: 'outline',\n  label: 'Indigo · thick',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.indigo.solid,\n    link_color: PAL.indigo.solid\n  }, borderColor(PAL.indigo.solid)), borderWidth('2px')), borderStyle('solid'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'outline-ink-thick',\n  category: 'outline',\n  label: 'Ink · thick',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.ink.solid,\n    link_color: PAL.ink.solid\n  }, borderColor(PAL.ink.solid)), borderWidth('2px')), borderStyle('solid'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'outline-double-ink',\n  category: 'outline',\n  label: 'Double-line · ink',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.ink.solid,\n    link_color: PAL.ink.solid\n  }, borderColor(PAL.ink.solid)), borderWidth('3px')), borderStyle('double'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'outline-double-indigo',\n  category: 'outline',\n  label: 'Double-line · indigo',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.indigo.solid,\n    link_color: PAL.indigo.solid\n  }, borderColor(PAL.indigo.solid)), borderWidth('3px')), borderStyle('double'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'outline-dashed-ink',\n  category: 'outline',\n  label: 'Dashed · ink',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.ink.solid,\n    link_color: PAL.ink.solid\n  }, borderColor(PAL.ink.solid)), borderWidth('2px')), borderStyle('dashed'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'outline-dotted-slate',\n  category: 'outline',\n  label: 'Dotted · slate',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.slate.solid,\n    link_color: PAL.slate.solid\n  }, borderColor(PAL.slate.solid)), borderWidth('2px')), borderStyle('dotted'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'outline-pill-indigo',\n  category: 'outline',\n  label: 'Pill · indigo',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.indigo.solid,\n    link_color: PAL.indigo.solid\n  }, borderColor(PAL.indigo.solid)), {}, {\n    border_radius: '999px'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}];\n\n// ─── TONAL (~22) ──────────────────────────────────────────────────────────\n\nvar TONAL = [makeTonal('indigo', 'Indigo', PAL.indigo), makeTonal('ink', 'Ink', PAL.ink), makeTonal('slate', 'Slate', PAL.slate), makeTonal('emerald', 'Emerald', PAL.emerald), makeTonal('amber', 'Amber', PAL.amber), makeTonal('crimson', 'Crimson', PAL.crimson), makeTonal('cyan', 'Cyan', PAL.cyan), makeTonal('violet', 'Violet', PAL.violet), makeTonal('rose', 'Rose', PAL.rose), makeTonal('orange', 'Orange', PAL.orange), makeTonal('teal', 'Teal', PAL.teal), makeTonal('lime', 'Lime', PAL.lime), makeTonal('pink', 'Pink', PAL.pink), makeTonal('sky', 'Sky', PAL.sky), makeTonal('mint', 'Mint', PAL.mint), makeTonal('plum', 'Plum', PAL.plum), makeTonal('sage', 'Sage', PAL.sage), makeTonal('sand', 'Sand', PAL.sand), makeTonal('graphite', 'Graphite', PAL.graphite),\n// Pill variants\n{\n  id: 'tonal-pill-indigo',\n  category: 'tonal',\n  label: 'Pill · indigo',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.indigo.tone,\n    text_color: PAL.indigo.toneText,\n    link_color: PAL.indigo.toneText\n  }, borderColor(PAL.indigo.tone)), {}, {\n    border_radius: '999px'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'tonal-pill-rose',\n  category: 'tonal',\n  label: 'Pill · rose',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.rose.tone,\n    text_color: PAL.rose.toneText,\n    link_color: PAL.rose.toneText\n  }, borderColor(PAL.rose.tone)), {}, {\n    border_radius: '999px'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'tonal-chip-slate',\n  category: 'tonal',\n  label: 'Chip · slate',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.slate.tone,\n    text_color: PAL.slate.toneText,\n    link_color: PAL.slate.toneText\n  }, borderColor(PAL.slate.tone)), {}, {\n    border_radius: '999px',\n    font_size: '12px',\n    padding_top: 6,\n    padding_bottom: 6,\n    padding_left: 14,\n    padding_right: 14\n  })),\n  icon: null,\n  iconPosition: 'none'\n}];\n\n// ─── GHOST (~14) ──────────────────────────────────────────────────────────\n\nvar GHOST = [makeGhost('indigo', 'Indigo', PAL.indigo), makeGhost('ink', 'Ink', PAL.ink), makeGhost('slate', 'Muted', PAL.slate, {\n  text: PAL.slate.strong\n}), makeGhost('emerald', 'Emerald', PAL.emerald), makeGhost('crimson', 'Crimson', PAL.crimson), makeGhost('violet', 'Violet', PAL.violet), makeGhost('rose', 'Rose', PAL.rose),\n// Link variants\n{\n  id: 'ghost-link-indigo',\n  category: 'ghost',\n  label: 'Link · indigo',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.indigo.solid,\n    link_color: PAL.indigo.solid\n  }, borderColor('transparent')), {}, {\n    padding_top: 6,\n    padding_right: 4,\n    padding_bottom: 6,\n    padding_left: 4,\n    font_weight: '500'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'ghost-link-underlined',\n  category: 'ghost',\n  label: 'Link · underlined',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.indigo.solid,\n    link_color: PAL.indigo.solid\n  }, borderColor('transparent')), {}, {\n    padding_top: 6,\n    padding_right: 4,\n    padding_bottom: 6,\n    padding_left: 4\n    // text_decoration not in formatter; relies on .bp-link CSS via data-fx\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'ghost-uppercase-tracking',\n  category: 'ghost',\n  label: 'All-caps · tracking',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.ink.solid,\n    link_color: PAL.ink.solid\n  }, borderColor('transparent')), {}, {\n    padding_top: 6,\n    padding_right: 4,\n    padding_bottom: 6,\n    padding_left: 4,\n    font_weight: '600',\n    letter_spacing: 2,\n    font_size: '12px'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'ghost-arrow-subtle',\n  category: 'ghost',\n  label: 'Arrow · subtle',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.ink.solid,\n    link_color: PAL.ink.solid\n  }, borderColor('transparent')), {}, {\n    padding_top: 8,\n    padding_right: 8,\n    padding_bottom: 8,\n    padding_left: 8\n  })),\n  icon: 'arrow_forward',\n  iconPosition: 'right'\n}, makeGhost('small-muted', 'Muted · small', PAL.slate, {\n  text: PAL.slate.toneText,\n  extra: {\n    font_size: '12px',\n    padding_top: 4,\n    padding_right: 8,\n    padding_bottom: 4,\n    padding_left: 8\n  }\n}), makeGhost('amber', 'Amber', PAL.amber, {\n  text: PAL.amber.strong\n}), makeGhost('cyan', 'Cyan', PAL.cyan, {\n  text: PAL.cyan.strong\n})];\n\n// ─── GRADIENT (~32) ───────────────────────────────────────────────────────\n\nvar GRADIENT = [makeGradient('sunset', 'Sunset', 'linear-gradient(135deg, #f97316, #ec4899)', '#f97316'), makeGradient('ocean', 'Ocean', 'linear-gradient(135deg, #06b6d4, #2563eb)', '#2563eb'), makeGradient('neon', 'Neon', 'linear-gradient(135deg, #ec4899, #8b5cf6)', '#8b5cf6'), makeGradient('forest', 'Forest', 'linear-gradient(135deg, #84cc16, #14b8a6)', '#14b8a6'), makeGradient('mono-dark', 'Mono · dark', 'linear-gradient(180deg, #334155, #0f172a)', '#0f172a'), makeGradient('mono-light', 'Mono · light', 'linear-gradient(180deg, #ffffff, #e5e7eb)', '#e5e7eb', '#111827', {\n  formats: borderColor('#d1d5db')\n}), makeGradient('brand-sweep', 'Brand sweep', 'linear-gradient(135deg, #2563eb, #1e40af)', '#1e40af'), makeGradient('iridescent', 'Iridescent', 'linear-gradient(135deg, #f472b6, #a78bfa, #60a5fa, #34d399)', '#a78bfa'), makeGradient('aurora', 'Aurora', 'linear-gradient(135deg, #14b8a6, #0ea5e9, #a855f7)', '#0ea5e9'), makeGradient('midnight', 'Midnight', 'linear-gradient(135deg, #1e1b4b, #312e81, #581c87)', '#1e1b4b'), makeGradient('peach', 'Peach', 'linear-gradient(135deg, #fed7aa, #fbcfe8)', '#fbcfe8', '#9d174d'), makeGradient('ember', 'Ember', 'linear-gradient(135deg, #f97316, #dc2626)', '#dc2626'), makeGradient('violet-dawn', 'Violet dawn', 'linear-gradient(135deg, #8b5cf6, #ec4899, #f59e0b)', '#8b5cf6'), makeGradient('rose-gold', 'Rose gold', 'linear-gradient(135deg, #f59e0b, #f43f5e)', '#f43f5e'), makeGradient('arctic', 'Arctic', 'linear-gradient(135deg, #e0f2fe, #bae6fd, #7dd3fc)', '#7dd3fc', '#075985'), makeGradient('sahara', 'Sahara', 'linear-gradient(135deg, #fde047, #fb923c)', '#fb923c', '#7c2d12'), makeGradient('jade', 'Jade', 'linear-gradient(135deg, #10b981, #14b8a6)', '#14b8a6'), makeGradient('nebula', 'Nebula', 'linear-gradient(135deg, #4338ca, #db2777, #c026d3)', '#4338ca'), makeGradient('twilight', 'Twilight', 'linear-gradient(135deg, #334155, #581c87)', '#581c87'), makeGradient('spring', 'Spring', 'linear-gradient(135deg, #bef264, #4ade80)', '#4ade80', '#365314'), makeGradient('candy', 'Candy', 'linear-gradient(135deg, #f9a8d4, #c4b5fd)', '#c4b5fd', '#6d28d9'), makeGradient('noir', 'Noir', 'linear-gradient(135deg, #1f2937, #0f172a)', '#0f172a'), makeGradient('marigold', 'Marigold', 'linear-gradient(135deg, #f59e0b, #eab308)', '#eab308', '#713f12'), makeGradient('lavender', 'Lavender', 'linear-gradient(135deg, #c084fc, #a78bfa)', '#a78bfa'), makeGradient('mist', 'Mist', 'linear-gradient(135deg, #e5e7eb, #cbd5e1)', '#cbd5e1', '#334155'), makeGradient('vapor', 'Vapor', 'linear-gradient(135deg, #67e8f9, #c4b5fd, #f9a8d4)', '#c4b5fd'), makeGradient('retro', 'Retro', 'linear-gradient(135deg, #fbbf24, #ef4444, #8b5cf6)', '#ef4444'), makeGradient('crimson-flame', 'Crimson flame', 'linear-gradient(135deg, #ef4444, #dc2626, #7f1d1d)', '#7f1d1d'), makeGradient('oceanic', 'Oceanic', 'linear-gradient(135deg, #0284c7, #1e3a8a)', '#1e3a8a'), makeGradient('electric', 'Electric', 'linear-gradient(135deg, #22d3ee, #60a5fa)', '#60a5fa'), makeGradient('blossom', 'Blossom', 'linear-gradient(135deg, #ec4899, #a855f7)', '#a855f7'), makeGradient('rainbow', 'Rainbow', 'linear-gradient(90deg, #ef4444, #f59e0b, #10b981, #3b82f6, #8b5cf6)', '#8b5cf6'), makeGradient('solar', 'Solar', 'linear-gradient(135deg, #facc15, #f97316, #dc2626)', '#f97316', '#7f1d1d')];\n\n// ─── ELEVATED (~18, page-only) ───────────────────────────────────────────\n\nvar ELEVATED = [makeElevated('indigo-3d', 'Indigo · 3D', PAL.indigo, '0 4px 0 #1e40af, 0 6px 12px rgba(37,99,235,0.35)'), makeElevated('ink-3d', 'Ink · 3D', PAL.ink, '0 4px 0 #030712, 0 6px 12px rgba(17,24,39,0.45)'), makeElevated('violet-3d', 'Violet · 3D', PAL.violet, '0 4px 0 #4c1d95, 0 6px 12px rgba(124,58,237,0.35)'), makeElevated('emerald-3d', 'Emerald · 3D', PAL.emerald, '0 4px 0 #14532d, 0 6px 12px rgba(22,163,74,0.35)'), makeElevated('crimson-3d', 'Crimson · 3D', PAL.crimson, '0 4px 0 #7f1d1d, 0 6px 12px rgba(220,38,38,0.35)'), makeElevated('indigo-drop-sm', 'Indigo · drop sm', PAL.indigo, SHADOW_SCALE.sm), makeElevated('indigo-drop-md', 'Indigo · drop md', PAL.indigo, SHADOW_SCALE.md), makeElevated('indigo-drop-lg', 'Indigo · drop lg', PAL.indigo, SHADOW_SCALE.lg), makeElevated('indigo-drop-xl', 'Indigo · drop xl', PAL.indigo, SHADOW_SCALE.xl), makeElevated('ink-drop-lg', 'Ink · heavy drop', PAL.ink, SHADOW_SCALE.lg), makeElevated('amber-float', 'Amber · float', PAL.amber, '0 18px 32px -10px rgba(245,158,11,0.48)'), makeElevated('paper-soft', 'Paper · pillow', PAL.paper, '0 2px 8px rgba(0,0,0,0.08), 0 8px 20px rgba(0,0,0,0.06)', {\n  fg: '#111827',\n  formats: borderColor('#e5e7eb')\n}), makeElevated('emerald-float', 'Emerald · float', PAL.emerald, '0 18px 32px -10px rgba(22,163,74,0.4)'), makeElevated('rose-float', 'Rose · float', PAL.rose, '0 18px 32px -10px rgba(225,29,72,0.45)'), makeElevated('double-shadow', 'Double shadow', PAL.indigo, '0 4px 10px rgba(37,99,235,0.3), 0 12px 32px rgba(37,99,235,0.25)'), makeElevated('pressed-inner', 'Pressed · inner', PAL.indigo, SHADOW_SCALE.inner), makeElevated('stacked-card', 'Stacked card', PAL.paper, '2px 2px 0 #e5e7eb, 4px 4px 0 #d1d5db, 6px 6px 0 #9ca3af', {\n  fg: '#111827'\n}), makeElevated('pro-charcoal', 'Pro · charcoal', PAL.charcoal, SHADOW_SCALE.xl)];\n\n// ─── GLASS & GLOW (~16, page-only) ───────────────────────────────────────\n\nvar GLASS = [{\n  id: 'glass-default',\n  category: 'glass',\n  label: 'Glass',\n  flags: PAGE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'rgba(255,255,255,0.18)',\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor('rgba(255,255,255,0.4)')), borderWidth('1px'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'glass-frost',\n  category: 'glass',\n  label: 'Frost · heavy blur',\n  flags: PAGE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'rgba(255,255,255,0.32)',\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor('rgba(255,255,255,0.6)')), borderWidth('1px'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'glass-tinted-violet',\n  category: 'glass',\n  label: 'Glass · tinted violet',\n  flags: PAGE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'rgba(124,58,237,0.2)',\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor('rgba(196,181,253,0.4)')), borderWidth('1px'))),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'glass-tinted-cyan',\n  category: 'glass',\n  label: 'Glass · tinted cyan',\n  flags: PAGE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'rgba(6,182,212,0.2)',\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor('rgba(103,232,249,0.4)')), borderWidth('1px'))),\n  icon: null,\n  iconPosition: 'none'\n}, makeGlow('glow-violet', 'Glow · violet', PAL.violet, '0 0 24px rgba(124,58,237,0.55)'), makeGlow('glow-cyan', 'Glow · cyan', PAL.cyan, '0 0 24px rgba(6,182,212,0.6)'), makeGlow('glow-rose', 'Glow · rose', PAL.rose, '0 0 24px rgba(225,29,72,0.6)'), makeGlow('glow-emerald', 'Glow · emerald', PAL.emerald, '0 0 24px rgba(22,163,74,0.6)'), makeGlow('glow-amber', 'Glow · amber', PAL.amber, '0 0 24px rgba(245,158,11,0.7)'), makeGlow('glow-pink', 'Glow · pink', PAL.pink, '0 0 24px rgba(219,39,119,0.6)'), makeGlow('glow-strong-violet', 'Glow · strong', PAL.violet, '0 0 0 4px rgba(124,58,237,0.2), 0 0 32px rgba(124,58,237,0.85)'), makeGlow('halo-warm', 'Halo · warm', PAL.amber, '0 0 0 4px rgba(245,158,11,0.2), 0 0 28px rgba(245,158,11,0.6)'), makeGlow('halo-cool', 'Halo · cool', PAL.cyan, '0 0 0 4px rgba(6,182,212,0.2), 0 0 28px rgba(6,182,212,0.6)'), makeGlow('pulse-violet', 'Pulse · violet', PAL.violet, '0 0 0 2px rgba(124,58,237,0.25), 0 0 16px rgba(124,58,237,0.45), 0 0 32px rgba(124,58,237,0.25)'), makeGlow('neon-edge', 'Neon edge', PAL.pink, '0 0 0 1px #ff79c6, 0 0 12px #ff79c6, 0 0 24px rgba(255,121,198,0.6)'), {\n  id: 'glass-bordered-ink',\n  category: 'glass',\n  label: 'Glass · bordered ink',\n  flags: PAGE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: 'rgba(17,24,39,0.35)',\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor('rgba(255,255,255,0.25)')), borderWidth('1px')), {}, {\n    box_shadow: '0 8px 24px rgba(0,0,0,0.35)'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}];\n\n// ─── BRUTALIST (~14) ─────────────────────────────────────────────────────\n\nvar BRUTALIST = [makeBrutalist('yellow', 'Yellow · classic', '#fde047', '#111827'), makeBrutalist('pink-loud', 'Pink · loud', '#ec4899', '#ffffff'), makeBrutalist('mono', 'Mono · stark', '#ffffff', '#111827', '#111827', {\n  formats: _objectSpread(_objectSpread({}, borderWidth('3px')), {}, {\n    box_shadow: '6px 6px 0 #111827',\n    font_weight: '700'\n  })\n}), makeBrutalist('orange', 'Orange · loud', '#fb923c', '#ffffff'), makeBrutalist('cyan', 'Cyan · loud', '#22d3ee', '#0f172a'), makeBrutalist('lime', 'Lime · sharp', '#bef264', '#1c1917'), makeBrutalist('purple', 'Purple · loud', '#a855f7', '#ffffff'), {\n  id: 'brutalist-editorial-underline',\n  category: 'brutalist',\n  label: 'Editorial · underline',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: 'transparent',\n    text_color: '#111827',\n    link_color: '#111827'\n  }, borderColor('transparent')), {}, {\n    border_radius: '0px',\n    font_family: 'Georgia, \"Times New Roman\", serif',\n    font_weight: '400',\n    font_size: '16px',\n    letter_spacing: null\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'brutalist-serif-italic',\n  category: 'brutalist',\n  label: 'Serif · italic',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: '#ffffff',\n    text_color: '#111827',\n    link_color: '#111827'\n  }, borderColor('#111827')), borderWidth('1px')), {}, {\n    border_radius: '0px',\n    font_family: 'Georgia, \"Times New Roman\", serif'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, {\n  id: 'brutalist-all-caps',\n  category: 'brutalist',\n  label: 'All-caps · bordered',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: '#ffffff',\n    text_color: '#111827',\n    link_color: '#111827'\n  }, borderColor('#111827')), borderWidth('2px')), {}, {\n    border_radius: '0px',\n    letter_spacing: 2,\n    font_weight: '700',\n    font_size: '12px'\n  })),\n  icon: null,\n  iconPosition: 'none'\n}, makeBrutalist('red', 'Red · sharp', '#ef4444', '#ffffff'), makeBrutalist('green', 'Green · sharp', '#22c55e', '#ffffff'), makeBrutalist('sky', 'Sky · loud', '#7dd3fc', '#0c4a6e'), {\n  id: 'brutalist-tab-style',\n  category: 'brutalist',\n  label: 'Tab-style',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread(_objectSpread({\n    background_color: '#111827',\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor('#111827')), borderWidth('0px')), {}, {\n    border_radius: '0px',\n    font_weight: '600',\n    letter_spacing: 1\n  })),\n  icon: null,\n  iconPosition: 'none'\n}];\n\n// ─── ICON-LED (~14) ──────────────────────────────────────────────────────\n\nvar ICON_LED = [{\n  id: 'icon-left-download',\n  category: 'icon',\n  label: 'Download · left',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.indigo.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.indigo.solid))),\n  icon: 'download',\n  iconPosition: 'left'\n}, {\n  id: 'icon-right-arrow',\n  category: 'icon',\n  label: 'Continue · arrow',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.indigo.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.indigo.solid))),\n  icon: 'arrow_forward',\n  iconPosition: 'right'\n}, {\n  id: 'icon-right-launch',\n  category: 'icon',\n  label: 'Open · external',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.indigo.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.indigo.solid))),\n  icon: 'open_in_new',\n  iconPosition: 'right'\n}, {\n  id: 'icon-left-cart',\n  category: 'icon',\n  label: 'Cart · add',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.emerald.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.emerald.solid))),\n  icon: 'shopping_cart',\n  iconPosition: 'left'\n}, {\n  id: 'icon-left-mail',\n  category: 'icon',\n  label: 'Email · left',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.cyan.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.cyan.solid))),\n  icon: 'mail',\n  iconPosition: 'left'\n}, {\n  id: 'icon-left-play',\n  category: 'icon',\n  label: 'Play video',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.rose.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.rose.solid))),\n  icon: 'play_arrow',\n  iconPosition: 'left'\n}, {\n  id: 'icon-only-heart-c',\n  category: 'icon',\n  label: 'Heart · circle',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.rose.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.rose.solid)), {}, {\n    border_radius: '999px',\n    padding_top: 10,\n    padding_right: 10,\n    padding_bottom: 10,\n    padding_left: 10\n  })),\n  icon: 'favorite',\n  iconPosition: 'only'\n}, {\n  id: 'icon-only-share-s',\n  category: 'icon',\n  label: 'Share · square',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.slate.tone,\n    text_color: PAL.slate.strong,\n    link_color: PAL.slate.strong\n  }, borderColor(PAL.slate.tone)), {}, {\n    border_radius: '6px',\n    padding_top: 10,\n    padding_right: 10,\n    padding_bottom: 10,\n    padding_left: 10\n  })),\n  icon: 'share',\n  iconPosition: 'only'\n}, {\n  id: 'icon-only-fab-add',\n  category: 'icon',\n  label: 'FAB · add',\n  flags: PAGE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.indigo.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.indigo.solid)), {}, {\n    border_radius: '999px',\n    padding_top: 18,\n    padding_right: 18,\n    padding_bottom: 18,\n    padding_left: 18,\n    box_shadow: '0 8px 24px rgba(37,99,235,0.4)'\n  })),\n  icon: 'add',\n  iconPosition: 'only'\n}, {\n  id: 'icon-only-mini-edit',\n  category: 'icon',\n  label: 'Mini edit',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.indigo.tone,\n    text_color: PAL.indigo.toneText,\n    link_color: PAL.indigo.toneText\n  }, borderColor(PAL.indigo.tone)), {}, {\n    border_radius: '6px',\n    padding_top: 6,\n    padding_right: 6,\n    padding_bottom: 6,\n    padding_left: 6,\n    font_size: '12px'\n  })),\n  icon: 'edit',\n  iconPosition: 'only'\n}, {\n  id: 'icon-left-back',\n  category: 'icon',\n  label: 'Back · arrow',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: 'transparent',\n    text_color: PAL.ink.solid,\n    link_color: PAL.ink.solid\n  }, borderColor('transparent'))),\n  icon: 'arrow_back',\n  iconPosition: 'left'\n}, {\n  id: 'icon-left-check',\n  category: 'icon',\n  label: 'Confirm · check',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.emerald.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.emerald.solid))),\n  icon: 'check',\n  iconPosition: 'left'\n}, {\n  id: 'icon-left-phone',\n  category: 'icon',\n  label: 'Call · phone',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread(_objectSpread({\n    background_color: PAL.ink.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.ink.solid)), {}, {\n    border_radius: '999px'\n  })),\n  icon: 'call',\n  iconPosition: 'left'\n}, {\n  id: 'icon-right-send',\n  category: 'icon',\n  label: 'Send · message',\n  flags: SAFE,\n  formats: Object.assign({}, DEFAULT_MD, _objectSpread({\n    background_color: PAL.violet.solid,\n    text_color: '#ffffff',\n    link_color: '#ffffff'\n  }, borderColor(PAL.violet.solid))),\n  icon: 'send',\n  iconPosition: 'right'\n}];\n\n// ─── REGISTRY ────────────────────────────────────────────────────────────\n\nvar PRESETS = [].concat(SOLID, OUTLINE, TONAL, GHOST, GRADIENT, ELEVATED, GLASS, BRUTALIST, ICON_LED);\nvar CATEGORIES = [{\n  id: 'solid',\n  label: 'Solid',\n  order: 1\n}, {\n  id: 'outline',\n  label: 'Outline',\n  order: 2\n}, {\n  id: 'tonal',\n  label: 'Tonal',\n  order: 3\n}, {\n  id: 'ghost',\n  label: 'Ghost',\n  order: 4\n}, {\n  id: 'gradient',\n  label: 'Gradient',\n  order: 5\n}, {\n  id: 'elevated',\n  label: 'Elevated',\n  order: 6\n}, {\n  id: 'glass',\n  label: 'Glass & Glow',\n  order: 7\n}, {\n  id: 'brutalist',\n  label: 'Brutalist',\n  order: 8\n}, {\n  id: 'icon',\n  label: 'Icon-Led',\n  order: 9\n}];\n\n/**\n * Find a preset by id. Returns null if not found (caller must decide: skip,\n * fall back to 'solid-indigo', or throw). Saved templates may carry a\n * preset_id that was removed in a later revision — callers should treat\n * null as \"unknown preset, keep current formatter as-is\".\n */\nfunction findPreset(id) {\n  if (!id) return null;\n  return PRESETS.find(function (p) {\n    return p.id === id;\n  }) || null;\n}\nfunction presetsByCategory(catId) {\n  return PRESETS.filter(function (p) {\n    return p.category === catId;\n  });\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n  SIZE_SCALE: SIZE_SCALE,\n  SIZE_KEYS: SIZE_KEYS,\n  SHADOW_SCALE: SHADOW_SCALE,\n  SHADOW_KEYS: SHADOW_KEYS,\n  HOVER_EFFECT_KEYS: HOVER_EFFECT_KEYS,\n  PRESETS: PRESETS,\n  CATEGORIES: CATEGORIES,\n  findPreset: findPreset,\n  presetsByCategory: presetsByCategory\n});\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/buttonPresets.js?");

/***/ }),

/***/ "./src/includes/overlays/AIRewritePopoverOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/AIRewritePopoverOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * AIRewritePopoverOverlay — W6.1 inline AI rewrite popover.\n *\n * TEXT_INLINE_PLAN W6.1 (2026-04-21). First consumer of the new AI Task\n * framework. Mounts on the toolbar's sparkle button, lets the user\n * transform the current selection via 8 action presets × tone × length ×\n * custom prompt × variant carousel.\n *\n * Calls POST {builder.ai.inlineRewriteUrl} with payload:\n *   { text, action, tone?, length?, custom_instruction?, variant_count,\n *     element: { type, role }, block: { purpose, siblings },\n *     currentPage: builder.getData() }\n *\n * Response (uniform AITaskResult shape):\n *   { status, primary, variants[], data: { action, variant_count }, engine, model }\n *\n * UX states (W6.1 acceptance):\n *   - idle:      action chip grid + tone + length + custom prompt + Rewrite CTA\n *   - loading:   inputs disabled, shimmer over result slot, sparkle pulses\n *   - result:    variant card(s) with arrow nav + Apply / Try again / Undo\n *   - error:     red banner + retry button (status preserved)\n *   - rate-limited: friendly countdown\n *   - disabled:  \"AI not configured\" panel (when ai.enabled=false or url null)\n *\n * HARD RULES applied:\n *   T1 (selection = source of truth): popover holds saved selection range,\n *      restores before applying variant.\n *   T2 (no rerender on apply): selection's containing element receives the\n *      new HTML via `range.deleteContents()` + `range.insertNode()` then\n *      element is asked for a stable inline-only re-snapshot.\n *   T6 (failure visible): every error path renders an error bubble.\n *   T8 (host page sacred): mounts inside .bjs-overlay-root (popover host).\n *   T9 (inline scope): backend-side InlineHtmlSanitizer enforces; frontend\n *      uses InlineSanitizer.normalize after insert.\n */\n\n\n\n\nvar QUICK_ACTIONS = [{\n  key: 'improve',\n  icon: 'auto_fix_normal',\n  labelKey: 'ai_rewrite.action_improve'\n}, {\n  key: 'shorten',\n  icon: 'compress',\n  labelKey: 'ai_rewrite.action_shorten'\n}, {\n  key: 'expand',\n  icon: 'expand',\n  labelKey: 'ai_rewrite.action_expand'\n}, {\n  key: 'simplify',\n  icon: 'lightbulb',\n  labelKey: 'ai_rewrite.action_simplify'\n}, {\n  key: 'fix_grammar',\n  icon: 'spellcheck',\n  labelKey: 'ai_rewrite.action_fix_grammar'\n}, {\n  key: 'cta_ify',\n  icon: 'campaign',\n  labelKey: 'ai_rewrite.action_cta_ify'\n}, {\n  key: 'translate',\n  icon: 'translate',\n  labelKey: 'ai_rewrite.action_translate'\n}, {\n  key: 'rewrite',\n  icon: 'edit_note',\n  labelKey: 'ai_rewrite.action_custom'\n}];\nvar TONES = ['formal', 'casual', 'playful', 'persuasive', 'friendly', 'urgent'];\nvar LENGTHS = ['shorter', 'same', 'longer'];\nvar AIRewritePopoverOverlay = /*#__PURE__*/function () {\n  /**\n   * @param {TextInlineToolbarOverlay} toolbar — owner, used to share selection save/restore.\n   * @param {{ anchorBtn: HTMLElement, builder: object }} opts\n   */\n  function AIRewritePopoverOverlay(toolbar, opts) {\n    _classCallCheck(this, AIRewritePopoverOverlay);\n    if (!toolbar || !opts || !opts.anchorBtn || !opts.builder) {\n      throw new Error('AIRewritePopoverOverlay: toolbar + opts.anchorBtn + opts.builder required');\n    }\n    this._toolbar = toolbar;\n    this._builder = opts.builder;\n    this._anchorBtn = opts.anchorBtn;\n    this._ai = opts.builder && opts.builder.ai || {};\n    this.domNode = null;\n    this._positionHandle = null;\n    this._onDocKey = null;\n    this._onDocMouseDown = null;\n    this._mounted = false;\n\n    // Form state\n    this._action = 'rewrite';\n    this._tone = null;\n    this._length = 'same';\n    this._custom = '';\n    this._variantCount = 1;\n\n    // Result state\n    this._variants = [];\n    this._activeVariantIndex = 0;\n    this._previousHtml = null; // for undo\n    this._savedRange = null; // selection range at open time\n    this._snapshotText = null; // original text for fallback\n    this._isLoading = false;\n    this._errorState = null;\n  }\n  return _createClass(AIRewritePopoverOverlay, [{\n    key: \"open\",\n    value: function open() {\n      var _this = this;\n      if (this._mounted) return;\n      try {\n        this._captureSelection();\n        this._build();\n        document.body.appendChild(this.domNode);\n        this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n          anchor: function anchor() {\n            return _this._anchorBtn.getBoundingClientRect();\n          },\n          target: this.domNode,\n          offset: 8,\n          collisionPadding: 12,\n          preferredSide: 'below',\n          flip: true\n        });\n        this._registerDismissListeners();\n        this._mounted = true;\n        this._anchorBtn.setAttribute('aria-expanded', 'true');\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:ai-rewrite] open failed:', err);\n        this.close();\n      }\n    }\n  }, {\n    key: \"close\",\n    value: function close() {\n      if (!this._mounted && !this.domNode) return;\n      this._unregisterDismissListeners();\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.dispose();\n        } catch (_) {}\n        this._positionHandle = null;\n      }\n      if (this.domNode && this.domNode.parentNode) {\n        try {\n          this.domNode.parentNode.removeChild(this.domNode);\n        } catch (_) {}\n      }\n      this.domNode = null;\n      this._mounted = false;\n      this._anchorBtn.removeAttribute('aria-expanded');\n    }\n  }, {\n    key: \"isOpen\",\n    value: function isOpen() {\n      return this._mounted;\n    }\n\n    /* ── selection ────────────────────────────────────────────────── */\n  }, {\n    key: \"_captureSelection\",\n    value: function _captureSelection() {\n      var tracker = this._builder && this._builder.textSelectionTracker;\n      var last = tracker && typeof tracker.getLast === 'function' ? tracker.getLast() : null;\n      if (last && last.range) {\n        this._savedRange = last.range.cloneRange();\n        this._snapshotText = last.text || last.range.toString();\n        return;\n      }\n      // Fallback — try active selection in iframe.\n      try {\n        var iframeDoc = this._builder.iframe && this._builder.iframe.contentDocument || document;\n        var sel = iframeDoc.getSelection ? iframeDoc.getSelection() : null;\n        if (sel && sel.rangeCount > 0) {\n          this._savedRange = sel.getRangeAt(0).cloneRange();\n          this._snapshotText = sel.toString();\n        }\n      } catch (_) {\n        this._savedRange = null;\n        this._snapshotText = null;\n      }\n    }\n\n    /* ── build DOM ────────────────────────────────────────────────── */\n  }, {\n    key: \"_build\",\n    value: function _build() {\n      var p = document.createElement('div');\n      p.className = 'bjs-ovl bjs-ovl-ai-rewrite';\n      p.setAttribute('role', 'dialog');\n      p.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.dialog_title'));\n      p.setAttribute('data-interactive', '');\n      var aiAvailable = !!(this._ai.enabled && this._ai.inlineRewriteUrl);\n      if (!aiAvailable) {\n        p.appendChild(this._renderDisabled());\n        this.domNode = p;\n        return;\n      }\n      p.appendChild(this._renderHeader());\n      this._bodyEl = document.createElement('div');\n      this._bodyEl.className = 'bjs-ovl-ai-body';\n      p.appendChild(this._bodyEl);\n      this._renderForm();\n      this.domNode = p;\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var _this2 = this;\n      var h = document.createElement('div');\n      h.className = 'bjs-ovl-ai-header';\n      h.innerHTML = \"\\n            <span class=\\\"bjs-ovl-ai-title\\\">\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.dialog_title')), \"</span>\\n            <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-close\\\" aria-label=\\\"\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.close')), \"\\\">\\n                <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">close</span>\\n            </button>\\n        \");\n      h.querySelector('.bjs-ovl-ai-close').addEventListener('click', function (e) {\n        e.preventDefault();\n        _this2.close();\n      });\n      return h;\n    }\n  }, {\n    key: \"_renderDisabled\",\n    value: function _renderDisabled() {\n      var _this3 = this;\n      var d = document.createElement('div');\n      d.className = 'bjs-ovl-ai-disabled';\n      d.innerHTML = \"\\n            <div class=\\\"bjs-ovl-ai-disabled-icon\\\"><span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">block</span></div>\\n            <div class=\\\"bjs-ovl-ai-disabled-title\\\">\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.disabled_title')), \"</div>\\n            <div class=\\\"bjs-ovl-ai-disabled-msg\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.disabled_msg')), \"</div>\\n            <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary\\\" data-action=\\\"close\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.close')), \"</button>\\n        \");\n      d.querySelector('[data-action=\"close\"]').addEventListener('click', function () {\n        return _this3.close();\n      });\n      return d;\n    }\n  }, {\n    key: \"_renderForm\",\n    value: function _renderForm() {\n      var _this4 = this;\n      this._bodyEl.innerHTML = '';\n\n      // Quick actions chip grid\n      var actionsLabel = document.createElement('div');\n      actionsLabel.className = 'bjs-ovl-ai-section-label';\n      actionsLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.quick_actions');\n      this._bodyEl.appendChild(actionsLabel);\n      var actionsGrid = document.createElement('div');\n      actionsGrid.className = 'bjs-ovl-ai-actions-grid';\n      QUICK_ACTIONS.forEach(function (act) {\n        var btn = document.createElement('button');\n        btn.type = 'button';\n        btn.className = 'bjs-ovl-ai-action-chip';\n        btn.dataset.action = act.key;\n        if (_this4._action === act.key) btn.classList.add('is-selected');\n        btn.innerHTML = \"\\n                <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\".concat(act.icon, \"</span>\\n                <span class=\\\"bjs-ovl-ai-action-label\\\">\").concat(_this4._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(act.labelKey)), \"</span>\\n            \");\n        btn.addEventListener('click', function () {\n          _this4._action = act.key;\n          _this4._bodyEl.querySelectorAll('.bjs-ovl-ai-action-chip').forEach(function (c) {\n            return c.classList.remove('is-selected');\n          });\n          btn.classList.add('is-selected');\n          _this4._updateRewriteEnabled();\n        });\n        actionsGrid.appendChild(btn);\n      });\n      this._bodyEl.appendChild(actionsGrid);\n\n      // Tone chip row\n      var toneLabel = document.createElement('div');\n      toneLabel.className = 'bjs-ovl-ai-section-label';\n      toneLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.tone');\n      this._bodyEl.appendChild(toneLabel);\n      var toneRow = document.createElement('div');\n      toneRow.className = 'bjs-ovl-ai-tone-row';\n      TONES.forEach(function (t) {\n        var chip = document.createElement('button');\n        chip.type = 'button';\n        chip.className = 'bjs-ovl-ai-tone-chip';\n        chip.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.tone_' + t);\n        chip.dataset.tone = t;\n        if (_this4._tone === t) chip.classList.add('is-selected');\n        chip.addEventListener('click', function () {\n          _this4._tone = _this4._tone === t ? null : t;\n          toneRow.querySelectorAll('.bjs-ovl-ai-tone-chip').forEach(function (c) {\n            return c.classList.remove('is-selected');\n          });\n          if (_this4._tone === t) chip.classList.add('is-selected');\n        });\n        toneRow.appendChild(chip);\n      });\n      this._bodyEl.appendChild(toneRow);\n\n      // Length segmented\n      var lengthLabel = document.createElement('div');\n      lengthLabel.className = 'bjs-ovl-ai-section-label';\n      lengthLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.length');\n      this._bodyEl.appendChild(lengthLabel);\n      var lengthSeg = document.createElement('div');\n      lengthSeg.className = 'bjs-ovl-ai-length-seg';\n      LENGTHS.forEach(function (len) {\n        var seg = document.createElement('button');\n        seg.type = 'button';\n        seg.className = 'bjs-ovl-ai-length-seg-btn';\n        seg.dataset.length = len;\n        seg.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.length_' + len);\n        if (_this4._length === len) seg.classList.add('is-selected');\n        seg.addEventListener('click', function () {\n          _this4._length = len;\n          lengthSeg.querySelectorAll('.bjs-ovl-ai-length-seg-btn').forEach(function (c) {\n            return c.classList.remove('is-selected');\n          });\n          seg.classList.add('is-selected');\n        });\n        lengthSeg.appendChild(seg);\n      });\n      this._bodyEl.appendChild(lengthSeg);\n\n      // Custom prompt\n      var customLabel = document.createElement('div');\n      customLabel.className = 'bjs-ovl-ai-section-label';\n      customLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.custom_prompt');\n      this._bodyEl.appendChild(customLabel);\n      var customWrap = document.createElement('div');\n      customWrap.className = 'bjs-ovl-ai-custom-wrap';\n      var customInput = document.createElement('textarea');\n      customInput.className = 'bjs-ovl-ai-custom-input';\n      customInput.rows = 2;\n      customInput.maxLength = 300;\n      customInput.placeholder = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.custom_placeholder');\n      customInput.value = this._custom;\n      customInput.addEventListener('input', function () {\n        _this4._custom = customInput.value;\n        _this4._updateRewriteEnabled();\n      });\n      customInput.addEventListener('keydown', function (e) {\n        if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n          e.preventDefault();\n          _this4._runRewrite();\n        }\n      });\n      customWrap.appendChild(customInput);\n      this._bodyEl.appendChild(customWrap);\n\n      // CTA\n      var cta = document.createElement('div');\n      cta.className = 'bjs-ovl-ai-cta';\n      var cancelBtn = document.createElement('button');\n      cancelBtn.type = 'button';\n      cancelBtn.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary';\n      cancelBtn.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.cancel');\n      cancelBtn.addEventListener('click', function () {\n        return _this4.close();\n      });\n      var rewriteBtn = document.createElement('button');\n      rewriteBtn.type = 'button';\n      rewriteBtn.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-primary';\n      rewriteBtn.dataset.role = 'rewrite';\n      rewriteBtn.innerHTML = \"\\n            <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.rewrite')), \"</span>\\n            <span class=\\\"bjs-ovl-ai-cta-shortcut\\\">\\u2318\\u21B5</span>\\n        \");\n      rewriteBtn.addEventListener('click', function () {\n        return _this4._runRewrite();\n      });\n      this._rewriteBtn = rewriteBtn;\n      cta.appendChild(cancelBtn);\n      cta.appendChild(rewriteBtn);\n      this._bodyEl.appendChild(cta);\n      this._updateRewriteEnabled();\n    }\n  }, {\n    key: \"_updateRewriteEnabled\",\n    value: function _updateRewriteEnabled() {\n      if (!this._rewriteBtn) return;\n      // Always enabled once an action is selected (default 'rewrite' = true).\n      var enabled = !this._isLoading && !!this._action;\n      this._rewriteBtn.disabled = !enabled;\n      this._rewriteBtn.classList.toggle('is-disabled', !enabled);\n    }\n\n    /* ── result rendering ─────────────────────────────────────────── */\n  }, {\n    key: \"_renderLoading\",\n    value: function _renderLoading() {\n      this._bodyEl.innerHTML = '';\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-ai-loading';\n      // Skeleton shimmer lines — grey tones, staggered pulse; 3 bouncing\n      // dots in the status row. No sparkle, no violet. Feels \"thumbing\"\n      // (alive) while staying in the builderjs neutral palette.\n      wrap.innerHTML = \"\\n            <div class=\\\"bjs-ovl-ai-loading-lines\\\" aria-hidden=\\\"true\\\">\\n                <div class=\\\"bjs-ovl-ai-loading-line\\\"></div>\\n                <div class=\\\"bjs-ovl-ai-loading-line\\\"></div>\\n                <div class=\\\"bjs-ovl-ai-loading-line\\\"></div>\\n            </div>\\n            <div class=\\\"bjs-ovl-ai-loading-text\\\">\\n                <span class=\\\"bjs-ovl-ai-loading-dots\\\" aria-hidden=\\\"true\\\">\\n                    <span class=\\\"bjs-ovl-ai-loading-dot\\\"></span>\\n                    <span class=\\\"bjs-ovl-ai-loading-dot\\\"></span>\\n                    <span class=\\\"bjs-ovl-ai-loading-dot\\\"></span>\\n                </span>\\n                <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.loading')), \"</span>\\n            </div>\\n        \");\n      this._bodyEl.appendChild(wrap);\n    }\n  }, {\n    key: \"_renderResult\",\n    value: function _renderResult() {\n      var _this5 = this;\n      this._bodyEl.innerHTML = '';\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-ai-result';\n\n      // Variant carousel header\n      if (this._variants.length > 1) {\n        var tabs = document.createElement('div');\n        tabs.className = 'bjs-ovl-ai-variant-tabs';\n        this._variants.forEach(function (_, i) {\n          var tab = document.createElement('button');\n          tab.type = 'button';\n          tab.className = 'bjs-ovl-ai-variant-tab';\n          tab.textContent = String(i + 1);\n          if (i === _this5._activeVariantIndex) tab.classList.add('is-active');\n          tab.addEventListener('click', function () {\n            _this5._activeVariantIndex = i;\n            _this5._renderResult();\n          });\n          tabs.appendChild(tab);\n        });\n        wrap.appendChild(tabs);\n      }\n\n      // Active variant card\n      var card = document.createElement('div');\n      card.className = 'bjs-ovl-ai-variant-card';\n      card.innerHTML = this._variants[this._activeVariantIndex] || '';\n      wrap.appendChild(card);\n\n      // Action row\n      var actions = document.createElement('div');\n      actions.className = 'bjs-ovl-ai-result-actions';\n      var tryAgain = document.createElement('button');\n      tryAgain.type = 'button';\n      tryAgain.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary';\n      tryAgain.innerHTML = \"<span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">refresh</span> <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.try_again')), \"</span>\");\n      tryAgain.addEventListener('click', function () {\n        return _this5._runRewrite();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-ai-btn bjs-ovl-ai-btn-primary';\n      apply.innerHTML = \"<span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">check</span> <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.apply')), \"</span>\");\n      apply.addEventListener('click', function () {\n        return _this5._applyVariant(_this5._variants[_this5._activeVariantIndex]);\n      });\n      actions.appendChild(tryAgain);\n      actions.appendChild(apply);\n      wrap.appendChild(actions);\n      this._bodyEl.appendChild(wrap);\n    }\n  }, {\n    key: \"_renderError\",\n    value: function _renderError(errorType, message, retryAfter) {\n      var _this6 = this;\n      this._bodyEl.innerHTML = '';\n      var labels = {\n        rate_limit: 'ai_rewrite.error_rate_limit',\n        disabled: 'ai_rewrite.error_disabled',\n        timeout: 'ai_rewrite.error_timeout',\n        engine: 'ai_rewrite.error_engine',\n        configuration: 'ai_rewrite.error_configuration',\n        validation: 'ai_rewrite.error_validation',\n        internal: 'ai_rewrite.error_internal',\n        task_not_found: 'ai_rewrite.error_task_not_found'\n      };\n      var labelKey = labels[errorType] || 'ai_rewrite.error_unknown';\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-ai-error';\n      var iconText = errorType === 'rate_limit' ? 'hourglass_empty' : 'error';\n      var retryHint = errorType === 'rate_limit' && retryAfter ? \" (~\".concat(retryAfter, \"s)\") : '';\n      wrap.innerHTML = \"\\n            <div class=\\\"bjs-ovl-ai-error-icon\\\"><span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">\".concat(iconText, \"</span></div>\\n            <div class=\\\"bjs-ovl-ai-error-label\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(labelKey))).concat(this._escape(retryHint), \"</div>\\n            <div class=\\\"bjs-ovl-ai-error-msg\\\">\").concat(this._escape(message || ''), \"</div>\\n            <div class=\\\"bjs-ovl-ai-error-actions\\\">\\n                <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-btn bjs-ovl-ai-btn-secondary\\\" data-action=\\\"back\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.back')), \"</button>\\n                <button type=\\\"button\\\" class=\\\"bjs-ovl-ai-btn bjs-ovl-ai-btn-primary\\\" data-action=\\\"retry\\\">\").concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.try_again')), \"</button>\\n            </div>\\n        \");\n      wrap.querySelector('[data-action=\"back\"]').addEventListener('click', function () {\n        return _this6._renderForm();\n      });\n      wrap.querySelector('[data-action=\"retry\"]').addEventListener('click', function () {\n        return _this6._runRewrite();\n      });\n      this._bodyEl.appendChild(wrap);\n    }\n\n    /* ── network ──────────────────────────────────────────────────── */\n  }, {\n    key: \"_runRewrite\",\n    value: (function () {\n      var _runRewrite2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n        var url, text, payload, _headers, res, data;\n        return _regeneratorRuntime().wrap(function _callee$(_context) {\n          while (1) switch (_context.prev = _context.next) {\n            case 0:\n              url = this._ai.inlineRewriteUrl;\n              if (url) {\n                _context.next = 4;\n                break;\n              }\n              this._renderError('configuration', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.disabled_msg'));\n              return _context.abrupt(\"return\");\n            case 4:\n              text = this._snapshotText || '';\n              if (text.trim()) {\n                _context.next = 8;\n                break;\n              }\n              this._renderError('validation', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.error_empty_selection'));\n              return _context.abrupt(\"return\");\n            case 8:\n              this._isLoading = true;\n              this._renderLoading();\n              payload = {\n                text: text,\n                action: this._action,\n                tone: this._tone || undefined,\n                length: this._length || undefined,\n                custom_instruction: this._custom || undefined,\n                variant_count: this._variantCount,\n                element: this._collectElementContext(),\n                block: this._collectBlockContext(),\n                // Optional locale hint — backend/LLM can use to bias output\n                // language when ambiguous. Auto-detected from BuilderJS I18n.\n                user_locale: (typeof _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getLocale === 'function' ? _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getLocale() : null) || undefined\n              }; // Include page only for actions that benefit (matches backend\n              // BuilderPageContextProvider tier-3 trigger list).\n              if (['improve', 'cta_ify', 'rewrite_on_brand'].includes(this._action)) {\n                try {\n                  payload.currentPage = this._builder.getData();\n                } catch (_) {}\n              }\n              _context.prev = 12;\n              // F11.1 (2026-04-28) — hosted AI endpoints typically require\n              // auth via web session OR API token. Send Authorization: Bearer\n              // header when consumer supplied `ai.apiToken` (BuilderJS demo\n              // cross-origin path) — preferred over `?api_token=` query for\n              // header hygiene. Same-origin server-rendered callers ride the\n              // session cookie and leave apiToken empty.\n              _headers = {\n                'Accept': 'application/json',\n                'Content-Type': 'application/json',\n                'X-CSRF-TOKEN': this._ai.csrfToken || ''\n              };\n              if (this._ai.apiToken) _headers['Authorization'] = 'Bearer ' + this._ai.apiToken;\n              _context.next = 17;\n              return fetch(url, {\n                method: 'POST',\n                headers: _headers,\n                body: JSON.stringify(payload)\n              });\n            case 17:\n              res = _context.sent;\n              _context.next = 20;\n              return res.json()[\"catch\"](function () {\n                return {};\n              });\n            case 20:\n              data = _context.sent;\n              this._isLoading = false;\n              if (!(!res.ok || data.status === 'error')) {\n                _context.next = 25;\n                break;\n              }\n              this._renderError(data.error_type || 'unknown', data.message || \"HTTP \".concat(res.status), data.retry_after);\n              return _context.abrupt(\"return\");\n            case 25:\n              this._variants = Array.isArray(data.variants) && data.variants.length > 0 ? data.variants : data.primary ? [data.primary] : [];\n              if (!(this._variants.length === 0)) {\n                _context.next = 29;\n                break;\n              }\n              this._renderError('engine', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.error_no_variants'));\n              return _context.abrupt(\"return\");\n            case 29:\n              this._activeVariantIndex = 0;\n              this._renderResult();\n              _context.next = 37;\n              break;\n            case 33:\n              _context.prev = 33;\n              _context.t0 = _context[\"catch\"](12);\n              this._isLoading = false;\n              this._renderError('internal', String(_context.t0 && _context.t0.message || _context.t0));\n            case 37:\n            case \"end\":\n              return _context.stop();\n          }\n        }, _callee, this, [[12, 33]]);\n      }));\n      function _runRewrite() {\n        return _runRewrite2.apply(this, arguments);\n      }\n      return _runRewrite;\n    }() /* ── apply / undo ─────────────────────────────────────────────── */)\n  }, {\n    key: \"_applyVariant\",\n    value: function _applyVariant(variantHtml) {\n      if (!variantHtml || !this._savedRange) {\n        this.close();\n        return;\n      }\n      try {\n        var range = this._savedRange;\n        var container = range.commonAncestorContainer;\n        var host = container && container.nodeType === 1 ? container : container && container.parentElement;\n\n        // Snapshot for history.\n        var elementHost = host && host.closest ? host.closest('[builder-element]') : null;\n        var elementUid = elementHost ? elementHost.getAttribute('builder-element-uid') : null;\n        var elementType = elementHost ? elementHost.getAttribute('builder-element-kind') || elementHost.tagName.toLowerCase() : null;\n        var originalSnippet = this._snapshotText || '';\n\n        // Replace selection contents with new HTML.\n        range.deleteContents();\n        var tmp = document.createElement('span');\n        tmp.innerHTML = variantHtml;\n        var frag = document.createDocumentFragment();\n        while (tmp.firstChild) frag.appendChild(tmp.firstChild);\n        range.insertNode(frag);\n\n        // Normalize inline markup (T9).\n        if (host && _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"] && typeof _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].normalize === 'function') {\n          try {\n            _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].normalize(host);\n          } catch (_) {}\n        }\n\n        // Keep the element's internal state in sync — inline toolbar uses\n        // a char-offset SHIM pattern; we update the owning element's text\n        // cache so next render/parse reflects what the user sees.\n        if (elementUid && this._builder && this._builder.findElement) {\n          try {\n            var el = this._builder.findElement(elementUid);\n            if (el && typeof el.setText === 'function' && host) {\n              el.setText(host.innerHTML);\n            }\n          } catch (_) {/* tolerate */}\n        }\n\n        // Commit a rich history entry so Undo/Redo restores pre-rewrite\n        // state and the HistoryWidget shows a meaningful label + icon.\n        // Uses new change type 'ai:inline_rewrite' — mapped to\n        // `auto_fix_normal` icon in HistoryWidget.ICON_FOR_CHANGE.\n        try {\n          if (this._builder && this._builder.history && typeof this._builder.history.commit === 'function') {\n            var actionKey = this._action || 'rewrite';\n            var actionLabel = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('history.ai_action_' + actionKey) || actionKey.replace(/_/g, ' ');\n            this._builder.history.commit('history.ai_inline_rewrite', {\n              source: 'ai',\n              change: 'ai:inline_rewrite',\n              elementUid: elementUid,\n              elementType: elementType,\n              action: actionKey,\n              prompt: actionLabel,\n              tone: this._tone || null,\n              length: this._length || null,\n              oldValue: this._truncate(originalSnippet, 80),\n              newValue: this._truncate(this._stripTags(variantHtml), 80)\n            });\n          }\n        } catch (err) {\n          // eslint-disable-next-line no-console\n          console.warn('[bjs:ai-rewrite] history commit failed:', err);\n        }\n        this._showAppliedToast();\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:ai-rewrite] apply failed:', err);\n      }\n      this.close();\n    }\n  }, {\n    key: \"_truncate\",\n    value: function _truncate(s, n) {\n      var str = String(s == null ? '' : s);\n      return str.length > n ? str.slice(0, n - 1) + '…' : str;\n    }\n  }, {\n    key: \"_stripTags\",\n    value: function _stripTags(s) {\n      return String(s == null ? '' : s).replace(/<[^>]*>/g, '');\n    }\n  }, {\n    key: \"_showAppliedToast\",\n    value: function _showAppliedToast() {\n      try {\n        var toast = document.createElement('div');\n        toast.className = 'bjs-ovl-ai-toast';\n        toast.innerHTML = \"\\n                <span class=\\\"material-symbols-rounded\\\" aria-hidden=\\\"true\\\">check</span>\\n                <span>\".concat(this._escape(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('ai_rewrite.applied_toast')), \"</span>\\n            \");\n        document.body.appendChild(toast);\n        setTimeout(function () {\n          toast.classList.add('is-fading');\n          setTimeout(function () {\n            try {\n              toast.remove();\n            } catch (_) {}\n          }, 300);\n        }, 3500);\n      } catch (_) {}\n    }\n\n    /* ── context collection ───────────────────────────────────────── */\n  }, {\n    key: \"_collectElementContext\",\n    value: function _collectElementContext() {\n      try {\n        var node = this._savedRange ? this._savedRange.commonAncestorContainer : null;\n        var host = node && node.nodeType === 1 ? node : node && node.parentElement;\n        var inlineHost = host && host.closest ? host.closest('[data-bjs-inline-text]') : null;\n        var elementHost = host && host.closest ? host.closest('[builder-element]') : null;\n        return {\n          type: elementHost ? elementHost.getAttribute('builder-element-kind') || elementHost.tagName.toLowerCase() : null,\n          role: inlineHost ? inlineHost.getAttribute('data-bjs-inline-text') || null : null\n        };\n      } catch (_) {\n        return null;\n      }\n    }\n  }, {\n    key: \"_collectBlockContext\",\n    value: function _collectBlockContext() {\n      var _this7 = this;\n      try {\n        var node = this._savedRange ? this._savedRange.commonAncestorContainer : null;\n        var host = node && node.nodeType === 1 ? node : node && node.parentElement;\n        var block = host && host.closest ? host.closest('[builder-element=\"BlockElement\"]') : null;\n        if (!block) return null;\n        var siblings = [];\n        block.querySelectorAll('[data-bjs-inline-text]').forEach(function (el) {\n          var txt = (el.textContent || '').trim();\n          if (txt && txt !== _this7._snapshotText) siblings.push(txt.slice(0, 80));\n        });\n        return {\n          purpose: block.getAttribute('data-block-purpose') || null,\n          siblings: siblings.slice(0, 4)\n        };\n      } catch (_) {\n        return null;\n      }\n    }\n\n    /* ── dismissal ────────────────────────────────────────────────── */\n  }, {\n    key: \"_registerDismissListeners\",\n    value: function _registerDismissListeners() {\n      var _this8 = this;\n      this._onDocKey = function (e) {\n        if (e.key === 'Escape') {\n          e.preventDefault();\n          _this8.close();\n        }\n      };\n      this._onDocMouseDown = function (e) {\n        if (!_this8.domNode) return;\n        var inside = _this8.domNode.contains(e.target) || _this8._anchorBtn && _this8._anchorBtn.contains(e.target);\n        if (!inside) _this8.close();\n      };\n      document.addEventListener('keydown', this._onDocKey, true);\n      document.addEventListener('mousedown', this._onDocMouseDown, true);\n    }\n  }, {\n    key: \"_unregisterDismissListeners\",\n    value: function _unregisterDismissListeners() {\n      if (this._onDocKey) document.removeEventListener('keydown', this._onDocKey, true);\n      if (this._onDocMouseDown) document.removeEventListener('mousedown', this._onDocMouseDown, true);\n      this._onDocKey = null;\n      this._onDocMouseDown = null;\n    }\n\n    /* ── util ─────────────────────────────────────────────────────── */\n  }, {\n    key: \"_escape\",\n    value: function _escape(s) {\n      return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AIRewritePopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/AIRewritePopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/AnchoredPopoverOverlay.js":
/*!*********************************************************!*\
  !*** ./src/includes/overlays/AnchoredPopoverOverlay.js ***!
  \*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * AnchoredPopoverOverlay — 2026-04-19 (Image overlay refactor Phase E).\n *\n * Compact popover for `'edit'`-mode overlays that should NOT take over\n * the full viewport with a modal mask. Anchors next to a target rect\n * (typically the action-bar button that opened it) so the canvas stays\n * visible + the user keeps spatial context. Sibling primitive of\n * `InlineEditorOverlay` (modal form); pick whichever fits the UX:\n *\n *   InlineEditorOverlay      — full-viewport mask + centered card.\n *                              Best for deep editing (full crop UI with\n *                              preview, focus dot, sliders).\n *   AnchoredPopoverOverlay   — small popover next to anchor; canvas\n *                              stays interactive (click outside to close).\n *                              Best for quick edits without losing canvas.\n *\n * Both primitives can host the SAME body content (embedded controls)\n * because the surface chrome (mask vs popover, header vs no-header) is\n * the only thing that differs. Subclasses build the body once and pass\n * it to the surface variant of their choice.\n *\n * Lifecycle:\n *   - render() — subclass builds DOM (the popover panel + body).\n *   - position() — anchors next to opts.anchorTo (function returning\n *     DOMRect in viewport coords) with smart flip logic.\n *   - On open: registers Esc + outside-click → exitEditMode.\n *   - beforeDestroy() — removes listeners + lets subclass dispose\n *     embedded controls.\n *\n * Positioning algorithm:\n *   1. Compute anchor rect.\n *   2. Try preferred side (default 'right'); if not enough space, try\n *      'left'; if neither fits horizontally, try 'bottom'; final\n *      fallback 'top'.\n *   3. Vertical alignment: align with anchor's vertical center, then\n *      clamp into viewport with 12px margin.\n *\n * Constructor opts:\n *   anchorTo       — function() → DOMRect | DOMRect | HTMLElement\n *                    (required; if missing, falls back to element.domNode rect)\n *   side           — 'right' | 'left' | 'bottom' | 'top' (preferred; default 'right')\n *   gap            — pixels between anchor and popover (default 8)\n *   width          — popover width in px (default 320)\n *   maxHeight      — popover max-height in px (default 480)\n */\n\nvar VIEWPORT_MARGIN = 12;\nvar DEFAULT_GAP = 8;\nvar DEFAULT_WIDTH = 320;\nvar DEFAULT_MAX_HEIGHT = 480;\nvar AnchoredPopoverOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function AnchoredPopoverOverlay() {\n    _classCallCheck(this, AnchoredPopoverOverlay);\n    return _callSuper(this, AnchoredPopoverOverlay, arguments);\n  }\n  _inherits(AnchoredPopoverOverlay, _BaseOverlay);\n  return _createClass(AnchoredPopoverOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'edit';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      // Subclass MUST build this.domNode + assign body content. This\n      // base render() just sets up the shared chrome class + listeners.\n      if (!this.domNode) {\n        this.domNode = document.createElement('div');\n      }\n      this.domNode.classList.add('bjs-ovl-anchored-popover');\n      this.domNode.setAttribute('data-interactive', '');\n      this.domNode.setAttribute('role', 'dialog');\n\n      // Esc to close.\n      this._onKey = function (e) {\n        if (e.key === 'Escape') {\n          e.stopPropagation();\n          if (_this.element && typeof _this.element.exitEditMode === 'function') {\n            _this.element.exitEditMode();\n          }\n        }\n      };\n      document.addEventListener('keydown', this._onKey, true);\n\n      // Outside-click to close. Use capture phase + check via\n      // composedPath/closest to handle clicks across iframe boundary.\n      this._onOutsideClick = function (e) {\n        if (!_this.domNode) return;\n        var t = e.target;\n        if (_this.domNode.contains(t)) return;\n        // Allow clicks on the action bar button that opened the\n        // popover — without this guard the button click that opens\n        // the popover instantly closes it again.\n        if (t && typeof t.closest === 'function' && t.closest('.bjs-ovl-pill')) return;\n        if (_this.element && typeof _this.element.exitEditMode === 'function') {\n          _this.element.exitEditMode();\n        }\n      };\n      // Defer one tick so the click that OPENED the popover isn't\n      // immediately picked up by this handler (would close instantly).\n      setTimeout(function () {\n        document.addEventListener('mousedown', _this._onOutsideClick, true);\n      }, 0);\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      if (this._onKey) document.removeEventListener('keydown', this._onKey, true);\n      if (this._onOutsideClick) document.removeEventListener('mousedown', this._onOutsideClick, true);\n      this._onKey = null;\n      this._onOutsideClick = null;\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      if (!this.domNode) return;\n\n      // Set explicit width up-front so measurement is stable.\n      var width = this.opts && this.opts.width || DEFAULT_WIDTH;\n      var maxHeight = this.opts && this.opts.maxHeight || DEFAULT_MAX_HEIGHT;\n      Object.assign(this.domNode.style, {\n        position: 'fixed',\n        width: width + 'px',\n        maxHeight: maxHeight + 'px'\n      });\n\n      // Force a layout to read the actual rendered height (bound by content + maxHeight).\n      var popoverHeight = this.domNode.offsetHeight || 0;\n      var anchorRect = this._resolveAnchorRect();\n      if (!anchorRect) {\n        // Fallback — center on viewport.\n        Object.assign(this.domNode.style, {\n          top: Math.max(VIEWPORT_MARGIN, (window.innerHeight - popoverHeight) / 2) + 'px',\n          left: Math.max(VIEWPORT_MARGIN, (window.innerWidth - width) / 2) + 'px'\n        });\n        return;\n      }\n      var gap = this.opts && typeof this.opts.gap === 'number' ? this.opts.gap : DEFAULT_GAP;\n      var preferredSide = this.opts && this.opts.side || 'right';\n\n      // Try sides in preference order.\n      var ordered = this._sideOrder(preferredSide);\n      var chosen = null;\n      var _iterator = _createForOfIteratorHelper(ordered),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var side = _step.value;\n          var placed = this._tryPlace(side, anchorRect, width, popoverHeight, gap);\n          if (placed) {\n            chosen = placed;\n            break;\n          }\n        }\n        // Fallback — best-effort right side, clamped to viewport.\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n      if (!chosen) chosen = this._tryPlace('right', anchorRect, width, popoverHeight, gap, true);\n      Object.assign(this.domNode.style, {\n        top: chosen.top + 'px',\n        left: chosen.left + 'px'\n      });\n      this.domNode.classList.toggle('bjs-ovl-anchored-popover--right', chosen.side === 'right');\n      this.domNode.classList.toggle('bjs-ovl-anchored-popover--left', chosen.side === 'left');\n      this.domNode.classList.toggle('bjs-ovl-anchored-popover--top', chosen.side === 'top');\n      this.domNode.classList.toggle('bjs-ovl-anchored-popover--bottom', chosen.side === 'bottom');\n    }\n  }, {\n    key: \"_sideOrder\",\n    value: function _sideOrder(preferred) {\n      var all = ['right', 'left', 'bottom', 'top'];\n      return [preferred].concat(_toConsumableArray(all.filter(function (s) {\n        return s !== preferred;\n      })));\n    }\n  }, {\n    key: \"_resolveAnchorRect\",\n    value: function _resolveAnchorRect() {\n      var anchor = this.opts && this.opts.anchorTo;\n      if (!anchor) {\n        // Default — element's own DOM rect (in iframe coordinates ⇒\n        // translate to viewport coords via the iframe's frameElement).\n        var dom = this.element && this.element.domNode;\n        if (!dom) return null;\n        var r = dom.getBoundingClientRect();\n        var ifr = dom.ownerDocument.defaultView.frameElement;\n        var ir = ifr ? ifr.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        return {\n          top: ir.top + r.top,\n          left: ir.left + r.left,\n          right: ir.left + r.right,\n          bottom: ir.top + r.bottom,\n          width: r.width,\n          height: r.height\n        };\n      }\n      if (typeof anchor === 'function') return anchor();\n      if (anchor instanceof Element) return anchor.getBoundingClientRect();\n      return anchor; // assume DOMRect-like\n    }\n  }, {\n    key: \"_tryPlace\",\n    value: function _tryPlace(side, anchorRect, width, height, gap, allowOverflow) {\n      var vw = window.innerWidth;\n      var vh = window.innerHeight;\n      var top, left;\n      if (side === 'right') {\n        left = anchorRect.right + gap;\n        if (!allowOverflow && left + width > vw - VIEWPORT_MARGIN) return null;\n        top = anchorRect.top + anchorRect.height / 2 - height / 2;\n      } else if (side === 'left') {\n        left = anchorRect.left - gap - width;\n        if (!allowOverflow && left < VIEWPORT_MARGIN) return null;\n        top = anchorRect.top + anchorRect.height / 2 - height / 2;\n      } else if (side === 'bottom') {\n        top = anchorRect.bottom + gap;\n        if (!allowOverflow && top + height > vh - VIEWPORT_MARGIN) return null;\n        left = anchorRect.left + anchorRect.width / 2 - width / 2;\n      } else {\n        // top\n        top = anchorRect.top - gap - height;\n        if (!allowOverflow && top < VIEWPORT_MARGIN) return null;\n        left = anchorRect.left + anchorRect.width / 2 - width / 2;\n      }\n      // Clamp into viewport.\n      top = Math.max(VIEWPORT_MARGIN, Math.min(top, vh - height - VIEWPORT_MARGIN));\n      left = Math.max(VIEWPORT_MARGIN, Math.min(left, vw - width - VIEWPORT_MARGIN));\n      return {\n        side: side,\n        top: top,\n        left: left\n      };\n    }\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AnchoredPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/AnchoredPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/BlockDragAnchorOverlay.js":
/*!*********************************************************!*\
  !*** ./src/includes/overlays/BlockDragAnchorOverlay.js ***!
  \*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./NativeDragHandleOverlay.js */ \"./src/includes/overlays/NativeDragHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * BlockDragAnchorOverlay — Phase 1.6\n *\n * Overlay replacement for the hand-rolled `BlockElement.addDragAnchor()`\n * anchor (legacy at BlockElement.js:339-401). Gated on the builder flag\n * `builder.useOverlayDragAnchor` — when OFF, `BlockElement.getOverlays()`\n * returns [] and the legacy anchor pipeline stays in charge.\n *\n * Trigger: 'hover' — mounts on UIManager.mouseover → block.mountOverlays,\n * unmounts on UIManager.mouseout flush timeout (preserved 50 ms debounce,\n * SA invariant I1).\n *\n * Extends `NativeDragHandleOverlay` (Phase 1.2) — NOT `DraggableHandleOverlay`\n * (SA invariant I2: pointer events and HTML5 DnD are mutually exclusive).\n * Inherits the Safari drag-ghost 3-layer workaround (I3):\n *   1. `dataTransfer.setData('text/plain', '')`\n *   2. `dataTransfer.effectAllowed = 'all'`\n *   3. Safari-only off-screen clone at `left: -10000px` for setDragImage\n *\n * `onDragStart` hands off to `uiManager.dragStart(block)` (same function the\n * legacy anchor's dragstart handler invoked at UIManager.js:729) — does NOT\n * fork the DnD pipeline. Post-dragstart the overlay destroys itself on a\n * 100 ms timer to mirror legacy `UIManager.dragStart → hideDragAnchor` at\n * line 757 (anchor visually disappears during drag; reappears on next hover).\n *\n * Visual parity with legacy `.drag-anchor` via `.bjs-ovl-block-drag` CSS —\n * same 20×20 grab affordance, `front_hand` material icon inside a rounded\n * pill. Legacy DOM markup preserved so host-app CSS targeting `.drag-label`\n * keeps working even in overlay mode.\n *\n * See docs/core/OVERLAY.md §7.4 + docs/archived/OVERLAY_PLAN.md §3.7.\n */\n\nvar HIDE_AFTER_DRAGSTART_MS = 100;\nvar BlockDragAnchorOverlay = /*#__PURE__*/function (_NativeDragHandleOver) {\n  function BlockDragAnchorOverlay() {\n    _classCallCheck(this, BlockDragAnchorOverlay);\n    return _callSuper(this, BlockDragAnchorOverlay, arguments);\n  }\n  _inherits(BlockDragAnchorOverlay, _NativeDragHandleOver);\n  return _createClass(BlockDragAnchorOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'hover';\n    }\n  }, {\n    key: \"_buildHandle\",\n    value: function _buildHandle() {\n      // Match legacy markup at BlockElement.js:347-349 so any CSS/tests\n      // targeting `.drag-label` keep working. The inner <span> is the\n      // draggable=\"true\" grabber (SA I2 — the element carrying the\n      // draggable attr gets the dragstart event).\n      this.domNode.classList.add('bjs-ovl-block-drag');\n      this.domNode.innerHTML = \"\\n            <div class=\\\"drag-label\\\"><span class=\\\"material-symbols-rounded fs-4 border bg-light p-1 rounded-circle\\\" draggable=\\\"true\\\">front_hand</span></div>\\n        \";\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this = this;\n      // Match legacy positioning at BlockElement.js:356-384 — right-middle\n      // of the block, poking out by 2 px (domWidth - 18 with anchor width 20).\n      // matchingDomNode wires observers so this re-runs on every reflow.\n      this.element.matchingDomNode(this.domNode, 5, function () {\n        if (!_this.domNode) return;\n        if (!_this.element.domNode) return;\n        var ownerView = _this.element.domNode.ownerDocument && _this.element.domNode.ownerDocument.defaultView;\n        var iframe = ownerView && ownerView.frameElement;\n        if (!iframe) return;\n        var domRect = _this.element.domNode.getBoundingClientRect();\n        var iframeRect = iframe.getBoundingClientRect();\n        var absoluteTop = iframeRect.top + domRect.top;\n        var absoluteLeft = iframeRect.left + domRect.left;\n        Object.assign(_this.domNode.style, {\n          position: 'fixed',\n          top: \"\".concat(absoluteTop + domRect.height / 2 - 10, \"px\"),\n          left: \"\".concat(absoluteLeft + domRect.width - 18, \"px\"),\n          width: '20px',\n          height: '20px'\n        });\n      });\n    }\n  }, {\n    key: \"onDragStart\",\n    value: function onDragStart(/* e */\n    ) {\n      var _this2 = this;\n      // Hand off to the existing UIManager.dragStart pipeline — does NOT\n      // fork DnD. The `NativeDragHandleOverlay` parent has already applied\n      // setData + effectAllowed + Safari 3-layer clone workaround before\n      // this hook fires (see src/includes/overlays/NativeDragHandleOverlay.js).\n      var host = this.host;\n      if (host && host.uiManager && typeof host.uiManager.dragStart === 'function') {\n        try {\n          host.uiManager.dragStart(this.element);\n        } catch (err) {\n          /* eslint-disable-next-line no-console */\n          console.error('[overlay] BlockDragAnchorOverlay onDragStart → uiManager.dragStart threw:', err);\n        }\n      }\n\n      // Hide the anchor during drag (matches legacy\n      // UIManager.dragStart → hideDragAnchor at UIManager.js:757 with the\n      // identical 100 ms delay). Destroying the overlay here is safe —\n      // the Safari drag ghost has already been captured by setDragImage\n      // in the parent's dragstart handler (microtask-0 clone removal).\n      // The overlay re-mounts on the next UIManager.mouseover → hover\n      // trigger cycle after dragend.\n      setTimeout(function () {\n        try {\n          _this2.destroy();\n        } catch (_) {/* already destroyed */}\n      }, HIDE_AFTER_DRAGSTART_MS);\n    }\n  }]);\n}(_NativeDragHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (BlockDragAnchorOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/BlockDragAnchorOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ButtonActionsOverlay.js":
/*!*******************************************************!*\
  !*** ./src/includes/overlays/ButtonActionsOverlay.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FloatingActionBarOverlay.js */ \"./src/includes/overlays/FloatingActionBarOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ButtonActionsOverlay — 3-pill floating toolbar (2026-04-19 refactor).\n *\n *   Link:      opens LinkPopoverOverlay anchored next to the Link pill\n *              (mode 'link-popover'). Compact in-place URL editor.\n *   Settings:  opens ButtonSettingsPopoverOverlay anchored next to the\n *              gear pill (mode 'settings-popover'). Full modifier stack —\n *              size / radius / shadow / hover / icon / position / width —\n *              in a single popover so the user can tune without leaving\n *              the canvas.\n *   Style:     opens ButtonPresetPickerOverlay anchored next to the\n *              palette pill (mode 'style-picker'). 9-tab preset picker\n *              with ~210 styles. Click-to-apply (no modal mask).\n *\n * The older \"Edit text\" pill was dropped — the <a>'s `[inline-edit=\"text\"]`\n * span is contenteditable on focus already, so a dedicated pill was pure\n * redundancy. Click the text → caret appears → type.\n *\n * Icons render via the shared inline-SVG registry so pills work even when\n * the theme iframe doesn't load Material Symbols.\n *\n * `e.stopPropagation()` on each click prevents the element's select/deselect\n * flow from firing from a button click (Lesson 23 Rule 5 + 11 + 12).\n *\n * Visual parity with ImageActionsOverlay — same FloatingActionBarOverlay\n * primitive, same `.bjs-ovl-action-bar` + `.bjs-ovl-pill` markup.\n *\n * See docs/core/OVERLAY.md §7.5 + §7.7 + docs/BUTTON_UPGRADE_PLAN.md.\n */\n\n\nvar ButtonActionsOverlay = /*#__PURE__*/function (_FloatingActionBarOve) {\n  function ButtonActionsOverlay(element) {\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, ButtonActionsOverlay);\n    return _callSuper(this, ButtonActionsOverlay, [element, Object.assign({\n      anchor: 'top-right'\n    }, opts)]);\n  }\n  _inherits(ButtonActionsOverlay, _FloatingActionBarOve);\n  return _createClass(ButtonActionsOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"getButtons\",\n    value: function getButtons() {\n      var _this = this;\n      return [{\n        icon: 'link',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.link', 'Link'),\n        onClick: function onClick(e) {\n          return _this._enter(e, 'link-popover');\n        }\n      }, {\n        icon: 'settings',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.settings', 'Settings'),\n        onClick: function onClick(e) {\n          return _this._enter(e, 'settings-popover');\n        }\n      }, {\n        icon: 'palette',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.style', 'Style'),\n        onClick: function onClick(e) {\n          return _this._enter(e, 'style-picker');\n        }\n      }];\n    }\n\n    /**\n     * Generic pill-click handler. Each pill stashes its own click rect on\n     * `element._lastActionAnchorRect` so the downstream AnchoredPopover\n     * anchors to whichever pill was clicked, then flips the element into\n     * the matching edit mode (getOverlays() filters on `getEditMode()` so\n     * the right popover mounts).\n     */\n  }, {\n    key: \"_enter\",\n    value: function _enter(e, mode) {\n      if (!this.element) return;\n      if (typeof this.element.enterEditMode !== 'function') return;\n      if (e && e.currentTarget && typeof e.currentTarget.getBoundingClientRect === 'function') {\n        this.element._lastActionAnchorRect = e.currentTarget.getBoundingClientRect();\n      } else {\n        this.element._lastActionAnchorRect = null;\n      }\n      this.element.enterEditMode(mode);\n    }\n  }]);\n}(_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonActionsOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ButtonActionsOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ButtonPresetPickerOverlay.js":
/*!************************************************************!*\
  !*** ./src/includes/overlays/ButtonPresetPickerOverlay.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ButtonPresetPickerOverlay — anchored popover for picking a button\n * style preset. Mounts in 'style-picker' edit mode (set by either the\n * sidebar StylePickerControl Change button OR the action-bar's 3rd\n * palette pill — both stash `element._lastActionAnchorRect`).\n *\n * Layout\n * ──────\n *   ┌──────────────────────────────────────────┐\n *   │ Pick a button style                  [×] │\n *   ├──────────────────────────────────────────┤\n *   │ Solid · Outline · Tonal · Ghost · …     │  ← tabs (scrollable)\n *   ├──────────────────────────────────────────┤\n *   │ ┌──────┐ ┌──────┐                        │\n *   │ │ ▣ A  │ │ ▣ B  │  ← 2-col grid          │\n *   │ └──────┘ └──────┘                        │\n *   │ ┌──────┐ ┌──────┐                        │\n *   │ │ ▣ C  │ │ ▣ D  │                        │\n *   │ └──────┘ └──────┘                        │\n *   ├──────────────────────────────────────────┤\n *   │ Esc to cancel · Click outside to close   │\n *   └──────────────────────────────────────────┘\n *\n * Click a preset card → element.applyPreset(presetId) → popover stays\n * open so the user can compare styles by clicking through the grid.\n * Esc / outside-click / × button closes.\n *\n * Snapshot + Cancel\n * ─────────────────\n *   On mount we snapshot { preset_id, size_key } so the user can\n *   experiment then bail out via Esc; close-via-Esc reverts. Close-via-\n *   outside-click commits (treats the click as a deliberate exit).\n *\n * Same primitive as LinkPopoverOverlay / ImageEffectPopoverOverlay etc.\n * — extends AnchoredPopoverOverlay (smart-flip placement, viewport\n * margin clamp, shared `.bjs-ovl-anchored-popover` chrome).\n */\n\n\n\n\n\nvar POPOVER_WIDTH = 420;\nvar POPOVER_MAX_HEIGHT = 520;\nvar ButtonPresetPickerOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n  function ButtonPresetPickerOverlay(element) {\n    var _this;\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, ButtonPresetPickerOverlay);\n    var anchorTo = function anchorTo() {\n      return element._lastActionAnchorRect || null;\n    };\n    _this = _callSuper(this, ButtonPresetPickerOverlay, [element, Object.assign({\n      anchorTo: anchorTo,\n      side: 'right',\n      width: POPOVER_WIDTH,\n      maxHeight: POPOVER_MAX_HEIGHT\n    }, opts)]);\n    _this._activeCategory = null; // resolved on render()\n    _this._snapshot = null;\n    _this._committedOnExit = false;\n    return _this;\n  }\n  _inherits(ButtonPresetPickerOverlay, _AnchoredPopoverOverl);\n  return _createClass(ButtonPresetPickerOverlay, [{\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'style-picker';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ButtonPresetPickerOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-button-picker');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-button-picker-title');\n\n      // Snapshot for Cancel\n      this._snapshot = {\n        preset_id: this.element.preset_id || null,\n        size_key: this.element.size_key || 'md',\n        shadow_key: this.element.shadow_key || 'none',\n        hover_effect: this.element.hover_effect || 'none',\n        icon: this.element.icon || null,\n        icon_position: this.element.icon_position || 'none',\n        formats: this.element.formatter ? Object.assign({}, this.element.formatter.formats) : null\n      };\n      this._committedOnExit = false;\n\n      // Default tab: category of current preset, else 'solid'\n      var cur = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.findPreset)(this.element.preset_id);\n      this._activeCategory = cur && cur.category || 'solid';\n      this.domNode.appendChild(this._renderHeader());\n      this.domNode.appendChild(this._renderTabs());\n      this.domNode.appendChild(this._renderBody());\n      this.domNode.appendChild(this._renderFooter());\n    }\n\n    /* ─── Subclass overrides for AnchoredPopoverOverlay lifecycle ─── */\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {\n      // Focus the active tab so keyboard users land on something useful\n      if (!this.domNode) return;\n      var activeTab = this.domNode.querySelector('.bjs-ovl-button-picker-tab.is-active');\n      if (activeTab) {\n        try {\n          activeTab.focus();\n        } catch (_) {/* no-op */}\n      }\n    }\n\n    /* ─── Header / tabs / body / footer ─── */\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var _this2 = this;\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-button-picker-header';\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-button-picker-title';\n      title.id = 'bjs-ovl-button-picker-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.title', 'Pick a button style');\n      var close = document.createElement('button');\n      close.type = 'button';\n      close.className = 'bjs-ovl-button-picker-close';\n      close.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.close', 'Close'));\n      close.innerHTML = '<span class=\"bjs-ovl-button-picker-close-icon\" aria-hidden=\"true\">' + _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('close', {\n        size: 18,\n        color: 'currentColor'\n      }) + '</span>';\n      close.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this2._commitAndClose();\n      });\n      header.appendChild(title);\n      header.appendChild(close);\n      return header;\n    }\n  }, {\n    key: \"_renderTabs\",\n    value: function _renderTabs() {\n      var _this3 = this;\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-button-picker-tabs';\n      wrap.setAttribute('role', 'tablist');\n      var sorted = _buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.CATEGORIES.slice().sort(function (a, b) {\n        return a.order - b.order;\n      });\n      sorted.forEach(function (cat) {\n        var isActive = cat.id === _this3._activeCategory;\n        var tab = document.createElement('button');\n        tab.type = 'button';\n        tab.className = 'bjs-ovl-button-picker-tab' + (isActive ? ' is-active' : '');\n        tab.setAttribute('role', 'tab');\n        tab.setAttribute('aria-selected', String(isActive));\n        tab.dataset.cat = cat.id;\n        tab.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.cat_' + cat.id, cat.label);\n        tab.addEventListener('click', function (e) {\n          e.preventDefault();\n          _this3._switchCategory(cat.id);\n        });\n        wrap.appendChild(tab);\n      });\n      return wrap;\n    }\n  }, {\n    key: \"_renderBody\",\n    value: function _renderBody() {\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-button-picker-body';\n      body.appendChild(this._renderGrid(this._activeCategory));\n      return body;\n    }\n  }, {\n    key: \"_renderGrid\",\n    value: function _renderGrid(catId) {\n      var _this4 = this;\n      var grid = document.createElement('div');\n      grid.className = 'bjs-ovl-button-picker-grid';\n      grid.dataset.cat = catId;\n      var presets = (0,_buttonPresets_js__WEBPACK_IMPORTED_MODULE_3__.presetsByCategory)(catId);\n      var currentId = this.element.preset_id;\n      presets.forEach(function (p) {\n        var cell = document.createElement('button');\n        cell.type = 'button';\n        cell.className = 'bjs-ovl-button-picker-cell' + (p.id === currentId ? ' is-current' : '');\n        cell.dataset.presetId = p.id;\n        cell.setAttribute('aria-label', p.label);\n\n        // Inline-style mini button mirrors the preset exactly\n        cell.appendChild(_this4._renderPresetThumb(p));\n\n        // Label below thumb\n        var label = document.createElement('span');\n        label.className = 'bjs-ovl-button-picker-cell-label';\n        label.textContent = p.label;\n        cell.appendChild(label);\n\n        // Page-only / VML warn badge\n        if (p.flags) {\n          if (p.flags.pageOnly) {\n            var b = document.createElement('span');\n            b.className = 'bjs-ovl-button-picker-cell-badge bjs-ovl-button-picker-cell-badge--page';\n            b.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.page_only_short', 'Page');\n            cell.appendChild(b);\n          } else if (p.flags.requiresVML) {\n            var _b = document.createElement('span');\n            _b.className = 'bjs-ovl-button-picker-cell-badge bjs-ovl-button-picker-cell-badge--warn';\n            _b.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.vml_short', 'VML');\n            cell.appendChild(_b);\n          }\n        }\n\n        // Tick on current\n        if (p.id === currentId) {\n          var tick = document.createElement('span');\n          tick.className = 'bjs-ovl-button-picker-cell-tick';\n          tick.setAttribute('aria-hidden', 'true');\n          tick.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('check_circle', {\n            size: 18,\n            color: 'currentColor'\n          });\n          cell.appendChild(tick);\n        }\n        cell.addEventListener('click', function (e) {\n          e.preventDefault();\n          e.stopPropagation();\n          _this4._applyPreset(p.id);\n        });\n        grid.appendChild(cell);\n      });\n      if (presets.length === 0) {\n        var empty = document.createElement('div');\n        empty.className = 'bjs-ovl-button-picker-empty';\n        empty.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.empty', 'No presets in this category yet.');\n        grid.appendChild(empty);\n      }\n      return grid;\n    }\n  }, {\n    key: \"_renderPresetThumb\",\n    value: function _renderPresetThumb(preset) {\n      var f = preset.formats || {};\n      var text = this.element && this.element.text || _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.sample_text', 'Action');\n      var node = document.createElement('a');\n      node.className = 'bjs-ovl-button-picker-spec';\n      var styleParts = [f.background_image ? \"background:\".concat(f.background_image) : \"background:\".concat(f.background_color || '#2563eb'), f.background_color ? \"background-color:\".concat(f.background_color) : '', \"color:\".concat(f.text_color || '#fff'), f.border_top_color ? \"border:\".concat(f.border_top_width || '1px', \" \").concat(f.border_top_style || 'solid', \" \").concat(f.border_top_color) : 'border:0', \"border-radius:\".concat(f.border_radius || '6px'), f.box_shadow ? \"box-shadow:\".concat(f.box_shadow) : '', f.font_family ? \"font-family:\".concat(f.font_family) : '', f.font_weight ? \"font-weight:\".concat(f.font_weight) : 'font-weight:500', 'font-size:13px', 'padding:6px 14px', 'text-decoration:none', 'display:inline-flex', 'align-items:center', 'line-height:1.4'].filter(Boolean).join(';');\n      node.setAttribute('style', styleParts);\n\n      // 2026-04-19 — icon spacing. Use explicit side margins instead of a\n      // flex `gap` so left-icon-only / right-icon-only / icon-only\n      // variants each get the right amount of breathing room. `gap`\n      // applies to every child pair and is too tight at 6px once the\n      // icon sits next to a word (especially when the first char is\n      // narrow like `&` or `|`).\n      var iconSpan = function iconSpan(px, cls) {\n        var s = document.createElement('span');\n        s.className = 'bjs-ovl-button-picker-cell-icon ' + cls;\n        s.setAttribute('aria-hidden', 'true');\n        s.style.display = 'inline-flex';\n        s.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render(preset.icon, {\n          size: px,\n          color: 'currentColor'\n        });\n        if (cls === 'is-left') s.style.marginRight = '8px';\n        if (cls === 'is-right') s.style.marginLeft = '8px';\n        return s;\n      };\n      if (preset.icon && preset.iconPosition === 'left') {\n        node.appendChild(iconSpan(15, 'is-left'));\n      }\n      if (preset.iconPosition !== 'only') {\n        var t = document.createElement('span');\n        // innerHTML (NOT textContent) so HTML entities like &nbsp; and\n        // user-authored inline tags match the rendered <a> in the\n        // canvas (where EJS <%- text %> is unescaped). Consistent\n        // behavior prevents \"looks different in picker vs canvas\"\n        // surprises — esp. when users insert a leading &nbsp; for\n        // optical centering.\n        t.innerHTML = text;\n        node.appendChild(t);\n      }\n      if (preset.icon && preset.iconPosition === 'right') {\n        node.appendChild(iconSpan(15, 'is-right'));\n      }\n      if (preset.icon && preset.iconPosition === 'only') {\n        node.appendChild(iconSpan(17, 'is-only'));\n      }\n      return node;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this5 = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-button-picker-footer';\n      var hint = document.createElement('span');\n      hint.className = 'bjs-ovl-button-picker-footer-hint';\n      hint.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.footer_hint', 'Esc to cancel · Click outside to apply');\n      footer.appendChild(hint);\n      var reset = document.createElement('button');\n      reset.type = 'button';\n      reset.className = 'bjs-ovl-button-picker-reset';\n      reset.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.picker.reset', 'Reset');\n      reset.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this5._cancel();\n      });\n      footer.appendChild(reset);\n      return footer;\n    }\n\n    /* ─── Actions ─── */\n  }, {\n    key: \"_switchCategory\",\n    value: function _switchCategory(catId) {\n      if (catId === this._activeCategory) return;\n      this._activeCategory = catId;\n      // Refresh tabs active state\n      this.domNode.querySelectorAll('.bjs-ovl-button-picker-tab').forEach(function (t) {\n        var isActive = t.dataset.cat === catId;\n        t.classList.toggle('is-active', isActive);\n        t.setAttribute('aria-selected', String(isActive));\n      });\n      // Replace grid\n      var body = this.domNode.querySelector('.bjs-ovl-button-picker-body');\n      if (body) {\n        body.innerHTML = '';\n        body.appendChild(this._renderGrid(catId));\n      }\n    }\n  }, {\n    key: \"_applyPreset\",\n    value: function _applyPreset(presetId) {\n      if (!this.element || typeof this.element.applyPreset !== 'function') return;\n      this.element.applyPreset(presetId);\n      // Update grid current marker\n      this.domNode.querySelectorAll('.bjs-ovl-button-picker-cell').forEach(function (cell) {\n        var tick = cell.querySelector('.bjs-ovl-button-picker-cell-tick');\n        if (cell.dataset.presetId === presetId) {\n          cell.classList.add('is-current');\n          if (!tick) {\n            var t = document.createElement('span');\n            t.className = 'bjs-ovl-button-picker-cell-tick';\n            t.setAttribute('aria-hidden', 'true');\n            t.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('check_circle', {\n              size: 18,\n              color: 'currentColor'\n            });\n            cell.appendChild(t);\n          }\n        } else {\n          cell.classList.remove('is-current');\n          if (tick) tick.remove();\n        }\n      });\n    }\n  }, {\n    key: \"_commitAndClose\",\n    value: function _commitAndClose() {\n      // Close button = explicit commit (keep current state)\n      this._committedOnExit = true;\n      if (typeof this.element.exitEditMode === 'function') {\n        this.element.exitEditMode();\n      }\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      // Reset button OR Esc (handled by AnchoredPopoverOverlay) — restore snapshot\n      if (!this.element || !this._snapshot) return;\n      var s = this._snapshot;\n      this.element.preset_id = s.preset_id;\n      this.element.size_key = s.size_key;\n      this.element.shadow_key = s.shadow_key;\n      this.element.hover_effect = s.hover_effect;\n      this.element.icon = s.icon;\n      this.element.icon_position = s.icon_position;\n      if (s.formats && this.element.formatter) {\n        this.element.formatter.formats = Object.assign({}, s.formats);\n      }\n      if (typeof this.element.applyFormatStyles === 'function') {\n        this.element.applyFormatStyles();\n      }\n      if (typeof this.element.applyButtonExtras === 'function') {\n        this.element.applyButtonExtras();\n      }\n      if (typeof this.element.notifySyncListeners === 'function') {\n        this.element.notifySyncListeners();\n      }\n      if (typeof this.element.exitEditMode === 'function') {\n        this.element.exitEditMode();\n      }\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      _superPropGet(ButtonPresetPickerOverlay, \"beforeDestroy\", this, 3)([]);\n      this._snapshot = null;\n    }\n  }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonPresetPickerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ButtonPresetPickerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ButtonSettingsPopoverOverlay.js":
/*!***************************************************************!*\
  !*** ./src/includes/overlays/ButtonSettingsPopoverOverlay.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\n/* harmony import */ var _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../SegmentedTextControl.js */ \"./src/includes/SegmentedTextControl.js\");\n/* harmony import */ var _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../IconPickerControl.js */ \"./src/includes/IconPickerControl.js\");\n/* harmony import */ var _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../buttonPresets.js */ \"./src/includes/buttonPresets.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ButtonSettingsPopoverOverlay — anchored popover hosting the full\n * Button modifier stack (size · radius · shadow · hover · icon · position\n * · width) next to the canvas button. Opens via the gear \"Settings\" pill\n * in ButtonActionsOverlay. Sibling of ButtonPresetPickerOverlay — same\n * AnchoredPopover primitive, same `_lastActionAnchorRect` anchor, but\n * shows axis controls instead of the preset grid.\n *\n * Why this exists\n * ───────────────\n *   Sidebar is excellent for deliberate tuning but requires the user to\n *   leave the canvas to reach it, and the canvas button may be far from\n *   the sidebar when the row is wide. This popover keeps the full axis\n *   surface one click away from the selected button. Preset identity\n *   stays with the Style picker — they're orthogonal.\n *\n * Sync contract (SA I13 — dual-view)\n * ──────────────────────────────────\n *   Every embedded SegmentedTextControl and the IconPickerControl\n *   subscribes to element.addSyncListener so mutations on ANY surface\n *   (sidebar, preset picker, this popover) flow into each other's\n *   visual state without tight coupling between the surfaces.\n *\n *     [popover chip click]\n *        → SegmentedTextControl._select → element.apply*()\n *           → formatter mutation + applyButtonExtras\n *           → notifySyncListeners()\n *              → [sidebar chip syncValue] (no callback re-fire)\n *              → [popover chip syncValue]  (already set — no-op)\n *\n *   Guard — syncValue on SegmentedTextControl is silent (no callback\n *   fire) so the propagation can't loop. IconPickerControl manual patch\n *   similarly silent.\n *\n * Snapshot + Cancel\n * ─────────────────\n *   On mount we snapshot { size_key, shadow_key, hover_effect, icon,\n *   icon_position, width_key, radius_key } + the formatter. Esc /\n *   Reset restores snapshot + exits edit mode.\n *\n * Icons render via the shared inline-SVG registry — popover chrome\n * (close X) and optional icon preview use SVG, no Material Symbols\n * dependency inside the popover surface.\n */\n\n\n\n\n\n\n\nvar POPOVER_WIDTH = 380;\nvar POPOVER_MAX_HEIGHT = 560;\nvar ButtonSettingsPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n  function ButtonSettingsPopoverOverlay(element) {\n    var _this;\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, ButtonSettingsPopoverOverlay);\n    var anchorTo = function anchorTo() {\n      return element._lastActionAnchorRect || null;\n    };\n    _this = _callSuper(this, ButtonSettingsPopoverOverlay, [element, Object.assign({\n      anchorTo: anchorTo,\n      side: 'right',\n      width: POPOVER_WIDTH,\n      maxHeight: POPOVER_MAX_HEIGHT\n    }, opts)]);\n    _this._snapshot = null;\n    _this._controls = []; // disposable refs\n    return _this;\n  }\n  _inherits(ButtonSettingsPopoverOverlay, _AnchoredPopoverOverl);\n  return _createClass(ButtonSettingsPopoverOverlay, [{\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'settings-popover';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ButtonSettingsPopoverOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-button-settings');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-button-settings-title');\n      this._snapshot = this._captureSnapshot();\n      this.domNode.appendChild(this._renderHeader());\n      this.domNode.appendChild(this._renderBody());\n      this.domNode.appendChild(this._renderFooter());\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      _superPropGet(ButtonSettingsPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n      // Release each embedded control's sync subscription so re-opening\n      // the popover doesn't leak listeners.\n      (this._controls || []).forEach(function (c) {\n        try {\n          c && typeof c.destroy === 'function' && c.destroy();\n        } catch (_) {/* no-op */}\n      });\n      this._controls = [];\n      this._snapshot = null;\n    }\n\n    /* ─── Snapshot helpers ─── */\n  }, {\n    key: \"_captureSnapshot\",\n    value: function _captureSnapshot() {\n      return {\n        size_key: this.element.size_key || 'md',\n        shadow_key: this.element.shadow_key || 'none',\n        hover_effect: this.element.hover_effect || 'none',\n        icon: this.element.icon || null,\n        icon_position: this.element.icon_position || 'none',\n        width_key: this.element._currentWidthKey ? this.element._currentWidthKey() : 'auto',\n        radius_key: this.element._currentRadiusKey ? this.element._currentRadiusKey() || 'md' : 'md',\n        formats: this.element.formatter ? Object.assign({}, this.element.formatter.formats) : null\n      };\n    }\n  }, {\n    key: \"_restoreSnapshot\",\n    value: function _restoreSnapshot() {\n      var s = this._snapshot;\n      if (!s || !this.element) return;\n      this.element.size_key = s.size_key;\n      this.element.shadow_key = s.shadow_key;\n      this.element.hover_effect = s.hover_effect;\n      this.element.icon = s.icon;\n      this.element.icon_position = s.icon_position;\n      if (s.formats && this.element.formatter) {\n        this.element.formatter.formats = Object.assign({}, s.formats);\n      }\n      if (typeof this.element.applyFormatStyles === 'function') this.element.applyFormatStyles();\n      if (typeof this.element.applyButtonExtras === 'function') this.element.applyButtonExtras();\n      if (typeof this.element.notifySyncListeners === 'function') this.element.notifySyncListeners();\n    }\n\n    /* ─── Chrome ─── */\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var _this2 = this;\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-button-settings-header';\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-button-settings-title';\n      title.id = 'bjs-ovl-button-settings-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.settings.title', 'Button settings');\n      var close = document.createElement('button');\n      close.type = 'button';\n      close.className = 'bjs-ovl-button-settings-close';\n      close.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.close', 'Close'));\n      close.innerHTML = '<span aria-hidden=\"true\">' + _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].render('close', {\n        size: 18,\n        color: 'currentColor'\n      }) + '</span>';\n      close.addEventListener('click', function (e) {\n        e.preventDefault();\n        // Close button = explicit commit (accept current state)\n        if (typeof _this2.element.exitEditMode === 'function') _this2.element.exitEditMode();\n      });\n      header.appendChild(title);\n      header.appendChild(close);\n      return header;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this3 = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-button-settings-footer';\n      var hint = document.createElement('span');\n      hint.className = 'bjs-ovl-button-settings-hint';\n      hint.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.settings.hint', 'Esc to cancel · Click outside to apply');\n      footer.appendChild(hint);\n      var reset = document.createElement('button');\n      reset.type = 'button';\n      reset.className = 'bjs-ovl-button-settings-reset';\n      reset.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.settings.reset', 'Reset');\n      reset.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this3._restoreSnapshot();\n        if (typeof _this3.element.exitEditMode === 'function') _this3.element.exitEditMode();\n      });\n      footer.appendChild(reset);\n      return footer;\n    }\n\n    /* ─── Body ─── */\n  }, {\n    key: \"_renderBody\",\n    value: function _renderBody() {\n      var _this4 = this;\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-button-settings-body';\n\n      // ── Size + Radius ──\n      body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.shape', 'Shape & size'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.shape_desc', 'Baseline size and corner radius.')));\n      body.appendChild(this._renderSegmented('size', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.size.label', 'Size'), this.element.size_key || 'md', function (v) {\n        return _this4.element.applySize(v);\n      }, _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__.SIZE_KEYS.map(function (k) {\n        return {\n          value: k,\n          label: k.toUpperCase()\n        };\n      }), function () {\n        return _this4.element.size_key || 'md';\n      }));\n      body.appendChild(this._renderSegmented('radius', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.label', 'Radius'), this.element._currentRadiusKey() || 'md', function (v) {\n        return _this4.element.applyRadiusKey(v);\n      }, [{\n        value: 'sharp',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.sharp', 'Sharp')\n      }, {\n        value: 'sm',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.sm', 'SM')\n      }, {\n        value: 'md',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.md', 'MD')\n      }, {\n        value: 'lg',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.lg', 'LG')\n      }, {\n        value: 'pill',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.radius.pill', 'Pill')\n      }], function () {\n        return _this4.element._currentRadiusKey() || 'md';\n      }));\n\n      // ── Effects ──\n      body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.effects', 'Effects'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.effects_desc', 'Depth and micro-interactions. Page mode only.')));\n      body.appendChild(this._renderSegmented('shadow', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.shadow.label', 'Shadow'), this.element.shadow_key || 'none', function (v) {\n        return _this4.element.applyShadow(v);\n      }, _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__.SHADOW_KEYS.map(function (k) {\n        return {\n          value: k,\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.shadow.' + k, k === 'inner' ? 'Inner' : k.toUpperCase())\n        };\n      }), function () {\n        return _this4.element.shadow_key || 'none';\n      }));\n      body.appendChild(this._renderSegmented('hover', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.hover.label', 'Hover effect'), this.element.hover_effect || 'none', function (v) {\n        return _this4.element.applyHoverEffect(v);\n      }, _buttonPresets_js__WEBPACK_IMPORTED_MODULE_5__.HOVER_EFFECT_KEYS.map(function (k) {\n        return {\n          value: k,\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.hover.' + k, k.charAt(0).toUpperCase() + k.slice(1))\n        };\n      }), function () {\n        return _this4.element.hover_effect || 'none';\n      }));\n\n      // ── Icon ──\n      body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.icon', 'Icon'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.icon_desc', 'Optional pictogram beside, before, or instead of the label.')));\n      body.appendChild(this._renderIconPicker());\n      body.appendChild(this._renderSegmented('iconPos', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.label', 'Position'), this.element.icon_position || 'none', function (v) {\n        return _this4.element.applyIconPosition(v);\n      }, [{\n        value: 'left',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.left', 'Left')\n      }, {\n        value: 'right',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.right', 'Right')\n      }, {\n        value: 'only',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.only', 'Only')\n      }, {\n        value: 'none',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon_pos.none', 'None')\n      }], function () {\n        return _this4.element.icon_position || 'none';\n      }));\n\n      // ── Layout ──\n      body.appendChild(this._renderSectionLabel(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.layout', 'Layout'), _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.section.layout_desc', 'Width within the block row.')));\n      body.appendChild(this._renderSegmented('width', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.label', 'Width'), this.element._currentWidthKey(), function (v) {\n        return _this4.element.applyWidth(v);\n      }, [{\n        value: 'auto',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.auto', 'Auto')\n      }, {\n        value: 'half',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.half', '50%')\n      }, {\n        value: 'full',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.width.full', 'Full')\n      }], function () {\n        return _this4.element._currentWidthKey();\n      }));\n      return body;\n    }\n  }, {\n    key: \"_renderSectionLabel\",\n    value: function _renderSectionLabel(label, desc) {\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-button-settings-section';\n      var h = document.createElement('div');\n      h.className = 'bjs-ovl-button-settings-section-label';\n      h.textContent = label;\n      wrap.appendChild(h);\n      if (desc) {\n        var d = document.createElement('div');\n        d.className = 'bjs-ovl-button-settings-section-desc';\n        d.textContent = desc;\n        wrap.appendChild(d);\n      }\n      return wrap;\n    }\n  }, {\n    key: \"_renderSegmented\",\n    value: function _renderSegmented(key, label, value, onChange, options, readValue) {\n      var ctl = new _SegmentedTextControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](label, value, onChange, options, {\n        element: this.element,\n        readValue: readValue\n      });\n      this._controls.push(ctl);\n      return ctl.domNode;\n    }\n  }, {\n    key: \"_renderIconPicker\",\n    value: function _renderIconPicker() {\n      var _this5 = this;\n      var picker = new _IconPickerControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('button.icon.label', 'Icon'), this.element.icon || '', {\n        setValue: function setValue(name) {\n          return _this5.element.applyIcon(name || null, _this5.element.icon_position && _this5.element.icon_position !== 'none' ? _this5.element.icon_position : 'left');\n        }\n      });\n\n      // Silent sync — mirror element.icon into the picker's visual state\n      // without re-firing the callback. Mirrors ButtonElement._buildIconPicker\n      // so both sidebar + popover pickers stay aligned.\n      var dispose = this.element.addSyncListener('ButtonSettingsIconPicker:' + Math.random().toString(36).slice(2, 7), function () {\n        var next = _this5.element.icon || '';\n        if (picker.value !== next) {\n          picker.value = next;\n          picker.isCustomOpen = picker._detectCustom(next);\n          if (typeof picker._refreshTrigger === 'function') picker._refreshTrigger();\n        }\n      });\n      var prevDestroy = typeof picker.destroy === 'function' ? picker.destroy.bind(picker) : null;\n      picker.destroy = function () {\n        try {\n          dispose && dispose();\n        } catch (_) {/* no-op */}\n        if (prevDestroy) {\n          try {\n            prevDestroy();\n          } catch (_) {/* no-op */}\n        }\n      };\n      this._controls.push(picker);\n      return picker.domNode;\n    }\n  }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ButtonSettingsPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ButtonSettingsPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/DraggableHandleOverlay.js":
/*!*********************************************************!*\
  !*** ./src/includes/overlays/DraggableHandleOverlay.js ***!
  \*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * DraggableHandleOverlay — pointer-driven drag handle primitive.\n *\n * Use for NEW gestures with NO HTML5 DnD involvement:\n *   - Grid column separator drag\n *   - Image crop handles\n *   - Resize corners\n *\n * DO NOT use for HTML5 DnD participants (Block drag anchor). Pointer events\n * and HTML5 DnD are mutually exclusive on the same node — once `dragstart`\n * fires, browser suppresses pointermove/pointerup. See §5.1b of OVERLAY.md +\n * SA invariant I2. `render()` asserts the target is NOT draggable=\"true\".\n *\n * Subclasses override:\n *   - onDragStart(e)   — pointerdown fired, capture acquired\n *   - onDrag(dx, dy, e)— pointermove with delta from start (px)\n *   - onDragEnd(e)     — pointerup/pointercancel\n *\n * Subclasses may also override render() for custom DOM — but MUST call\n * super.render() to wire pointer handlers + run the draggable=true assert.\n */\n\n\nvar DraggableHandleOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function DraggableHandleOverlay() {\n    _classCallCheck(this, DraggableHandleOverlay);\n    return _callSuper(this, DraggableHandleOverlay, arguments);\n  }\n  _inherits(DraggableHandleOverlay, _BaseOverlay);\n  return _createClass(DraggableHandleOverlay, [{\n    key: \"render\",\n    value: function render() {\n      if (!this.domNode) {\n        this.domNode = document.createElement('div');\n      }\n      this.domNode.classList.add('bjs-ovl-handle');\n      // Functional handles MUST escape canvas-clip — they sit on / past\n      // the element edge by design (resize edges, corners, grid column\n      // dividers all protrude). Clipping them at canvas edge would chop\n      // half the grab target off when the element sits flush with the\n      // canvas viewport. See OVERLAY.md §24 Canvas-clip contract.\n      this.domNode.classList.add('bjs-ovl-no-clip');\n      this.domNode.setAttribute('data-interactive', '');\n\n      // SA invariant I2 assert — pointer events + HTML5 DnD mutually exclusive.\n      // Check this.domNode itself AND any ancestor already in DOM. (If appended\n      // later under a draggable=true parent, the ancestor check runs at mount\n      // time, but we also check the node itself here which covers most cases.)\n      if (this.domNode.getAttribute('draggable') === 'true') {\n        throw new Error('DraggableHandleOverlay: target node has draggable=\"true\". ' + 'Pointer events are suppressed after dragstart. Use NativeDragHandleOverlay instead.');\n      }\n      this._bindPointer();\n    }\n  }, {\n    key: \"_bindPointer\",\n    value: function _bindPointer() {\n      var _this = this;\n      if (this._pointerBound) return; // idempotent in subclasses that re-render\n      this._pointerBound = true;\n      this.domNode.addEventListener('pointerdown', function (e) {\n        // Let middle-click / right-click pass through.\n        if (e.button !== 0) return;\n        e.preventDefault();\n        e.stopPropagation();\n\n        // Guard: if somehow we ended up inside a draggable=true ancestor,\n        // HTML5 DnD would fire dragstart next — we'd lose pointermove.\n        // Abort loudly before silent-failure territory.\n        if (_this.domNode.closest('[draggable=\"true\"]')) {\n          // eslint-disable-next-line no-console\n          console.error('[overlay] DraggableHandleOverlay grabbed inside draggable=true ancestor — ' + 'pointer events will be suppressed by HTML5 DnD. Aborting drag. ' + 'Use NativeDragHandleOverlay for HTML5 DnD handles (SA invariant I2).');\n          return;\n        }\n        _this._dragPointerId = e.pointerId;\n        _this._dragStart = {\n          x: e.clientX,\n          y: e.clientY\n        };\n        _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].acquire(_this.domNode, e.pointerId);\n        _this.domNode.classList.add('is-dragging');\n        try {\n          _this.onDragStart(e);\n        } catch (err) {\n          /* eslint-disable-next-line no-console */console.error('[overlay] onDragStart threw:', err);\n        }\n        var onMove = function onMove(ev) {\n          if (ev.pointerId !== _this._dragPointerId) return;\n          try {\n            _this.onDrag(ev.clientX - _this._dragStart.x, ev.clientY - _this._dragStart.y, ev);\n          } catch (err) {\n            /* eslint-disable-next-line no-console */console.error('[overlay] onDrag threw:', err);\n          }\n        };\n        var _cleanup = function cleanup(ev) {\n          if (ev.pointerId !== _this._dragPointerId) return;\n          _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].release(_this.domNode, ev.pointerId);\n          _this.domNode.classList.remove('is-dragging');\n          _this.domNode.removeEventListener('pointermove', onMove);\n          _this.domNode.removeEventListener('pointerup', _cleanup);\n          _this.domNode.removeEventListener('pointercancel', _cleanup);\n          try {\n            _this.onDragEnd(ev);\n          } catch (err) {\n            /* eslint-disable-next-line no-console */console.error('[overlay] onDragEnd threw:', err);\n          }\n        };\n        _this.domNode.addEventListener('pointermove', onMove);\n        _this.domNode.addEventListener('pointerup', _cleanup);\n        _this.domNode.addEventListener('pointercancel', _cleanup);\n      });\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      var _superPropGet2;\n      // If destroyed mid-drag, PointerCaptureRegistry's lostpointercapture\n      // listener (registered at acquire time) auto-cleans the registry when\n      // this.domNode detaches. No manual release needed here. See §4.I5.\n      (_superPropGet2 = _superPropGet(DraggableHandleOverlay, \"beforeDestroy\", this, 3)) === null || _superPropGet2 === void 0 || _superPropGet2([]);\n    }\n\n    // Subclass hooks:\n  }, {\n    key: \"onDragStart\",\n    value: function onDragStart(/* e */) {}\n  }, {\n    key: \"onDrag\",\n    value: function onDrag(/* dx, dy, e */) {}\n  }, {\n    key: \"onDragEnd\",\n    value: function onDragEnd(/* e */) {}\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DraggableHandleOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/DraggableHandleOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/EdgeResizerOverlay.js":
/*!*****************************************************!*\
  !*** ./src/includes/overlays/EdgeResizerOverlay.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * EdgeResizerOverlay — 6-px bar on one edge, drag to resize.\n *\n * Use for resize gestures along a named edge:\n *   - Cell right-edge (Phase 1.5 Grid v2)\n *   - (future) box bottom-edge, corner-less resize\n *\n * Subclass signature:\n *   new EdgeResizerOverlay(element, { edge: 'left' | 'right' | 'top' | 'bottom' })\n *\n * Drag delta math is delegated to subclass `onDrag(dx, dy, e)`. This class\n * only owns positioning (bar sits on the named edge, 6px thick) and cursor.\n *\n * Subclasses typically compute percentage deltas against parent width/height\n * and call `element.formatter.setFormat('width', '50%') + applyFormatStyles()`.\n * NEVER renderElementControls in the drag loop (SA invariant I9).\n */\n\nvar EdgeResizerOverlay = /*#__PURE__*/function (_DraggableHandleOverl) {\n  function EdgeResizerOverlay() {\n    _classCallCheck(this, EdgeResizerOverlay);\n    return _callSuper(this, EdgeResizerOverlay, arguments);\n  }\n  _inherits(EdgeResizerOverlay, _DraggableHandleOverl);\n  return _createClass(EdgeResizerOverlay, [{\n    key: \"render\",\n    value: function render() {\n      _superPropGet(EdgeResizerOverlay, \"render\", this, 3)([]); // wires pointer handlers + I2 assert\n      this.domNode.classList.add('bjs-ovl-edge-resizer');\n      var edge = this.opts.edge || 'right';\n      this.domNode.classList.add(\"bjs-ovl-edge-\".concat(edge));\n\n      // Cursor hint per axis.\n      var isHorizontal = edge === 'left' || edge === 'right';\n      this.domNode.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';\n\n      // a11y — announce as separator with orientation. Arrow-key support is\n      // the subclass's responsibility (they know the formatter key to nudge).\n      this.domNode.setAttribute('role', 'separator');\n      this.domNode.setAttribute('aria-orientation', isHorizontal ? 'vertical' : 'horizontal');\n      this.domNode.setAttribute('tabindex', '0');\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this = this;\n      var edge = this.opts.edge || 'right';\n      var THICK = 6;\n      this.element.matchingDomNode(this.domNode, 0, function () {\n        var domRect = _this.element.domNode.getBoundingClientRect();\n        var iframe = _this.element.domNode.ownerDocument.defaultView.frameElement;\n        var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var absTop = iframeRect.top + domRect.top;\n        var absLeft = iframeRect.left + domRect.left;\n        var style = {\n          position: 'fixed'\n        };\n        if (edge === 'left') Object.assign(style, {\n          top: absTop + 'px',\n          left: absLeft - THICK / 2 + 'px',\n          width: THICK + 'px',\n          height: domRect.height + 'px'\n        });else if (edge === 'right') Object.assign(style, {\n          top: absTop + 'px',\n          left: absLeft + domRect.width - THICK / 2 + 'px',\n          width: THICK + 'px',\n          height: domRect.height + 'px'\n        });else if (edge === 'top') Object.assign(style, {\n          top: absTop - THICK / 2 + 'px',\n          left: absLeft + 'px',\n          width: domRect.width + 'px',\n          height: THICK + 'px'\n        });else Object.assign(style, {\n          top: absTop + domRect.height - THICK / 2 + 'px',\n          left: absLeft + 'px',\n          width: domRect.width + 'px',\n          height: THICK + 'px'\n        });\n        Object.assign(_this.domNode.style, style);\n      });\n    }\n  }]);\n}(_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (EdgeResizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/EdgeResizerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/FloatingActionBarOverlay.js":
/*!***********************************************************!*\
  !*** ./src/includes/overlays/FloatingActionBarOverlay.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../pricingCardIcons.js */ \"./src/includes/pricingCardIcons.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * FloatingActionBarOverlay — pill row of icon buttons anchored to a corner.\n *\n * Use for selection-time contextual actions on an element:\n *   - Image Upload / Replace / Crop / Link (Phase 1.4)\n *   - (future) Button text / link editors\n *\n * Subclass signature:\n *   new FloatingActionBarOverlay(element, { anchor: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' })\n *\n * Subclass MUST implement `getButtons()` returning:\n *   [ { icon: 'upload', label: 'Upload', onClick: () => {...} }, ... ]\n *\n * Buttons render icons via the shared inline-SVG registry\n * (`pricingCardIcons.js`) when the name is known, so the action bar stays\n * visible even when the theme doesn't load Material Symbols font (common\n * inside email template iframes). Unknown names fall back to the Material\n * Symbols font span (still works in page mode / parent doc).\n *\n * `e.stopPropagation()` runs on each click so the underlying element's\n * select/deselect flow doesn't fire from a button click. (Required per\n * §12 OVERLAY.md troubleshooting.)\n */\n\n\nvar ANCHOR_INSET = 8; // px from element edge\nvar FloatingActionBarOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function FloatingActionBarOverlay() {\n    _classCallCheck(this, FloatingActionBarOverlay);\n    return _callSuper(this, FloatingActionBarOverlay, arguments);\n  }\n  _inherits(FloatingActionBarOverlay, _BaseOverlay);\n  return _createClass(FloatingActionBarOverlay, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode = document.createElement('div');\n      this.domNode.classList.add('bjs-ovl-action-bar');\n      this.domNode.setAttribute('data-interactive', '');\n      this.domNode.setAttribute('role', 'toolbar');\n      var buttons = this.getButtons() || [];\n      buttons.forEach(function (btnSpec) {\n        if (!btnSpec) return;\n        var btn = document.createElement('button');\n        btn.type = 'button';\n        btn.classList.add('bjs-ovl-pill');\n        if (btnSpec.label) {\n          btn.setAttribute('data-tooltip', btnSpec.label);\n          btn.setAttribute('aria-label', btnSpec.label);\n          // Action bars anchor to top-right/top-left/bottom-right/bottom-left\n          // of an element. Top-anchored bars → tooltip would clip above the\n          // viewport, so flip placement to match anchor direction.\n          var anchor = _this.opts.anchor || 'top-right';\n          if (anchor.startsWith('top')) {\n            btn.setAttribute('data-tooltip-placement', 'bottom');\n          }\n        }\n        if (btnSpec.icon) {\n          var ic = document.createElement('span');\n          ic.classList.add('bjs-ovl-pill-icon');\n          ic.setAttribute('aria-hidden', 'true');\n          if (_pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].hasIcon(btnSpec.icon)) {\n            ic.innerHTML = _pricingCardIcons_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].render(btnSpec.icon, {\n              size: 18,\n              color: 'currentColor'\n            });\n          } else {\n            // Fallback to Material Symbols font (parent doc loads it)\n            ic.classList.add('material-symbols-rounded');\n            ic.textContent = btnSpec.icon;\n          }\n          btn.appendChild(ic);\n        }\n        btn.addEventListener('click', function (e) {\n          e.preventDefault();\n          e.stopPropagation();\n          if (typeof btnSpec.onClick === 'function') {\n            try {\n              btnSpec.onClick(e);\n            } catch (err) {\n              /* eslint-disable-next-line no-console */console.error('[overlay] action bar onClick threw:', err);\n            }\n          }\n        });\n        _this.domNode.appendChild(btn);\n      });\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this2 = this;\n      var anchor = this.opts.anchor || 'top-right';\n      this.element.matchingDomNode(this.domNode, 0, function () {\n        var domRect = _this2.element.domNode.getBoundingClientRect();\n        var iframe = _this2.element.domNode.ownerDocument.defaultView.frameElement;\n        var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var elemTop = iframeRect.top + domRect.top;\n        var elemLeft = iframeRect.left + domRect.left;\n        var elemRight = elemLeft + domRect.width;\n        var elemBottom = elemTop + domRect.height;\n\n        // We measure bar size AFTER first attach — fall back to approx.\n        var barRect = _this2.domNode.getBoundingClientRect();\n        var barW = barRect.width || 120;\n        var barH = barRect.height || 40;\n        var style = {\n          position: 'fixed'\n        };\n        if (anchor === 'top-right') {\n          style.top = elemTop + ANCHOR_INSET + 'px';\n          style.left = elemRight - barW - ANCHOR_INSET + 'px';\n        } else if (anchor === 'top-left') {\n          style.top = elemTop + ANCHOR_INSET + 'px';\n          style.left = elemLeft + ANCHOR_INSET + 'px';\n        } else if (anchor === 'bottom-right') {\n          style.top = elemBottom - barH - ANCHOR_INSET + 'px';\n          style.left = elemRight - barW - ANCHOR_INSET + 'px';\n        } else {\n          // bottom-left\n          style.top = elemBottom - barH - ANCHOR_INSET + 'px';\n          style.left = elemLeft + ANCHOR_INSET + 'px';\n        }\n        Object.assign(_this2.domNode.style, style);\n      });\n    }\n\n    /** Subclass override: return array of { icon, label, onClick } specs. */\n  }, {\n    key: \"getButtons\",\n    value: function getButtons() {\n      return [];\n    }\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FloatingActionBarOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/FloatingActionBarOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/FontPopoverOverlay.js":
/*!*****************************************************!*\
  !*** ./src/includes/overlays/FontPopoverOverlay.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../FontFamilyControl.js */ \"./src/includes/FontFamilyControl.js\");\n/* harmony import */ var _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../FontWeightControl.js */ \"./src/includes/FontWeightControl.js\");\n/* harmony import */ var _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../NumberControl.js */ \"./src/includes/NumberControl.js\");\n/* harmony import */ var _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../TextSelectionTracker.js */ \"./src/includes/TextSelectionTracker.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * FontPopoverOverlay — W3.1 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * Anchored popover embedding Font Family (typeahead-style select via\n * `FontFamilyControl`), Font Weight (`FontWeightControl`), and Font Size\n * (`NumberControl` stepper ± px). Preview chip at the top shows \"The\n * quick brown fox\" rendered in the currently-selected family × weight ×\n * size so the user sees the outcome before clicking away.\n *\n * HARD RULE T3 (dual-view sync): the popover body instantiates the SAME\n * control classes the sidebar uses (`FontFamilyControl` / `FontWeight\n * Control` / `NumberControl`), each with the `{bus, elementUid,\n * formatterKey}` 4th-arg options so EVERY write (popover or sidebar)\n * emits `formatter:change` and BOTH surfaces mirror live via silent\n * `setValue(v, { silent: true })`. One write path (D13 v5), two\n * consumers, zero drift.\n *\n * Mount pattern mirrors `TextColorPopoverOverlay` /\n * `LinkOnSelectionPopoverOverlay`: lightweight non-`BaseOverlay` class,\n * owned by the singleton `TextInlineToolbarOverlay`, mounted in\n * `document.body`, anchored via `ToolbarPositioner.attach` to the\n * toolbar's Font button, disposed when the toolbar unmounts.\n *\n * Unit toggle (px / rem / em): NOT shipped in W3.1 initial. Storing a\n * unit on `font_size` requires a formatter schema migration (current\n * state is numeric px-only) and a serializer round-trip test. Deferred\n * — flagged for a W3.1b follow-up if user feedback asks.\n *\n * Selection preservation: the iframe selection is NOT restored on apply\n * because Font writes to element-level formatter (not range-level inline\n * tags). Clicking into the popover's inputs will naturally collapse the\n * canvas selection — that's fine; the popover writes through the\n * element's own write path (formatter → applyFormatStyles) which does\n * not depend on a live range.\n *\n * Scope-note surface (user feedback 2026-04-24). Every write here applies\n * to the WHOLE text element (shared write path with the sidebar). A user\n * who selected a partial range and opens this popover might expect the\n * change to land on just that range — so a muted info note under the\n * preview states the scope explicitly. Same constraint will apply to\n * W4.1 Advanced popover (line-height / letter-spacing / text-direction /\n * paragraph-spacing are all element-level CSS) — a matching note will\n * ship there. Color / Link / AI popovers are range-scoped (execCommand\n * + range mutation + replace) so they do NOT carry a scope note.\n */\n\n\n\n\n\n\n\nvar FontPopoverOverlay = /*#__PURE__*/function () {\n  /**\n   * @param {TextInlineToolbarOverlay} toolbar — owner.\n   * @param {{ anchorBtn: HTMLElement }} opts\n   */\n  function FontPopoverOverlay(toolbar, opts) {\n    _classCallCheck(this, FontPopoverOverlay);\n    if (!toolbar || !opts || !opts.anchorBtn) {\n      throw new Error('FontPopoverOverlay: toolbar + opts.anchorBtn required');\n    }\n    this._toolbar = toolbar;\n    this._builder = toolbar._builder;\n    this._anchorBtn = opts.anchorBtn;\n    this.domNode = null;\n    this._familyControl = null;\n    this._weightControl = null;\n    this._sizeControl = null;\n    this._previewEl = null;\n    this._positionHandle = null;\n    this._onDocKey = null;\n    this._onDocMouseDown = null;\n    this._busOffPreview = null;\n    this._mounted = false;\n    // W5.2 — selection snapshot captured at open time, restored on\n    // close so the user's highlight survives interacting with the\n    // popover's inputs (which steal focus in the parent document).\n    this._selectionSnap = null;\n  }\n\n  /* ── public lifecycle ─────────────────────────────────────────── */\n  return _createClass(FontPopoverOverlay, [{\n    key: \"open\",\n    value: function open() {\n      var _this = this;\n      if (this._mounted) return;\n      // W5.2 — snapshot the current selection BEFORE we mount. The popover's\n      // inputs (selects, number stepper) will steal focus in the parent\n      // document on click, which on some Chromium builds collapses the\n      // iframe selection. We restore on close so the user's highlight\n      // survives round-trip.\n      this._selectionSnap = _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_5__.SelectionGuard.save(this._builder);\n      try {\n        this._build();\n        if (!this.domNode) return;\n        document.body.appendChild(this.domNode);\n        this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n          anchor: function anchor() {\n            return _this._anchorBtn.getBoundingClientRect();\n          },\n          target: this.domNode,\n          offset: 8,\n          collisionPadding: 12,\n          preferredSide: 'below',\n          flip: true\n        });\n        this._registerDismissListeners();\n        this._subscribePreview();\n        this._mounted = true;\n        this._anchorBtn.setAttribute('aria-expanded', 'true');\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:font-popover] open failed:', err);\n        this.close();\n      }\n    }\n  }, {\n    key: \"close\",\n    value: function close() {\n      if (!this._mounted && !this.domNode) return;\n      this._unregisterDismissListeners();\n      if (this._busOffPreview) {\n        this._busOffPreview();\n        this._busOffPreview = null;\n      }\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.dispose();\n        } catch (_) {}\n        this._positionHandle = null;\n      }\n      // Destroy embedded controls so their bus subscriptions don't leak\n      // past the popover's lifetime.\n      [this._familyControl, this._weightControl, this._sizeControl].forEach(function (ctrl) {\n        if (ctrl && typeof ctrl.destroy === 'function') {\n          try {\n            ctrl.destroy();\n          } catch (_) {}\n        }\n      });\n      this._familyControl = null;\n      this._weightControl = null;\n      this._sizeControl = null;\n      this._previewEl = null;\n      if (this.domNode && this.domNode.parentNode) {\n        try {\n          this.domNode.parentNode.removeChild(this.domNode);\n        } catch (_) {}\n      }\n      this.domNode = null;\n      this._mounted = false;\n      try {\n        this._anchorBtn.setAttribute('aria-expanded', 'false');\n      } catch (_) {}\n      // W5.2 — restore the pre-open selection so the highlight visually\n      // returns and any downstream selection-aware code (toolbar state\n      // reads, keyboard shortcut dispatcher) picks up where it left off.\n      if (this._selectionSnap) {\n        _TextSelectionTracker_js__WEBPACK_IMPORTED_MODULE_5__.SelectionGuard.restore(this._builder, this._selectionSnap);\n        this._selectionSnap = null;\n      }\n    }\n  }, {\n    key: \"isOpen\",\n    value: function isOpen() {\n      return this._mounted;\n    }\n\n    /* ── build DOM ────────────────────────────────────────────────── */\n  }, {\n    key: \"_build\",\n    value: function _build() {\n      var _this2 = this;\n      var element = this._resolveElement();\n      if (!element) {\n        // No target element — nothing to write to. Bail gracefully.\n        return;\n      }\n      var p = document.createElement('div');\n      p.className = 'bjs-ovl bjs-ovl-font-popover';\n      p.setAttribute('role', 'dialog');\n      p.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.title'));\n      p.setAttribute('data-interactive', '');\n\n      // Header — title.\n      p.appendChild(this._renderHeader());\n\n      // Preview chip — \"The quick brown fox\" in current family × weight × size.\n      this._previewEl = this._renderPreview(element);\n      p.appendChild(this._previewEl);\n\n      // Scope note — Font writes are element-level, not range-level.\n      // Spelled out so a user with a partial range selected doesn't\n      // assume the change will land on just that range.\n      p.appendChild(this._renderScopeNote());\n\n      // Body — 3 dual-mounted controls. Each writes through element.formatter\n      // + emits `formatter:change`; sidebar instances silently mirror via\n      // the same bus. HARD RULE T3 (dual-view) held automatically.\n      var body = document.createElement('div');\n      body.className = 'bjs-font-popover-body';\n      var setFmt = function setFmt(key) {\n        return function (value) {\n          element.formatter.setFormat(key, value);\n          if (typeof element.applyFormatStyles === 'function') {\n            element.applyFormatStyles();\n          } else if (typeof element.render === 'function') {\n            element.render();\n          }\n          _this2._updatePreview();\n        };\n      };\n      var busOpts = function busOpts(key) {\n        return {\n          bus: _this2._builder && _this2._builder.events,\n          elementUid: element.id,\n          formatterKey: key\n        };\n      };\n      this._familyControl = new _FontFamilyControl_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_family'), element.formatter.getFormat('font_family'), {\n        setValue: setFmt('font_family')\n      }, busOpts('font_family'));\n      body.appendChild(this._familyControl.domNode);\n      this._weightControl = new _FontWeightControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_weight'), element.formatter.getFormat('font_weight'), {\n        setValue: setFmt('font_weight')\n      }, busOpts('font_weight'));\n      body.appendChild(this._weightControl.domNode);\n      this._sizeControl = new _NumberControl_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('controls.font_size'), element.formatter.getFormat('font_size'), {\n        setValue: setFmt('font_size')\n      }, _objectSpread({\n        defaultValue: 16,\n        minValue: 8,\n        maxValue: 72,\n        suffix: 'px',\n        allowZero: false\n      }, busOpts('font_size')));\n      body.appendChild(this._sizeControl.domNode);\n      p.appendChild(body);\n      this.domNode = p;\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-font-popover-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-font-popover-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'text_format';\n      icon.setAttribute('aria-hidden', 'true');\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-font-popover-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.title');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_renderPreview\",\n    value: function _renderPreview(element) {\n      var chip = document.createElement('div');\n      chip.className = 'bjs-font-popover-preview';\n      chip.setAttribute('aria-hidden', 'true'); // live region = not useful; visual only\n      chip.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.preview_text');\n      this._applyPreviewStyle(chip, element);\n      return chip;\n    }\n  }, {\n    key: \"_renderScopeNote\",\n    value: function _renderScopeNote() {\n      var note = document.createElement('div');\n      note.className = 'bjs-font-popover-scope-note';\n      note.setAttribute('role', 'note');\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded bjs-font-popover-scope-note-icon';\n      icon.setAttribute('aria-hidden', 'true');\n      icon.textContent = 'info';\n      var text = document.createElement('span');\n      text.className = 'bjs-font-popover-scope-note-text';\n      text.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('font_popover.scope_note');\n      note.appendChild(icon);\n      note.appendChild(text);\n      return note;\n    }\n  }, {\n    key: \"_applyPreviewStyle\",\n    value: function _applyPreviewStyle(chip, element) {\n      if (!chip) return;\n      var fmt = element && element.formatter;\n      if (!fmt) return;\n      var family = fmt.getFormat('font_family');\n      var weight = fmt.getFormat('font_weight');\n      var size = fmt.getFormat('font_size');\n      if (family) chip.style.fontFamily = family;else chip.style.removeProperty('font-family');\n      if (weight) chip.style.fontWeight = String(weight);else chip.style.removeProperty('font-weight');\n      if (size) chip.style.fontSize = typeof size === 'number' ? size + 'px' : String(size);else chip.style.removeProperty('font-size');\n    }\n  }, {\n    key: \"_updatePreview\",\n    value: function _updatePreview() {\n      var element = this._resolveElement();\n      if (!element || !this._previewEl) return;\n      this._applyPreviewStyle(this._previewEl, element);\n    }\n\n    /**\n     * Subscribe to `formatter:change` so the preview chip live-updates\n     * when the sidebar writes (same element, same key) — dual-view in\n     * reverse direction (sidebar → popover preview).\n     */\n  }, {\n    key: \"_subscribePreview\",\n    value: function _subscribePreview() {\n      var _this3 = this;\n      var bus = this._builder && this._builder.events;\n      var element = this._resolveElement();\n      if (!bus || !element || typeof bus.on !== 'function') return;\n      this._busOffPreview = bus.on('formatter:change', function (payload) {\n        if (!payload) return;\n        if (payload.elementUid !== element.id) return;\n        if (payload.key !== 'font_family' && payload.key !== 'font_weight' && payload.key !== 'font_size') return;\n        // Defer one microtask so the applying control has flushed its\n        // own setValue before we re-read the formatter.\n        setTimeout(function () {\n          return _this3._updatePreview();\n        }, 0);\n      });\n    }\n\n    /* ── element resolution ───────────────────────────────────────── */\n  }, {\n    key: \"_resolveElement\",\n    value: function _resolveElement() {\n      var payload = this._toolbar && this._toolbar._currentPayload;\n      if (!payload) return null;\n      var uid = payload.elementUid;\n      var uiMgr = this._builder && this._builder.uiManager;\n      if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n      return uiMgr.elements.find(function (el) {\n        return el && el.id === uid;\n      }) || null;\n    }\n\n    /* ── dismissal ────────────────────────────────────────────────── */\n  }, {\n    key: \"_registerDismissListeners\",\n    value: function _registerDismissListeners() {\n      var _this4 = this;\n      this._onDocKey = function (e) {\n        if (e.key === 'Escape') {\n          e.stopPropagation();\n          _this4.close();\n        }\n      };\n      document.addEventListener('keydown', this._onDocKey, true);\n      this._onDocMouseDown = function (e) {\n        if (!_this4.domNode) return;\n        var t = e.target;\n        if (_this4.domNode.contains(t)) return;\n        if (t && _this4._anchorBtn && _this4._anchorBtn.contains(t)) return;\n        _this4.close();\n      };\n      setTimeout(function () {\n        if (_this4._mounted) document.addEventListener('mousedown', _this4._onDocMouseDown, true);\n      }, 0);\n    }\n  }, {\n    key: \"_unregisterDismissListeners\",\n    value: function _unregisterDismissListeners() {\n      if (this._onDocKey) {\n        document.removeEventListener('keydown', this._onDocKey, true);\n        this._onDocKey = null;\n      }\n      if (this._onDocMouseDown) {\n        document.removeEventListener('mousedown', this._onDocMouseDown, true);\n        this._onDocMouseDown = null;\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FontPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/FontPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/GridColumnResizeOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/GridColumnResizeOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * GridColumnResizeOverlay — Phase 1.3\n *\n * Draggable 6px-wide vertical bar sitting between two neighboring cells\n * of a Grid. Dragging updates both cells' width formats, conserving sum\n * (if left grows, right shrinks). Each Grid contributes (cells.length - 1)\n * instances — one per inter-cell boundary.\n *\n * Positioning: straddles the cell edge (left - THICK/2, width = THICK).\n * Height = cell height (taken from leftCell, assumes rows have equal row-height).\n *\n * Width math:\n *   - Start-of-drag snapshots leftCell % and rightCell %, read via parseFloat.\n *   - dxPct = (e.clientX - startX) / gridWidth * 100\n *   - newLeft = clamp(startLeft + dxPct, 5, total - 5)\n *   - newRight = total - newLeft\n *   - `'width'` format emitted as \"NN.NN%\". Non-% width formats (px / em /\n *     auto / bare numeric) fall back gracefully — parseFloat('auto') = NaN\n *     treated as \"can't resize this boundary\" and drag bails.\n *\n * Keyboard: arrow keys while focused shift 1% (or 5% with Shift).\n *\n * NO-FLICKER (SA invariant I9): updates use `formatter.setFormat + applyFormatStyles`\n * on each cell. NEVER calls `builder.renderElementControls`.\n *\n * See docs/core/OVERLAY.md §6 tutorial, §7.1 Grid example, docs/archived/OVERLAY_PLAN.md §3.4.\n */\n\n\n// Hit-zone width — wide enough to forgive aim, but visually subtle (the\n// always-visible CSS pill thumb sits at the center). 12px covers typical\n// mouse precision (3px × 4) AND straddles the cell_gap fully when gap ≤ 12.\nvar THICK = 12;\nvar MIN_PCT = 5;\nvar GridColumnResizeOverlay = /*#__PURE__*/function (_DraggableHandleOverl) {\n  function GridColumnResizeOverlay() {\n    _classCallCheck(this, GridColumnResizeOverlay);\n    return _callSuper(this, GridColumnResizeOverlay, arguments);\n  }\n  _inherits(GridColumnResizeOverlay, _DraggableHandleOverl);\n  return _createClass(GridColumnResizeOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(GridColumnResizeOverlay, \"render\", this, 3)([]); // pointer handlers + I2 assert\n      this.domNode.classList.add('bjs-ovl-grid-separator');\n      this.domNode.style.cursor = 'col-resize';\n      this.domNode.setAttribute('role', 'separator');\n      this.domNode.setAttribute('aria-orientation', 'vertical');\n      this.domNode.setAttribute('tabindex', '0');\n      this.domNode.setAttribute('aria-label', 'Resize column');\n      this._bindKeyboard();\n    }\n  }, {\n    key: \"_bindKeyboard\",\n    value: function _bindKeyboard() {\n      var _this = this;\n      if (this._keyBound) return;\n      this._keyBound = true;\n      this.domNode.addEventListener('keydown', function (e) {\n        if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;\n        e.preventDefault();\n        var cells = _this._pair();\n        if (!cells) return;\n        var delta = (e.key === 'ArrowRight' ? 1 : -1) * (e.shiftKey ? 5 : 1);\n        var startLeft = _this._readPct(cells.left);\n        var startRight = _this._readPct(cells.right);\n        if (isNaN(startLeft) || isNaN(startRight)) return;\n        var total = startLeft + startRight;\n        var newLeft = Math.max(MIN_PCT, Math.min(total - MIN_PCT, startLeft + delta));\n        var newRight = total - newLeft;\n        _this._applyPair(cells, newLeft, newRight);\n      });\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this2 = this;\n      var cells = this._pair();\n      if (!cells) {\n        // Stale boundary (cells removed since mount) — hide rather than bail.\n        if (this.domNode) this.domNode.style.display = 'none';\n        return;\n      }\n      if (this.domNode) this.domNode.style.display = '';\n\n      // Position centered on the GAP between the two cells (not on the\n      // left cell's right edge). Critical for grids with cell_gap > 0:\n      // the visible whitespace between cells is what users instinctively\n      // aim at — a separator pinned to the left cell's right edge sits\n      // BEFORE that whitespace and is unhittable. Center on the midpoint\n      // of [leftCell.right, rightCell.left] and widen the bar to span at\n      // least the visible gap (so cursor anywhere in the gap hits it).\n      // matchingDomNode observers are wired to the LEFT cell — that's the\n      // primary reflow trigger; right cell reflows propagate via its own\n      // ResizeObserver chain.\n      var leftCell = cells.left;\n      var rightCell = cells.right;\n      leftCell.matchingDomNode(this.domNode, 0, function () {\n        var leftRect = leftCell.domNode.getBoundingClientRect();\n        var rightRect = rightCell.domNode.getBoundingClientRect();\n        var iframe = leftCell.domNode.ownerDocument.defaultView.frameElement;\n        var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var absTop = iframeRect.top + leftRect.top;\n        var absLeft = iframeRect.left + leftRect.left;\n\n        // Visible gap pixels (right cell may be in the next row if the\n        // grid wrapped — tests for vertical separation and bails to\n        // edge-of-left-cell positioning in that case).\n        var gapPx = Math.max(0, rightRect.left - leftRect.right);\n        var sameRow = Math.abs(rightRect.top - leftRect.top) < 4;\n        var barWidth = sameRow ? Math.max(THICK, gapPx + THICK) : THICK;\n        var gapCenter = sameRow ? (leftRect.right + rightRect.left) / 2 : leftRect.right;\n        Object.assign(_this2.domNode.style, {\n          position: 'fixed',\n          top: absTop + 'px',\n          left: iframeRect.left + gapCenter - barWidth / 2 + 'px',\n          width: barWidth + 'px',\n          height: leftRect.height + 'px'\n        });\n      });\n    }\n\n    // ─── Drag lifecycle ─────────────────────────────────────────────\n  }, {\n    key: \"onDragStart\",\n    value: function onDragStart(/* e */\n    ) {\n      var cells = this._pair();\n      if (!cells) return;\n      this._dragCells = cells;\n      this._dragGridWidth = this.element.domNode.getBoundingClientRect().width;\n      this._dragStartLeft = this._readPct(cells.left);\n      this._dragStartRight = this._readPct(cells.right);\n\n      // Auto-promote non-percent boundaries to percent so the user can drag\n      // ANY adjacent pair, not just the ones that happened to be authored\n      // with `%` widths. Sample data ships cells with `auto`/`fill`/`px`/\n      // grow-share — silently bailing here meant \"drag does nothing\" which\n      // reads as a broken UI. We measure the cells' RENDERED widths against\n      // the grid width, write back as `N%`, and proceed with normal % math.\n      // Conserved sum = leftPct + rightPct (rest of the row keeps its\n      // existing widths, including any other auto/fill cells).\n      if (isNaN(this._dragStartLeft) || isNaN(this._dragStartRight)) {\n        var _cells$left$formatter, _cells$right$formatte;\n        var grid = this.element;\n        var gridW = grid.domNode && grid.domNode.getBoundingClientRect().width || 0;\n        if (gridW > 0 && cells.left.domNode && cells.right.domNode && typeof ((_cells$left$formatter = cells.left.formatter) === null || _cells$left$formatter === void 0 ? void 0 : _cells$left$formatter.setFormat) === 'function' && typeof ((_cells$right$formatte = cells.right.formatter) === null || _cells$right$formatte === void 0 ? void 0 : _cells$right$formatte.setFormat) === 'function') {\n          var lW = cells.left.domNode.getBoundingClientRect().width;\n          var rW = cells.right.domNode.getBoundingClientRect().width;\n          // Subtract the cell-gap share so the % math doesn't double-\n          // count gap pixels (Cell.template.html already deducts a\n          // proportional share of cell_gap from the flex-basis).\n          var gap = typeof grid.cell_gap === 'number' ? grid.cell_gap : 0;\n          var count = Array.isArray(grid.cells) ? grid.cells.length : 1;\n          var gapShare = count > 1 && gap > 0 ? gap * (count - 1) / count : 0;\n          var lPct = (lW + gapShare) / gridW * 100;\n          var rPct = (rW + gapShare) / gridW * 100;\n          if (lPct >= MIN_PCT && rPct >= MIN_PCT && lPct + rPct <= 100) {\n            var fmt = function fmt(v) {\n              return v.toFixed(2).replace(/\\.00$/, '') + '%';\n            };\n            cells.left.formatter.setFormat('width', fmt(lPct));\n            cells.right.formatter.setFormat('width', fmt(rPct));\n            if (typeof cells.left.applyFormatStyles === 'function') cells.left.applyFormatStyles();\n            if (typeof cells.right.applyFormatStyles === 'function') cells.right.applyFormatStyles();\n            this._dragStartLeft = lPct;\n            this._dragStartRight = rPct;\n            return; // primed for normal drag math\n          }\n        }\n        // Promotion not possible (zero-width cells, missing DOM, etc.) →\n        // bail. Visible cursor still says col-resize so user knows the\n        // affordance exists; subsequent moves will no-op gracefully.\n        this._dragCells = null;\n      }\n    }\n  }, {\n    key: \"onDrag\",\n    value: function onDrag(dx /*, dy, e */) {\n      if (!this._dragCells || !this._dragGridWidth) return;\n      var dxPct = dx / this._dragGridWidth * 100;\n      var total = this._dragStartLeft + this._dragStartRight;\n      var newLeft = Math.max(MIN_PCT, Math.min(total - MIN_PCT, this._dragStartLeft + dxPct));\n      var newRight = total - newLeft;\n      this._applyPair(this._dragCells, newLeft, newRight);\n    }\n  }, {\n    key: \"onDragEnd\",\n    value: function onDragEnd(/* e */\n    ) {\n      this._dragCells = null;\n      this._dragGridWidth = 0;\n    }\n\n    // ─── Helpers ─────────────────────────────────────────────────────\n\n    /** Resolve the {left, right} cell pair for this boundary. Returns null\n     *  if boundary index is out of range (cell removed since mount). */\n  }, {\n    key: \"_pair\",\n    value: function _pair() {\n      var cells = this.element.cells;\n      var i = this.opts.boundaryIndex;\n      if (!Array.isArray(cells) || i < 0 || i >= cells.length - 1) return null;\n      var left = cells[i];\n      var right = cells[i + 1];\n      if (!left || !left.domNode || !right || !right.domNode) return null;\n      return {\n        left: left,\n        right: right\n      };\n    }\n  }, {\n    key: \"_readPct\",\n    value: function _readPct(cell) {\n      var raw = cell.formatter.getFormat('width');\n      if (raw === null || raw === undefined) return NaN;\n      if (typeof raw === 'number') return raw; // bare-legacy\n      var s = String(raw).trim();\n      if (/%$/.test(s)) return parseFloat(s);\n      // 'auto', 'px', 'em' etc. — treat as un-resizable via this boundary.\n      return NaN;\n    }\n  }, {\n    key: \"_applyPair\",\n    value: function _applyPair(cells, newLeft, newRight) {\n      var fmt = function fmt(v) {\n        return v.toFixed(2).replace(/\\.00$/, '') + '%';\n      };\n      cells.left.formatter.setFormat('width', fmt(newLeft));\n      cells.right.formatter.setFormat('width', fmt(newRight));\n      // NO-FLICKER (I9): patch inline styles — NEVER renderElementControls.\n      if (typeof cells.left.applyFormatStyles === 'function') cells.left.applyFormatStyles();\n      if (typeof cells.right.applyFormatStyles === 'function') cells.right.applyFormatStyles();\n      // If applyFormatStyles isn't present on the cell (legacy), fall back\n      // to render() — less efficient but structurally correct.\n      else {\n        if (typeof cells.left.render === 'function') cells.left.render();\n        if (typeof cells.right.render === 'function') cells.right.render();\n      }\n    }\n  }]);\n}(_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridColumnResizeOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/GridColumnResizeOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/GridInsertColumnOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/GridInsertColumnOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * GridInsertColumnOverlay — Phase 1.5\n *\n * One \"+\" button instance per insertion boundary on a Grid. For an\n * n-cell grid, GridElement.getOverlays() composes (n + 1) instances:\n *   insertAt = 0           → button on left edge of cell 0 (insert-before-first)\n *   insertAt = i (1..n-1)  → button on right edge of cell i-1\n *   insertAt = n           → button on right edge of last cell (insert-at-end)\n *\n * Click → grid.addCellAt(insertAt) → re-select previously-selected element\n * (cell index shifts by +1 if insert was at-or-before the old position).\n * Re-select is a one-shot, user-driven action — well within SA invariant\n * I9 (NO-FLICKER applies to drag/keystroke hot-paths, not click boundaries).\n *\n * Trigger: 'select' on the parent Grid. Grid's own isHoverable() is false\n * so this only mounts when the user explicitly selects the grid via the\n * breadcrumb / GridControl card (SA invariant I7).\n *\n * Visual: 24×24 circle button with material-symbols \"add\" icon. Positioned\n * 12 px above the grid's top edge, horizontally centered on the boundary\n * X coordinate. Top placement is deliberate — keeps the button clear of\n * the GridColumnResizeOverlay drag zone (full cell height) so the two\n * affordances never collide.\n *\n * See docs/core/OVERLAY.md §7.1 + docs/archived/OVERLAY_PLAN.md §3.6.\n */\n\n\nvar SIZE = 24;\nvar ABOVE_OFFSET = 12; // half-button above grid top edge\nvar GridInsertColumnOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function GridInsertColumnOverlay() {\n    _classCallCheck(this, GridInsertColumnOverlay);\n    return _callSuper(this, GridInsertColumnOverlay, arguments);\n  }\n  _inherits(GridInsertColumnOverlay, _BaseOverlay);\n  return _createClass(GridInsertColumnOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      this.domNode = document.createElement('button');\n      this.domNode.type = 'button';\n      this.domNode.classList.add('bjs-ovl-insert-button');\n      // Functional control — escapes canvas-clip (the insert button sits\n      // straddling the column boundary, often half-outside the cell rect).\n      // See OVERLAY.md §24 Canvas-clip contract.\n      this.domNode.classList.add('bjs-ovl-no-clip');\n      this.domNode.setAttribute('data-interactive', '');\n      this.domNode.setAttribute('tabindex', '0');\n      var labelKey = this.opts.boundary === 'before' ? 'overlay.insert_column_before' : 'overlay.insert_column_after';\n      var labelFallback = this.opts.boundary === 'before' ? 'Insert column before' : 'Insert column after';\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey, labelFallback);\n      this.domNode.setAttribute('aria-label', label);\n      this.domNode.setAttribute('data-tooltip', label);\n      var icon = document.createElement('span');\n      icon.classList.add('material-symbols-rounded');\n      icon.setAttribute('aria-hidden', 'true');\n      icon.textContent = 'add';\n      this.domNode.appendChild(icon);\n      this.domNode.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this._insert();\n      });\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this2 = this;\n      var grid = this.element;\n      if (!grid || !grid.domNode) return;\n      var cells = Array.isArray(grid.cells) ? grid.cells : [];\n      var insertAt = this.opts.insertAt;\n\n      // Boundary anchor cell + edge:\n      //   insertAt 0          → cell 0 left edge\n      //   insertAt cells.len  → last cell right edge\n      //   else                → cell (insertAt - 1) right edge\n      var targetCell;\n      var edge;\n      if (insertAt === 0) {\n        targetCell = cells[0];\n        edge = 'left';\n      } else if (insertAt >= cells.length) {\n        targetCell = cells[cells.length - 1];\n        edge = 'right';\n      } else {\n        targetCell = cells[insertAt - 1];\n        edge = 'right';\n      }\n      if (!targetCell || !targetCell.domNode) {\n        // Stale boundary (cell was removed since mount) — hide rather\n        // than throw. Next reflow will retry.\n        this.domNode.style.display = 'none';\n        return;\n      }\n      this.domNode.style.display = '';\n\n      // Wire observers to the target cell so the button repositions on\n      // any reflow that affects that cell (and, transitively, the grid).\n      targetCell.matchingDomNode(this.domNode, 0, function () {\n        var rect = targetCell.domNode.getBoundingClientRect();\n        var iframe = targetCell.domNode.ownerDocument.defaultView.frameElement;\n        var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var gridRect = grid.domNode.getBoundingClientRect();\n        var boundaryX = edge === 'left' ? iframeRect.left + rect.left : iframeRect.left + rect.right;\n        // Anchor at grid's top edge so all (n+1) buttons line up on the\n        // SAME row regardless of cell-height variation. Falls back to\n        // cell rect if grid rect is degenerate.\n        var topAnchor = gridRect.height ? gridRect.top : rect.top;\n        var top = iframeRect.top + topAnchor - ABOVE_OFFSET;\n        Object.assign(_this2.domNode.style, {\n          position: 'fixed',\n          top: top + 'px',\n          left: boundaryX - SIZE / 2 + 'px',\n          width: SIZE + 'px',\n          height: SIZE + 'px'\n        });\n      });\n    }\n\n    /**\n     * Insert a cell at this overlay's boundary, then re-select whatever\n     * element was selected before so the sidebar + canvas overlays\n     * refresh with the new cell count. Cell index shifts by +1 if the\n     * previously-selected cell sits at-or-after the insert boundary.\n     */\n  }, {\n    key: \"_insert\",\n    value: function _insert() {\n      var grid = this.element;\n      if (!grid || typeof grid.addCellAt !== 'function') return;\n      var host = this.host;\n      var prevSelected = host ? host.selectedElement : null;\n      var prevCellIndex = prevSelected && Array.isArray(grid.cells) ? grid.cells.indexOf(prevSelected) : -1;\n      try {\n        grid.addCellAt(this.opts.insertAt);\n      } catch (err) {\n        /* eslint-disable-next-line no-console */\n        console.error('[overlay] GridInsertColumnOverlay addCellAt threw:', err);\n        return;\n      }\n      if (!host || typeof host.selectElement !== 'function') return;\n\n      // Decide what to re-select:\n      //   - cell was selected → its NEW index after the insert\n      //   - grid was selected → re-select grid (refreshes overlays)\n      //   - nothing was selected → select grid so user sees new structure\n      var target;\n      if (prevCellIndex >= 0) {\n        var newIndex = prevCellIndex >= this.opts.insertAt ? prevCellIndex + 1 : prevCellIndex;\n        target = grid.cells[newIndex] || grid;\n      } else {\n        target = grid;\n      }\n\n      // selectElement is a full-cycle re-init: unselect → render controls\n      // → highlight → mount overlays. One-shot at click boundary; not in\n      // hot-path. Within SA I9 budget.\n      host.selectElement(target);\n    }\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridInsertColumnOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/GridInsertColumnOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/GridStructureOverlay.js":
/*!*******************************************************!*\
  !*** ./src/includes/overlays/GridStructureOverlay.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StructureVisualizerOverlay.js */ \"./src/includes/overlays/StructureVisualizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * GridStructureOverlay — Phase 1.3\n *\n * When a Grid is selected, draws a dashed outline per cell so the user\n * sees the logical column structure while editing. Pair with (n-1)\n * `GridColumnResizeOverlay` instances that give drag-to-resize separators\n * between neighboring cells.\n *\n * `GridElement.isHoverable()` is false, so this overlay's trigger is\n * 'select' — mounts when user selects the grid via breadcrumb or\n * `GridControl` card in the sidebar (SA invariant I7).\n *\n * Composition: `layoutChildren()` runs on every reflow (scroll / resize /\n * DOM mutation / ResizeObserver fire) and redraws per-cell dashed boundaries.\n * The drawing is absolute-positioned children inside the overlay's root\n * (which covers the whole grid domNode).\n *\n * See docs/core/OVERLAY.md §7.1, docs/archived/OVERLAY_PLAN.md §3.4.\n */\n\nvar GridStructureOverlay = /*#__PURE__*/function (_StructureVisualizerO) {\n  function GridStructureOverlay() {\n    _classCallCheck(this, GridStructureOverlay);\n    return _callSuper(this, GridStructureOverlay, arguments);\n  }\n  _inherits(GridStructureOverlay, _StructureVisualizerO);\n  return _createClass(GridStructureOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(GridStructureOverlay, \"render\", this, 3)([]); // builds this.domNode with pointer-events: none\n      this.domNode.classList.add('bjs-ovl-grid-structure');\n    }\n  }, {\n    key: \"layoutChildren\",\n    value: function layoutChildren() {\n      var _this = this;\n      // Wipe previous boundary children; separator overlays are separate\n      // instances (Phase 1.3 GridColumnResizeOverlay) mounted alongside,\n      // not inside this domNode — their pointer events can't be blocked\n      // by this overlay's pass-through mask.\n      this.domNode.innerHTML = '';\n      var gridEl = this.element;\n      if (!gridEl.cells || gridEl.cells.length === 0) return;\n      var gridRect = gridEl.domNode.getBoundingClientRect();\n      if (!gridRect.width || !gridRect.height) return;\n      gridEl.cells.forEach(function (cell) {\n        if (!cell || !cell.domNode) return;\n        var cellRect = cell.domNode.getBoundingClientRect();\n        if (!cellRect.width || !cellRect.height) return;\n        var boundary = document.createElement('div');\n        boundary.className = 'bjs-ovl-grid-cell-boundary';\n        // Coordinates are LOCAL to the overlay's root (which matchingDomNode\n        // sized to match gridRect). Don't add iframe offset here.\n        Object.assign(boundary.style, {\n          position: 'absolute',\n          left: cellRect.left - gridRect.left + 'px',\n          top: cellRect.top - gridRect.top + 'px',\n          width: cellRect.width + 'px',\n          height: cellRect.height + 'px'\n        });\n        _this.domNode.appendChild(boundary);\n      });\n    }\n  }]);\n}(_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (GridStructureOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/GridStructureOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageActionsOverlay.js":
/*!******************************************************!*\
  !*** ./src/includes/overlays/ImageActionsOverlay.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FloatingActionBarOverlay.js */ \"./src/includes/overlays/FloatingActionBarOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageActionsOverlay — Phase 1.4\n *\n * Floating pill row anchored top-right of a selected image. Gives the user\n * one-click Upload / Effects / Resize / Crop / Link actions without leaving\n * the canvas.\n *\n * Trigger: 'select'. Mounts when user selects an ImageElement.\n *\n *   Upload:  opens file picker → FileReader dataURL → element.src = X + render()\n *   Effects: enterEditMode('effects-popover') — mounts ImageEffectPopoverOverlay\n *   Resize:  enterEditMode('resize-popover') / 'resize' — popover or modal\n *   Crop:    enterEditMode('crop-popover') / 'crop' — popover or modal\n *   Link:    enterEditMode('link-popover') — mounts LinkPopoverOverlay\n *            (2026-04-19, replaces the legacy BuilderjsPopup.prompt flow).\n *\n * `e.stopPropagation()` on each click prevents the element's select/deselect\n * flow from firing from a button click. (§12 OVERLAY.md troubleshooting.)\n *\n * See docs/core/OVERLAY.md §7.2 + docs/archived/OVERLAY_PLAN.md §3.5.\n */\n\n\n\n/* Surface preference per action — single map, swap a value to flip\n * between the modal popup and the anchored popover for that action.\n * Long-term knob (per IMAGE_OVERLAY_REFACTOR_PLAN.md user feedback):\n * keep both surfaces flexible — toggling crop / resize / link between\n * 'popup' and 'popover' should be a one-line edit here, not a\n * code-path rewrite.\n *\n *   'popup'   → InlineEditorOverlay subclass (full-viewport mask).\n *               Best for deep editing.\n *   'popover' → AnchoredPopoverOverlay subclass (anchored next to\n *               the action button, canvas stays interactive).\n *               Best for quick edits without losing context.\n */\nvar SURFACE_MODE = {\n  crop: 'popover',\n  // ← change to 'popup' to flip Crop to modal\n  resize: 'popover',\n  // ← change to 'popup' to flip Resize to modal\n  effects: 'popover',\n  // ← change to 'popup' to flip Effects to modal\n  link: 'popover' // ← change to 'popup' to flip Link to modal (restore BuilderjsPopup.prompt)\n};\nvar EDIT_MODE = {\n  crop: {\n    popup: 'crop',\n    popover: 'crop-popover'\n  },\n  resize: {\n    popup: 'resize',\n    popover: 'resize-popover'\n  },\n  effects: {\n    popup: 'effects',\n    popover: 'effects-popover'\n  },\n  link: {\n    popup: 'link',\n    popover: 'link-popover'\n  }\n};\nvar ImageActionsOverlay = /*#__PURE__*/function (_FloatingActionBarOve) {\n  function ImageActionsOverlay(element) {\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, ImageActionsOverlay);\n    return _callSuper(this, ImageActionsOverlay, [element, Object.assign({\n      anchor: 'top-right'\n    }, opts)]);\n  }\n  _inherits(ImageActionsOverlay, _FloatingActionBarOve);\n  return _createClass(ImageActionsOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"getButtons\",\n    value: function getButtons() {\n      var _this = this;\n      return [{\n        icon: 'upload',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.upload', 'Upload'),\n        onClick: function onClick() {\n          return _this._triggerUpload();\n        }\n      },\n      // 2026-04-19 — replaced \"Replace\" (which duplicated Upload) with\n      // \"Effects\" so the action bar covers all five distinct image\n      // operations: Upload · Effects · Resize · Crop · Link. Each\n      // edit-mode action opens via the SURFACE_MODE map so users get\n      // a coherent Image edit surface.\n      {\n        icon: 'wand_shine',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.effects', 'Effects'),\n        onClick: function onClick(e) {\n          return _this._enterAction('effects', e);\n        }\n      }, {\n        icon: 'open_in_full',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize', 'Resize'),\n        onClick: function onClick(e) {\n          return _this._enterAction('resize', e);\n        }\n      }, {\n        icon: 'crop',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop', 'Crop'),\n        onClick: function onClick(e) {\n          return _this._enterAction('crop', e);\n        }\n      }, {\n        icon: 'link',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.link', 'Link'),\n        onClick: function onClick(e) {\n          return _this._enterAction('link', e);\n        }\n      }];\n    }\n\n    /** Enter the edit mode for `action` ('crop' | 'resize') using the\n     *  surface ('popup' | 'popover') configured in SURFACE_MODE.\n     *  Records the action button rect so the anchored variant can\n     *  position itself next to the click target. */\n  }, {\n    key: \"_enterAction\",\n    value: function _enterAction(action, e) {\n      if (typeof this.element.enterEditMode !== 'function') return;\n      var surface = SURFACE_MODE[action] || 'popup';\n      var editMode = EDIT_MODE[action][surface];\n      // Stash anchor rect for the popover variant — read at\n      // popover.position() time. The action button is e.currentTarget.\n      if (e && e.currentTarget && typeof e.currentTarget.getBoundingClientRect === 'function') {\n        this.element._lastActionAnchorRect = e.currentTarget.getBoundingClientRect();\n      } else {\n        this.element._lastActionAnchorRect = null;\n      }\n      this.element.enterEditMode(editMode);\n    }\n  }, {\n    key: \"_triggerUpload\",\n    value: function _triggerUpload() {\n      var _this2 = this;\n      var input = document.createElement('input');\n      input.type = 'file';\n      input.accept = 'image/*';\n      input.style.display = 'none';\n      input.addEventListener('change', function (e) {\n        var file = e.target.files && e.target.files[0];\n        if (!file) return;\n        // Size guard — refuse files > 10MB (spec'd in failure-state audit;\n        // matches host app convention; emit console.warn for visibility).\n        var MAX_BYTES = 10 * 1024 * 1024;\n        if (file.size > MAX_BYTES) {\n          // eslint-disable-next-line no-console\n          console.warn('[overlay] image upload >10MB refused:', file.size, 'bytes');\n          return;\n        }\n        // MIME guard — refuse non-image (input accept=\"image/*\" is advisory only).\n        if (!/^image\\//.test(file.type || '')) {\n          // eslint-disable-next-line no-console\n          console.warn('[overlay] image upload rejected — not an image:', file.type);\n          return;\n        }\n        var reader = new FileReader();\n        reader.onload = function () {\n          _this2.element.src = reader.result;\n          if (typeof _this2.element.render === 'function') _this2.element.render();\n          // Dual-view sync (SA invariant I4): patch sidebar preview\n          // in place. Pattern parallels the ImageCropInlineOverlay\n          // sync established in Phase 1.4 (D33). NO renderElementControls\n          // (NO-FLICKER, SA invariant I9) — `syncFromExternal` patches\n          // <img src> + filename + dimensions in the existing DOM.\n          _this2._syncSidebar();\n        };\n        reader.onerror = function () {\n          // eslint-disable-next-line no-console\n          console.error('[overlay] image upload FileReader error:', reader.error);\n        };\n        reader.readAsDataURL(file);\n      });\n      document.body.appendChild(input);\n      input.click();\n      // Clean up input node after click — file picker keeps working via closure.\n      setTimeout(function () {\n        if (input.parentNode) input.parentNode.removeChild(input);\n      }, 0);\n    }\n  }, {\n    key: \"_enterCrop\",\n    value: function _enterCrop() {\n      if (typeof this.element.enterEditMode === 'function') {\n        this.element.enterEditMode('crop');\n      }\n    }\n\n    /**\n     * Notify the sidebar's ImageControl (if mounted) that this element's\n     * `src` / `alt` changed via the overlay. Looks the control up on the\n     * shared `builder._activeControls.image` slot — set at construction\n     * time by every ImageControl instance. Same pattern as the\n     * ImageCropInlineOverlay → ImageCropControl sync established in\n     * Phase 1.4 (D33). No-op when no sidebar control is currently mounted\n     * (e.g. element has just been deselected — overlay still alive\n     * mid-upload).\n     */\n  }, {\n    key: \"_syncSidebar\",\n    value: function _syncSidebar() {\n      var _this$host;\n      var ctrl = (_this$host = this.host) === null || _this$host === void 0 || (_this$host = _this$host._activeControls) === null || _this$host === void 0 ? void 0 : _this$host.image;\n      if (ctrl && typeof ctrl.syncFromExternal === 'function') {\n        ctrl.syncFromExternal({\n          src: this.element.src,\n          alt: this.element.alt\n        });\n      }\n    }\n\n    /* The Link action is now an edit-mode entrypoint via `_enterAction('link', e)`\n     * — LinkPopoverOverlay handles apply/cancel + sidebar refresh. Flip back\n     * to the modal popup: set SURFACE_MODE.link = 'popup' + restore a\n     * BuilderjsPopup.prompt({ title, label, value, placeholder, kind })\n     * method here for the 'popup' branch. */\n  }]);\n}(_FloatingActionBarOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageActionsOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageActionsOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageCropInlineOverlay.js":
/*!*********************************************************!*\
  !*** ./src/includes/overlays/ImageCropInlineOverlay.js ***!
  \*********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./InlineEditorOverlay.js */ \"./src/includes/overlays/InlineEditorOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageCropInlineOverlay — 2026-04-19 (refactored to embed the real\n * ImageCropControl per IMAGE_OVERLAY_REFACTOR_PLAN.md Phase C).\n *\n * Modal \"Crop image\" popup mounted by ImageActionsOverlay's Crop action.\n * The popup body EMBEDS the same ImageCropControl the sidebar uses —\n * single source of truth for the rich crop UI (preview with focus dot,\n * aspect chips, custom ratio input, zoom slider, focus X/Y sliders,\n * reset button). Multiple instances of the control coexist (sidebar +\n * this popup); both subscribe to element.crop via `addSyncListener` so\n * any mutation in either surface re-syncs the other live (SA I13 R3).\n *\n * Body composition:\n *   1. Header — \"Crop image\" + crop icon.\n *   2. Embedded ImageCropControl (the entire rich UI from the sidebar).\n *   3. Footer — Cancel / Done. Cancel reverts element.crop to the\n *      pre-edit snapshot (Object.assign in place — preserves the live\n *      reference held by sidebar control's _sourceValueRef.crop).\n *\n * The previous implementation duplicated a stripped-down toggle + chip\n * grid + info banner inline. That divergence was the source of \"two\n * places to maintain crop UI\" complaints. After refactor, adding any\n * crop feature happens in ImageCropControl alone — sidebar + popup\n * pick it up automatically.\n *\n * Lifecycle: embedded control is destroyed in beforeDestroy() so its\n * subscribe disposer fires (SA I14).\n *\n * NO-FLICKER (SA I9): every mutation routes through the embedded\n * control's setCrop callback → element.render() → notifySyncListeners.\n * NEVER builder.renderElementControls in any path.\n */\n\n\nvar ImageCropInlineOverlay = /*#__PURE__*/function (_InlineEditorOverlay) {\n  function ImageCropInlineOverlay() {\n    _classCallCheck(this, ImageCropInlineOverlay);\n    return _callSuper(this, ImageCropInlineOverlay, arguments);\n  }\n  _inherits(ImageCropInlineOverlay, _InlineEditorOverlay);\n  return _createClass(ImageCropInlineOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'edit';\n    }\n  }, {\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'crop';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageCropInlineOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-image-crop-mask');\n      this.domNode.setAttribute('aria-modal', 'true');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-crop-title');\n\n      // Snapshot pre-edit state for Cancel revert.\n      this._snapshot = this._cloneCrop(this.element.crop);\n      this._embedded = null;\n      var panel = document.createElement('div');\n      panel.className = 'bjs-ovl-image-crop-panel';\n      panel.setAttribute('data-interactive', '');\n      panel.appendChild(this._renderHeader());\n\n      // Scrollable body — embed the real ImageCropControl.\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-image-crop-body';\n      body.appendChild(this._renderEmbeddedControl());\n      panel.appendChild(body);\n      panel.appendChild(this._renderFooter());\n      this.domNode.appendChild(panel);\n      this._panel = panel;\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      if (this._embedded && typeof this._embedded.destroy === 'function') {\n        try {\n          this._embedded.destroy();\n        } catch (_) {/* no-op */}\n      }\n      this._embedded = null;\n    }\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {\n      var _this = this;\n      // First focus → the crop toggle inside the embedded control. The\n      // ImageCropControl renders an <input class=\"icrop-toggle-input\">\n      // checkbox at the top of its DOM.\n      requestAnimationFrame(function () {\n        var toggle = _this.domNode.querySelector('.icrop-toggle-input');\n        if (toggle && typeof toggle.focus === 'function') toggle.focus();\n      });\n    }\n\n    // ────────────────────────── Sub-renderers ─────────────────────────────\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-image-crop-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'crop';\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-image-crop-title';\n      title.id = 'bjs-ovl-image-crop-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_title', 'Crop image');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_renderEmbeddedControl\",\n    value: function _renderEmbeddedControl() {\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-image-crop-embed';\n      // ImageElement.buildCropControl() returns a fresh, sync-aware\n      // instance. The popup never knows the internal DOM shape — it\n      // just appends the control's domNode. When the user mutates\n      // anything (toggle, chip, slider, reset), the control's\n      // setCrop callback fires → element.render() →\n      // notifySyncListeners → sidebar instance + this instance both\n      // re-sync via syncFromExternal.\n      this._embedded = this.element.buildCropControl();\n      if (this._embedded && this._embedded.domNode) {\n        wrap.appendChild(this._embedded.domNode);\n      }\n      return wrap;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this2 = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-image-crop-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this2._cancel();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this2._apply();\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n\n    // ────────────────────────── State actions ─────────────────────────────\n  }, {\n    key: \"_cloneCrop\",\n    value: function _cloneCrop(c) {\n      if (!c) return null;\n      return {\n        enabled: !!c.enabled,\n        ratioX: c.ratioX,\n        ratioY: c.ratioY,\n        zoom: c.zoom,\n        posX: c.posX,\n        posY: c.posY\n      };\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      // Revert via Object.assign IN PLACE so the sidebar control's\n      // _sourceValueRef.crop reference stays valid (SA I13 R1).\n      if (!this.element.crop) {\n        this.element.crop = {\n          enabled: false,\n          ratioX: 3,\n          ratioY: 2,\n          zoom: 1,\n          posX: 50,\n          posY: 50\n        };\n      }\n      if (this._snapshot) {\n        Object.assign(this.element.crop, this._snapshot);\n      } else {\n        Object.assign(this.element.crop, {\n          enabled: false,\n          ratioX: 3,\n          ratioY: 2,\n          zoom: 1,\n          posX: 50,\n          posY: 50\n        });\n      }\n      if (typeof this.element.render === 'function') this.element.render();\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }]);\n}(_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageCropInlineOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageCropInlineOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageCropPopoverOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/ImageCropPopoverOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageCropPopoverOverlay — 2026-04-19 (Phase E).\n *\n * Anchored popover variant of ImageCropInlineOverlay. Same body\n * (embedded ImageCropControl), different surface chrome — popover\n * anchored next to the action-bar Crop button rather than full-viewport\n * modal. Mounted via `enterEditMode('crop-popover')` so the standard\n * mode filter routes it correctly.\n */\n\n\nvar ImageCropPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n  function ImageCropPopoverOverlay() {\n    _classCallCheck(this, ImageCropPopoverOverlay);\n    return _callSuper(this, ImageCropPopoverOverlay, arguments);\n  }\n  _inherits(ImageCropPopoverOverlay, _AnchoredPopoverOverl);\n  return _createClass(ImageCropPopoverOverlay, [{\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'crop-popover';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageCropPopoverOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-image-crop-popover');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-crop-popover-title');\n\n      // Snapshot for Cancel revert.\n      this._snapshot = this._cloneCrop(this.element.crop);\n      this._embedded = null;\n      this.domNode.appendChild(this._renderHeader());\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-image-crop-popover-body bjs-ovl-image-crop-body';\n      // Embed the same ImageCropControl factory as the modal popup.\n      // Two surfaces, one control class — they auto-sync via subscribe.\n      this._embedded = this.element.buildCropControl();\n      if (this._embedded && this._embedded.domNode) {\n        body.appendChild(this._embedded.domNode);\n      }\n      this.domNode.appendChild(body);\n      this.domNode.appendChild(this._renderFooter());\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      _superPropGet(ImageCropPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n      if (this._embedded && typeof this._embedded.destroy === 'function') {\n        try {\n          this._embedded.destroy();\n        } catch (_) {/* no-op */}\n      }\n      this._embedded = null;\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-image-crop-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'crop';\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-image-crop-title';\n      title.id = 'bjs-ovl-image-crop-popover-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_title', 'Crop image');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-image-crop-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._cancel();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._apply();\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n  }, {\n    key: \"_cloneCrop\",\n    value: function _cloneCrop(c) {\n      if (!c) return null;\n      return {\n        enabled: !!c.enabled,\n        ratioX: c.ratioX,\n        ratioY: c.ratioY,\n        zoom: c.zoom,\n        posX: c.posX,\n        posY: c.posY\n      };\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      if (!this.element.crop) {\n        this.element.crop = {\n          enabled: false,\n          ratioX: 3,\n          ratioY: 2,\n          zoom: 1,\n          posX: 50,\n          posY: 50\n        };\n      }\n      if (this._snapshot) {\n        Object.assign(this.element.crop, this._snapshot);\n      } else {\n        Object.assign(this.element.crop, {\n          enabled: false,\n          ratioX: 3,\n          ratioY: 2,\n          zoom: 1,\n          posX: 50,\n          posY: 50\n        });\n      }\n      if (typeof this.element.render === 'function') this.element.render();\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageCropPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageCropPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageEdgeResizerOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/ImageEdgeResizerOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./EdgeResizerOverlay.js */ \"./src/includes/overlays/EdgeResizerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageEdgeResizerOverlay — 2026-04-19 (aspect-lock visibility gating)\n *\n * Single-axis resize handle on a named edge of a selected ImageElement.\n *   - 'left' / 'right' edges → drag adjusts WIDTH only (height unchanged).\n *   - 'top' / 'bottom' edges → drag adjusts HEIGHT only (width unchanged).\n *\n * Edges are the **distortion affordance** — the only way to deliberately\n * squash/stretch the image (or crop frame, when crop is on). Corners are\n * the \"nice resize\" affordance and always preserve the current aspect.\n *\n * Design contract — the popover \"Lock aspect ratio\" toggle governs edge\n * **visibility** only; drag math is unchanged (always single-axis, always\n * distorts when the user drags):\n *   - LOCK ON (element._aspectLocked === true, the default) — edges are\n *     HIDDEN. Enforcement surface: the toggle promises \"my proportions\n *     are protected\", so the app removes the distortion handles to keep\n *     that promise. Corners stay visible and ratio-preserving.\n *   - LOCK OFF — edges visible; user can distort freely per axis. Corners\n *     still stay ratio-preserving (corners have fixed semantics — the\n *     toggle does NOT flip corner drag behavior).\n *\n * Works identically whether crop is on (drag resizes the crop FRAME) or\n * off (drag resizes the IMAGE) — the formatter writes affect width/height\n * on the element's wrapper, and `_getHighlightTarget()` routes positioning\n * to the visible target. Mental model: \"edges distort whatever you see.\"\n *\n * Visibility is driven reactively by subscribing to the element's sync\n * listener channel in `afterMount()` and flipping `display` on the domNode\n * whenever `_aspectLocked` changes. Mount is unconditional so toggling the\n * lock in either direction is immediately reflected without re-entering\n * the overlay mount/destroy cycle. Disposer fires in `beforeDestroy` so\n * the sync-listener Map stays bounded across selection cycles (SA I14).\n *\n * Trigger: `'select'`. Four instances mounted per selected image.\n *\n * Width/height format: same auto-promote pattern as the corner overlay —\n * first drag from `'auto'` / unset / non-px writes back as `Npx`; subsequent\n * drags work in pixels until the user changes the unit via the sidebar\n * DimensionControl or the new ResizeInline overlay.\n *\n * NO-FLICKER (SA I9): `formatter.setFormat + applyFormatStyles` per frame\n * if available, else `element.render()`. Never `renderElementControls`.\n *\n * See docs/core/OVERLAY.md §7.2 (Image overlays).\n */\n\nvar HORIZONTAL = ['left', 'right'];\nvar ImageEdgeResizerOverlay = /*#__PURE__*/function (_EdgeResizerOverlay) {\n  function ImageEdgeResizerOverlay(element) {\n    var _this;\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, ImageEdgeResizerOverlay);\n    _this = _callSuper(this, ImageEdgeResizerOverlay, [element, opts]);\n    _this._lockListenerId = null;\n    _this._lockDisposer = null;\n    return _this;\n  }\n  _inherits(ImageEdgeResizerOverlay, _EdgeResizerOverlay);\n  return _createClass(ImageEdgeResizerOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageEdgeResizerOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-image-handle');\n      this.domNode.classList.add('bjs-ovl-image-handle--edge');\n      this.domNode.classList.add(\"bjs-ovl-image-handle--edge-\".concat(this.opts.edge));\n    }\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {\n      var _this2 = this;\n      // Subscribe to element-state changes so toggling aspect-lock\n      // (popover or inline overlay) flips edge visibility on the next\n      // frame. Listener name is per-instance so all four edges coexist\n      // in the sync Map without stomping.\n      this._lockListenerId = \"ImageEdgeResizer:\".concat(this.opts.edge, \":\").concat(Math.random().toString(36).slice(2, 7));\n      this._lockDisposer = this.element.addSyncListener(this._lockListenerId, function () {\n        return _this2._refreshLockVisibility();\n      });\n      this._refreshLockVisibility();\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      var _superPropGet2;\n      if (typeof this._lockDisposer === 'function') {\n        try {\n          this._lockDisposer();\n        } catch (_) {/* no-op */}\n      }\n      this._lockDisposer = null;\n      this._lockListenerId = null;\n      (_superPropGet2 = _superPropGet(ImageEdgeResizerOverlay, \"beforeDestroy\", this, 3)) === null || _superPropGet2 === void 0 || _superPropGet2([]);\n    }\n\n    /** Toggle edge visibility based on element._aspectLocked. Default is\n     *  LOCK ON (undefined → treated as locked via !==false), so a fresh\n     *  selection hides the edges until the user opts into free distortion. */\n  }, {\n    key: \"_refreshLockVisibility\",\n    value: function _refreshLockVisibility() {\n      if (!this.domNode) return;\n      var locked = this.element._aspectLocked !== false;\n      this.domNode.style.display = locked ? 'none' : '';\n      // When coming back into view, refresh the position — observers\n      // keep the transform live during a session, but a resize-before-\n      // unhide edge case would leave stale coords if we relied on that\n      // alone.\n      if (!locked) this.position();\n    }\n\n    /** Override edge primitive's element-wrapper-hugging position with one\n     *  that hugs the visible image. Same rationale as\n     *  ImageResizeCornerOverlay.position() — wrapper is wider than image\n     *  when parent has padding / alignment, so handles sit off-image. */\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this3 = this;\n      var edge = this.opts.edge || 'right';\n      var THICK = 6;\n      // Read `_visualTarget()` INSIDE the callback so the closure\n      // never holds a stale DOM reference after ImageElement re-render\n      // replaces the inner <img>. See ImageResizeCornerOverlay.position\n      // for the full root-cause story (2026-04-19 user report: \"after\n      // resize popup closes anchors don't show\").\n      this.element.matchingDomNode(this.domNode, 0, function () {\n        var target = _this3._visualTarget();\n        if (!target) return;\n        var r = target.getBoundingClientRect();\n        var iframe = target.ownerDocument.defaultView.frameElement;\n        var ir = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var absTop = ir.top + r.top;\n        var absLeft = ir.left + r.left;\n        var style = {\n          position: 'fixed'\n        };\n        if (edge === 'left') Object.assign(style, {\n          top: absTop + 'px',\n          left: absLeft - THICK / 2 + 'px',\n          width: THICK + 'px',\n          height: r.height + 'px'\n        });else if (edge === 'right') Object.assign(style, {\n          top: absTop + 'px',\n          left: absLeft + r.width - THICK / 2 + 'px',\n          width: THICK + 'px',\n          height: r.height + 'px'\n        });else if (edge === 'top') Object.assign(style, {\n          top: absTop - THICK / 2 + 'px',\n          left: absLeft + 'px',\n          width: r.width + 'px',\n          height: THICK + 'px'\n        });else Object.assign(style, {\n          top: absTop + r.height - THICK / 2 + 'px',\n          left: absLeft + 'px',\n          width: r.width + 'px',\n          height: THICK + 'px'\n        });\n        Object.assign(_this3.domNode.style, style);\n      });\n    }\n  }, {\n    key: \"_visualTarget\",\n    value: function _visualTarget() {\n      if (typeof this.element._getHighlightTarget === 'function') {\n        return this.element._getHighlightTarget();\n      }\n      return this.element.domNode;\n    }\n  }, {\n    key: \"onDragStart\",\n    value: function onDragStart(/* e */\n    ) {\n      var tgt = this._visualTarget() || this.element.domNode;\n      var rect = tgt.getBoundingClientRect();\n      this._dragStartRect = {\n        width: rect.width,\n        height: rect.height\n      };\n      var isHorizontal = HORIZONTAL.includes(this.opts.edge);\n      var fmtKey = isHorizontal ? 'width' : 'height';\n      var raw = this.element.formatter.getFormat(fmtKey);\n      var str = raw == null ? '' : String(raw).trim();\n      if (/%$/.test(str)) {\n        this._dragUnit = '%';\n        var parent = this.element.domNode.parentElement;\n        this._dragParentSize = isHorizontal ? parent ? parent.getBoundingClientRect().width : rect.width : parent ? parent.getBoundingClientRect().height : rect.height;\n      } else {\n        // auto / fill / px / em / unset → first drag promotes to Npx.\n        this._dragUnit = 'px';\n      }\n    }\n  }, {\n    key: \"onDrag\",\n    value: function onDrag(dx, dy /*, e */) {\n      if (!this._dragStartRect) return;\n      var edge = this.opts.edge;\n      // Edge → axis + sign:\n      //   left   → -dx grows width   (drag left = bigger when on left edge)\n      //   right  → +dx grows width\n      //   top    → -dy grows height\n      //   bottom → +dy grows height\n      var newPx;\n      var fmtKey;\n      if (edge === 'right') {\n        newPx = this._dragStartRect.width + dx;\n        fmtKey = 'width';\n      } else if (edge === 'left') {\n        newPx = this._dragStartRect.width - dx;\n        fmtKey = 'width';\n      } else if (edge === 'bottom') {\n        newPx = this._dragStartRect.height + dy;\n        fmtKey = 'height';\n      } else {\n        // top\n        newPx = this._dragStartRect.height - dy;\n        fmtKey = 'height';\n      }\n\n      // Clamp to a sane minimum (below ~16px the image is practically invisible\n      // and the handle stack collapses). Image-specific minimum, larger than\n      // the generic 5px corner clamp because edges deliberately allow non-\n      // aspect-preserved distortion and tiny dimensions would be a UX trap.\n      newPx = Math.max(16, newPx);\n      var serialized;\n      if (this._dragUnit === '%' && this._dragParentSize > 0) {\n        var pct = newPx / this._dragParentSize * 100;\n        serialized = pct.toFixed(2).replace(/\\.00$/, '') + '%';\n      } else {\n        serialized = Math.round(newPx) + 'px';\n      }\n      this.element.formatter.setFormat(fmtKey, serialized);\n      if (typeof this.element.applyFormatStyles === 'function') {\n        this.element.applyFormatStyles();\n      } else if (typeof this.element.render === 'function') {\n        this.element.render();\n      }\n    }\n  }, {\n    key: \"onDragEnd\",\n    value: function onDragEnd(/* e */\n    ) {\n      this._dragStartRect = null;\n      this._dragUnit = 'px';\n      this._dragParentSize = 0;\n    }\n  }]);\n}(_EdgeResizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageEdgeResizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageEdgeResizerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageEffectPopoverOverlay.js":
/*!************************************************************!*\
  !*** ./src/includes/overlays/ImageEffectPopoverOverlay.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageEffectPopoverOverlay — 2026-04-19 (Phase E expansion).\n *\n * Anchored popover for image effects (filters: grayscale, sepia, invert,\n * blur, brightness, contrast, saturate, hue-rotate, opacity). Mounted by\n * ImageActionsOverlay's \"Effects\" action when SURFACE_MODE.effects ===\n * 'popover'. Embeds the same ImageEffectControl factory the sidebar\n * uses — single source of truth for the slider math + preview render +\n * reset logic. Multi-surface sync via subscribe (SA I13).\n *\n * Anatomy:\n *   1. Header — \"Effects\" + tune icon.\n *   2. Embedded ImageEffectControl (preview thumbnail + 9 slider rows\n *      with reset buttons + \"Reset all\" footer button).\n *   3. Footer — Cancel / Done. Cancel reverts element.effect to the\n *      pre-edit snapshot (Object.assign in place — preserves the live\n *      reference any other surface holds).\n *\n * Mode: 'effects-popover'. Modal counterpart 'effects' is reserved for\n * future SURFACE_MODE.effects = 'popup' switching.\n */\n\n\nvar ImageEffectPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n  function ImageEffectPopoverOverlay() {\n    _classCallCheck(this, ImageEffectPopoverOverlay);\n    return _callSuper(this, ImageEffectPopoverOverlay, arguments);\n  }\n  _inherits(ImageEffectPopoverOverlay, _AnchoredPopoverOverl);\n  return _createClass(ImageEffectPopoverOverlay, [{\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'effects-popover';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageEffectPopoverOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-image-effect-popover');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-effect-popover-title');\n\n      // Snapshot for Cancel revert (clone — no shared mutation).\n      this._snapshot = Object.assign({}, this.element.effect);\n      this._embedded = null;\n      this.domNode.appendChild(this._renderHeader());\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-image-effect-popover-body bjs-ovl-image-crop-body';\n      // Embed the SAME ImageEffectControl the sidebar uses. Both\n      // instances subscribe to element.effect via the factory's\n      // capability token and stay in sync via syncFromExternal.\n      this._embedded = this.element.buildEffectControl();\n      if (this._embedded && this._embedded.domNode) {\n        body.appendChild(this._embedded.domNode);\n      }\n      this.domNode.appendChild(body);\n      this.domNode.appendChild(this._renderFooter());\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      _superPropGet(ImageEffectPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n      if (this._embedded && typeof this._embedded.destroy === 'function') {\n        try {\n          this._embedded.destroy();\n        } catch (_) {/* no-op */}\n      }\n      this._embedded = null;\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-image-crop-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'wand_shine';\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-image-crop-title';\n      title.id = 'bjs-ovl-image-effect-popover-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.effects', 'Effects');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-image-crop-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._cancel();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._apply();\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      // Revert effect via Object.assign in place — preserves the\n      // reference held by any concurrent surface (sidebar, etc).\n      if (this._snapshot) {\n        Object.assign(this.element.effect, this._snapshot);\n      }\n      if (typeof this.element.render === 'function') this.element.render();\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageEffectPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageEffectPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageResizeCornerOverlay.js":
/*!***********************************************************!*\
  !*** ./src/includes/overlays/ImageResizeCornerOverlay.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ResizeCornerOverlay.js */ \"./src/includes/overlays/ResizeCornerOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageResizeCornerOverlay — Phase 1.4\n *\n * Draggable corner handle (nw / ne / se / sw) on a selected image. Drag\n * updates `width` + `height` formatter values proportionally — corners are\n * **always** aspect-locked regardless of the popover \"Lock aspect ratio\"\n * toggle (design contract, matches Figma/Photoshop/Canva — corners are\n * the \"nice resize\" affordance, edges are the \"deliberate distort\"\n * affordance). The toggle affects the popover Width/Height INPUTS only;\n * canvas handles have fixed semantics so muscle memory works the same\n * whether the toggle is on or off, whether crop is on or off.\n *\n * The preserved ratio is the **current** rendered aspect captured at drag\n * start (`rect.width / rect.height`) — dragging preserves whatever\n * proportion the user is looking at right now, including after prior\n * edge-drag distortion. To restore the original natural ratio, the user\n * flips the lock on in the popover and edits the inputs.\n *\n * Uses the ResizeCornerOverlay primitive for positioning + cursor; subclasses\n * only the drag-math callbacks.\n *\n * Trigger: 'select'. Four instances mounted per selected image.\n *\n * Width format: respects existing unit convention. Reads current\n * `formatter.getFormat('width')` string; if it's \"%\" based, treats dragging as\n * relative to parent width; if \"px\" based, absolute px. Falls back to px.\n *\n * NO-FLICKER (I9): `formatter.setFormat + applyFormatStyles` per frame if\n * available, else `element.render()`.\n *\n * See docs/core/OVERLAY.md §7.2 + docs/archived/OVERLAY_PLAN.md §3.5.\n */\n\nvar ImageResizeCornerOverlay = /*#__PURE__*/function (_ResizeCornerOverlay) {\n  function ImageResizeCornerOverlay(element) {\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, ImageResizeCornerOverlay);\n    // `aspectLock: true` is the fixed design contract for image\n    // corners — see header rationale. Not derived from element state.\n    return _callSuper(this, ImageResizeCornerOverlay, [element, Object.assign({\n      aspectLock: true\n    }, opts)]);\n  }\n  _inherits(ImageResizeCornerOverlay, _ResizeCornerOverlay);\n  return _createClass(ImageResizeCornerOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageResizeCornerOverlay, \"render\", this, 3)([]);\n      // Image-specific class so styling diverges from generic `.bjs-ovl-resize-corner`\n      // (warm accent + rounder handle) without forking the primitive.\n      this.domNode.classList.add('bjs-ovl-image-handle');\n      this.domNode.classList.add('bjs-ovl-image-handle--corner');\n    }\n\n    /** Override the primitive's element-wrapper-hugging position with one\n     *  that hugs the actual VISIBLE IMAGE (the `<img>` inside the wrapper,\n     *  or the crop wrapper when crop is enabled). Without this the corners\n     *  sit on the wrapper edge — which is wider than the image when the\n     *  parent has padding or auto-centers — and the user sees a gap\n     *  between the image edge and the handle. Mirrors the same trick\n     *  ImageElement.addSelectedHighlight uses for `image-highlight-box`. */\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this = this;\n      var corner = this.opts.corner || 'se';\n      // Read `_visualTarget()` INSIDE the callback (not outside) — the\n      // inner <img> / crop wrapper gets replaced whenever ImageElement\n      // re-renders (popup mutations, sidebar edits, programmatic\n      // setFormat). Capturing the target outside leaves the closure\n      // holding a detached DOM node whose getBoundingClientRect\n      // returns zeros — handles position at (0,0) and visually\n      // disappear off-canvas. (User report 2026-04-19: \"after resize\n      // popup closes, anchors don't show; click re-shows them\" — the\n      // re-click triggered fresh select-mount which re-evaluated the\n      // target, masking the stale-closure root cause.)\n      this.element.matchingDomNode(this.domNode, 0, function () {\n        var target = _this._visualTarget();\n        if (!target) return;\n        var r = target.getBoundingClientRect();\n        var iframe = target.ownerDocument.defaultView.frameElement;\n        var ir = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var half = 7; // half of CSS handle size (14)\n        var absTop = ir.top + r.top;\n        var absLeft = ir.left + r.left;\n        var top, left;\n        switch (corner) {\n          case 'nw':\n            top = absTop - half;\n            left = absLeft - half;\n            break;\n          case 'ne':\n            top = absTop - half;\n            left = absLeft + r.width - half;\n            break;\n          case 'sw':\n            top = absTop + r.height - half;\n            left = absLeft - half;\n            break;\n          case 'se':\n          default:\n            top = absTop + r.height - half;\n            left = absLeft + r.width - half;\n            break;\n        }\n        Object.assign(_this.domNode.style, {\n          position: 'fixed',\n          top: top + 'px',\n          left: left + 'px'\n        });\n      });\n    }\n  }, {\n    key: \"_visualTarget\",\n    value: function _visualTarget() {\n      if (typeof this.element._getHighlightTarget === 'function') {\n        return this.element._getHighlightTarget();\n      }\n      return this.element.domNode;\n    }\n  }, {\n    key: \"onDragStart\",\n    value: function onDragStart(/* e */\n    ) {\n      var tgt = this._visualTarget() || this.element.domNode;\n      var rect = tgt.getBoundingClientRect();\n      this._dragStartRect = {\n        width: rect.width,\n        height: rect.height\n      };\n      this._dragAspect = rect.height > 0 ? rect.width / rect.height : 1;\n      // Detect unit from current width format. Treat unset / 'auto' as px\n      // so first-time drag always works (auto-promote pattern, mirrors\n      // GridColumnResizeOverlay 2026-04-19 fix).\n      var wFmt = this.element.formatter.getFormat('width');\n      var wStr = wFmt == null ? '' : String(wFmt).trim();\n      if (/%$/.test(wStr)) {\n        this._dragUnit = '%';\n        var parent = this.element.domNode.parentElement;\n        this._dragParentWidth = parent ? parent.getBoundingClientRect().width : rect.width;\n        this._dragStartPct = parseFloat(wStr) || 100;\n      } else {\n        // 'auto' / 'fill' / unset / 'px' / 'em' etc → drag in px against\n        // the rendered rect. The setFormat below writes 'Npx' which\n        // makes subsequent drags trivially in-range.\n        this._dragUnit = 'px';\n      }\n    }\n  }, {\n    key: \"onDrag\",\n    value: function onDrag(dx, dy /*, e */) {\n      if (!this._dragStartRect) return;\n      var corner = this.opts.corner || 'se';\n      // Translate drag direction per corner. SE grows with (+dx, +dy);\n      // NW shrinks with (+dx, +dy); NE = +dx, -dy; SW = -dx, +dy.\n      var dirX = corner === 'ne' || corner === 'se' ? 1 : -1;\n      var dirY = corner === 'se' || corner === 'sw' ? 1 : -1;\n      var newWidthPx = this._dragStartRect.width + dirX * dx;\n      var newHeightPx = this._dragStartRect.height + dirY * dy;\n\n      // Aspect-lock — corners are ALWAYS aspect-preserving (fixed\n      // design contract per docs/core/OVERLAY.md §7.2; decoupled from the\n      // popover's `_aspectLocked` toggle, which only governs the\n      // Width/Height inputs + edge-handle visibility). Width dominates\n      // (typical resize gestures are horizontal-first).\n      if (this.opts.aspectLock !== false && this._dragAspect > 0) {\n        newHeightPx = newWidthPx / this._dragAspect;\n      }\n\n      // Clamp to 20px minimum (below that the handles crowd each other).\n      newWidthPx = Math.max(20, newWidthPx);\n      newHeightPx = Math.max(20, newHeightPx);\n      var newWidthStr, newHeightStr;\n      if (this._dragUnit === '%' && this._dragParentWidth > 0) {\n        var pct = newWidthPx / this._dragParentWidth * 100;\n        newWidthStr = pct.toFixed(2).replace(/\\.00$/, '') + '%';\n        // Height: keep px for % width (common pattern: \"width: 50%; height: auto\" —\n        // here we force a numeric height to preserve the dragged aspect).\n        newHeightStr = Math.round(newHeightPx) + 'px';\n      } else {\n        newWidthStr = Math.round(newWidthPx) + 'px';\n        newHeightStr = Math.round(newHeightPx) + 'px';\n      }\n      this.element.formatter.setFormat('width', newWidthStr);\n      this.element.formatter.setFormat('height', newHeightStr);\n      // NO-FLICKER: prefer applyFormatStyles, fall back to render.\n      if (typeof this.element.applyFormatStyles === 'function') {\n        this.element.applyFormatStyles();\n      } else if (typeof this.element.render === 'function') {\n        this.element.render();\n      }\n    }\n  }, {\n    key: \"onDragEnd\",\n    value: function onDragEnd(/* e */\n    ) {\n      this._dragStartRect = null;\n      this._dragAspect = 0;\n      this._dragUnit = 'px';\n      this._dragParentWidth = 0;\n    }\n  }]);\n}(_ResizeCornerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageResizeCornerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageResizeCornerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageResizeInlineOverlay.js":
/*!***********************************************************!*\
  !*** ./src/includes/overlays/ImageResizeInlineOverlay.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./InlineEditorOverlay.js */ \"./src/includes/overlays/InlineEditorOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageResizeInlineOverlay — 2026-04-19 (refactored to embed real\n * DimensionControl instances per IMAGE_OVERLAY_REFACTOR_PLAN.md Phase C).\n *\n * Modal \"Resize image\" popup mounted by ImageActionsOverlay's Resize\n * action. The popup body EMBEDS the same DimensionControl instances the\n * sidebar uses — single source of truth for the input/slider/unit/preset\n * UI. Multiple instances of the same control coexist (sidebar + this\n * popup); both subscribe to element state via `addSyncListener` so any\n * mutation in either surface re-syncs the other live (SA I13 R3 + R4).\n *\n * Body composition (top to bottom):\n *   1. Image preview thumbnail — context for dimension changes.\n *   2. Width — embedded DimensionControl (full feature set: slider +\n *      input + unit dropdown + presets in dim-menu).\n *   3. Height — same.\n *   4. Aspect lock toggle — in-memory element state (`element._aspectLocked`,\n *      default ON). When ON, editing either width or height in the\n *      embedded DimensionControl couples the companion axis via\n *      `ImageElement._writeCoupledDimensions` using the crop/natural\n *      aspect ratio. State persists across popup open/close within the\n *      session (NOT serialized — saved templates stay free of UI\n *      preferences). See ImageElement.buildAspectLockRow for the shared\n *      row DOM + sync wiring.\n *   5. Crop-on hint banner — only when element.crop.enabled.\n *   6. Advanced collapsible — embeds 4 more DimensionControls\n *      (max_width, max_height, min_width, min_height).\n *\n * Footer: Cancel / Done. Cancel reverts the formatter to a snapshot\n * captured in render(); Done exits cleanly (mutations already committed\n * via the embedded DimensionControl onChange callbacks).\n *\n * Lifecycle: each embedded control is destroyed in beforeDestroy() so\n * its subscribe disposer fires and the element's listener Set stays\n * bounded across open/close cycles (SA I14 control lifecycle).\n *\n * NO-FLICKER (SA I9): every mutation routes through the embedded\n * control's onChange → element.setFormat → element.render() →\n * notifySyncListeners. NEVER builder.renderElementControls in any path.\n */\n\n\nvar ImageResizeInlineOverlay = /*#__PURE__*/function (_InlineEditorOverlay) {\n  function ImageResizeInlineOverlay() {\n    _classCallCheck(this, ImageResizeInlineOverlay);\n    return _callSuper(this, ImageResizeInlineOverlay, arguments);\n  }\n  _inherits(ImageResizeInlineOverlay, _InlineEditorOverlay);\n  return _createClass(ImageResizeInlineOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'edit';\n    }\n  }, {\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'resize';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageResizeInlineOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-image-crop-mask');\n      this.domNode.classList.add('bjs-ovl-image-resize-mask');\n      this.domNode.setAttribute('aria-modal', 'true');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-resize-title');\n\n      // Snapshot every formatter key the popup edits, so Cancel can\n      // revert the entire dimension set in one go.\n      this._snapshot = this._snapshotFormats();\n      this._aspectDisposer = null;\n      this._embeddedControls = [];\n      var panel = document.createElement('div');\n      panel.className = 'bjs-ovl-image-crop-panel bjs-ovl-image-resize-panel';\n      panel.setAttribute('data-interactive', '');\n      panel.appendChild(this._renderHeader());\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-image-crop-body';\n\n      // 1. Preview thumbnail — small image preserved-aspect thumb so the\n      // user keeps visual context while editing dimensions.\n      body.appendChild(this._renderPreview());\n\n      // 2 + 3. Width + Height — embedded DimensionControl instances.\n      // coupleAspect: true wires these to element._aspectLocked.\n      var widthSection = this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_width', 'Width'), 'width', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n        coupleAspect: true\n      }));\n      body.appendChild(widthSection);\n      var heightSection = this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_height', 'Height'), 'height', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n        coupleAspect: true\n      }));\n      body.appendChild(heightSection);\n\n      // 4. Aspect lock toggle — shared helper on ImageElement\n      // (single source of truth for DOM + state wiring).\n      var aspect = this.element.buildAspectLockRow({\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_aspect_lock', 'Lock aspect ratio'),\n        hint: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_aspect_hint', 'Editing one dimension updates the other proportionally.')\n      });\n      body.appendChild(aspect.row);\n      this._aspectDisposer = aspect.dispose;\n\n      // 5. Crop-on hint banner — observer pattern would be overkill for\n      // a single conditional render; we re-check on each open.\n      if (this._isCropOn()) body.appendChild(this._renderCropHint());\n\n      // 6. Advanced section with max/min DimensionControls.\n      body.appendChild(this._renderAdvancedSection());\n      panel.appendChild(body);\n      panel.appendChild(this._renderFooter());\n      this.domNode.appendChild(panel);\n      this._panel = panel;\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      // Destroy every embedded control so its subscribe disposer fires —\n      // keeps element.addSyncListener Set bounded (SA I14).\n      if (typeof this._aspectDisposer === 'function') {\n        try {\n          this._aspectDisposer();\n        } catch (_) {/* no-op */}\n        this._aspectDisposer = null;\n      }\n      if (Array.isArray(this._embeddedControls)) {\n        var _iterator = _createForOfIteratorHelper(this._embeddedControls),\n          _step;\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var c = _step.value;\n            if (c && typeof c.destroy === 'function') {\n              try {\n                c.destroy();\n              } catch (_) {/* no-op */}\n            }\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      }\n      this._embeddedControls = null;\n    }\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {\n      var _this = this;\n      // First focus → the width input (the most common edit target).\n      requestAnimationFrame(function () {\n        var input = _this.domNode.querySelector('.bjs-ovl-image-resize-embed .dim-value');\n        if (input && typeof input.focus === 'function') {\n          input.focus();\n          if (typeof input.select === 'function') input.select();\n        }\n      });\n    }\n\n    // ────────────────────────── Sub-renderers ─────────────────────────────\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-image-crop-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'open_in_full';\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-image-crop-title';\n      title.id = 'bjs-ovl-image-resize-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_title', 'Resize image');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_renderPreview\",\n    value: function _renderPreview() {\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-ovl-image-resize-preview';\n      var img = document.createElement('img');\n      img.className = 'bjs-ovl-image-resize-preview-img';\n      img.src = this.element.transferMediaAbsUrl ? this.element.transferMediaAbsUrl(this.element.src) : this.element.src || '';\n      img.alt = '';\n      img.draggable = false;\n      wrap.appendChild(img);\n      return wrap;\n    }\n\n    /** Embed a control's domNode + register destroy disposer. Returns a\n     *  section wrapper so callers get back a single child to append. */\n  }, {\n    key: \"_embedControl\",\n    value: function _embedControl(control) {\n      var section = document.createElement('div');\n      section.className = 'bjs-ovl-image-resize-embed';\n      if (control && control.domNode) {\n        section.appendChild(control.domNode);\n      }\n      if (control) this._embeddedControls.push(control);\n      return section;\n    }\n  }, {\n    key: \"_renderAdvancedSection\",\n    value: function _renderAdvancedSection() {\n      var _this2 = this;\n      var section = document.createElement('div');\n      section.className = 'bjs-ovl-image-resize-advanced';\n      var header = document.createElement('button');\n      header.type = 'button';\n      header.className = 'bjs-ovl-image-resize-advanced-toggle';\n      header.setAttribute('aria-expanded', 'false');\n      var chev = document.createElement('span');\n      chev.className = 'material-symbols-rounded bjs-ovl-image-resize-advanced-chev';\n      chev.textContent = 'chevron_right';\n      var label = document.createElement('span');\n      label.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_advanced', 'Advanced — max / min');\n      header.appendChild(chev);\n      header.appendChild(label);\n      header.addEventListener('click', function (e) {\n        e.preventDefault();\n        var open = !section.classList.contains('is-open');\n        section.classList.toggle('is-open', open);\n        header.setAttribute('aria-expanded', open ? 'true' : 'false');\n      });\n      section.appendChild(header);\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-image-resize-advanced-body';\n      var advConfig = [{\n        key: 'max_width',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.max_width', 'Max Width'),\n        units: ['px', '%', 'em', 'rem', 'vw']\n      }, {\n        key: 'max_height',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.max_height', 'Max Height'),\n        units: ['px', '%', 'em', 'rem', 'vh']\n      }, {\n        key: 'min_width',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.min_width', 'Min Width'),\n        units: ['px', '%', 'em', 'rem', 'vw']\n      }, {\n        key: 'min_height',\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('controls.min_height', 'Min Height'),\n        units: ['px', '%', 'em', 'rem', 'vh']\n      }];\n      advConfig.forEach(function (cfg) {\n        body.appendChild(_this2._embedControl(_this2.element.buildDimensionControl(cfg.label, cfg.key, cfg.units)));\n      });\n      section.appendChild(body);\n      return section;\n    }\n  }, {\n    key: \"_renderCropHint\",\n    value: function _renderCropHint() {\n      var banner = document.createElement('div');\n      banner.className = 'bjs-ovl-image-crop-info bjs-ovl-image-resize-crop-hint';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded bjs-ovl-image-crop-info-icon';\n      icon.textContent = 'crop';\n      var text = document.createElement('span');\n      text.className = 'bjs-ovl-image-crop-info-text';\n      var c = this.element.crop || {};\n      text.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_crop_hint', \"Crop is on (\".concat(c.ratioX || '?', \":\").concat(c.ratioY || '?', \"). Resizing keeps the crop frame; the cropped area re-fits to your new dimensions.\"));\n      banner.appendChild(icon);\n      banner.appendChild(text);\n      return banner;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this3 = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-image-crop-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this3._cancel();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this3._apply();\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n\n    // ────────────────────────── State actions ─────────────────────────────\n  }, {\n    key: \"_isCropOn\",\n    value: function _isCropOn() {\n      return !!(this.element.crop && this.element.crop.enabled);\n    }\n  }, {\n    key: \"_snapshotFormats\",\n    value: function _snapshotFormats() {\n      var f = this.element.formatter;\n      return {\n        width: f.getFormat('width'),\n        height: f.getFormat('height'),\n        max_width: f.getFormat('max_width'),\n        max_height: f.getFormat('max_height'),\n        min_width: f.getFormat('min_width'),\n        min_height: f.getFormat('min_height')\n      };\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      var f = this.element.formatter;\n      Object.entries(this._snapshot || {}).forEach(function (_ref) {\n        var _ref2 = _slicedToArray(_ref, 2),\n          k = _ref2[0],\n          v = _ref2[1];\n        f.setFormat(k, v);\n      });\n      if (typeof this.element.render === 'function') this.element.render();\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }]);\n}(_InlineEditorOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageResizeInlineOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageResizeInlineOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ImageResizePopoverOverlay.js":
/*!************************************************************!*\
  !*** ./src/includes/overlays/ImageResizePopoverOverlay.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ImageResizePopoverOverlay — 2026-04-19 (Phase E).\n *\n * Anchored popover variant of ImageResizeInlineOverlay. Embeds the same\n * DimensionControl factories (single source of truth for the input/\n * slider/unit UI), surrounded by anchored popover chrome instead of a\n * full-viewport modal mask. Mounted via `enterEditMode('resize-popover')`.\n *\n * Body composition mirrors the modal version:\n *   1. Width — embedded DimensionControl (sync-aware).\n *   2. Height — embedded DimensionControl.\n *   3. Aspect lock toggle — overlay-specific affordance.\n *   4. Crop-on hint banner (when element.crop.enabled).\n *\n * Advanced section + image preview omitted from the popover variant —\n * the popover is sized for quick edits without losing canvas context.\n * For deep editing (advanced max/min, preview), the modal popup is the\n * better fit.\n */\n\n\nvar ImageResizePopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n  function ImageResizePopoverOverlay() {\n    _classCallCheck(this, ImageResizePopoverOverlay);\n    return _callSuper(this, ImageResizePopoverOverlay, arguments);\n  }\n  _inherits(ImageResizePopoverOverlay, _AnchoredPopoverOverl);\n  return _createClass(ImageResizePopoverOverlay, [{\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'resize-popover';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ImageResizePopoverOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-image-resize-popover');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-image-resize-popover-title');\n      this._snapshot = this._snapshotFormats();\n      this._embeddedControls = [];\n      this._aspectDisposer = null;\n      this.domNode.appendChild(this._renderHeader());\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-image-resize-popover-body bjs-ovl-image-crop-body';\n\n      // coupleAspect: true — width/height edits honor element._aspectLocked.\n      body.appendChild(this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_width', 'Width'), 'width', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n        coupleAspect: true\n      })));\n      body.appendChild(this._embedControl(this.element.buildDimensionControl(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_height', 'Height'), 'height', ['px', '%', 'em', 'rem', 'vw', 'vh', 'auto'], {\n        coupleAspect: true\n      })));\n      var aspect = this.element.buildAspectLockRow({\n        label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_aspect_lock', 'Lock aspect ratio')\n      });\n      body.appendChild(aspect.row);\n      this._aspectDisposer = aspect.dispose;\n      if (this._isCropOn()) body.appendChild(this._renderCropHint());\n      this.domNode.appendChild(body);\n      this.domNode.appendChild(this._renderFooter());\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      _superPropGet(ImageResizePopoverOverlay, \"beforeDestroy\", this, 3)([]);\n      if (typeof this._aspectDisposer === 'function') {\n        try {\n          this._aspectDisposer();\n        } catch (_) {/* no-op */}\n        this._aspectDisposer = null;\n      }\n      if (Array.isArray(this._embeddedControls)) {\n        var _iterator = _createForOfIteratorHelper(this._embeddedControls),\n          _step;\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var c = _step.value;\n            if (c && typeof c.destroy === 'function') {\n              try {\n                c.destroy();\n              } catch (_) {/* no-op */}\n            }\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      }\n      this._embeddedControls = null;\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-image-crop-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'open_in_full';\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-image-crop-title';\n      title.id = 'bjs-ovl-image-resize-popover-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_title', 'Resize image');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_embedControl\",\n    value: function _embedControl(control) {\n      var section = document.createElement('div');\n      section.className = 'bjs-ovl-image-resize-embed';\n      if (control && control.domNode) section.appendChild(control.domNode);\n      if (control) this._embeddedControls.push(control);\n      return section;\n    }\n  }, {\n    key: \"_renderCropHint\",\n    value: function _renderCropHint() {\n      var banner = document.createElement('div');\n      banner.className = 'bjs-ovl-image-crop-info bjs-ovl-image-resize-crop-hint';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded bjs-ovl-image-crop-info-icon';\n      icon.textContent = 'crop';\n      var text = document.createElement('span');\n      text.className = 'bjs-ovl-image-crop-info-text';\n      var c = this.element.crop || {};\n      text.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.resize_crop_hint', \"Crop is on (\".concat(c.ratioX || '?', \":\").concat(c.ratioY || '?', \"). Resizing keeps the crop frame; the cropped area re-fits to your new dimensions.\"));\n      banner.appendChild(icon);\n      banner.appendChild(text);\n      return banner;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-image-crop-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._cancel();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._apply();\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n  }, {\n    key: \"_isCropOn\",\n    value: function _isCropOn() {\n      return !!(this.element.crop && this.element.crop.enabled);\n    }\n  }, {\n    key: \"_snapshotFormats\",\n    value: function _snapshotFormats() {\n      var f = this.element.formatter;\n      return {\n        width: f.getFormat('width'),\n        height: f.getFormat('height')\n      };\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      var f = this.element.formatter;\n      Object.entries(this._snapshot || {}).forEach(function (_ref) {\n        var _ref2 = _slicedToArray(_ref, 2),\n          k = _ref2[0],\n          v = _ref2[1];\n        return f.setFormat(k, v);\n      });\n      if (typeof this.element.render === 'function') this.element.render();\n      if (typeof this.element.exitEditMode === 'function') this.element.exitEditMode();\n    }\n  }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ImageResizePopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ImageResizePopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/InlineEditorOverlay.js":
/*!******************************************************!*\
  !*** ./src/includes/overlays/InlineEditorOverlay.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * InlineEditorOverlay — full-cover editor UI for `'edit'` trigger overlays.\n *\n * Use for modal-like inline editing on the canvas:\n *   - Image inline crop (Phase 1.4)\n *   - (future) inline alt-text editor, inline link editor\n *\n * Entered via element.enterEditMode(modeName) from a 'select'-trigger\n * overlay (e.g. ImageActionsOverlay's Crop button). Exited via:\n *   - this.element.exitEditMode() from inside (Done/Confirm button)\n *   - Escape keydown (auto-wired by this class)\n *   - Element deselected / removed (framework cleanup)\n *\n * Base class wires:\n *   - Escape key handler (document-level, cleaned up in beforeDestroy)\n *   - pointer-events: auto on root (so full-cover mask catches clicks)\n *\n * Subclasses override render() to build the specific editor UI + call\n * super.render() first to get Escape wiring.\n */\n\nvar InlineEditorOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function InlineEditorOverlay() {\n    _classCallCheck(this, InlineEditorOverlay);\n    return _callSuper(this, InlineEditorOverlay, arguments);\n  }\n  _inherits(InlineEditorOverlay, _BaseOverlay);\n  return _createClass(InlineEditorOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'edit';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      if (!this.domNode) {\n        this.domNode = document.createElement('div');\n      }\n      this.domNode.classList.add('bjs-ovl-inline-editor');\n      this.domNode.setAttribute('data-interactive', '');\n      this.domNode.setAttribute('role', 'dialog');\n      this.domNode.setAttribute('aria-modal', 'false'); // inline, not a true modal\n\n      this._bindEscape();\n    }\n\n    /**\n     * Override BaseOverlay.position() — inline editors are full-viewport modal\n     * masks, NOT element-hug overlays. If we delegated to matchingDomNode()\n     * (which sizes the node to the element's bounding rect), centering the\n     * panel inside that rect overflows the viewport whenever the element sits\n     * near a viewport edge (reported 2026-04-18: crop panel's header clipped\n     * above the top of the window when the target image was near the top of\n     * the canvas). Pinning to the viewport via `position: fixed; inset: 0`\n     * keeps the internal flex centering relative to the window — identical\n     * positioning semantics to a real `<dialog>` / .bjs-popup backdrop.\n     *\n     * Skipping matchingDomNode also means we don't install its iframe-scroll\n     * / resize observers — which is correct here because a full-cover mask\n     * never needs to re-anchor on scroll.\n     */\n  }, {\n    key: \"position\",\n    value: function position() {\n      if (!this.domNode) return;\n      Object.assign(this.domNode.style, {\n        position: 'fixed',\n        top: '0',\n        left: '0',\n        right: '0',\n        bottom: '0',\n        width: 'auto',\n        height: 'auto'\n      });\n    }\n  }, {\n    key: \"_bindEscape\",\n    value: function _bindEscape() {\n      var _this = this;\n      if (this._escapeBound) return;\n      this._escapeBound = true;\n      this._onKey = function (e) {\n        if (e.key === 'Escape' || e.key === 'Esc') {\n          e.preventDefault();\n          try {\n            _this.element.exitEditMode();\n          } catch (err) {\n            // eslint-disable-next-line no-console\n            console.error('[overlay] InlineEditorOverlay exit threw:', err);\n          }\n        }\n      };\n      document.addEventListener('keydown', this._onKey);\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      var _superPropGet2;\n      if (this._onKey) {\n        document.removeEventListener('keydown', this._onKey);\n        this._onKey = null;\n        this._escapeBound = false;\n      }\n      (_superPropGet2 = _superPropGet(InlineEditorOverlay, \"beforeDestroy\", this, 3)) === null || _superPropGet2 === void 0 || _superPropGet2([]);\n    }\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InlineEditorOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/InlineEditorOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/LinkOnSelectionPopoverOverlay.js":
/*!****************************************************************!*\
  !*** ./src/includes/overlays/LinkOnSelectionPopoverOverlay.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../LinkConfigControl.js */ \"./src/includes/LinkConfigControl.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * LinkOnSelectionPopoverOverlay — W1.3 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * NOT the existing `LinkPopoverOverlay` (which wraps the whole element's\n * href). This popover wraps JUST the selected text range in `<a>`.\n *\n * Mount pattern mirrors `TextColorPopoverOverlay` / `AIRewritePopoverOverlay`:\n * a lightweight non-`BaseOverlay` class, owned by the singleton\n * `TextInlineToolbarOverlay` (one popover per open cycle), mounted inside\n * `document.body`, anchored to the toolbar's Link button via\n * `ToolbarPositioner.attach`, disposed on toolbar unmount.\n *\n * HARD RULE T9 consequence #8 — anchor-wrap logic:\n *   (a) selection fully OUTSIDE any `<a>` → `execCommand('createLink', url)`.\n *       Browser's native surroundContents handles DOM validity; post-process\n *       patches `target` / `rel` / `title` / `download` on the newly-created\n *       anchor(s).\n *   (b) selection fully INSIDE an existing `<a>` (non-host) → mutate attrs in\n *       place; no execCommand. Removing the link unwraps the anchor.\n *   (c) selection CROSSES anchor boundary → `execCommand('createLink', url)`\n *       which the browser handles by splitting + re-wrapping. Post-process\n *       patches non-href attrs. `unlink` covers the removal case same way.\n *   (d) selection host IS an `<a>` (LinkElement) → mutate host attrs directly\n *       (element-level link). Remove is DISABLED (unwrapping would break the\n *       element — user must delete the element from canvas).\n *\n * Dual-view sync (HARD RULE T3): the popover body embeds the shared\n * `LinkConfigControl` — exact same class the sidebar Link tab uses. Future\n * W4.3 will extend that control (aria-label / referrerpolicy / UTM builder);\n * popover inherits those for free.\n *\n * Selection preservation (HARD RULE T1 / T2): the iframe selection range is\n * captured at open and restored immediately before the apply path runs, so\n * the user clicking into the popover's inputs never loses the range. Apply\n * writes via execCommand (engine-native range-split) + `InlineSanitizer.\n * normalize(host)` + `input` event dispatch + `tracker.refresh()` — caret\n * stable, round-trip invariant preserved.\n *\n * Failure-visible (HARD RULE T6): execCommand failures flash `.is-error` on\n * the Apply button; `hostIsAnchor` Remove attempt surfaces a sticky banner\n * instead of silently no-opping.\n */\n\n\n\n\n\nvar LinkOnSelectionPopoverOverlay = /*#__PURE__*/function () {\n  /**\n   * @param {TextInlineToolbarOverlay} toolbar — owner (shares selection\n   *   save/restore + iframe access).\n   * @param {{ anchorBtn: HTMLElement }} opts\n   */\n  function LinkOnSelectionPopoverOverlay(toolbar, opts) {\n    _classCallCheck(this, LinkOnSelectionPopoverOverlay);\n    if (!toolbar || !opts || !opts.anchorBtn) {\n      throw new Error('LinkOnSelectionPopoverOverlay: toolbar + opts.anchorBtn required');\n    }\n    this._toolbar = toolbar;\n    this._builder = toolbar._builder;\n    this._anchorBtn = opts.anchorBtn;\n    this.domNode = null;\n    this._linkControl = null;\n    this._positionHandle = null;\n    this._onDocKey = null;\n    this._onDocMouseDown = null;\n    this._mounted = false;\n\n    // Selection at open time — captured before any input can steal focus\n    // from the iframe (which would collapse the selection).\n    this._savedRange = null;\n\n    // Scope snapshot at open. Drives Remove-link visibility + Apply\n    // routing. Re-computed at Apply time too (selection may have\n    // shifted inside the popover interaction).\n    this._scopeAtOpen = null;\n  }\n\n  /* ── public lifecycle ─────────────────────────────────────────── */\n  return _createClass(LinkOnSelectionPopoverOverlay, [{\n    key: \"open\",\n    value: function open() {\n      var _this = this;\n      if (this._mounted) return;\n      try {\n        this._captureSelection();\n        this._scopeAtOpen = this._resolveAnchorScope();\n        this._build();\n        document.body.appendChild(this.domNode);\n        this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n          anchor: function anchor() {\n            return _this._anchorBtn.getBoundingClientRect();\n          },\n          target: this.domNode,\n          offset: 8,\n          collisionPadding: 12,\n          preferredSide: 'below',\n          flip: true\n        });\n        this._registerDismissListeners();\n        this._mounted = true;\n        this._anchorBtn.setAttribute('aria-expanded', 'true');\n        // Defer focus — ToolbarPositioner needs one tick to measure.\n        setTimeout(function () {\n          return _this._focusFirstInput();\n        }, 0);\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:link-popover] open failed:', err);\n        this.close();\n      }\n    }\n  }, {\n    key: \"close\",\n    value: function close() {\n      if (!this._mounted && !this.domNode) return;\n      this._unregisterDismissListeners();\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.dispose();\n        } catch (_) {}\n        this._positionHandle = null;\n      }\n      if (this._linkControl && typeof this._linkControl.destroy === 'function') {\n        try {\n          this._linkControl.destroy();\n        } catch (_) {}\n      }\n      this._linkControl = null;\n      if (this.domNode && this.domNode.parentNode) {\n        try {\n          this.domNode.parentNode.removeChild(this.domNode);\n        } catch (_) {}\n      }\n      this.domNode = null;\n      this._mounted = false;\n      this._savedRange = null;\n      this._scopeAtOpen = null;\n      try {\n        this._anchorBtn.setAttribute('aria-expanded', 'false');\n      } catch (_) {}\n    }\n  }, {\n    key: \"isOpen\",\n    value: function isOpen() {\n      return this._mounted;\n    }\n\n    /* ── selection capture / restore ──────────────────────────────── */\n  }, {\n    key: \"_captureSelection\",\n    value: function _captureSelection() {\n      var payload = this._toolbar && this._toolbar._currentPayload;\n      if (payload && payload.range) {\n        this._savedRange = payload.range.cloneRange();\n        return;\n      }\n      // Fallback — active selection inside iframe.\n      try {\n        var idoc = this._iframeDoc();\n        var sel = idoc && idoc.defaultView && idoc.defaultView.getSelection();\n        if (sel && sel.rangeCount > 0) {\n          this._savedRange = sel.getRangeAt(0).cloneRange();\n        }\n      } catch (_) {\n        this._savedRange = null;\n      }\n    }\n  }, {\n    key: \"_restoreSelection\",\n    value: function _restoreSelection() {\n      if (!this._savedRange) return false;\n      try {\n        var idoc = this._iframeDoc();\n        var iwin = idoc && idoc.defaultView;\n        if (!iwin) return false;\n        var sel = iwin.getSelection();\n        sel.removeAllRanges();\n        sel.addRange(this._savedRange);\n        return true;\n      } catch (_) {\n        return false;\n      }\n    }\n  }, {\n    key: \"_iframeDoc\",\n    value: function _iframeDoc() {\n      return this._builder && this._builder.iframe && this._builder.iframe.contentDocument;\n    }\n  }, {\n    key: \"_host\",\n    value: function _host() {\n      var payload = this._toolbar && this._toolbar._currentPayload;\n      var idoc = this._iframeDoc();\n      if (!idoc || !payload || !payload.elementUid) return null;\n      return idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n    }\n\n    /* ── anchor scope detection ───────────────────────────────────── */\n\n    /**\n     * Introspect the saved range against the element host to classify the\n     * selection into one of: OUTSIDE / INSIDE / CROSSING / HOST_IS_ANCHOR.\n     * Returns a stable shape — all fields present even when not applicable.\n     */\n  }, {\n    key: \"_resolveAnchorScope\",\n    value: function _resolveAnchorScope() {\n      var host = this._host();\n      var range = this._savedRange;\n      var result = {\n        host: host,\n        hostIsAnchor: false,\n        anchorEl: null,\n        insideAnchor: false,\n        crossing: false,\n        existingHref: '',\n        existingTarget: '',\n        existingRel: '',\n        existingTitle: '',\n        existingDownload: ''\n      };\n      if (!host || !range) return result;\n      if (host.tagName === 'A') {\n        result.hostIsAnchor = true;\n        result.anchorEl = host;\n        result.insideAnchor = true;\n        result.existingHref = host.getAttribute('href') || '';\n        result.existingTarget = host.getAttribute('target') || '';\n        result.existingRel = host.getAttribute('rel') || '';\n        result.existingTitle = host.getAttribute('title') || '';\n        result.existingDownload = host.getAttribute('download') || '';\n        result.existingAriaLabel = host.getAttribute('aria-label') || '';\n        return result;\n      }\n      var startA = this._closestAnchor(range.startContainer, host);\n      var endA = this._closestAnchor(range.endContainer, host);\n      if (startA && endA && startA === endA) {\n        this._seedFromAnchor(result, startA);\n        result.insideAnchor = true;\n        result.anchorEl = startA;\n        return result;\n      }\n      if (startA || endA) {\n        // One end inside an <a>, other end outside — or two different\n        // anchors. Either way this is a crossing.\n        result.crossing = true;\n        // Seed fields from whichever anchor we found — reasonable default\n        // if user wants to \"edit the link they're crossing out of\".\n        this._seedFromAnchor(result, startA || endA);\n        return result;\n      }\n\n      // Downward scan — covers the `selectNodeContents(host)` case where\n      // the range's start/end containers are the host itself (so walking\n      // UP never finds an anchor child). If the range intersects exactly\n      // one anchor and the range's text is identical to that anchor's\n      // textContent, the user effectively selected the whole anchor —\n      // treat as INSIDE. If the range text spans beyond the anchor(s) or\n      // touches >1 anchors, it's CROSSING.\n      try {\n        var allAnchors = Array.from(host.querySelectorAll('a[href]'));\n        var intersecting = allAnchors.filter(function (a) {\n          try {\n            return range.intersectsNode(a);\n          } catch (_) {\n            return false;\n          }\n        });\n        if (intersecting.length > 0) {\n          var rangeText = range.toString();\n          var singleAnchor = intersecting.length === 1 ? intersecting[0] : null;\n          if (singleAnchor && rangeText.length > 0 && rangeText === singleAnchor.textContent) {\n            this._seedFromAnchor(result, singleAnchor);\n            result.insideAnchor = true;\n            result.anchorEl = singleAnchor;\n          } else {\n            // Text extends past the anchor(s), or hits multiple.\n            result.crossing = true;\n            this._seedFromAnchor(result, intersecting[0]);\n          }\n        }\n      } catch (_) {/* keep OUTSIDE default */}\n      return result;\n    }\n  }, {\n    key: \"_seedFromAnchor\",\n    value: function _seedFromAnchor(result, a) {\n      if (!a) return;\n      result.existingHref = a.getAttribute('href') || '';\n      result.existingTarget = a.getAttribute('target') || '';\n      result.existingRel = a.getAttribute('rel') || '';\n      result.existingTitle = a.getAttribute('title') || '';\n      result.existingDownload = a.getAttribute('download') || '';\n      result.existingAriaLabel = a.getAttribute('aria-label') || '';\n    }\n  }, {\n    key: \"_closestAnchor\",\n    value: function _closestAnchor(node, host) {\n      var cur = node && node.nodeType === 1 ? node : node && node.parentElement;\n      while (cur && cur !== host && cur !== host.parentElement) {\n        if (cur.tagName === 'A') return cur;\n        cur = cur.parentElement;\n      }\n      return null;\n    }\n\n    /* ── build DOM ────────────────────────────────────────────────── */\n  }, {\n    key: \"_build\",\n    value: function _build() {\n      var p = document.createElement('div');\n      p.className = 'bjs-ovl bjs-ovl-link-on-selection-popover';\n      p.setAttribute('role', 'dialog');\n      p.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.title'));\n      p.setAttribute('data-interactive', '');\n      p.setAttribute('data-scope', this._scopeString(this._scopeAtOpen));\n\n      // Preserve iframe selection on mousedown inside the popover body —\n      // otherwise clicking the popover chrome would collapse the range.\n      // Inputs/buttons still take focus normally via stopPropagation gates.\n      p.addEventListener('mousedown', function (e) {\n        var t = e.target;\n        if (t && t.closest('input, textarea, select, button')) return;\n        e.preventDefault();\n      });\n      p.appendChild(this._renderHeader());\n      p.appendChild(this._renderBody());\n      p.appendChild(this._renderFooter());\n      this.domNode = p;\n    }\n  }, {\n    key: \"_scopeString\",\n    value: function _scopeString(scope) {\n      if (!scope) return 'outside';\n      if (scope.hostIsAnchor) return 'host-anchor';\n      if (scope.crossing) return 'crossing';\n      if (scope.insideAnchor) return 'inside';\n      return 'outside';\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var _this2 = this;\n      var header = document.createElement('div');\n      header.className = 'bjs-link-popover-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-link-popover-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'link';\n      icon.setAttribute('aria-hidden', 'true');\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-link-popover-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.title');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n\n      // Remove-link chip — visible only when selection is inside an <a>.\n      var scope = this._scopeAtOpen;\n      if (scope && (scope.insideAnchor || scope.crossing)) {\n        var chip = document.createElement('button');\n        chip.type = 'button';\n        chip.className = 'bjs-link-popover-remove';\n        chip.setAttribute('data-action', 'remove');\n        var chipIcon = document.createElement('span');\n        chipIcon.className = 'material-symbols-rounded';\n        chipIcon.textContent = 'link_off';\n        chipIcon.setAttribute('aria-hidden', 'true');\n        var chipText = document.createElement('span');\n        chipText.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove');\n        chip.appendChild(chipIcon);\n        chip.appendChild(chipText);\n        chip.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove'));\n        if (scope.hostIsAnchor) {\n          // Can't unlink without breaking the element — disable +\n          // announce via tooltip why (HARD RULE T6).\n          chip.classList.add('is-disabled');\n          chip.setAttribute('aria-disabled', 'true');\n          chip.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove_disabled_host_anchor'));\n          chip.addEventListener('click', function (e) {\n            e.preventDefault();\n            _this2._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove_disabled_host_anchor'));\n          });\n        } else {\n          chip.addEventListener('click', function (e) {\n            e.preventDefault();\n            _this2._removeLink();\n          });\n        }\n        header.appendChild(chip);\n      }\n      return header;\n    }\n  }, {\n    key: \"_renderBody\",\n    value: function _renderBody() {\n      var body = document.createElement('div');\n      body.className = 'bjs-link-popover-body';\n      var scope = this._scopeAtOpen;\n      this._linkControl = new _LinkConfigControl_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"](_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.title'), {\n        url: scope ? scope.existingHref : '',\n        target: scope ? scope.existingTarget : '',\n        rel: scope ? scope.existingRel : '',\n        title: scope ? scope.existingTitle : '',\n        download: scope ? scope.existingDownload : '',\n        ariaLabel: scope ? scope.existingAriaLabel : ''\n      },\n      // No-op callback — commits happen on Apply click, not field blur.\n      // LinkConfigControl still validates on every change + paints\n      // `.is-error` states, so the user gets live feedback without a\n      // premature DOM write that would mid-edit the selection.\n      {\n        setLink: function setLink() {}\n      }, null);\n      body.appendChild(this._linkControl.domNode);\n\n      // Banner slot for failure-visible messages (HARD RULE T6).\n      this._banner = document.createElement('div');\n      this._banner.className = 'bjs-link-popover-banner';\n      this._banner.setAttribute('role', 'status');\n      this._banner.setAttribute('aria-live', 'polite');\n      this._banner.hidden = true;\n      body.appendChild(this._banner);\n      return body;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this3 = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-link-popover-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-link-popover-btn bjs-link-popover-btn--secondary';\n      cancel.setAttribute('data-action', 'cancel');\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this3.close();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-link-popover-btn bjs-link-popover-btn--primary';\n      apply.setAttribute('data-action', 'apply');\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.apply');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this3._applyLink(apply);\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n  }, {\n    key: \"_focusFirstInput\",\n    value: function _focusFirstInput() {\n      if (!this.domNode) return;\n      var input = this.domNode.querySelector('input[data-field=\"web.url\"], input[data-field=\"email.to\"], input[data-field=\"phone.number\"], input[data-field=\"anchor.id\"], .bjs-text-input');\n      if (input) {\n        try {\n          input.focus();\n          input.select && input.select();\n        } catch (_) {}\n      }\n    }\n\n    /* ── apply / remove ───────────────────────────────────────────── */\n  }, {\n    key: \"_applyLink\",\n    value: function _applyLink(applyBtn) {\n      var payload = this._linkControl && typeof this._linkControl.getValue === 'function' ? this._linkControl.getValue() : null;\n      if (!payload) {\n        this._flashButtonError(applyBtn);\n        return;\n      }\n      // Validate errors already surfaced via LinkConfigControl's own UI.\n      // If URL is empty post-validation, Apply becomes an implicit\n      // \"remove link\" when selection is inside an anchor. Otherwise it's\n      // a no-op (wrap with no href = invalid T9) — banner the user.\n      if (!payload.url) {\n        if (this._scopeAtOpen && (this._scopeAtOpen.insideAnchor || this._scopeAtOpen.crossing)) {\n          this._removeLink();\n        } else {\n          this._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.err_empty_url'));\n        }\n        return;\n      }\n      var ok = this._doWriteAnchor(payload);\n      if (!ok) {\n        this._flashButtonError(applyBtn);\n        return;\n      }\n      this.close();\n    }\n  }, {\n    key: \"_removeLink\",\n    value: function _removeLink() {\n      var scope = this._resolveAnchorScope();\n      if (scope.hostIsAnchor) {\n        // Defensive — UI should already prevent this.\n        this._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.remove_disabled_host_anchor'));\n        return;\n      }\n      var host = scope.host;\n      if (!host) return;\n      var restored = this._restoreSelection();\n      if (!restored) return;\n      var idoc = this._iframeDoc();\n      var ok = false;\n      try {\n        ok = idoc.execCommand('unlink', false, null);\n      } catch (_) {\n        ok = false;\n      }\n      if (!ok) {\n        // Fallback — manual unwrap of the known anchor.\n        if (scope.anchorEl && scope.anchorEl.parentNode) {\n          try {\n            while (scope.anchorEl.firstChild) {\n              scope.anchorEl.parentNode.insertBefore(scope.anchorEl.firstChild, scope.anchorEl);\n            }\n            scope.anchorEl.parentNode.removeChild(scope.anchorEl);\n            ok = true;\n          } catch (_) {\n            ok = false;\n          }\n        }\n      }\n      if (!ok) {\n        this._flashBanner(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('link_popover.err_remove_failed'));\n        return;\n      }\n      this._postWrite(host);\n      this.close();\n    }\n\n    /**\n     * @param {{url, target, rel, title, download}} payload\n     * @returns {boolean} success\n     */\n  }, {\n    key: \"_doWriteAnchor\",\n    value: function _doWriteAnchor(payload) {\n      var _this4 = this;\n      var scope = this._resolveAnchorScope();\n      var host = scope.host;\n      if (!host) return false;\n      var restored = this._restoreSelection();\n      if (!restored) return false;\n      var idoc = this._iframeDoc();\n      if (!idoc) return false;\n      try {\n        if (scope.hostIsAnchor) {\n          // LinkElement — mutate host attrs only. Don't try to wrap\n          // (would nest); don't unwrap (would destroy the element).\n          this._setAnchorAttrs(host, payload);\n          // Push through the element's link setter so Formatter /\n          // serializer / sidebar stay in sync. LinkElement exposes\n          // `setLink({url, target, rel, title, download})`.\n          var el = this._resolveElement(host);\n          if (el && typeof el.setLink === 'function') {\n            try {\n              el.setLink(payload);\n            } catch (_) {}\n          }\n        } else if (scope.insideAnchor && !scope.crossing) {\n          // Case (b) — edit in place.\n          if (scope.anchorEl) {\n            this._setAnchorAttrs(scope.anchorEl, payload);\n          }\n        } else {\n          // Case (a) — outside, or case (c) — crossing.\n          // Use browser-native createLink to handle range surround +\n          // split. `document.execCommand` returns false on unsupported\n          // / empty-selection; fall back to manual surroundContents\n          // for the outside case.\n          var createdOk = false;\n          try {\n            createdOk = idoc.execCommand('createLink', false, payload.url);\n          } catch (_) {\n            createdOk = false;\n          }\n          if (!createdOk) {\n            if (!scope.crossing) {\n              // OUTSIDE — try manual wrap.\n              var a = idoc.createElement('a');\n              this._setAnchorAttrs(a, payload);\n              try {\n                this._savedRange.surroundContents(a);\n                createdOk = true;\n              } catch (_) {\n                createdOk = false;\n              }\n            }\n          }\n          if (!createdOk) return false;\n\n          // Patch non-href attrs onto whatever anchors now carry the\n          // target href inside the host. createLink only sets href;\n          // target/rel/title/download must be written after.\n          var matches = host.querySelectorAll('a[href]');\n          matches.forEach(function (a) {\n            if ((a.getAttribute('href') || '') === payload.url) {\n              _this4._setAnchorAttrs(a, payload);\n            }\n          });\n        }\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:link-popover] write failed:', err);\n        return false;\n      }\n      this._postWrite(host);\n      return true;\n    }\n  }, {\n    key: \"_setAnchorAttrs\",\n    value: function _setAnchorAttrs(a, payload) {\n      if (!a) return;\n      if (payload.url) a.setAttribute('href', payload.url);else a.removeAttribute('href');\n      if (payload.target) a.setAttribute('target', payload.target);else a.removeAttribute('target');\n      if (payload.rel) a.setAttribute('rel', payload.rel);else a.removeAttribute('rel');\n      if (payload.title) a.setAttribute('title', payload.title);else a.removeAttribute('title');\n      if (payload.download) a.setAttribute('download', payload.download);else a.removeAttribute('download');\n\n      // W4.3 — optional a11y override surviving round-trip.\n      if (payload.ariaLabel) a.setAttribute('aria-label', payload.ariaLabel);else a.removeAttribute('aria-label');\n    }\n  }, {\n    key: \"_resolveElement\",\n    value: function _resolveElement(host) {\n      if (!host) return null;\n      var uid = host.getAttribute('data-bjs-inline-text');\n      if (!uid) return null;\n      var uiMgr = this._builder && this._builder.uiManager;\n      if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n      return uiMgr.elements.find(function (el) {\n        return el && el.id === uid;\n      }) || null;\n    }\n\n    /**\n     * Post-write housekeeping — canonicalize markup, fire input event so\n     * W0.2b's auto-wired `setText` picks up the new HTML, refresh tracker\n     * so toolbar button states re-read. Shared by both wrap/edit paths and\n     * the remove-link path.\n     */\n  }, {\n    key: \"_postWrite\",\n    value: function _postWrite(host) {\n      if (!host) return;\n      try {\n        _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].normalize(host);\n      } catch (_) {}\n      try {\n        var idoc = this._iframeDoc();\n        if (idoc) {\n          host.dispatchEvent(new idoc.defaultView.Event('input', {\n            bubbles: true\n          }));\n        }\n      } catch (_) {}\n      try {\n        var tracker = this._builder && this._builder.textSelectionTracker;\n        if (tracker && typeof tracker.refresh === 'function') tracker.refresh();\n      } catch (_) {}\n    }\n\n    /* ── error surfacing (HARD RULE T6) ───────────────────────────── */\n  }, {\n    key: \"_flashButtonError\",\n    value: function _flashButtonError(btn) {\n      if (!btn) return;\n      btn.classList.add('is-error');\n      setTimeout(function () {\n        return btn.classList.remove('is-error');\n      }, 600);\n    }\n  }, {\n    key: \"_flashBanner\",\n    value: function _flashBanner(msg) {\n      if (!this._banner) return;\n      this._banner.textContent = msg;\n      this._banner.hidden = false;\n      this._banner.classList.add('is-visible');\n    }\n\n    /* ── dismissal ────────────────────────────────────────────────── */\n  }, {\n    key: \"_registerDismissListeners\",\n    value: function _registerDismissListeners() {\n      var _this5 = this;\n      this._onDocKey = function (e) {\n        if (e.key === 'Escape') {\n          e.stopPropagation();\n          _this5.close();\n        }\n      };\n      document.addEventListener('keydown', this._onDocKey, true);\n      this._onDocMouseDown = function (e) {\n        if (!_this5.domNode) return;\n        var t = e.target;\n        if (_this5.domNode.contains(t)) return;\n        if (t && _this5._anchorBtn && _this5._anchorBtn.contains(t)) return;\n        _this5.close();\n      };\n      // Defer one tick — the click that OPENED this popover mustn't be\n      // picked up by the outside-click handler (would close immediately).\n      setTimeout(function () {\n        if (_this5._mounted) document.addEventListener('mousedown', _this5._onDocMouseDown, true);\n      }, 0);\n    }\n  }, {\n    key: \"_unregisterDismissListeners\",\n    value: function _unregisterDismissListeners() {\n      if (this._onDocKey) {\n        document.removeEventListener('keydown', this._onDocKey, true);\n        this._onDocKey = null;\n      }\n      if (this._onDocMouseDown) {\n        document.removeEventListener('mousedown', this._onDocMouseDown, true);\n        this._onDocMouseDown = null;\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkOnSelectionPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/LinkOnSelectionPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/LinkPopoverOverlay.js":
/*!*****************************************************!*\
  !*** ./src/includes/overlays/LinkPopoverOverlay.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AnchoredPopoverOverlay.js */ \"./src/includes/overlays/AnchoredPopoverOverlay.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * LinkPopoverOverlay — 2026-04-19.\n *\n * Anchored popover for editing an element's link without taking over the\n * viewport with a modal. Embeds the REAL control the sidebar uses — not a\n * hand-rolled mini version — so the popover and sidebar stay in lock-step\n * via the dual-view sync bus (SA I13 subscribe/readState).\n *\n * Pattern mirrors ImageCropPopoverOverlay / ImageResizePopoverOverlay /\n * ImageEffectPopoverOverlay:\n *\n *   - Shared `.bjs-ovl-anchored-popover` shell (Esc + outside-click + smart-\n *     flip anchoring). No custom chrome here, just header + body + footer.\n *   - Body = `this.element.buildLinkControl().domNode`. Factory returns a\n *     fresh LinkConfigControl / LinkInputControl instance wired to the\n *     element via subscribe/readState. Opening the popover does NOT clone\n *     state into the popover — it binds the popover to the same source of\n *     truth (the element), so every keystroke propagates to the sidebar\n *     control without manual bridging.\n *   - Snapshot on mount → Cancel reverts via one `setLink()` call, which\n *     fires `applyLinkAttrs()` + `notifySyncListeners()` so every live\n *     control snaps back in place.\n *\n * Surface flip: keep both `BuilderjsPopup.prompt` + this popover in reach.\n * ImageActionsOverlay / ButtonActionsOverlay each expose a SURFACE_MODE\n * map; set SURFACE_MODE.link = 'popup' and restore the legacy prompt call\n * to revert — no code deletion required, the popover stays registered but\n * dormant (edit-mode 'link-popover' is never entered).\n *\n * See docs/core/OVERLAY.md §7.5 + BUILDER.md Lesson 39.\n */\n\n\nvar LinkPopoverOverlay = /*#__PURE__*/function (_AnchoredPopoverOverl) {\n  function LinkPopoverOverlay() {\n    _classCallCheck(this, LinkPopoverOverlay);\n    return _callSuper(this, LinkPopoverOverlay, arguments);\n  }\n  _inherits(LinkPopoverOverlay, _AnchoredPopoverOverl);\n  return _createClass(LinkPopoverOverlay, [{\n    key: \"getEditMode\",\n    value: function getEditMode() {\n      return 'link-popover';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      _superPropGet(LinkPopoverOverlay, \"render\", this, 3)([]);\n      this.domNode.classList.add('bjs-ovl-link-popover');\n      this.domNode.setAttribute('aria-labelledby', 'bjs-ovl-link-popover-title');\n\n      // Snapshot so Cancel / Esc reverts via one setLink round-trip.\n      // Reads whatever fields the element carries — url for everything,\n      // target + rel + title + download on ButtonElement, just url +\n      // target on ImageElement. The element's own setLink callback\n      // picks off the fields it cares about.\n      this._snapshot = {\n        url: this.element.url || '',\n        target: this.element.target || '',\n        rel: this.element.rel || '',\n        title: this.element.title || '',\n        download: this.element.download || ''\n      };\n      this._embedded = null;\n      this.domNode.appendChild(this._renderHeader());\n      var body = document.createElement('div');\n      body.className = 'bjs-ovl-link-popover-body';\n\n      // Embed the real control — same class as the sidebar, wired to the\n      // element via subscribe/readState. Sidebar + popover see the same\n      // source of truth (the element); there is no separate \"popover\n      // state\" to keep in sync.\n      this._embedded = this.element.buildLinkControl();\n      if (this._embedded && this._embedded.domNode) {\n        body.appendChild(this._embedded.domNode);\n      }\n      this.domNode.appendChild(body);\n      this.domNode.appendChild(this._renderFooter());\n    }\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {\n      // Focus the first text input inside the embedded control so Enter\n      // / Esc feel natural without a click. Works for both LinkConfig\n      // (first [data-field=\"web.url\"]) and LinkInputControl (first\n      // [name=\"link-url\"]).\n      if (!this.domNode) return;\n      var input = this.domNode.querySelector('[data-field=\"web.url\"], [name=\"link-url\"], .bjs-text-input');\n      if (input) {\n        try {\n          input.focus();\n          input.select && input.select();\n        } catch (_) {/* no-op on detached / weird DOM */}\n      }\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      _superPropGet(LinkPopoverOverlay, \"beforeDestroy\", this, 3)([]);\n      // Dispose the embedded control's subscription so it stops reacting\n      // to element mutations after the popover closes. Without this the\n      // popover's control stays subscribed to a detached DOM (SA I13c).\n      if (this._embedded && typeof this._embedded.destroy === 'function') {\n        try {\n          this._embedded.destroy();\n        } catch (_) {/* no-op */}\n      }\n      this._embedded = null;\n    }\n  }, {\n    key: \"_renderHeader\",\n    value: function _renderHeader() {\n      var header = document.createElement('div');\n      header.className = 'bjs-ovl-image-crop-header';\n      var iconWrap = document.createElement('span');\n      iconWrap.className = 'bjs-ovl-image-crop-header-icon';\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.textContent = 'link';\n      iconWrap.appendChild(icon);\n      var title = document.createElement('h3');\n      title.className = 'bjs-ovl-image-crop-title';\n      title.id = 'bjs-ovl-link-popover-title';\n      title.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.link', 'Link');\n      header.appendChild(iconWrap);\n      header.appendChild(title);\n      return header;\n    }\n  }, {\n    key: \"_renderFooter\",\n    value: function _renderFooter() {\n      var _this = this;\n      var footer = document.createElement('div');\n      footer.className = 'bjs-ovl-image-crop-footer';\n      var cancel = document.createElement('button');\n      cancel.type = 'button';\n      cancel.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--secondary';\n      cancel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_cancel', 'Cancel');\n      cancel.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._cancel();\n      });\n      var apply = document.createElement('button');\n      apply.type = 'button';\n      apply.className = 'bjs-ovl-image-crop-btn bjs-ovl-image-crop-btn--primary';\n      apply.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('overlay.crop_confirm', 'Done');\n      apply.addEventListener('click', function (e) {\n        e.preventDefault();\n        _this._apply();\n      });\n      footer.appendChild(cancel);\n      footer.appendChild(apply);\n      return footer;\n    }\n  }, {\n    key: \"_apply\",\n    value: function _apply() {\n      // Live edits have already flowed through the embedded control's\n      // debounced input → element.setLink → notifySyncListeners path.\n      // Apply is just \"close the popover\".\n      if (this.element && typeof this.element.exitEditMode === 'function') {\n        this.element.exitEditMode();\n      }\n    }\n  }, {\n    key: \"_cancel\",\n    value: function _cancel() {\n      // Revert to snapshot. Prefer the element's own setter (keeps\n      // derived logic — applyLinkAttrs + sync notify — consistent with\n      // any other setLink callsite). Falls back to direct assign + render\n      // for elements whose setter signature doesn't match the Button/\n      // Image contract.\n      if (!this.element) return;\n      var s = this._snapshot || {};\n      var controls = this.element.getControls ? null : null; // kept for reference\n      // ButtonElement's link control callback takes `{ url, target, rel, title, download }`;\n      // ImageElement's LinkInputControl callback takes `(url, target)`. The\n      // element's buildLinkControl factory wires both shapes — we just set\n      // the element fields directly here (they're the source of truth)\n      // + run applyLinkAttrs OR render, same as the factory callback.\n      this.element.url = s.url;\n      this.element.target = s.target;\n      if ('rel' in this.element) this.element.rel = s.rel;\n      if ('title' in this.element) this.element.title = s.title;\n      if ('download' in this.element) this.element.download = s.download;\n      if (typeof this.element.applyLinkAttrs === 'function') {\n        this.element.applyLinkAttrs();\n      } else if (typeof this.element.render === 'function') {\n        this.element.render();\n      }\n      if (typeof this.element.exitEditMode === 'function') {\n        this.element.exitEditMode();\n      }\n    }\n  }]);\n}(_AnchoredPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LinkPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/LinkPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/NativeDragHandleOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/NativeDragHandleOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * NativeDragHandleOverlay — HTML5 DnD drag handle primitive.\n *\n * Counterpart to DraggableHandleOverlay. Use this ONLY when the gesture\n * must produce native `dragstart → dragover → drop` events that feed into\n * existing HTML5 DnD pipelines (UIManager.dragOver / drop). Block drag\n * anchor is the canonical example (Phase 1.6).\n *\n * The grabber (typically an inner <span draggable=\"true\">) fires `dragstart`.\n * Pointer events (pointerdown/move/up) are NOT used — they're suppressed\n * by the browser once dragstart fires. Do NOT mix with setPointerCapture.\n *\n * Preserves Safari drag-ghost 3-layer workaround (SA invariant I3 + BUILDER.md\n * Lesson 11) — without these, Safari emits blank drag ghosts when the source\n * is inside an overflow:hidden ancestor:\n *   Layer 1: dataTransfer.setData('text/plain', '')\n *   Layer 2: dataTransfer.effectAllowed = 'all'\n *   Layer 3: off-screen clone at left:-10000px for Safari-only setDragImage\n *\n * Subclasses override:\n *   - _buildHandle()   — populate this.domNode with draggable=\"true\" grabber\n *   - onDragStart(e)   — hook into UIManager.addDraggableItem() pipeline\n */\n\nvar NativeDragHandleOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function NativeDragHandleOverlay() {\n    _classCallCheck(this, NativeDragHandleOverlay);\n    return _callSuper(this, NativeDragHandleOverlay, arguments);\n  }\n  _inherits(NativeDragHandleOverlay, _BaseOverlay);\n  return _createClass(NativeDragHandleOverlay, [{\n    key: \"render\",\n    value: function render() {\n      var _this = this;\n      if (!this.domNode) {\n        this.domNode = document.createElement('div');\n      }\n      this.domNode.classList.add('bjs-ovl-native-handle');\n      // Functional handles MUST escape canvas-clip — block drag anchor\n      // explicitly protrudes past the element right edge by 2 px so the\n      // user can grab \"outside\" the block. Clipping at canvas edge would\n      // hide the handle when a block sits at canvas right edge.\n      // See OVERLAY.md §24 Canvas-clip contract.\n      this.domNode.classList.add('bjs-ovl-no-clip');\n      this.domNode.setAttribute('data-interactive', '');\n\n      // Subclass populates the grabber.\n      this._buildHandle();\n\n      // dragstart bubbles from the inner draggable grabber.\n      this.domNode.addEventListener('dragstart', function (e) {\n        return _this._onNativeDragStart(e);\n      });\n    }\n  }, {\n    key: \"_onNativeDragStart\",\n    value: function _onNativeDragStart(e) {\n      e.stopPropagation();\n\n      // HTML5 DnD requires setData + effectAllowed for Safari compatibility.\n      try {\n        e.dataTransfer.setData('text/plain', '');\n        e.dataTransfer.effectAllowed = 'all';\n      } catch (_) {\n        // Non-fatal on some browsers/contexts.\n      }\n\n      // Safari drag-ghost 3-layer workaround (SA invariant I3).\n      // Chrome handles default drag-image capture fine — do NOT setDragImage\n      // on Chrome (can interact badly with ancestor transforms).\n      var ua = typeof navigator !== 'undefined' && navigator.userAgent || '';\n      var isSafari = /safari/i.test(ua) && !/chrome|chromium|crios|android/i.test(ua);\n      if (isSafari && e.dataTransfer && typeof e.dataTransfer.setDragImage === 'function') {\n        try {\n          var clone = this.domNode.cloneNode(true);\n          Object.assign(clone.style, {\n            position: 'fixed',\n            top: '0',\n            left: '-10000px',\n            // off-screen but rendered\n            pointerEvents: 'none',\n            // don't block real pointer input\n            opacity: '0.95',\n            zIndex: '-1'\n          });\n          document.body.appendChild(clone);\n          var rect = this.domNode.getBoundingClientRect();\n          e.dataTransfer.setDragImage(clone, rect.width / 2, rect.height / 2);\n          // Remove clone after Safari has captured (sync in dragstart, so\n          // microtask-0 is enough).\n          setTimeout(function () {\n            if (clone.parentNode) clone.parentNode.removeChild(clone);\n          }, 0);\n        } catch (_) {\n          // Non-fatal — fall back to browser default drag-image.\n        }\n      }\n\n      // Subclass hook to wire into UIManager pipeline.\n      try {\n        this.onDragStart(e);\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[overlay] NativeDragHandleOverlay.onDragStart threw:', err);\n      }\n    }\n\n    /** Subclass populates this.domNode with a grabber that has draggable=\"true\".\n     *  Example: `this.domNode.innerHTML = '<span draggable=\"true\">...</span>';`\n     *  Framework does NOT auto-set draggable on this.domNode because the\n     *  intended grabber is usually a specific inner element. */\n  }, {\n    key: \"_buildHandle\",\n    value: function _buildHandle() {\n      // Default: make the root itself draggable. Subclasses typically override\n      // to put the draggable attribute on an inner grabber span.\n      this.domNode.setAttribute('draggable', 'true');\n    }\n\n    /** Subclass hook — called after Safari workaround is applied. Typical\n     *  implementation hands off to UIManager.addDraggableItem(...) or similar. */\n  }, {\n    key: \"onDragStart\",\n    value: function onDragStart(/* e */) {}\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NativeDragHandleOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/NativeDragHandleOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/PaddingVisualizerOverlay.js":
/*!***********************************************************!*\
  !*** ./src/includes/overlays/PaddingVisualizerOverlay.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./StructureVisualizerOverlay.js */ \"./src/includes/overlays/StructureVisualizerOverlay.js\");\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ui/holedBoxClipPath.js */ \"./src/includes/ui/holedBoxClipPath.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * PaddingVisualizerOverlay — inset guides + per-side region fills that\n * visualise the 4 padding sides of a container element.\n *\n * PLAN_EFFECT W0.2. Implements D4 (Hybrid) + D5 (edge tick marks):\n *   - Quiet state (default, every side): 1px dashed inset guide at the\n *     inner padding boundary. 10–45 % alpha accent. Constant passive\n *     affordance when an element is selected.\n *   - Focused state (one side at a time): 22 % alpha fill + solid inner\n *     border. Triggered by `region:focus` on `builder.events` with\n *     matching `elementUid`. Subsequent `region:blur` reverts to quiet.\n *   - Label + ruler tick marks land in W3.3 + W3.4 (this primitive\n *     already exposes `data-region` hooks those items will extend).\n *\n * Contract:\n *   - trigger: 'select'. Owner element decides whether to return this\n *     overlay from getOverlays() (consumer wiring = W3.1 + W3.5 + W3.6).\n *   - Reads `padding_top` / `padding_right` / `padding_bottom` /\n *     `padding_left` from `element.formatter`. Non-numeric / null values\n *     collapse to 0 (region hidden).\n *   - Structure-preserving: first layoutChildren() builds 4 <div>s once;\n *     subsequent reflows patch `left/top/width/height/display` in place.\n *     No innerHTML churn on every reflow (I5).\n *   - Observer cleanup: BaseOverlay.destroy() disconnects\n *     MutationObserver + ResizeObserver via matchingDomNode. Our\n *     beforeDestroy() additionally disposes bus subscribers (I3).\n *\n * Not part of this primitive (handled elsewhere):\n *   - getOverlays() wiring on BlockElement / CellElement / PageElement\n *     (W3.1 / W3.5 / W3.6, flag-gated by `usePaddingVisualizer`).\n *   - PaddingMarginControl → bus emit on input focus/blur (W3.2).\n *   - Dim-label sub-primitive (W3.3).\n *   - Ruler tick marks (W3.4).\n */\n\n\n\nvar REGION_KEYS = ['padding-top', 'padding-right', 'padding-bottom', 'padding-left'];\nvar PaddingVisualizerOverlay = /*#__PURE__*/function (_StructureVisualizerO) {\n  /**\n   * @param {BaseElement} element\n   * @param {object}      opts\n   * @param {string}      [opts.namespace='padding']   — W3.6. Bus\n   *                       filter scope. Default matches the 5 legacy\n   *                       events (region:focus/blur, panel-focus/blur,\n   *                       padding:pin/unpin). A non-default namespace\n   *                       (e.g. 'block_padding') scopes the overlay\n   *                       to a different control instance on the same\n   *                       element — lets PageElement run two\n   *                       independent padding controls without the\n   *                       bus events cross-talking.\n   * @param {object}      [opts.keys]                  — W3.6. If\n   *                       provided, read padding values from these\n   *                       keys on the element itself (e.g.\n   *                       `{ top: 'block_padding_top', … }`) instead\n   *                       of from `element.formatter.getFormat('padding_*')`.\n   *                       Matches PageElement.block_padding_* which\n   *                       lives as instance props, not in the formatter.\n   * @param {Function}    [opts.readSide]               — W3.7. Most\n   *                       flexible value source: `(side) => number`,\n   *                       called with 'top'/'right'/'bottom'/'left'.\n   *                       Takes precedence over both `opts.keys` and\n   *                       the formatter fallback. Used by BlockElement\n   *                       to cascade to page.block_padding_* when\n   *                       the Block's own formatter value is null.\n   */\n  function PaddingVisualizerOverlay(element) {\n    var _this;\n    var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n    _classCallCheck(this, PaddingVisualizerOverlay);\n    _this = _callSuper(this, PaddingVisualizerOverlay, [element, opts]);\n    _this.namespace = opts.namespace || 'padding';\n    _this.keys = opts.keys || null;\n    _this.readSide = typeof opts.readSide === 'function' ? opts.readSide : null;\n    _this._busDisposers = [];\n    _this._regionNodes = null; // built lazily in layoutChildren\n    // State drivers — recomputed by _recomputeAllStates() whenever any\n    // of these flip.\n    _this._panelFocused = false; // region:panel-focus held\n    _this._sideFocused = null; // which regionKey has focus, if any\n    _this._pinned = false; // Set membership cache\n    return _this;\n  }\n  _inherits(PaddingVisualizerOverlay, _StructureVisualizerO);\n  return _createClass(PaddingVisualizerOverlay, [{\n    key: \"getTrigger\",\n    value: function getTrigger() {\n      return 'select';\n    }\n  }, {\n    key: \"render\",\n    value: function render() {\n      if (!this.domNode) {\n        this.domNode = document.createElement('div');\n      }\n      this.domNode.classList.add('bjs-ovl-padding');\n      // StructureVisualizerOverlay sets pointer-events: none on the root\n      // via CSS; belt-and-suspenders here for clarity.\n      this.domNode.style.pointerEvents = 'none';\n    }\n  }, {\n    key: \"afterMount\",\n    value: function afterMount() {\n      var _this$host$options,\n        _this$host,\n        _this$host2,\n        _this2 = this;\n      // Resolve host. `BaseElement.mountOverlays()` assigns\n      // `overlay.host = element.host` before mount(), but tests\n      // sometimes construct + mount the overlay directly. As a\n      // fallback, read the host off the owned element.\n      if (!this.host && this.element && this.element.host) {\n        this.host = this.element.host;\n      }\n\n      // Self-skip when host's `usePaddingVisualizer` flag is off.\n      // Originally gated at parse-time in CellElement / PageElement /\n      // BlockElement getOverlays(); commit 6 moves the gate here so\n      // those parse-time global reach-ins can drop out entirely\n      // (parse runs before _adopt — host is null then).\n      //\n      // No host AT ALL → mount under \"primitive test\" semantics\n      // (e.g. e2e/padding-visualizer-overlay.spec.js exercising\n      // shape + bus wiring without a Builder). Treat absent host as\n      // \"flag is on\" so the primitive itself stays testable.\n      if (this.host && ((_this$host$options = this.host.options) === null || _this$host$options === void 0 ? void 0 : _this$host$options.usePaddingVisualizer) !== true) {\n        try {\n          this.destroy();\n        } catch (_) {/* not yet mounted */}\n        return;\n      }\n\n      // Bus + pin set come from the owning Builder via host injection\n      // (W3.6: pinKey includes namespace so Page's two padding\n      // controls pin independently). When no host is wired, leave\n      // both null — primitive renders quiet state, no bus traffic.\n      var bus = ((_this$host = this.host) === null || _this$host === void 0 ? void 0 : _this$host.events) || null;\n      var pinSet = ((_this$host2 = this.host) === null || _this$host2 === void 0 ? void 0 : _this$host2._pinnedPaddingElements) || null;\n      if (pinSet && typeof pinSet.has === 'function') {\n        this._pinned = pinSet.has(this._pinKey());\n      }\n      if (bus) {\n        this._busDisposers.push(bus.on('region:panel-focus', function (p) {\n          return _this2._onPanelFocus(p);\n        }));\n        this._busDisposers.push(bus.on('region:panel-blur', function (p) {\n          return _this2._onPanelBlur(p);\n        }));\n        this._busDisposers.push(bus.on('region:focus', function (p) {\n          return _this2._onSideFocus(p);\n        }));\n        this._busDisposers.push(bus.on('region:blur', function (p) {\n          return _this2._onSideBlur(p);\n        }));\n        this._busDisposers.push(bus.on('padding:pin', function (p) {\n          return _this2._onPin(p);\n        }));\n        this._busDisposers.push(bus.on('padding:unpin', function (p) {\n          return _this2._onUnpin(p);\n        }));\n      }\n\n      // Apply pin-derived state immediately so the overlay shows its\n      // initial visual (e.g. a pinned-then-reselected element renders\n      // rich right away without waiting for a bus event).\n      this._recomputeAllStates();\n    }\n  }, {\n    key: \"_pinKey\",\n    value: function _pinKey() {\n      // Back-compat: default namespace uses the bare UID (pre-W3.6\n      // Map members — existing tests still pass). Non-default\n      // namespace composes a distinct key.\n      return this.namespace === 'padding' ? this.element.id : \"\".concat(this.element.id, \"::\").concat(this.namespace);\n    }\n  }, {\n    key: \"beforeDestroy\",\n    value: function beforeDestroy() {\n      var _iterator = _createForOfIteratorHelper(this._busDisposers),\n        _step;\n      try {\n        for (_iterator.s(); !(_step = _iterator.n()).done;) {\n          var dispose = _step.value;\n          try {\n            dispose();\n          } catch (err) {\n            _BJS_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].error('PaddingVisualizerOverlay:dispose', err);\n          }\n        }\n      } catch (err) {\n        _iterator.e(err);\n      } finally {\n        _iterator.f();\n      }\n      this._busDisposers = [];\n      this._regionNodes = null;\n    }\n  }, {\n    key: \"_isMine\",\n    value: function _isMine(payload) {\n      if (!payload || payload.elementUid !== this.element.id) return false;\n      // W3.6 — match namespace. Absent namespace defaults to\n      // 'padding' (back-compat with callers that predate this field).\n      var ns = payload.namespace || 'padding';\n      return ns === this.namespace;\n    }\n  }, {\n    key: \"_onPanelFocus\",\n    value: function _onPanelFocus(payload) {\n      if (!this._isMine(payload)) return;\n      if (this._panelFocused) return;\n      this._panelFocused = true;\n      this._recomputeAllStates();\n    }\n  }, {\n    key: \"_onPanelBlur\",\n    value: function _onPanelBlur(payload) {\n      if (!this._isMine(payload)) return;\n      if (!this._panelFocused) return;\n      this._panelFocused = false;\n      this._recomputeAllStates();\n    }\n  }, {\n    key: \"_onSideFocus\",\n    value: function _onSideFocus(payload) {\n      if (!this._isMine(payload)) return;\n      if (!REGION_KEYS.includes(payload.regionKey)) return;\n      if (this._sideFocused === payload.regionKey) return;\n      this._sideFocused = payload.regionKey;\n      this._recomputeAllStates();\n    }\n  }, {\n    key: \"_onSideBlur\",\n    value: function _onSideBlur(payload) {\n      if (!this._isMine(payload)) return;\n      if (!REGION_KEYS.includes(payload.regionKey)) return;\n      if (this._sideFocused !== payload.regionKey) return;\n      this._sideFocused = null;\n      this._recomputeAllStates();\n    }\n  }, {\n    key: \"_onPin\",\n    value: function _onPin(payload) {\n      if (!this._isMine(payload)) return;\n      if (this._pinned) return;\n      this._pinned = true;\n      this._recomputeAllStates();\n    }\n  }, {\n    key: \"_onUnpin\",\n    value: function _onUnpin(payload) {\n      if (!this._isMine(payload)) return;\n      if (!this._pinned) return;\n      this._pinned = false;\n      this._recomputeAllStates();\n    }\n\n    /**\n     * Per-side state ladder (highest priority wins):\n     *   1. rich-focused  — side's input is currently focused\n     *   2. rich-pinned   — user pinned this element via the toggle\n     *   3. rich-grouped  — panel has any focused input\n     *   4. quiet         — default\n     *\n     * On every flip we recompute ALL 4 sides in one pass so the DOM stays\n     * canonical (no partial updates, no stale states).\n     */\n  }, {\n    key: \"_recomputeAllStates\",\n    value: function _recomputeAllStates() {\n      if (!this._regionNodes) return;\n      for (var _i = 0, _REGION_KEYS = REGION_KEYS; _i < _REGION_KEYS.length; _i++) {\n        var regionKey = _REGION_KEYS[_i];\n        var node = this._regionNodes[regionKey];\n        if (!node) continue;\n        var state = void 0;\n        if (this._sideFocused === regionKey) state = 'rich-focused';else if (this._pinned) state = 'rich-pinned';else if (this._panelFocused) state = 'rich-grouped';else state = 'quiet';\n        if (node.dataset.state !== state) node.dataset.state = state;\n      }\n      // Hatch-box pattern follows pin state (hatch ↔ dots). Cheap class\n      // toggle, no layout thrash.\n      this._syncHatchMode();\n    }\n\n    /**\n     * StructureVisualizerOverlay's position() wires us into every reflow.\n     * Read current padding + resize/position the 4 region divs in place.\n     */\n  }, {\n    key: \"layoutChildren\",\n    value: function layoutChildren() {\n      var _this3 = this;\n      if (!this.domNode) return;\n\n      // W3.6 / W3.7 — source resolution priority:\n      //   1. `opts.readSide` — full callback (most flexible; W3.7\n      //      Block cascade uses it to fall back to page.block_padding).\n      //   2. `opts.keys` — direct instance prop names (PageElement's\n      //      block_padding_* lives on instance, not formatter).\n      //   3. `element.formatter.getFormat('padding_*')` — default.\n      var readSide;\n      if (this.readSide) {\n        readSide = this.readSide;\n      } else if (this.keys) {\n        readSide = function readSide(side) {\n          var propName = _this3.keys[side];\n          if (!propName) return 0;\n          return Number(_this3.element[propName]) || 0;\n        };\n      } else {\n        var f = this.element && this.element.formatter;\n        if (!f || typeof f.getFormat !== 'function') return;\n        readSide = function readSide(side) {\n          return Number(f.getFormat(\"padding_\".concat(side))) || 0;\n        };\n      }\n      var padding = {\n        'padding-top': readSide('top'),\n        'padding-right': readSide('right'),\n        'padding-bottom': readSide('bottom'),\n        'padding-left': readSide('left')\n      };\n\n      // Build region nodes lazily — once per overlay lifetime.\n      if (!this._regionNodes) {\n        this.domNode.innerHTML = '';\n\n        // Unified hatch/dots layer (holed-box primitive). Carries the\n        // pattern fill for the whole padding frame — single gradient\n        // origin, zero seam jog. The 4 per-side regions below keep\n        // borders + labels + per-side rich tint; they no longer render\n        // a background of their own. Pattern swaps based on pin state\n        // (quiet/grouped/focused = --hatch, pinned = --dots) so pinned\n        // reads as a distinct mode at a glance.\n        this._hatchBox = document.createElement('div');\n        this._hatchBox.classList.add('bjs-holed-box', 'bjs-holed-box--hatch');\n        this._hatchBox.dataset.role = 'hatch';\n        this.domNode.appendChild(this._hatchBox);\n        var map = {};\n        for (var _i2 = 0, _REGION_KEYS2 = REGION_KEYS; _i2 < _REGION_KEYS2.length; _i2++) {\n          var regionKey = _REGION_KEYS2[_i2];\n          var d = document.createElement('div');\n          d.classList.add('bjs-ovl-padding-region');\n          d.dataset.region = regionKey;\n          d.dataset.side = regionKey.replace('padding-', '');\n          d.dataset.state = 'quiet';\n          d.style.position = 'absolute';\n          d.style.pointerEvents = 'none';\n          d.style.boxSizing = 'border-box';\n          // Placeholder for W3.3 — dim-label chip. Populated lazily\n          // when the side's state enters rich-*. Kept as a child so\n          // the region can position the chip relative to itself.\n          var label = document.createElement('span');\n          label.classList.add('bjs-ovl-padding-label');\n          label.setAttribute('aria-hidden', 'true');\n          d.appendChild(label);\n          this.domNode.appendChild(d);\n          map[regionKey] = d;\n        }\n        this._regionNodes = map;\n        // Now that nodes exist, push any deferred state in (e.g.\n        // overlay mounted while pinned — afterMount set this._pinned\n        // before layoutChildren ran).\n        this._recomputeAllStates();\n      }\n      var rect = this.domNode.getBoundingClientRect();\n      var W = rect.width;\n      var H = rect.height;\n\n      // Guard: if an author sets padding larger than the element, we still\n      // render something sensible — the opposing side just gets zero\n      // remaining vertical/horizontal space, not a negative strip.\n      var top = Math.max(0, Math.min(padding['padding-top'], H));\n      var bottom = Math.max(0, Math.min(padding['padding-bottom'], H - top));\n      var left = Math.max(0, Math.min(padding['padding-left'], W));\n      var right = Math.max(0, Math.min(padding['padding-right'], W - left));\n      var midH = Math.max(0, H - top - bottom);\n\n      // PLAN_EFFECT W3.3 — compact threshold.\n      //\n      // Below ~14 CSS px of region thickness the label can't fit\n      // inside its strip without dominating it. `data-compact=\"true\"`\n      // short-circuits the CSS display rule that shows the label —\n      // the dashed inner-edge guide stays, only the dimension chip\n      // hides. The structure (DOM, classes) stays identical.\n      var COMPACT_PX = 14;\n      var apply = function apply(node, style, visible, labelText, thickness) {\n        Object.assign(node.style, style);\n        node.style.display = visible ? '' : 'none';\n        var compact = thickness < COMPACT_PX;\n        node.dataset.compact = compact ? 'true' : 'false';\n        var label = node.querySelector('.bjs-ovl-padding-label');\n        if (label) label.textContent = labelText;\n      };\n      apply(this._regionNodes['padding-top'], {\n        top: '0px',\n        left: '0px',\n        right: '0px',\n        width: 'auto',\n        bottom: 'auto',\n        height: top + 'px'\n      }, top > 0, \"\".concat(padding['padding-top'], \" px\"), top);\n      apply(this._regionNodes['padding-bottom'], {\n        bottom: '0px',\n        left: '0px',\n        right: '0px',\n        width: 'auto',\n        top: 'auto',\n        height: bottom + 'px'\n      }, bottom > 0, \"\".concat(padding['padding-bottom'], \" px\"), bottom);\n      apply(this._regionNodes['padding-left'], {\n        top: top + 'px',\n        left: '0px',\n        right: 'auto',\n        bottom: 'auto',\n        width: left + 'px',\n        height: midH + 'px'\n      }, left > 0 && midH > 0, \"\".concat(padding['padding-left'], \" px\"), left);\n      apply(this._regionNodes['padding-right'], {\n        top: top + 'px',\n        right: '0px',\n        left: 'auto',\n        bottom: 'auto',\n        width: right + 'px',\n        height: midH + 'px'\n      }, right > 0 && midH > 0, \"\".concat(padding['padding-right'], \" px\"), right);\n\n      // Holed-box hatch frame — clip-path carves the child (content)\n      // rect so the pattern only shows on the 4 padding strips. The\n      // pattern MODIFIER (hatch vs dots) is toggled in _syncHatchMode()\n      // based on pin state; this block just handles geometry.\n      if (this._hatchBox) {\n        var hasAnyPadding = top + right + bottom + left > 0;\n        this._hatchBox.style.display = hasAnyPadding ? '' : 'none';\n        if (hasAnyPadding) {\n          this._hatchBox.style.clipPath = (0,_ui_holedBoxClipPath_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])({\n            width: W,\n            height: H\n          }, {\n            left: left,\n            top: top,\n            right: W - right,\n            bottom: H - bottom\n          });\n        }\n        this._syncHatchMode();\n      }\n    }\n\n    /**\n     * Swap the hatch box's pattern modifier based on the overlay's\n     * current state mix. Quiet / grouped / focused use `--hatch`\n     * (diagonal stripes). Pinned swaps to `--dots` so the pinned mode\n     * reads as a distinct emphasis tier without changing density band.\n     * Called from layoutChildren (once on build, after every reflow)\n     * and from _recomputeAllStates (when pin / focus flags flip\n     * without a geometry change).\n     */\n  }, {\n    key: \"_syncHatchMode\",\n    value: function _syncHatchMode() {\n      if (!this._hatchBox) return;\n      var wantsDots = !!this._pinned;\n      this._hatchBox.classList.toggle('bjs-holed-box--dots', wantsDots);\n      this._hatchBox.classList.toggle('bjs-holed-box--hatch', !wantsDots);\n    }\n  }]);\n}(_StructureVisualizerOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PaddingVisualizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/PaddingVisualizerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/ResizeCornerOverlay.js":
/*!******************************************************!*\
  !*** ./src/includes/overlays/ResizeCornerOverlay.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DraggableHandleOverlay.js */ \"./src/includes/overlays/DraggableHandleOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && \"function\" == typeof p ? function (t) { return p.apply(e, t); } : p; }\nfunction _get() { return _get = \"undefined\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); }\nfunction _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * ResizeCornerOverlay — 10×10 square handle at a named corner.\n *\n * Use for 2-axis resize gestures:\n *   - Image resize (4 corners on ImageElement — Phase 1.4)\n *   - (future) block max-width/max-height resize\n *\n * Subclass signature:\n *   new ResizeCornerOverlay(element, { corner: 'nw' | 'ne' | 'se' | 'sw', aspectLock: true|false })\n *\n * Drag delta math is delegated to subclass `onDrag(dx, dy, e)`. This class\n * owns positioning (small square at the chosen corner) and cursor hint.\n *\n * Subclasses decide what formatter keys to update (width + height, or\n * max_width + max_height, etc) and optionally enforce aspect-lock.\n */\n\nvar CORNER_CURSORS = {\n  nw: 'nwse-resize',\n  ne: 'nesw-resize',\n  se: 'nwse-resize',\n  sw: 'nesw-resize'\n};\nvar HANDLE_SIZE = 10;\nvar ResizeCornerOverlay = /*#__PURE__*/function (_DraggableHandleOverl) {\n  function ResizeCornerOverlay() {\n    _classCallCheck(this, ResizeCornerOverlay);\n    return _callSuper(this, ResizeCornerOverlay, arguments);\n  }\n  _inherits(ResizeCornerOverlay, _DraggableHandleOverl);\n  return _createClass(ResizeCornerOverlay, [{\n    key: \"render\",\n    value: function render() {\n      _superPropGet(ResizeCornerOverlay, \"render\", this, 3)([]); // pointer handlers + I2 assert\n      this.domNode.classList.add('bjs-ovl-resize-corner');\n      var corner = this.opts.corner || 'se';\n      this.domNode.classList.add(\"bjs-ovl-corner-\".concat(corner));\n      this.domNode.style.cursor = CORNER_CURSORS[corner] || 'nwse-resize';\n\n      // a11y\n      this.domNode.setAttribute('role', 'slider');\n      this.domNode.setAttribute('aria-label', \"Resize (\".concat(corner.toUpperCase(), \" corner)\"));\n      this.domNode.setAttribute('tabindex', '0');\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this = this;\n      var corner = this.opts.corner || 'se';\n      this.element.matchingDomNode(this.domNode, 0, function () {\n        var domRect = _this.element.domNode.getBoundingClientRect();\n        var iframe = _this.element.domNode.ownerDocument.defaultView.frameElement;\n        var iframeRect = iframe ? iframe.getBoundingClientRect() : {\n          top: 0,\n          left: 0\n        };\n        var absTop = iframeRect.top + domRect.top;\n        var absLeft = iframeRect.left + domRect.left;\n        var half = HANDLE_SIZE / 2;\n        var top, left;\n        switch (corner) {\n          case 'nw':\n            top = absTop - half;\n            left = absLeft - half;\n            break;\n          case 'ne':\n            top = absTop - half;\n            left = absLeft + domRect.width - half;\n            break;\n          case 'sw':\n            top = absTop + domRect.height - half;\n            left = absLeft - half;\n            break;\n          case 'se':\n          default:\n            top = absTop + domRect.height - half;\n            left = absLeft + domRect.width - half;\n            break;\n        }\n        Object.assign(_this.domNode.style, {\n          position: 'fixed',\n          top: top + 'px',\n          left: left + 'px',\n          width: HANDLE_SIZE + 'px',\n          height: HANDLE_SIZE + 'px'\n        });\n      });\n    }\n  }]);\n}(_DraggableHandleOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ResizeCornerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/ResizeCornerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/RichDropdownMenuOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/RichDropdownMenuOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t[\"return\"] || t[\"return\"](); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * RichDropdownMenuOverlay — W2.1 (TEXT_INLINE_PLAN, 2026-04-24).\n *\n * macOS / Notion-style sectioned dropdown menu. Standalone primitive —\n * NOT coupled to the inline toolbar. Backs W2.2 (clipboard + format\n * section), W2.3 (paragraph / case / insert / semantic submenus), and\n * any future kebab / overflow menu in BuilderJS.\n *\n * Section + item model (matches Notion's native menu):\n *\n *   {\n *     ariaLabel?: string,            // screen-reader label for root menu\n *     width?: number,                // default 260px (auto-fits long shortcut hints)\n *     sections: [\n *       {\n *         heading?: string,          // optional section label row\n *         items: [\n *           {\n *             id?: string,           // stable key (surfaced to onSelect)\n *             icon?: string,         // material-symbols-rounded glyph (left)\n *             label: string,         // row label (required)\n *             shortcut?: string,     // keyboard hint (right-aligned kbd)\n *             disabled?: boolean,    // dims + aria-disabled=true, skipped by kbd nav\n *             destructive?: boolean, // red text + red hover (delete / remove link)\n *             onActivate?: fn,       // row-specific callback, runs before onSelect\n *             submenu?: {            // nested menu — opens on → / hover / click\n *               ariaLabel?: string,\n *               sections: [...]\n *             },\n *             ariaLabel?: string,    // override label for a11y when icon-only\n *           },\n *           { divider: true },       // same-section horizontal line row\n *         ],\n *       },\n *     ],\n *     onSelect?: fn(id, item),       // global activation callback\n *     onClose?: fn(),                // lifecycle hook\n *     preferredSide?: 'below' | 'above' | 'right' | 'left',  // default 'below'\n *   }\n *\n * Keyboard contract (HARD RULE T5 — real accelerators, not macOS cloning):\n *\n *   ↑ / ↓           move focus prev / next enabled item, wraps, skips\n *                   dividers + headings + disabled.\n *   Home / End      first / last enabled.\n *   Enter / Space   activate current item (fires onActivate + onSelect\n *                   then close() — except submenu rows, which open).\n *   Esc             close menu (if inside submenu, close submenu first\n *                   and return focus to parent row).\n *   →               on a submenu row, open submenu + focus its first.\n *   ←               inside submenu, close submenu + focus parent row.\n *   A–Z type-ahead  1-second buffer; prefix-matches item.label\n *                   (case-insensitive, skipping disabled).\n *\n * ARIA (WCAG 2.1 \"Menu\" pattern):\n *\n *   root          role=\"menu\" + aria-label\n *   item          role=\"menuitem\" + aria-disabled (when disabled)\n *   submenu item  additionally aria-haspopup=\"menu\" + aria-expanded\n *   divider       role=\"separator\" + aria-hidden (purely visual)\n *   heading       role=\"presentation\" (screen-reader visible via grouped items)\n *\n * Dismissal (7-path contract — mirrors W1.2 / W1.3 / W3.1 popovers):\n *\n *   (a) Escape                                            → close (submenu first)\n *   (b) Click outside root                                → close\n *   (c) Activating an item (non-submenu)                  → close\n *   (d) External owner calls .close()                     → close\n *   (e) Focus leaves menu + submenu                       → close (after 1 tick, so Tab still works)\n *   (f) anchorEl removed from DOM                         → close (MutationObserver)\n *   (g) Window scroll / resize                            → reposition (not close)\n *\n * Anchored via `ToolbarPositioner.attach` — so scroll / resize / anchor\n * motion keeps the menu pinned. Preferred side defaults to 'below' (drop-\n * down semantics); submenus default to 'right' (nested menu semantics).\n *\n * Not a BaseOverlay subclass. The inline toolbar + every other caller\n * owns the single-popover invariant themselves (e.g. `toolbar._richMenu`).\n */\n\n\n\nvar DEFAULT_WIDTH = 260;\nvar TYPEAHEAD_WINDOW_MS = 1000;\nvar RichDropdownMenuOverlay = /*#__PURE__*/function () {\n  /**\n   * @param {{\n   *   anchorEl: HTMLElement,\n   *   sections: Array,\n   *   ariaLabel?: string,\n   *   width?: number,\n   *   preferredSide?: 'below'|'above'|'right'|'left',\n   *   onSelect?: Function,\n   *   onClose?: Function,\n   *   parent?: RichDropdownMenuOverlay,  // internal — set on submenus\n   * }} opts\n   */\n  function RichDropdownMenuOverlay(opts) {\n    _classCallCheck(this, RichDropdownMenuOverlay);\n    if (!opts || !opts.anchorEl) {\n      throw new Error('RichDropdownMenuOverlay: opts.anchorEl required');\n    }\n    if (!Array.isArray(opts.sections) || opts.sections.length === 0) {\n      throw new Error('RichDropdownMenuOverlay: opts.sections must be a non-empty array');\n    }\n    this._anchorEl = opts.anchorEl;\n    this._sections = opts.sections;\n    this._ariaLabel = opts.ariaLabel || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('rich_menu.aria_label');\n    this._width = typeof opts.width === 'number' ? opts.width : DEFAULT_WIDTH;\n    this._preferredSide = opts.preferredSide || 'below';\n    this._onSelect = typeof opts.onSelect === 'function' ? opts.onSelect : null;\n    this._onClose = typeof opts.onClose === 'function' ? opts.onClose : null;\n    this._parent = opts.parent || null;\n    this.domNode = null;\n    this._mounted = false;\n    this._positionHandle = null;\n    this._rowEls = []; // enabled item row elements (in tab order)\n    this._focusIndex = -1;\n    this._typeahead = '';\n    this._typeaheadTimer = null;\n    this._openSubmenu = null; // child RichDropdownMenuOverlay instance\n    this._openSubmenuRow = null; // HTMLElement of the row that opened it\n\n    this._onDocKey = null;\n    this._onDocMouseDown = null;\n    this._onFocusOut = null;\n    this._onAnchorDetach = null; // MutationObserver\n  }\n\n  /* ── public lifecycle ─────────────────────────────────────────── */\n  return _createClass(RichDropdownMenuOverlay, [{\n    key: \"open\",\n    value: function open() {\n      var _this = this;\n      if (this._mounted) return;\n      this._build();\n      if (!this.domNode) return;\n      document.body.appendChild(this.domNode);\n      this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n        anchor: function anchor() {\n          return _this._anchorEl.getBoundingClientRect();\n        },\n        target: this.domNode,\n        offset: 6,\n        collisionPadding: 12,\n        preferredSide: this._preferredSide,\n        flip: true\n      });\n      this._registerDismissListeners();\n      this._watchAnchorDetach();\n      this._mounted = true;\n      try {\n        this._anchorEl.setAttribute('aria-expanded', 'true');\n      } catch (_) {}\n      // Focus first enabled row so keyboard users land somewhere actionable.\n      this._focusIndex = this._firstEnabledIndex();\n      this._applyFocusVisual();\n    }\n  }, {\n    key: \"close\",\n    value: function close() {\n      if (!this._mounted && !this.domNode) return;\n      // Cascade — close nested submenu first so focus can return cleanly.\n      if (this._openSubmenu) {\n        try {\n          this._openSubmenu.close();\n        } catch (_) {}\n        this._openSubmenu = null;\n        this._openSubmenuRow = null;\n      }\n      this._unregisterDismissListeners();\n      this._stopWatchingAnchor();\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.dispose();\n        } catch (_) {}\n        this._positionHandle = null;\n      }\n      if (this.domNode && this.domNode.parentNode) {\n        try {\n          this.domNode.parentNode.removeChild(this.domNode);\n        } catch (_) {}\n      }\n      this.domNode = null;\n      this._mounted = false;\n      this._rowEls = [];\n      this._focusIndex = -1;\n      this._clearTypeahead();\n      try {\n        this._anchorEl.setAttribute('aria-expanded', 'false');\n      } catch (_) {}\n      if (this._onClose) {\n        try {\n          this._onClose();\n        } catch (_) {}\n      }\n    }\n  }, {\n    key: \"isOpen\",\n    value: function isOpen() {\n      return this._mounted;\n    }\n\n    /** Re-anchor + reposition without rebuilding. For owners that keep\n     *  the anchor stable but want to nudge placement after layout shifts. */\n  }, {\n    key: \"reposition\",\n    value: function reposition() {\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.reposition();\n        } catch (_) {}\n      }\n    }\n\n    /* ── build ────────────────────────────────────────────────────── */\n  }, {\n    key: \"_build\",\n    value: function _build() {\n      var root = document.createElement('div');\n      root.className = 'bjs-ovl bjs-ovl-rich-menu';\n      root.setAttribute('role', 'menu');\n      root.setAttribute('aria-label', this._ariaLabel);\n      root.setAttribute('data-interactive', '');\n      if (this._parent) root.setAttribute('data-submenu', '1');\n      root.style.width = this._width + 'px';\n\n      // Keyboard owner — capture keydowns on the menu itself so arrow\n      // keys don't bubble into host-page shortcut handlers.\n      root.addEventListener('keydown', this._onMenuKeyDown.bind(this));\n      this._rowEls = [];\n      for (var i = 0; i < this._sections.length; i++) {\n        var section = this._sections[i];\n        // Divider between sections (skip before first).\n        if (i > 0) root.appendChild(this._renderSectionDivider());\n        if (section.heading) root.appendChild(this._renderHeading(section.heading));\n        var _iterator = _createForOfIteratorHelper(section.items || []),\n          _step;\n        try {\n          for (_iterator.s(); !(_step = _iterator.n()).done;) {\n            var item = _step.value;\n            if (item && item.divider) {\n              root.appendChild(this._renderDivider());\n              continue;\n            }\n            var rowEl = this._renderItem(item);\n            root.appendChild(rowEl);\n            if (!item.disabled) this._rowEls.push(rowEl);\n          }\n        } catch (err) {\n          _iterator.e(err);\n        } finally {\n          _iterator.f();\n        }\n      }\n      this.domNode = root;\n    }\n  }, {\n    key: \"_renderHeading\",\n    value: function _renderHeading(text) {\n      var h = document.createElement('div');\n      h.className = 'bjs-rich-menu-heading';\n      h.setAttribute('role', 'presentation');\n      h.textContent = text;\n      return h;\n    }\n  }, {\n    key: \"_renderDivider\",\n    value: function _renderDivider() {\n      var d = document.createElement('div');\n      d.className = 'bjs-rich-menu-divider';\n      d.setAttribute('role', 'separator');\n      d.setAttribute('aria-hidden', 'true');\n      return d;\n    }\n  }, {\n    key: \"_renderSectionDivider\",\n    value: function _renderSectionDivider() {\n      // Same glyph, but distinct class so sections can adjust margin in\n      // CSS (a bit more breathing room than an inline divider).\n      var d = this._renderDivider();\n      d.classList.add('bjs-rich-menu-section-divider');\n      return d;\n    }\n  }, {\n    key: \"_renderItem\",\n    value: function _renderItem(item) {\n      var _this2 = this;\n      var row = document.createElement('button');\n      row.type = 'button';\n      row.className = 'bjs-rich-menu-item';\n      row.setAttribute('role', 'menuitem');\n      if (item.id) row.setAttribute('data-item-id', item.id);\n      var hasSubmenu = !!(item.submenu && Array.isArray(item.submenu.sections) && item.submenu.sections.length);\n      if (hasSubmenu) {\n        row.classList.add('has-submenu');\n        row.setAttribute('aria-haspopup', 'menu');\n        row.setAttribute('aria-expanded', 'false');\n      }\n      if (item.disabled) {\n        row.classList.add('is-disabled');\n        row.setAttribute('aria-disabled', 'true');\n        row.setAttribute('tabindex', '-1');\n      }\n      if (item.destructive) row.classList.add('is-destructive');\n      if (item.ariaLabel) row.setAttribute('aria-label', item.ariaLabel);\n\n      // Left — icon cell (always present so rows line up even when icon missing).\n      var iconCell = document.createElement('span');\n      iconCell.className = 'bjs-rich-menu-item-icon';\n      iconCell.setAttribute('aria-hidden', 'true');\n      if (item.icon) {\n        var ic = document.createElement('span');\n        ic.className = 'material-symbols-rounded';\n        ic.textContent = item.icon;\n        iconCell.appendChild(ic);\n      }\n      row.appendChild(iconCell);\n\n      // Middle — label.\n      var labelCell = document.createElement('span');\n      labelCell.className = 'bjs-rich-menu-item-label';\n      labelCell.textContent = item.label || '';\n      row.appendChild(labelCell);\n\n      // Right — shortcut or submenu caret.\n      if (hasSubmenu) {\n        var caret = document.createElement('span');\n        caret.className = 'bjs-rich-menu-item-caret material-symbols-rounded';\n        caret.setAttribute('aria-hidden', 'true');\n        caret.textContent = 'chevron_right';\n        row.appendChild(caret);\n      } else if (item.shortcut) {\n        var kbd = document.createElement('kbd');\n        kbd.className = 'bjs-rich-menu-item-shortcut';\n        kbd.setAttribute('aria-hidden', 'true'); // label already announces action\n        kbd.textContent = item.shortcut;\n        row.appendChild(kbd);\n      }\n\n      // Interaction — hover to focus (native menu behaviour), click to activate.\n      row.addEventListener('mouseenter', function () {\n        if (item.disabled) return;\n        var idx = _this2._rowEls.indexOf(row);\n        if (idx !== -1) {\n          _this2._focusIndex = idx;\n          _this2._applyFocusVisual();\n        }\n        // Submenu opens on hover (150ms delay would be ideal but native\n        // menus open immediately on hover — we match).\n        if (hasSubmenu && !_this2._submenuIsOpenFor(row)) {\n          _this2._openSubmenuFor(row, item, {\n            focusFirst: false\n          });\n        } else if (!hasSubmenu && _this2._openSubmenu) {\n          // Hovering a non-submenu row should close any open submenu —\n          // matches Notion / macOS.\n          _this2._closeSubmenu();\n        }\n      });\n      row.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        if (item.disabled) return;\n        if (hasSubmenu) {\n          if (_this2._submenuIsOpenFor(row)) {\n            _this2._closeSubmenu();\n          } else {\n            _this2._openSubmenuFor(row, item, {\n              focusFirst: true\n            });\n          }\n          return;\n        }\n        _this2._activate(item);\n      });\n      return row;\n    }\n\n    /* ── activation ───────────────────────────────────────────────── */\n  }, {\n    key: \"_activate\",\n    value: function _activate(item) {\n      // Run row callback, then global onSelect, then close (top-most).\n      var suppressClose = false;\n      try {\n        if (typeof item.onActivate === 'function') {\n          var r = item.onActivate(item);\n          if (r === false) suppressClose = true;\n        }\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:rich-menu] onActivate threw:', err);\n      }\n      if (this._onSelect) {\n        try {\n          var _r = this._onSelect(item.id || null, item);\n          if (_r === false) suppressClose = true;\n        } catch (err) {\n          // eslint-disable-next-line no-console\n          console.error('[bjs:rich-menu] onSelect threw:', err);\n        }\n      }\n      if (suppressClose) return;\n      this._closeAllFromRoot();\n    }\n  }, {\n    key: \"_closeAllFromRoot\",\n    value: function _closeAllFromRoot() {\n      // Walk up the parent chain and close the root.\n      var node = this;\n      while (node._parent) node = node._parent;\n      node.close();\n    }\n\n    /* ── submenu ──────────────────────────────────────────────────── */\n  }, {\n    key: \"_submenuIsOpenFor\",\n    value: function _submenuIsOpenFor(row) {\n      return this._openSubmenu && this._openSubmenuRow === row && this._openSubmenu.isOpen();\n    }\n  }, {\n    key: \"_openSubmenuFor\",\n    value: function _openSubmenuFor(row, item, _ref) {\n      var focusFirst = _ref.focusFirst;\n      if (this._openSubmenu) this._closeSubmenu();\n      var sub = new RichDropdownMenuOverlay({\n        anchorEl: row,\n        sections: item.submenu.sections,\n        ariaLabel: item.submenu.ariaLabel || item.label,\n        width: item.submenu.width,\n        preferredSide: 'right',\n        onSelect: this._onSelect,\n        parent: this\n      });\n      sub.open();\n      this._openSubmenu = sub;\n      this._openSubmenuRow = row;\n      row.setAttribute('aria-expanded', 'true');\n      if (focusFirst && sub.isOpen()) {\n        sub._focusIndex = sub._firstEnabledIndex();\n        sub._applyFocusVisual();\n      }\n    }\n  }, {\n    key: \"_closeSubmenu\",\n    value: function _closeSubmenu() {\n      if (!this._openSubmenu) return;\n      try {\n        this._openSubmenu.close();\n      } catch (_) {}\n      if (this._openSubmenuRow) {\n        try {\n          this._openSubmenuRow.setAttribute('aria-expanded', 'false');\n        } catch (_) {}\n      }\n      this._openSubmenu = null;\n      this._openSubmenuRow = null;\n    }\n\n    /* ── focus ────────────────────────────────────────────────────── */\n  }, {\n    key: \"_firstEnabledIndex\",\n    value: function _firstEnabledIndex() {\n      return this._rowEls.length ? 0 : -1;\n    }\n  }, {\n    key: \"_lastEnabledIndex\",\n    value: function _lastEnabledIndex() {\n      return this._rowEls.length - 1;\n    }\n  }, {\n    key: \"_applyFocusVisual\",\n    value: function _applyFocusVisual() {\n      for (var i = 0; i < this._rowEls.length; i++) {\n        var el = this._rowEls[i];\n        var isFocused = i === this._focusIndex;\n        el.classList.toggle('is-focus', isFocused);\n        if (isFocused) {\n          try {\n            el.focus({\n              preventScroll: true\n            });\n          } catch (_) {\n            try {\n              el.focus();\n            } catch (__) {}\n          }\n        }\n      }\n    }\n  }, {\n    key: \"_moveFocus\",\n    value: function _moveFocus(delta) {\n      if (!this._rowEls.length) return;\n      var idx = this._focusIndex;\n      if (idx < 0) idx = delta > 0 ? -1 : 0;\n      idx = (idx + delta + this._rowEls.length) % this._rowEls.length;\n      this._focusIndex = idx;\n      this._applyFocusVisual();\n    }\n  }, {\n    key: \"_focusTo\",\n    value: function _focusTo(idx) {\n      if (idx < 0 || idx >= this._rowEls.length) return;\n      this._focusIndex = idx;\n      this._applyFocusVisual();\n    }\n\n    /* ── keyboard ─────────────────────────────────────────────────── */\n  }, {\n    key: \"_onMenuKeyDown\",\n    value: function _onMenuKeyDown(e) {\n      // If a submenu is open it handles its own keydown via its own\n      // listener; don't double-process here.\n      if (this._openSubmenu && this._openSubmenu.isOpen()) return;\n      var key = e.key;\n      if (key === 'ArrowDown') {\n        e.preventDefault();\n        this._moveFocus(1);\n        return;\n      }\n      if (key === 'ArrowUp') {\n        e.preventDefault();\n        this._moveFocus(-1);\n        return;\n      }\n      if (key === 'Home') {\n        e.preventDefault();\n        this._focusTo(this._firstEnabledIndex());\n        return;\n      }\n      if (key === 'End') {\n        e.preventDefault();\n        this._focusTo(this._lastEnabledIndex());\n        return;\n      }\n      if (key === 'ArrowRight') {\n        var row = this._currentRow();\n        var item = this._currentItem();\n        if (row && item && item.submenu) {\n          e.preventDefault();\n          this._openSubmenuFor(row, item, {\n            focusFirst: true\n          });\n        }\n        return;\n      }\n      if (key === 'ArrowLeft') {\n        // Close this menu and return focus to parent row.\n        if (this._parent) {\n          e.preventDefault();\n          this._parent._closeSubmenu();\n          try {\n            this._parent._applyFocusVisual();\n          } catch (_) {}\n        }\n        return;\n      }\n      if (key === 'Enter' || key === ' ') {\n        var _item = this._currentItem();\n        var _row = this._currentRow();\n        if (!_item || !_row) return;\n        e.preventDefault();\n        if (_item.submenu) {\n          this._openSubmenuFor(_row, _item, {\n            focusFirst: true\n          });\n        } else {\n          this._activate(_item);\n        }\n        return;\n      }\n      if (key === 'Escape') {\n        e.preventDefault();\n        e.stopPropagation();\n        if (this._parent) {\n          // Inside submenu — close self, return to parent.\n          this._parent._closeSubmenu();\n          try {\n            this._parent._applyFocusVisual();\n          } catch (_) {}\n        } else {\n          this.close();\n        }\n        return;\n      }\n      // Type-ahead: printable single-char.\n      if (key.length === 1 && /\\S/.test(key)) {\n        this._typeaheadPush(key);\n      }\n    }\n  }, {\n    key: \"_currentRow\",\n    value: function _currentRow() {\n      return this._focusIndex >= 0 && this._focusIndex < this._rowEls.length ? this._rowEls[this._focusIndex] : null;\n    }\n  }, {\n    key: \"_currentItem\",\n    value: function _currentItem() {\n      var row = this._currentRow();\n      if (!row) return null;\n      var id = row.getAttribute('data-item-id');\n      // Walk sections to find the item matching id OR DOM identity.\n      var _iterator2 = _createForOfIteratorHelper(this._sections),\n        _step2;\n      try {\n        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n          var section = _step2.value;\n          var _iterator3 = _createForOfIteratorHelper(section.items || []),\n            _step3;\n          try {\n            for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n              var it = _step3.value;\n              if (it && it.divider) continue;\n              if (id && it.id === id) return it;\n              if (!id && row.querySelector('.bjs-rich-menu-item-label') && row.querySelector('.bjs-rich-menu-item-label').textContent === it.label) return it;\n            }\n          } catch (err) {\n            _iterator3.e(err);\n          } finally {\n            _iterator3.f();\n          }\n        }\n      } catch (err) {\n        _iterator2.e(err);\n      } finally {\n        _iterator2.f();\n      }\n      return null;\n    }\n  }, {\n    key: \"_typeaheadPush\",\n    value: function _typeaheadPush(ch) {\n      var _this3 = this;\n      this._typeahead += ch.toLowerCase();\n      if (this._typeaheadTimer) clearTimeout(this._typeaheadTimer);\n      this._typeaheadTimer = setTimeout(function () {\n        return _this3._clearTypeahead();\n      }, TYPEAHEAD_WINDOW_MS);\n      // Find first enabled row whose label starts with the buffer.\n      for (var i = 0; i < this._rowEls.length; i++) {\n        var el = this._rowEls[i];\n        var label = (el.querySelector('.bjs-rich-menu-item-label') || {}).textContent || '';\n        if (label.toLowerCase().startsWith(this._typeahead)) {\n          this._focusTo(i);\n          return;\n        }\n      }\n    }\n  }, {\n    key: \"_clearTypeahead\",\n    value: function _clearTypeahead() {\n      this._typeahead = '';\n      if (this._typeaheadTimer) {\n        clearTimeout(this._typeaheadTimer);\n        this._typeaheadTimer = null;\n      }\n    }\n\n    /* ── dismissal ────────────────────────────────────────────────── */\n  }, {\n    key: \"_registerDismissListeners\",\n    value: function _registerDismissListeners() {\n      var _this4 = this;\n      // Esc + arrow keys are on the menu itself (root keydown). These\n      // are the document-level fallbacks for outside-click + focus-loss.\n      this._onDocKey = function (e) {\n        // Only handle Escape at doc-level when focus is NOT inside the\n        // menu (menu's own handler already owns that path). This\n        // catches host-app Escape while the menu DOES still want to\n        // close — e.g. user clicked canvas then hit Esc.\n        if (e.key !== 'Escape') return;\n        if (_this4.domNode && document.activeElement && _this4.domNode.contains(document.activeElement)) return;\n        if (_this4._parent) return; // only root handles doc-level Esc\n        e.stopPropagation();\n        _this4.close();\n      };\n      document.addEventListener('keydown', this._onDocKey, true);\n      this._onDocMouseDown = function (e) {\n        if (!_this4.domNode) return;\n        if (_this4._parent) return; // only root handles outside-click; submenu is a child of root's closure\n        var t = e.target;\n        // Click inside root → keep open.\n        if (_this4.domNode.contains(t)) return;\n        // Click inside open submenu → keep open.\n        if (_this4._openSubmenu && _this4._openSubmenu.domNode && _this4._openSubmenu.domNode.contains(t)) return;\n        // Click on anchor that opened the menu → toggle-off\n        // (owner's click handler runs first; we stay idle so owner's\n        // toggle logic works. But if click is elsewhere on the anchor\n        // chain, defensive-close.)\n        if (t && _this4._anchorEl && _this4._anchorEl.contains(t)) return;\n        _this4.close();\n      };\n      // Defer so the click that opened us doesn't instantly close.\n      setTimeout(function () {\n        if (_this4._mounted) document.addEventListener('mousedown', _this4._onDocMouseDown, true);\n      }, 0);\n    }\n  }, {\n    key: \"_unregisterDismissListeners\",\n    value: function _unregisterDismissListeners() {\n      if (this._onDocKey) {\n        document.removeEventListener('keydown', this._onDocKey, true);\n        this._onDocKey = null;\n      }\n      if (this._onDocMouseDown) {\n        document.removeEventListener('mousedown', this._onDocMouseDown, true);\n        this._onDocMouseDown = null;\n      }\n    }\n\n    /* ── anchor-detach watcher ────────────────────────────────────── */\n  }, {\n    key: \"_watchAnchorDetach\",\n    value: function _watchAnchorDetach() {\n      var _this5 = this;\n      if (typeof MutationObserver === 'undefined') return;\n      var ownerDoc = this._anchorEl.ownerDocument || document;\n      var root = ownerDoc.body || ownerDoc.documentElement;\n      if (!root) return;\n      this._onAnchorDetach = new MutationObserver(function () {\n        if (!_this5._anchorEl || !_this5._anchorEl.isConnected) {\n          _this5.close();\n        }\n      });\n      try {\n        this._onAnchorDetach.observe(root, {\n          childList: true,\n          subtree: true\n        });\n      } catch (_) {\n        this._onAnchorDetach = null;\n      }\n    }\n  }, {\n    key: \"_stopWatchingAnchor\",\n    value: function _stopWatchingAnchor() {\n      if (this._onAnchorDetach) {\n        try {\n          this._onAnchorDetach.disconnect();\n        } catch (_) {}\n        this._onAnchorDetach = null;\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RichDropdownMenuOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/RichDropdownMenuOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/StructureVisualizerOverlay.js":
/*!*************************************************************!*\
  !*** ./src/includes/overlays/StructureVisualizerOverlay.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseOverlay.js */ \"./src/includes/BaseOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }\nfunction _possibleConstructorReturn(t, e) { if (e && (\"object\" == _typeof(e) || \"function\" == typeof e)) return e; if (void 0 !== e) throw new TypeError(\"Derived constructors may only return object or undefined\"); return _assertThisInitialized(t); }\nfunction _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); return e; }\nfunction _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }\nfunction _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }\nfunction _inherits(t, e) { if (\"function\" != typeof e && null !== e) throw new TypeError(\"Super expression must either be null or a function\"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, \"prototype\", { writable: !1 }), e && _setPrototypeOf(t, e); }\nfunction _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }\n/*\n * StructureVisualizerOverlay — full-element transparent cover that draws\n * child-structure hints.\n *\n * Use for showing the logical structure of a container:\n *   - Grid cell boundaries + column separators (Phase 1.3)\n *   - (future) flex-track markers, table-column gutters\n *\n * Subclass signature:\n *   class GridStructureOverlay extends StructureVisualizerOverlay {\n *     layoutChildren() { this.domNode.innerHTML = ''; ...draw per-child hints... }\n *   }\n *\n * Relayout on reflow is automatic — `position()` passes `layoutChildren` to\n * matchingDomNode's afterPosSize hook, so it fires on every iframe scroll /\n * resize / mutation / element reflow.\n *\n * The root is `pointer-events: none` (pass-through) — children that should\n * catch clicks/drags add `data-interactive` attribute or their own\n * pointer-events: auto rule. Ensure child primitives (EdgeResizerOverlay\n * instances, insert buttons) match this pattern — they already do via\n * `.bjs-ovl-handle` / `.bjs-ovl-action-bar` selectors in overlays CSS.\n */\n\nvar StructureVisualizerOverlay = /*#__PURE__*/function (_BaseOverlay) {\n  function StructureVisualizerOverlay() {\n    _classCallCheck(this, StructureVisualizerOverlay);\n    return _callSuper(this, StructureVisualizerOverlay, arguments);\n  }\n  _inherits(StructureVisualizerOverlay, _BaseOverlay);\n  return _createClass(StructureVisualizerOverlay, [{\n    key: \"render\",\n    value: function render() {\n      this.domNode = document.createElement('div');\n      this.domNode.classList.add('bjs-ovl-structure');\n      // Root pass-through; interactive children opt in.\n      this.domNode.style.pointerEvents = 'none';\n    }\n  }, {\n    key: \"position\",\n    value: function position() {\n      var _this = this;\n      // matchingDomNode's afterPosSize fires on every reflow; delegate child\n      // relayout there so the visualisation stays glued to current geometry.\n      this.element.matchingDomNode(this.domNode, 0, null, function () {\n        try {\n          _this.layoutChildren();\n        } catch (err) {\n          /* eslint-disable-next-line no-console */console.error('[overlay] layoutChildren threw:', err);\n        }\n      });\n    }\n\n    /** Subclass override: rebuild per-child visual hints inside this.domNode.\n     *  Called on every reflow. MUST be cheap (no async, no network). Default\n     *  is a no-op — useful for a bare \"this element is selected\" glow. */\n  }, {\n    key: \"layoutChildren\",\n    value: function layoutChildren() {\n      // no-op\n    }\n  }]);\n}(_BaseOverlay_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StructureVisualizerOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/StructureVisualizerOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/TextColorPopoverOverlay.js":
/*!**********************************************************!*\
  !*** ./src/includes/overlays/TextColorPopoverOverlay.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ui/ColorPalettePicker.js */ \"./src/includes/ui/ColorPalettePicker.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextColorPopoverOverlay — floating panel for picking a text color\n * (foreground, `execCommand('foreColor')`) or a highlight color\n * (background, `execCommand('hiliteColor')`).\n *\n * TEXT_INLINE_PLAN W1.2 (2026-04-20). 2026-04-21 refactor: the palette +\n * custom + eyedropper body is now a shared primitive\n * (`src/includes/ui/ColorPalettePicker.js`). This overlay is a thin chrome\n * host — mount/unmount, anchor positioning, dismissal wiring — around\n * the primitive. The sidebar `ColorPickerControl` will embed the same\n * primitive in a follow-up phase so canvas + sidebar share one grand\n * Google-style palette UX.\n *\n * Single class, two modes. `mode: 'foreColor' | 'hiliteColor'`.\n */\n\n\n\n\nvar RECENT_MAX = 10;\nvar TextColorPopoverOverlay = /*#__PURE__*/function () {\n  /**\n   * @param {TextInlineToolbarOverlay} toolbar — owner. Used to call back\n   *   `_applyColor` so the popover shares the toolbar's char-offset\n   *   selection save/restore pipeline.\n   * @param {{mode: 'foreColor'|'hiliteColor', anchorBtn: HTMLElement, initialColor?: string}} opts\n   */\n  function TextColorPopoverOverlay(toolbar, opts) {\n    _classCallCheck(this, TextColorPopoverOverlay);\n    if (!toolbar || !opts || !opts.anchorBtn) {\n      throw new Error('TextColorPopoverOverlay: toolbar + opts.anchorBtn required');\n    }\n    if (opts.mode !== 'foreColor' && opts.mode !== 'hiliteColor') {\n      throw new Error('TextColorPopoverOverlay: opts.mode must be foreColor or hiliteColor');\n    }\n    this._toolbar = toolbar;\n    this._mode = opts.mode;\n    this._anchorBtn = opts.anchorBtn;\n    this._initialColor = opts.initialColor || null;\n    this.domNode = null;\n    this._picker = null;\n    this._positionHandle = null;\n    this._onDocKey = null;\n    this._onDocMouseDown = null;\n    this._mounted = false;\n  }\n\n  /* ── public lifecycle ─────────────────────────────────────────── */\n  return _createClass(TextColorPopoverOverlay, [{\n    key: \"open\",\n    value: function open() {\n      var _this = this;\n      if (this._mounted) return;\n      try {\n        this._build();\n        document.body.appendChild(this.domNode);\n        this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].attach({\n          anchor: function anchor() {\n            return _this._anchorBtn.getBoundingClientRect();\n          },\n          target: this.domNode,\n          offset: 8,\n          collisionPadding: 12,\n          preferredSide: 'below',\n          flip: true\n        });\n        this._registerDismissListeners();\n        this._mounted = true;\n      } catch (err) {\n        // eslint-disable-next-line no-console\n        console.error('[bjs:text-color-popover] open failed:', err);\n        this.close();\n      }\n    }\n  }, {\n    key: \"close\",\n    value: function close() {\n      if (!this._mounted && !this.domNode) return;\n      this._unregisterDismissListeners();\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.dispose();\n        } catch (_) {}\n        this._positionHandle = null;\n      }\n      if (this.domNode && this.domNode.parentNode) {\n        try {\n          this.domNode.parentNode.removeChild(this.domNode);\n        } catch (_) {}\n      }\n      this.domNode = null;\n      this._picker = null;\n      this._mounted = false;\n    }\n  }, {\n    key: \"isOpen\",\n    value: function isOpen() {\n      return this._mounted;\n    }\n\n    /* ── build ────────────────────────────────────────────────────── */\n  }, {\n    key: \"_build\",\n    value: function _build() {\n      var _this2 = this;\n      var p = document.createElement('div');\n      p.className = 'bjs-ovl bjs-ovl-color-popover';\n      p.setAttribute('role', 'dialog');\n      p.setAttribute('aria-label', this._titleLabel());\n      p.setAttribute('data-interactive', '');\n      p.setAttribute('data-mode', this._mode);\n\n      // Preserve iframe selection across mousedown in the popover body.\n      p.addEventListener('mousedown', function (e) {\n        if (e.target && e.target.closest('input, textarea, select, button[data-role=\"eyedropper\"]')) return;\n        e.preventDefault();\n      });\n\n      // Shared primitive. Callbacks: pick → apply+close; reset → clear+close.\n      this._picker = new _ui_ColorPalettePicker_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]({\n        value: this._initialColor,\n        recent: this._getRecentColors(),\n        title: this._titleLabel(),\n        onPick: function onPick(hex) {\n          if (hex === null) {\n            _this2._handleReset();\n            return;\n          }\n          _this2._handlePick(hex);\n        },\n        onReset: function onReset() {\n          return _this2._handleReset();\n        }\n      });\n      p.appendChild(this._picker.domNode);\n      this.domNode = p;\n    }\n\n    /* ── apply ─────────────────────────────────────────────────────── */\n  }, {\n    key: \"_handlePick\",\n    value: function _handlePick(hex) {\n      var applied = this._toolbar._applyColor(this._mode, hex, this._anchorBtn);\n      if (applied !== false) {\n        this._pushRecent(hex);\n        // Update the toolbar button's color indicator (underline bar).\n        this._toolbar._updateColorIndicator(this._mode, hex);\n        this.close();\n      }\n    }\n  }, {\n    key: \"_handleReset\",\n    value: function _handleReset() {\n      var applied = this._mode === 'foreColor' ? this._toolbar._applyColor('foreColor', 'inherit', this._anchorBtn) : this._toolbar._applyColor('hiliteColor', 'transparent', this._anchorBtn);\n      if (applied !== false) {\n        this._toolbar._updateColorIndicator(this._mode, null);\n        this.close();\n      }\n    }\n\n    /* ── helpers ───────────────────────────────────────────────────── */\n  }, {\n    key: \"_titleLabel\",\n    value: function _titleLabel() {\n      return this._mode === 'foreColor' ? _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('inline_toolbar.text_color') : _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('inline_toolbar.highlight_color');\n    }\n  }, {\n    key: \"_getRecentColors\",\n    value: function _getRecentColors() {\n      var builder = this._toolbar && this._toolbar._builder;\n      if (!builder) return [];\n      var key = this._mode === 'foreColor' ? '_recentTextColors' : '_recentHighlightColors';\n      var arr = Array.isArray(builder[key]) ? builder[key] : [];\n      return arr.slice();\n    }\n  }, {\n    key: \"_pushRecent\",\n    value: function _pushRecent(hex) {\n      var builder = this._toolbar && this._toolbar._builder;\n      if (!builder) return;\n      if (hex === 'inherit' || hex === 'transparent') return;\n      var key = this._mode === 'foreColor' ? '_recentTextColors' : '_recentHighlightColors';\n      var arr = Array.isArray(builder[key]) ? builder[key].slice() : [];\n      var idx = arr.findIndex(function (c) {\n        return c.toLowerCase() === hex.toLowerCase();\n      });\n      if (idx >= 0) arr.splice(idx, 1);\n      arr.unshift(hex);\n      if (arr.length > RECENT_MAX) arr = arr.slice(0, RECENT_MAX);\n      builder[key] = arr;\n    }\n\n    /* ── dismiss ───────────────────────────────────────────────────── */\n  }, {\n    key: \"_registerDismissListeners\",\n    value: function _registerDismissListeners() {\n      var _this3 = this;\n      this._onDocKey = function (e) {\n        if (e.key === 'Escape') {\n          e.stopPropagation();\n          _this3.close();\n        }\n      };\n      document.addEventListener('keydown', this._onDocKey, true);\n      this._onDocMouseDown = function (e) {\n        if (!_this3.domNode) return;\n        var t = e.target;\n        if (_this3.domNode.contains(t)) return;\n        if (t && _this3._anchorBtn && _this3._anchorBtn.contains(t)) return;\n        _this3.close();\n      };\n      setTimeout(function () {\n        if (_this3._mounted) document.addEventListener('mousedown', _this3._onDocMouseDown, true);\n      }, 0);\n    }\n  }, {\n    key: \"_unregisterDismissListeners\",\n    value: function _unregisterDismissListeners() {\n      if (this._onDocKey) {\n        document.removeEventListener('keydown', this._onDocKey, true);\n        this._onDocKey = null;\n      }\n      if (this._onDocMouseDown) {\n        document.removeEventListener('mousedown', this._onDocMouseDown, true);\n        this._onDocMouseDown = null;\n      }\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextColorPopoverOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/TextColorPopoverOverlay.js?");

/***/ }),

/***/ "./src/includes/overlays/TextInlineToolbarOverlay.js":
/*!***********************************************************!*\
  !*** ./src/includes/overlays/TextInlineToolbarOverlay.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _BJS_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BJS.js */ \"./src/includes/BJS.js\");\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\n/* harmony import */ var _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../ToolbarPositioner.js */ \"./src/includes/ToolbarPositioner.js\");\n/* harmony import */ var _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../InlineSanitizer.js */ \"./src/includes/InlineSanitizer.js\");\n/* harmony import */ var _TextColorPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./TextColorPopoverOverlay.js */ \"./src/includes/overlays/TextColorPopoverOverlay.js\");\n/* harmony import */ var _LinkOnSelectionPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./LinkOnSelectionPopoverOverlay.js */ \"./src/includes/overlays/LinkOnSelectionPopoverOverlay.js\");\n/* harmony import */ var _FontPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./FontPopoverOverlay.js */ \"./src/includes/overlays/FontPopoverOverlay.js\");\n/* harmony import */ var _AIRewritePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AIRewritePopoverOverlay.js */ \"./src/includes/overlays/AIRewritePopoverOverlay.js\");\n/* harmony import */ var _RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./RichDropdownMenuOverlay.js */ \"./src/includes/overlays/RichDropdownMenuOverlay.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * TextInlineToolbarOverlay — floating pill that follows the user's text\n * selection and exposes the everyday RANGE-LEVEL formatting controls\n * (bold / italic / underline / strike) plus mount points for the later\n * popover waves (color, link, More menu, Font, Advanced, AI rewrite).\n *\n * Text alignment (L/C/R/J) was shipped in the first W1.1 cut but RETIRED\n * 2026-04-20 per TEXT_INLINE_PLAN D13/D14 — text-align is a BLOCK-LEVEL\n * CSS property (`<p style=\"text-align\">` not `<span style>`) so inline\n * align buttons would falsely promise range scope while actually mutating\n * the whole block (scope-honesty test FAIL — see BUILDER.md Hardened\n * Rules §D13). Alignment now lives exclusively in the sidebar\n * AlignControl on the owning element.\n *\n * TEXT_INLINE_PLAN W1.1 (2026-04-20). Primary release of Wave 1. Sits on\n * top of the W0 foundation:\n *   - W0.2b stamps `data-bjs-inline-text` on every inline-edit surface.\n *   - W0.3 (TextSelectionTracker) emits `text-selection:change` +\n *     `text-selection:clear` on `builder.events`.\n *   - W0.4 (ToolbarPositioner.attach) keeps the pill pinned to the\n *     selection range through scroll / resize / anchor-resize.\n *   - W0.5 (InlineSanitizer.normalize) canonicalises browser-divergent\n *     markup after every `execCommand` (Safari `<b>` → `<strong>` etc).\n *\n * Unlike BaseOverlay, this toolbar is NOT element-scoped — selection is\n * the source of truth (HARD RULE T1). A single instance lives on the\n * Builder (`builder._textInlineToolbar`), subscribes to the bus, mounts\n * on change, unmounts on clear. Element click never opens it; focus\n * loss alone never opens it; only a non-collapsed selection inside a\n * `[data-bjs-inline-text]` host does.\n *\n * Format apply never rerenders (HARD RULE T2). Bold / italic / underline\n * / strike all go through `iframeDoc.execCommand()`, then\n * `InlineSanitizer.normalize()` runs in-place on the host so round-trip\n * invariants hold, then the tracker is asked for a fresh read so button\n * `.is-active` / `.is-mixed` states update without a full re-render.\n *\n * Stub buttons (Color W1.2 · Highlight W1.2 · Link W1.3 · More W2.1 ·\n * Font W3.1 · Advanced W4.1 · AI W6.1) are visible but inert in W1.1.\n * They emit `text-inline-toolbar:open-{key}` on the bus so the later\n * waves can subscribe without re-authoring the chrome. Their tooltip\n * carries the wave hint (\"Coming in W1.2\") and they render the\n * `.is-stub` state so the user sees the button works but the popover\n * isn't wired yet. HARD RULE T6 — failure is visible, not silent.\n *\n * Iframe coordinate translation: the tracker's range lives in the\n * builder iframe; the toolbar lives in the parent document. We\n * translate iframe-relative rects into parent-viewport coords before\n * feeding them to ToolbarPositioner. (The same trick\n * FloatingActionBarOverlay.position() uses.)\n */\n\n\n\n\n\n\n\n\n\n\n\n// Stub map: button key → wave that ships it, for tooltip hint + bus event.\nvar STUB_WAVES = Object.freeze({\n  'text-color': 'W1.2',\n  'highlight-color': 'W1.2',\n  'link': 'W1.3',\n  'more': 'W2.1',\n  'font': 'W3.1',\n  'advanced': 'W4.1',\n  'ai-rewrite': 'W6.1',\n  'paragraph-style': 'W2.3'\n});\n\n// WYSIWYG production-render gate. A stub button renders on the live\n// canvas toolbar ONLY when its flag here is true; otherwise the user\n// sees only wired-up buttons (honest \"what-ships-is-what-user-sees\"\n// discipline). Showcase mocks (demo/_partials/design/components.php +\n// host-side static spec pages) render every button statically regardless\n// of this gate — the showcase\n// is a DESIGN SPEC reference, production is a WYSIWYG manifest. When a\n// wave ships (W1.2/W1.3/W2.1/W2.3/W3.1/W4.1/W6.1), flip the corresponding\n// flag here AND add the real behaviour — the stub's bus-event path stays\n// until the real popover subscriber replaces it.\nvar SHIPPED_STUBS = Object.freeze({\n  'paragraph-style': false,\n  // W2.3 Paragraph Styles submenu\n  'text-color': true,\n  // W1.2 Color popover (foreground) — SHIPPED\n  'highlight-color': true,\n  // W1.2 Color popover (background) — SHIPPED\n  'link': true,\n  // W1.3 Link-on-Selection popover — SHIPPED\n  'more': true,\n  // W2.2 More menu (clipboard + format + remove-link)\n  'font': true,\n  // W3.1 Font popover — SHIPPED\n  'advanced': false,\n  // W4.1 Advanced popover (dual-mount shared controls)\n  'ai-rewrite': true // W6.1 AI rewrite popover — SHIPPED\n});\n\n// Simple in-toolbar icon name → Material Symbols glyph. We rely on the\n// parent document having the font loaded (builder chrome + the engine's\n// peer-dep auto-injector both ensure this). InlineIcons registry exists\n// but its catalog does not cover\n// formatting glyphs — using the font directly is both cheaper and\n// keeps the icon set swappable at theme level.\nvar ICONS = Object.freeze({\n  bold: 'format_bold',\n  italic: 'format_italic',\n  underline: 'format_underlined',\n  strikeThrough: 'strikethrough_s',\n  // `title` and `ink_highlighter` are the underline-free variants — the\n  // colored-bar indicator under the icon is rendered by CSS, so the icon\n  // MUST NOT carry its own built-in underline (would double up into a\n  // broken-looking stripe). `format_color_text` + `format_ink_highlighter`\n  // DO carry a baked line and are rejected.\n  'text-color': 'title',\n  'highlight-color': 'ink_highlighter',\n  link: 'link',\n  'align-left': 'format_align_left',\n  'align-center': 'format_align_center',\n  'align-right': 'format_align_right',\n  'align-justify': 'format_align_justify',\n  more: 'more_horiz',\n  font: 'text_format',\n  advanced: 'tune',\n  'ai-rewrite': 'auto_awesome'\n});\n\n// Platform-aware modifier glyph for tooltip shortcut hints.\nvar MOD = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/.test(navigator.platform) ? '⌘' : 'Ctrl+';\nvar TextInlineToolbarOverlay = /*#__PURE__*/function () {\n  /**\n   * @param {Builder} host — owner. Reads `host.iframe`,\n   *   `host.events`, `host.textSelectionTracker`.\n   */\n  function TextInlineToolbarOverlay(host) {\n    _classCallCheck(this, TextInlineToolbarOverlay);\n    if (!host) {\n      throw new Error('TextInlineToolbarOverlay: host is required');\n    }\n    this._builder = host;\n    this._bus = host.events;\n    this.domNode = null;\n    this._mounted = false;\n    this._positionHandle = null;\n    this._currentPayload = null;\n    this._offChange = null;\n    this._offClear = null;\n    // W1.2 color popover singleton — at most one popover open at a\n    // time. When user clicks Text color while Highlight popover is\n    // already open, we swap (close → open) rather than stack.\n    this._colorPopover = null;\n    // W1.3 link-on-selection popover singleton. Same single-popover\n    // invariant — opening Link while a color popover is open swaps;\n    // opening a color popover while Link is open swaps the other way.\n    this._linkPopover = null;\n    // W3.1 font popover singleton. Extends the invariant to 4-way\n    // {color, link, font, AI} — at most ONE popover open.\n    this._fontPopover = null;\n    // W2.2 more-menu singleton (RichDropdownMenuOverlay instance).\n    // Extends the single-popover invariant to 5-way {color, link, font,\n    // more, AI} — opening any of the 5 closes the other 4.\n    this._moreMenu = null;\n    // W2.2 clipboard snapshot — captured at menu-open time so async\n    // clipboard writes survive the menu-close focus race. Threaded\n    // through `_runMoreMenuAction` as a local so the subsequent\n    // close cascade can null this field without affecting in-flight\n    // copy/cut promises.\n    this._moreSnapshot = null;\n    this._onSelectionChange = this._onSelectionChange.bind(this);\n    this._onSelectionClear = this._onSelectionClear.bind(this);\n  }\n\n  /** Subscribe to the selection bus. Idempotent. */\n  return _createClass(TextInlineToolbarOverlay, [{\n    key: \"attach\",\n    value: function attach() {\n      if (this._offChange) return;\n      this._offChange = this._bus.on('text-selection:change', this._onSelectionChange);\n      this._offClear = this._bus.on('text-selection:clear', this._onSelectionClear);\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-toolbar', 'attached');\n    }\n\n    /** Unsubscribe + tear down any mounted chrome. */\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      if (this._offChange) {\n        this._offChange();\n        this._offChange = null;\n      }\n      if (this._offClear) {\n        this._offClear();\n        this._offClear = null;\n      }\n      this._unmount();\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-toolbar', 'destroyed');\n    }\n\n    /* ── Bus handlers ─────────────────────────────────────────────── */\n  }, {\n    key: \"_onSelectionChange\",\n    value: function _onSelectionChange(payload) {\n      this._currentPayload = payload;\n      if (!this._mounted) {\n        this._mount();\n      } else {\n        this._updateButtonStates(payload);\n        if (this._positionHandle) this._positionHandle.reposition();\n      }\n    }\n  }, {\n    key: \"_onSelectionClear\",\n    value: function _onSelectionClear() {\n      this._unmount();\n    }\n\n    /* ── Mount / unmount ──────────────────────────────────────────── */\n  }, {\n    key: \"_mount\",\n    value: function _mount() {\n      var _this = this;\n      if (this._mounted) return;\n      try {\n        this._build();\n        document.body.appendChild(this.domNode);\n        this._updateButtonStates(this._currentPayload);\n        this._positionHandle = _ToolbarPositioner_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"].attach({\n          anchor: function anchor() {\n            return _this._computeAnchorRect();\n          },\n          target: this.domNode,\n          offset: 8,\n          collisionPadding: 12,\n          preferredSide: 'above',\n          flip: true\n        });\n        this._mounted = true;\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].log('text-inline-toolbar:mount', this._currentPayload && this._currentPayload.elementUid);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:mount', err);\n        this._unmount(); // partial-state rollback\n      }\n    }\n  }, {\n    key: \"_unmount\",\n    value: function _unmount() {\n      if (!this._mounted && !this.domNode) return;\n      // Any open color / link / font / more popover goes with the toolbar\n      // — otherwise they would linger anchored to a button that no longer\n      // exists. 5-way single-popover invariant (color/link/font/more/AI).\n      this._closeColorPopover();\n      this._closeLinkPopover();\n      this._closeFontPopover();\n      this._closeMoreMenu();\n      if (this._activePopover && typeof this._activePopover.close === 'function') {\n        try {\n          this._activePopover.close();\n        } catch (_) {}\n        this._activePopover = null;\n      }\n      if (this._positionHandle) {\n        try {\n          this._positionHandle.dispose();\n        } catch (_) {}\n        this._positionHandle = null;\n      }\n      if (this.domNode && this.domNode.parentNode) {\n        try {\n          this.domNode.parentNode.removeChild(this.domNode);\n        } catch (_) {}\n      }\n      this.domNode = null;\n      this._mounted = false;\n      this._currentPayload = null;\n    }\n  }, {\n    key: \"_computeAnchorRect\",\n    value: function _computeAnchorRect() {\n      var payload = this._currentPayload;\n      if (!payload || !payload.range) return null;\n      // Range.getBoundingClientRect() returns viewport coords in the\n      // range's OWN document (the iframe). Translate by the iframe's\n      // own rect in the parent document. Same translation the\n      // FloatingActionBarOverlay uses for its corner anchor.\n      var rr = payload.range.getBoundingClientRect();\n      var iframe = this._builder.iframe;\n      var ir = iframe ? iframe.getBoundingClientRect() : {\n        top: 0,\n        left: 0\n      };\n      return {\n        top: ir.top + rr.top,\n        left: ir.left + rr.left,\n        width: rr.width,\n        height: rr.height\n      };\n    }\n\n    /* ── DOM build ────────────────────────────────────────────────── */\n  }, {\n    key: \"_build\",\n    value: function _build() {\n      var t = document.createElement('div');\n      t.className = 'bjs-ovl bjs-ovl-text-inline-toolbar';\n      t.setAttribute('role', 'toolbar');\n      t.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.aria_label'));\n      t.setAttribute('data-interactive', '');\n\n      // Preserve iframe selection: mousedown on a button would steal\n      // focus from the iframe and collapse the selection; preventing\n      // default on mousedown keeps the range alive so execCommand\n      // targets the right text. Same trick RichTextControl uses.\n      t.addEventListener('mousedown', function (e) {\n        // Let inputs / color pickers still take focus (future W1.2),\n        // but block bare button clicks. In W1.1 every target is a\n        // button or divider so the blanket preventDefault is safe.\n        if (e.target && e.target.closest('input, textarea, select')) return;\n        e.preventDefault();\n      });\n\n      // Group 1 — paragraph-style chip (W2.3). Hidden until shipped.\n      if (SHIPPED_STUBS['paragraph-style']) {\n        t.appendChild(this._makeParagraphStyleChip());\n        t.appendChild(this._divider());\n      }\n\n      // Group 2 — formatting toggles (always shipped — W1.1 core)\n      var formatGroup = this._group();\n      formatGroup.appendChild(this._makeToggleButton('bold', MOD + 'B'));\n      formatGroup.appendChild(this._makeToggleButton('italic', MOD + 'I'));\n      formatGroup.appendChild(this._makeToggleButton('underline', MOD + 'U'));\n      formatGroup.appendChild(this._makeToggleButton('strikeThrough', MOD + '⇧X'));\n      t.appendChild(formatGroup);\n\n      // Group 3 — align segmented (restored 2026-04-20, reimplemented\n      // via formatter write path — NOT execCommand). Both sidebar\n      // AlignControl and this inline group now write to the same\n      // `element.formatter.text_align` + call `element.applyFormatStyles()`\n      // → single write path, no data-race. After write, we emit\n      // `formatter:change` on `builder.events` so any subscribing sidebar\n      // Control (future W4.1 dual-mount) re-reads state. Refer to\n      // TEXT_INLINE_PLAN §10 D13 v5 for the single-write-path rule.\n      t.appendChild(this._divider());\n      var alignGroup = this._group('bjs-toolbar-segmented');\n      alignGroup.setAttribute('role', 'group');\n      alignGroup.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.alignment'));\n      alignGroup.appendChild(this._makeAlignButton('left', MOD + '⇧L'));\n      alignGroup.appendChild(this._makeAlignButton('center', MOD + '⇧E'));\n      alignGroup.appendChild(this._makeAlignButton('right', MOD + '⇧R'));\n      alignGroup.appendChild(this._makeAlignButton('justify', MOD + '⇧J'));\n      t.appendChild(alignGroup);\n\n      // Group 4 — color + link (W1.2 shipped, W1.3 still stub).\n      if (SHIPPED_STUBS['text-color'] || SHIPPED_STUBS['highlight-color'] || SHIPPED_STUBS['link']) {\n        t.appendChild(this._divider());\n        var colorGroup = this._group();\n        // W1.2 — TextColorPopoverOverlay opens on click (foreColor).\n        if (SHIPPED_STUBS['text-color']) colorGroup.appendChild(this._makeColorButton('text-color', 'foreColor', 'inline_toolbar.text_color'));\n        // W1.2 — TextColorPopoverOverlay opens on click (hiliteColor).\n        if (SHIPPED_STUBS['highlight-color']) colorGroup.appendChild(this._makeColorButton('highlight-color', 'hiliteColor', 'inline_toolbar.highlight_color'));\n        if (SHIPPED_STUBS['link']) colorGroup.appendChild(this._makeLinkButton('inline_toolbar.link', MOD + 'K'));\n        t.appendChild(colorGroup);\n      }\n\n      // Group 5 — More / Font / Advanced / AI stubs (W2.1 / W3.1 / W4.1 / W6.1).\n      var hasMiscStub = SHIPPED_STUBS['more'] || SHIPPED_STUBS['font'] || SHIPPED_STUBS['advanced'] || SHIPPED_STUBS['ai-rewrite'];\n      if (hasMiscStub) {\n        t.appendChild(this._divider());\n        var miscGroup = this._group();\n        if (SHIPPED_STUBS['more']) miscGroup.appendChild(this._makeMoreButton('inline_toolbar.more'));\n        if (SHIPPED_STUBS['font']) miscGroup.appendChild(this._makeFontButton('inline_toolbar.font'));\n        if (SHIPPED_STUBS['advanced']) miscGroup.appendChild(this._makeStubButton('advanced', 'inline_toolbar.advanced'));\n        if (SHIPPED_STUBS['ai-rewrite']) miscGroup.appendChild(this._makeAIRewriteButton('inline_toolbar.ai_rewrite'));\n        t.appendChild(miscGroup);\n      }\n      this.domNode = t;\n    }\n  }, {\n    key: \"_divider\",\n    value: function _divider() {\n      var d = document.createElement('span');\n      d.className = 'bjs-toolbar-divider';\n      d.setAttribute('aria-hidden', 'true');\n      return d;\n    }\n  }, {\n    key: \"_group\",\n    value: function _group(extraClass) {\n      var g = document.createElement('span');\n      g.className = 'bjs-toolbar-group' + (extraClass ? ' ' + extraClass : '');\n      return g;\n    }\n  }, {\n    key: \"_makeIconBtn\",\n    value: function _makeIconBtn(iconKey) {\n      var btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = 'bjs-ovl-pill bjs-toolbar-btn';\n      if (ICONS[iconKey]) {\n        var ic = document.createElement('span');\n        ic.className = 'material-symbols-rounded';\n        ic.setAttribute('aria-hidden', 'true');\n        ic.textContent = ICONS[iconKey];\n        btn.appendChild(ic);\n      }\n      return btn;\n    }\n  }, {\n    key: \"_makeToggleButton\",\n    value: function _makeToggleButton(cmd, shortcutHint) {\n      var _this2 = this;\n      var btn = this._makeIconBtn(cmd);\n      var labelKey = 'inline_toolbar.' + (cmd === 'bold' ? 'bold' : cmd === 'italic' ? 'italic' : cmd === 'underline' ? 'underline' : 'strikethrough');\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-pressed', 'false');\n      btn.setAttribute('data-format-key', cmd);\n      btn.setAttribute('data-tooltip', shortcutHint ? \"\".concat(label, \" (\").concat(shortcutHint, \")\") : label);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this2._applyToggle(cmd, btn);\n      });\n      return btn;\n    }\n\n    /**\n     * W1.2 — Color button. Renders like a stub button (same icon, same\n     * chrome) but on click opens `TextColorPopoverOverlay` anchored to\n     * itself. `mode` picks which execCommand target to write.\n     */\n  }, {\n    key: \"_makeColorButton\",\n    value: function _makeColorButton(key, mode, labelKey) {\n      var _this3 = this;\n      var btn = this._makeIconBtn(key);\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      btn.classList.add('bjs-toolbar-color-btn');\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-haspopup', 'dialog');\n      btn.setAttribute('aria-expanded', 'false');\n      btn.setAttribute('data-color-key', key);\n      btn.setAttribute('data-color-mode', mode);\n      btn.setAttribute('data-tooltip', label);\n      // DO NOT set `--bjs-color-current` inline at mount. CSS renders\n      // the bar in theme-default text color via the fallback chain\n      // `var(--bjs-color-current, var(--bjs-text, #111))`; inline var\n      // only gets set AFTER the user actually picks a color via the\n      // popover. User rule 2026-04-21: \"dùng màu chữ khi reset hay\n      // ban đầu mới mở chưa chọn\".\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this3._toggleColorPopover(mode, btn);\n      });\n      return btn;\n    }\n\n    /**\n     * Update the underline color bar on the toolbar's Text-color or\n     * Highlight button. Called by `TextColorPopoverOverlay` after a\n     * successful apply OR after Reset. HARD RULE T6: this is a visible\n     * confirmation the user's pick landed.\n     *\n     * `hex` semantics:\n     *   - Valid hex / rgb string → set inline `--bjs-color-current` so\n     *     that color wins over the CSS theme-default fallback.\n     *   - `null` / `'transparent'` / `'inherit'` / undefined → REMOVE\n     *     the inline var so the CSS falls back to `var(--bjs-text)`\n     *     (light=#111, dark=#e5e7eb). This is the Reset / initial path.\n     */\n  }, {\n    key: \"_updateColorIndicator\",\n    value: function _updateColorIndicator(mode, hex) {\n      if (!this.domNode) return;\n      var btn = this.domNode.querySelector(\"[data-color-mode=\\\"\".concat(mode, \"\\\"]\"));\n      if (!btn) return;\n      var isResetLike = !hex || hex === 'transparent' || hex === 'inherit';\n      if (isResetLike) {\n        btn.style.removeProperty('--bjs-color-current');\n      } else {\n        btn.style.setProperty('--bjs-color-current', hex);\n      }\n    }\n  }, {\n    key: \"_toggleColorPopover\",\n    value: function _toggleColorPopover(mode, btn) {\n      // If an existing popover is open — either from the same button\n      // (toggle-off) or a sibling color button (swap) — close first.\n      if (this._colorPopover && this._colorPopover.isOpen()) {\n        var sameAnchor = this._colorPopover._anchorBtn === btn;\n        this._closeColorPopover();\n        if (sameAnchor) return; // toggle-off\n      }\n      // Sibling single-popover invariant — close any open link / font /\n      // more popover so at most one of {color, link, font, more, AI} is\n      // visible.\n      this._closeLinkPopover();\n      this._closeFontPopover();\n      this._closeMoreMenu();\n      var initial = this._readInitialColor(mode);\n      var pop = new _TextColorPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"](this, {\n        mode: mode,\n        anchorBtn: btn,\n        initialColor: initial\n      });\n      pop.open();\n      this._colorPopover = pop;\n      btn.setAttribute('aria-expanded', 'true');\n    }\n  }, {\n    key: \"_closeColorPopover\",\n    value: function _closeColorPopover() {\n      if (this._colorPopover) {\n        var prevBtn = this._colorPopover._anchorBtn;\n        try {\n          this._colorPopover.close();\n        } catch (_) {}\n        this._colorPopover = null;\n        if (prevBtn) prevBtn.setAttribute('aria-expanded', 'false');\n      }\n    }\n\n    /**\n     * W1.3 — Link-on-selection button. Renders like the color buttons\n     * (own chrome class, aria-haspopup, aria-expanded) and on click opens\n     * the `LinkOnSelectionPopoverOverlay` anchored to itself.\n     */\n  }, {\n    key: \"_makeLinkButton\",\n    value: function _makeLinkButton(labelKey, shortcutHint) {\n      var _this4 = this;\n      var btn = this._makeIconBtn('link');\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      btn.classList.add('bjs-toolbar-link-btn');\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-haspopup', 'dialog');\n      btn.setAttribute('aria-expanded', 'false');\n      btn.setAttribute('data-link-btn', '1');\n      btn.setAttribute('data-tooltip', shortcutHint ? \"\".concat(label, \" (\").concat(shortcutHint, \")\") : label);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this4._toggleLinkPopover(btn);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_toggleLinkPopover\",\n    value: function _toggleLinkPopover(btn) {\n      // Toggle-off if same button while already open.\n      if (this._linkPopover && this._linkPopover.isOpen()) {\n        this._closeLinkPopover();\n        return;\n      }\n      // Single-popover invariant — close sibling popovers before opening.\n      this._closeColorPopover();\n      this._closeFontPopover();\n      this._closeMoreMenu();\n      if (this._activePopover && typeof this._activePopover.close === 'function') {\n        try {\n          this._activePopover.close();\n        } catch (_) {}\n        this._activePopover = null;\n      }\n      var pop = new _LinkOnSelectionPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_5__[\"default\"](this, {\n        anchorBtn: btn\n      });\n      pop.open();\n      this._linkPopover = pop;\n    }\n  }, {\n    key: \"_closeLinkPopover\",\n    value: function _closeLinkPopover() {\n      if (this._linkPopover) {\n        try {\n          this._linkPopover.close();\n        } catch (_) {}\n        this._linkPopover = null;\n      }\n    }\n\n    /**\n     * W3.1 — Font button. Opens `FontPopoverOverlay` anchored to itself.\n     * Same mount/dismiss chrome as W1.3's Link button.\n     */\n  }, {\n    key: \"_makeFontButton\",\n    value: function _makeFontButton(labelKey) {\n      var _this5 = this;\n      var btn = this._makeIconBtn('font');\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      btn.classList.add('bjs-toolbar-font-btn');\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-haspopup', 'dialog');\n      btn.setAttribute('aria-expanded', 'false');\n      btn.setAttribute('data-font-btn', '1');\n      btn.setAttribute('data-tooltip', label);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this5._toggleFontPopover(btn);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_toggleFontPopover\",\n    value: function _toggleFontPopover(btn) {\n      if (this._fontPopover && this._fontPopover.isOpen()) {\n        this._closeFontPopover();\n        return;\n      }\n      // Single-popover invariant — close sibling popovers first.\n      this._closeColorPopover();\n      this._closeLinkPopover();\n      this._closeMoreMenu();\n      if (this._activePopover && typeof this._activePopover.close === 'function') {\n        try {\n          this._activePopover.close();\n        } catch (_) {}\n        this._activePopover = null;\n      }\n      var pop = new _FontPopoverOverlay_js__WEBPACK_IMPORTED_MODULE_6__[\"default\"](this, {\n        anchorBtn: btn\n      });\n      pop.open();\n      this._fontPopover = pop;\n    }\n  }, {\n    key: \"_closeFontPopover\",\n    value: function _closeFontPopover() {\n      if (this._fontPopover) {\n        try {\n          this._fontPopover.close();\n        } catch (_) {}\n        this._fontPopover = null;\n      }\n    }\n\n    /**\n     * W2.2 — More button. Opens a `RichDropdownMenuOverlay` anchored to\n     * itself carrying the curated clipboard + format + remove-link rows.\n     * Same single-popover invariant as the other 4 popovers — opening\n     * this closes {color, link, font, AI}; opening any of those closes\n     * this.\n     */\n  }, {\n    key: \"_makeMoreButton\",\n    value: function _makeMoreButton(labelKey) {\n      var _this6 = this;\n      var btn = this._makeIconBtn('more');\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      btn.classList.add('bjs-toolbar-more-btn');\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-haspopup', 'menu');\n      btn.setAttribute('aria-expanded', 'false');\n      btn.setAttribute('data-more-btn', '1');\n      btn.setAttribute('data-tooltip', label);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this6._toggleMoreMenu(btn);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_toggleMoreMenu\",\n    value: function _toggleMoreMenu(btn) {\n      var _this7 = this;\n      if (this._moreMenu && this._moreMenu.isOpen()) {\n        this._closeMoreMenu();\n        return;\n      }\n      this._closeColorPopover();\n      this._closeLinkPopover();\n      this._closeFontPopover();\n      if (this._activePopover && typeof this._activePopover.close === 'function') {\n        try {\n          this._activePopover.close();\n        } catch (_) {}\n        this._activePopover = null;\n      }\n      // Snapshot the selection's HTML + text + range-character-offsets NOW,\n      // before the menu mounts — by the time a menu row's onSelect fires,\n      // the menu DOM has already unmounted + focus may have bounced,\n      // invalidating any live range reference. Snapshot lets the async\n      // clipboard path always have stable data (HARD RULE T6 — failure\n      // visible only when the operation genuinely can't complete, not\n      // because focus raced with the menu close).\n      this._moreSnapshot = this._captureSelectionSnapshot();\n      var sections = this._buildMoreMenuSections();\n      var menu = new _RichDropdownMenuOverlay_js__WEBPACK_IMPORTED_MODULE_8__[\"default\"]({\n        anchorEl: btn,\n        ariaLabel: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.more'),\n        sections: sections,\n        preferredSide: 'below',\n        // Activation runs BEFORE close — we need the selection to\n        // still be live. `onSelect` returns nothing so the menu\n        // auto-closes after the action handler schedules its work.\n        onSelect: function onSelect(id) {\n          _this7._runMoreMenuAction(id, btn);\n        },\n        onClose: function onClose() {\n          _this7._moreMenu = null;\n        }\n      });\n      menu.open();\n      this._moreMenu = menu;\n    }\n  }, {\n    key: \"_closeMoreMenu\",\n    value: function _closeMoreMenu() {\n      if (this._moreMenu) {\n        var wasOpen = this._moreMenu.isOpen();\n        try {\n          this._moreMenu.close();\n        } catch (_) {}\n        this._moreMenu = null;\n        if (wasOpen && this.domNode) {\n          var btn = this.domNode.querySelector('[data-more-btn]');\n          if (btn) btn.setAttribute('aria-expanded', 'false');\n        }\n      }\n      // Drop the snapshot when the menu closes WITHOUT firing an action\n      // (Escape / outside-click / toggle-off). Actions that fire first\n      // consume the snapshot synchronously via `_runMoreMenuAction`'s\n      // dispatched handler, which runs BEFORE close cascade. This leaves\n      // `_moreSnapshot` stale for the async path — that's intentional,\n      // the async handler already captured its reference synchronously.\n      this._moreSnapshot = null;\n    }\n\n    /**\n     * Shape the 3-section dropdown for the current selection. Disabled\n     * states are computed once at menu-open time (static config — matches\n     * RichDropdownMenuOverlay's contract). Paste Format disabled when\n     * `builder._formatClipboard` empty; Remove Link disabled unless the\n     * selection sits inside an `<a>` descendant of the inline-text host.\n     * HARD RULE T6 — disabled rows render with `.is-disabled` visual +\n     * `aria-disabled`, skipped from keyboard nav.\n     *\n     * Paste / Paste Plain / Paste and Match Style items were CUT\n     * 2026-04-24 (post-W2.2 initial ship). Native ⌘V / Ctrl+V / right-\n     * click Paste routes through `BaseElement._wireInlineEdit`'s native\n     * `paste` listener which sanitises via InlineSanitizer without any\n     * permission prompt — reliable path. The menu versions required\n     * `navigator.clipboard.read()` which routinely rejects for focus /\n     * permission / secure-context reasons, flashing the More button red\n     * without landing anything — violates HARD RULE T6 (\"failure visible,\n     * not silent\") + T5 (\"menu density — every item must work\"). Cutting\n     * them removes the broken-looking UX; ⌘V is the one clean path.\n     */\n  }, {\n    key: \"_buildMoreMenuSections\",\n    value: function _buildMoreMenuSections() {\n      var hasFormatClip = !!this._builder._formatClipboard;\n      var linkScope = this._detectRemoveLinkState();\n      var removeLinkDisabled = linkScope !== 'removable';\n      return [{\n        heading: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.heading_clipboard'),\n        items: [{\n          id: 'cut',\n          icon: 'content_cut',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.cut'),\n          shortcut: MOD + 'X'\n        }, {\n          id: 'copy',\n          icon: 'content_copy',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.copy'),\n          shortcut: MOD + 'C'\n        }]\n      }, {\n        heading: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.heading_format'),\n        items: [{\n          id: 'copy-format',\n          icon: 'colorize',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.copy_format'),\n          shortcut: MOD + '⌥C'\n        }, {\n          id: 'paste-format',\n          icon: 'format_paint',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.paste_format'),\n          shortcut: MOD + '⌥V',\n          disabled: !hasFormatClip\n        }, {\n          id: 'clear-format',\n          icon: 'format_clear',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.clear_format'),\n          shortcut: MOD + '\\\\'\n        }]\n      }, {\n        items: [{\n          id: 'remove-link',\n          icon: 'link_off',\n          label: _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('more_menu.remove_link'),\n          shortcut: MOD + '⇧K',\n          destructive: true,\n          disabled: removeLinkDisabled\n        }]\n      }];\n    }\n\n    /**\n     * 'removable'     — selection is inside a descendant `<a>`; `unlink`\n     *                   will strip the anchor from the range.\n     * 'host-anchor'   — host itself is an `<a>` (LinkElement). The anchor\n     *                   wraps the whole element; unlinking inside it would\n     *                   produce a broken LinkElement. Sidebar owns this\n     *                   case (matches W1.3's host-anchor banner).\n     * 'no-link'       — selection has no ancestor `<a>` inside the host.\n     *\n     * Only 'removable' leaves Remove Link enabled.\n     */\n  }, {\n    key: \"_detectRemoveLinkState\",\n    value: function _detectRemoveLinkState() {\n      var payload = this._currentPayload;\n      if (!payload || !payload.range) return 'no-link';\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) return 'no-link';\n      var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n      if (!host) return 'no-link';\n      if (host.tagName && host.tagName.toLowerCase() === 'a') return 'host-anchor';\n      var ac = payload.range.commonAncestorContainer;\n      var cursor = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n      while (cursor && cursor !== host) {\n        if (cursor.tagName && cursor.tagName.toLowerCase() === 'a') return 'removable';\n        cursor = cursor.parentElement;\n      }\n      return 'no-link';\n    }\n  }, {\n    key: \"_runMoreMenuAction\",\n    value: function _runMoreMenuAction(id, moreBtn) {\n      // Capture the snapshot into a local at dispatch time. The menu\n      // close cascade nulls `this._moreSnapshot` synchronously after\n      // onSelect returns — the async clipboard actions would otherwise\n      // race that cleanup and read a null. Local-scoped = immune.\n      var snap = this._moreSnapshot;\n      switch (id) {\n        case 'cut':\n          this._doCut(moreBtn, snap);\n          break;\n        case 'copy':\n          this._doCopy(moreBtn, snap);\n          break;\n        case 'copy-format':\n          this._doCopyFormat(moreBtn);\n          break;\n        case 'paste-format':\n          this._doPasteFormat(moreBtn);\n          break;\n        case 'clear-format':\n          this._doClearFormat(moreBtn);\n          break;\n        case 'remove-link':\n          this._doRemoveLink(moreBtn);\n          break;\n      }\n    }\n\n    /* ── W2.2 clipboard actions ──────────────────────────────────── */\n\n    /**\n     * Put the current selection onto the OS clipboard as BOTH `text/html`\n     * (preserves inline markup — bold / italic / links) AND `text/plain`\n     * (for paste targets that don't accept HTML). Uses the modern async\n     * Clipboard API; falls back to `writeText` when the runtime lacks\n     * `ClipboardItem`. HARD RULE T6 — failure flashes the More button.\n     */\n  }, {\n    key: \"_copyRangeToClipboard\",\n    value: (function () {\n      var _copyRangeToClipboard2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(btn, snap) {\n        var html, text, live, item, ok;\n        return _regeneratorRuntime().wrap(function _callee$(_context) {\n          while (1) switch (_context.prev = _context.next) {\n            case 0:\n              // Prefer the snapshot taken at menu-open time — the menu close\n              // cascade may have disturbed the iframe selection / focus by the\n              // time this async path resumes. Fall back to live-read only if no\n              // snapshot was threaded through (e.g. future keyboard-shortcut\n              // caller outside the menu context).\n              html = snap && snap.html != null ? snap.html : '';\n              text = snap && snap.text != null ? snap.text : '';\n              if (snap) {\n                _context.next = 9;\n                break;\n              }\n              live = this._captureSelectionSnapshot();\n              if (live) {\n                _context.next = 7;\n                break;\n              }\n              this._flashError(btn);\n              return _context.abrupt(\"return\", false);\n            case 7:\n              html = live.html;\n              text = live.text;\n            case 9:\n              if (!(!text && !html)) {\n                _context.next = 12;\n                break;\n              }\n              this._flashError(btn);\n              return _context.abrupt(\"return\", false);\n            case 12:\n              if (!(typeof navigator !== 'undefined' && navigator.clipboard && typeof window !== 'undefined' && typeof window.ClipboardItem === 'function' && typeof navigator.clipboard.write === 'function')) {\n                _context.next = 23;\n                break;\n              }\n              _context.prev = 13;\n              item = new window.ClipboardItem({\n                'text/html': new Blob([html || text], {\n                  type: 'text/html'\n                }),\n                'text/plain': new Blob([text || ''], {\n                  type: 'text/plain'\n                })\n              });\n              _context.next = 17;\n              return navigator.clipboard.write([item]);\n            case 17:\n              return _context.abrupt(\"return\", true);\n            case 20:\n              _context.prev = 20;\n              _context.t0 = _context[\"catch\"](13);\n              _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:copy:clipboardItem', _context.t0);\n              // fall through\n            case 23:\n              if (!(navigator.clipboard && typeof navigator.clipboard.writeText === 'function')) {\n                _context.next = 33;\n                break;\n              }\n              _context.prev = 24;\n              _context.next = 27;\n              return navigator.clipboard.writeText(text || '');\n            case 27:\n              return _context.abrupt(\"return\", true);\n            case 30:\n              _context.prev = 30;\n              _context.t1 = _context[\"catch\"](24);\n              _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:copy:writeText', _context.t1);\n              // fall through\n            case 33:\n              // Last-resort sync fallback — widely compatible, works in non-secure\n              // contexts, and runs regardless of async clipboard permission state.\n              // Uses a hidden textarea + `document.execCommand('copy')`. Plain-text\n              // only (HTML is lost) but the user gets a working clipboard.\n              ok = this._execCommandCopyFallback(text || html || '');\n              if (!ok) this._flashError(btn);\n              return _context.abrupt(\"return\", ok);\n            case 36:\n            case \"end\":\n              return _context.stop();\n          }\n        }, _callee, this, [[13, 20], [24, 30]]);\n      }));\n      function _copyRangeToClipboard(_x, _x2) {\n        return _copyRangeToClipboard2.apply(this, arguments);\n      }\n      return _copyRangeToClipboard;\n    }())\n  }, {\n    key: \"_execCommandCopyFallback\",\n    value: function _execCommandCopyFallback(text) {\n      if (!text) return false;\n      var ta = null;\n      try {\n        ta = document.createElement('textarea');\n        ta.value = text;\n        ta.setAttribute('readonly', '');\n        ta.style.cssText = 'position:fixed;top:0;left:-9999px;opacity:0;pointer-events:none;';\n        document.body.appendChild(ta);\n        var prevActive = document.activeElement;\n        ta.focus();\n        ta.select();\n        var ok = document.execCommand && document.execCommand('copy');\n        // Restore focus so the toolbar's single-popover invariant +\n        // subsequent tracker reads aren't disturbed.\n        if (prevActive && prevActive !== document.body && typeof prevActive.focus === 'function') {\n          try {\n            prevActive.focus();\n          } catch (_) {}\n        }\n        return !!ok;\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:copy:execCommand', err);\n        return false;\n      } finally {\n        if (ta && ta.parentNode) {\n          try {\n            ta.parentNode.removeChild(ta);\n          } catch (_) {}\n        }\n      }\n    }\n  }, {\n    key: \"_doCopy\",\n    value: function () {\n      var _doCopy2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(btn, snap) {\n        return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n          while (1) switch (_context2.prev = _context2.next) {\n            case 0:\n              _context2.next = 2;\n              return this._copyRangeToClipboard(btn, snap);\n            case 2:\n            case \"end\":\n              return _context2.stop();\n          }\n        }, _callee2, this);\n      }));\n      function _doCopy(_x3, _x4) {\n        return _doCopy2.apply(this, arguments);\n      }\n      return _doCopy;\n    }()\n  }, {\n    key: \"_doCut\",\n    value: function () {\n      var _doCut2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(btn, snap) {\n        var copied, payload;\n        return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n          while (1) switch (_context3.prev = _context3.next) {\n            case 0:\n              _context3.next = 2;\n              return this._copyRangeToClipboard(btn, snap);\n            case 2:\n              copied = _context3.sent;\n              payload = this._currentPayload;\n              if (!(!payload || !payload.range)) {\n                _context3.next = 7;\n                break;\n              }\n              if (copied) this._flashError(btn);\n              return _context3.abrupt(\"return\");\n            case 7:\n              try {\n                payload.range.deleteContents();\n                this._normalizeHost();\n                this._notifyContentChanged();\n                this._refreshTracker();\n              } catch (err) {\n                _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:cut-delete', err);\n                this._flashError(btn);\n              }\n            case 8:\n            case \"end\":\n              return _context3.stop();\n          }\n        }, _callee3, this);\n      }));\n      function _doCut(_x5, _x6) {\n        return _doCut2.apply(this, arguments);\n      }\n      return _doCut;\n    }()\n    /**\n     * Clone the current selection into a serialisable `{ html, text }`\n     * snapshot. Called at menu-open time so the async clipboard actions\n     * always have stable data, even if the menu close disturbs focus.\n     */\n  }, {\n    key: \"_captureSelectionSnapshot\",\n    value: function _captureSelectionSnapshot() {\n      var payload = this._currentPayload;\n      if (!payload || !payload.range) return null;\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) return null;\n      try {\n        var frag = payload.range.cloneContents();\n        var tmp = idoc.createElement('div');\n        tmp.appendChild(frag);\n        return {\n          html: tmp.innerHTML,\n          text: payload.range.toString()\n        };\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:snapshot', err);\n        return null;\n      }\n    }\n\n    /* ── W2.2 format actions ─────────────────────────────────────── */\n\n    /**\n     * Stash the resolved computed style of the selection's common ancestor\n     * into `builder._formatClipboard`. Raw CSS values — no formatter\n     * coupling — so Paste Format can wrap any future selection in a single\n     * `<span style>` without knowing which Element owns the range. The\n     * keys mirror the W2.2 plan spec: `fontFamily`, `fontWeight`,\n     * `fontStyle`, `fontSize`, `color`, `backgroundColor`,\n     * `textDecorationLine`, `letterSpacing`, `lineHeight`.\n     */\n  }, {\n    key: \"_doCopyFormat\",\n    value: function _doCopyFormat(btn) {\n      var snap = this._snapshotComputedFormat();\n      if (!snap) {\n        this._flashError(btn);\n        return;\n      }\n      this._builder._formatClipboard = snap;\n    }\n\n    /**\n     * Wrap the current selection in a `<span style=\"…\">` carrying the\n     * properties snapshotted by Copy Format. HARD RULE T2: no element\n     * rerender — we go through `_applyExecCommand('insertHTML', …)` which\n     * saves + restores char-offset selection across the inline rebuild\n     * and runs `InlineSanitizer.normalize` to canonicalise the markup.\n     * Disabled-state is computed at menu-open time; this handler is\n     * defensive if the user somehow triggers it with an empty clipboard.\n     */\n  }, {\n    key: \"_doPasteFormat\",\n    value: function _doPasteFormat(btn) {\n      var snap = this._builder._formatClipboard;\n      if (!snap) {\n        this._flashError(btn);\n        return;\n      }\n      var css = this._cssFromFormat(snap);\n      if (!css) {\n        this._flashError(btn);\n        return;\n      }\n      var payload = this._currentPayload;\n      if (!payload || !payload.range) {\n        this._flashError(btn);\n        return;\n      }\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) {\n        this._flashError(btn);\n        return;\n      }\n      var frag = payload.range.cloneContents();\n      var tmp = idoc.createElement('div');\n      tmp.appendChild(frag);\n      var innerHtml = tmp.innerHTML;\n      if (!innerHtml) {\n        this._flashError(btn);\n        return;\n      }\n      var wrapped = \"<span style=\\\"\".concat(css, \"\\\">\").concat(innerHtml, \"</span>\");\n      this._applyExecCommand('insertHTML', wrapped, btn);\n    }\n  }, {\n    key: \"_doClearFormat\",\n    value: function _doClearFormat(btn) {\n      // `removeFormat` strips inline formatting (bold / italic /\n      // font-family / color / etc.) from the selection, keeps the\n      // text + block tag. `unlink` is intentionally NOT paired here —\n      // users remove links via the dedicated Remove Link row so they\n      // can keep character formatting without losing the anchor.\n      this._applyExecCommand('removeFormat', null, btn);\n    }\n  }, {\n    key: \"_doRemoveLink\",\n    value: function _doRemoveLink(btn) {\n      if (this._detectRemoveLinkState() !== 'removable') {\n        this._flashError(btn);\n        return;\n      }\n      this._applyExecCommand('unlink', null, btn);\n    }\n\n    /* ── W2.2 helpers ────────────────────────────────────────────── */\n\n    /**\n     * Resolve the inline-text host's getComputedStyle (range's common\n     * ancestor). Returns `null` when the iframe doc is unavailable or\n     * the range has no computed-style carrier. Reads the \"what would\n     * the user see right now\" rendered style — not the formatter-\n     * serialised style — so Copy Format works identically regardless\n     * of which element hosts the range.\n     */\n  }, {\n    key: \"_snapshotComputedFormat\",\n    value: function _snapshotComputedFormat() {\n      var payload = this._currentPayload;\n      if (!payload || !payload.range) return null;\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      var iwin = idoc && idoc.defaultView;\n      if (!idoc || !iwin) return null;\n      var ac = payload.range.commonAncestorContainer;\n      var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n      if (!el) return null;\n      var cs;\n      try {\n        cs = iwin.getComputedStyle(el);\n      } catch (_) {\n        return null;\n      }\n      if (!cs) return null;\n      return {\n        fontFamily: cs.fontFamily || '',\n        fontWeight: cs.fontWeight || '',\n        fontStyle: cs.fontStyle || '',\n        fontSize: cs.fontSize || '',\n        color: cs.color || '',\n        backgroundColor: cs.backgroundColor || '',\n        textDecorationLine: cs.textDecorationLine || cs.textDecoration || '',\n        letterSpacing: cs.letterSpacing || '',\n        lineHeight: cs.lineHeight || ''\n      };\n    }\n\n    /**\n     * Build a semicolon-separated inline CSS string from a format snapshot.\n     * Drops \"default / transparent\" values so the emitted `<span>` only\n     * carries meaningful overrides — matches what Paste Format should\n     * visibly change.\n     */\n  }, {\n    key: \"_cssFromFormat\",\n    value: function _cssFromFormat(snap) {\n      if (!snap) return '';\n      var isDefaultDecoration = function isDefaultDecoration(v) {\n        return !v || v === 'none' || v === 'initial' || v === 'inherit';\n      };\n      var isTransparent = function isTransparent(v) {\n        return !v || v === 'rgba(0, 0, 0, 0)' || v === 'transparent';\n      };\n      var isAutoOrNormal = function isAutoOrNormal(v) {\n        return !v || v === 'normal' || v === 'auto';\n      };\n      var parts = [];\n      if (snap.fontFamily && snap.fontFamily !== 'inherit') parts.push(\"font-family: \".concat(snap.fontFamily));\n      if (snap.fontWeight && snap.fontWeight !== '400' && snap.fontWeight !== 'normal') parts.push(\"font-weight: \".concat(snap.fontWeight));\n      if (snap.fontStyle && snap.fontStyle !== 'normal') parts.push(\"font-style: \".concat(snap.fontStyle));\n      if (snap.fontSize) parts.push(\"font-size: \".concat(snap.fontSize));\n      if (snap.color) parts.push(\"color: \".concat(snap.color));\n      if (!isTransparent(snap.backgroundColor)) parts.push(\"background-color: \".concat(snap.backgroundColor));\n      if (!isDefaultDecoration(snap.textDecorationLine)) parts.push(\"text-decoration: \".concat(snap.textDecorationLine));\n      if (!isAutoOrNormal(snap.letterSpacing)) parts.push(\"letter-spacing: \".concat(snap.letterSpacing));\n      if (!isAutoOrNormal(snap.lineHeight)) parts.push(\"line-height: \".concat(snap.lineHeight));\n      return parts.join('; ');\n    }\n\n    /**\n     * Read the current computed color of the selection's common ancestor\n     * so the popover can render the existing color as `.is-active`. Falls\n     * back to null (no active swatch) on mixed / missing selection.\n     * Intentionally conservative — HARD RULE T7 (ambiguity asks, never\n     * auto-picks silently).\n     */\n  }, {\n    key: \"_readInitialColor\",\n    value: function _readInitialColor(mode) {\n      var payload = this._currentPayload;\n      if (!payload || !payload.range) return null;\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) return null;\n      var ac = payload.range.commonAncestorContainer;\n      var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n      if (!el) return null;\n      var win = idoc.defaultView;\n      try {\n        var cs = win.getComputedStyle(el);\n        var raw = mode === 'foreColor' ? cs.color : cs.backgroundColor;\n        return this._rgbToHex(raw);\n      } catch (_) {\n        return null;\n      }\n    }\n  }, {\n    key: \"_rgbToHex\",\n    value: function _rgbToHex(raw) {\n      if (!raw) return null;\n      // computed-style returns \"rgb(R, G, B)\" or \"rgba(R, G, B, A)\".\n      // Capture alpha so a fully-transparent backgroundColor (what\n      // hiliteColor='transparent' resolves to, or an element with no\n      // explicit background) returns null — otherwise we'd treat\n      // `rgba(0, 0, 0, 0)` as solid black and set the indicator bar\n      // to #000000, which looks like \"black highlight\" to the user.\n      var m = String(raw).match(/rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*([\\d.]+))?/);\n      if (!m) return null;\n      var a = m[4] !== undefined ? parseFloat(m[4]) : 1;\n      if (a === 0) return null;\n      var r = parseInt(m[1], 10);\n      var g = parseInt(m[2], 10);\n      var b = parseInt(m[3], 10);\n      var hex = '#' + [r, g, b].map(function (v) {\n        return v.toString(16).padStart(2, '0');\n      }).join('');\n      return hex.toLowerCase();\n    }\n\n    /**\n     * Called by `TextColorPopoverOverlay` when the user picks a swatch /\n     * commits a hex / picks via eyedropper. Delegates to the toolbar's\n     * `_applyExecCommand` pipeline so char-offset save/restore +\n     * InlineSanitizer.normalize + tracker refresh all run. Returns `false`\n     * when execCommand failed (popover stays open + flashes the button).\n     */\n  }, {\n    key: \"_applyColor\",\n    value: function _applyColor(mode, colorValue, btn) {\n      var cmd = mode === 'foreColor' ? 'foreColor' : 'hiliteColor';\n      // execCommand doesn't accept 'inherit' — emit a bare color that\n      // matches the document's default. Easier: for 'inherit' remove\n      // color via `removeFormat` scoped to color only (execCommand has\n      // no sub-target, so we fall back to writing the element's\n      // computed color).\n      if (colorValue === 'inherit') {\n        var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n        var payload = this._currentPayload;\n        if (idoc && payload && payload.range) {\n          var ac = payload.range.commonAncestorContainer;\n          var el = ac && ac.nodeType === 1 ? ac : ac && ac.parentElement;\n          var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n          var ancestor = host ? host.parentElement || host : el;\n          try {\n            colorValue = idoc.defaultView.getComputedStyle(ancestor).color || '#000000';\n          } catch (_) {\n            colorValue = '#000000';\n          }\n        } else {\n          colorValue = '#000000';\n        }\n      }\n      // `execCommand('hiliteColor', 'transparent')` works in all major\n      // engines for clearing highlight. `foreColor` doesn't accept\n      // 'transparent' in all engines — use the computed fallback above.\n      var ok = this._applyExecCommand(cmd, colorValue, btn);\n      return ok;\n    }\n\n    /**\n     * W6.1 — Sparkle button. Renders like a wired-up icon button (no\n     * .is-stub) and on click opens AIRewritePopoverOverlay anchored to\n     * itself. The popover handles its own selection capture (reads\n     * builder._textSelectionTracker last range).\n     */\n  }, {\n    key: \"_makeAIRewriteButton\",\n    value: function _makeAIRewriteButton(labelKey) {\n      var _this8 = this;\n      var btn = this._makeIconBtn('ai-rewrite');\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      btn.classList.add('bjs-toolbar-ai-btn');\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-haspopup', 'dialog');\n      btn.setAttribute('aria-expanded', 'false');\n      btn.setAttribute('data-tooltip', label);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this8._toggleAIRewritePopover(btn);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_toggleAIRewritePopover\",\n    value: function _toggleAIRewritePopover(anchorBtn) {\n      // Close any sibling popover first (single-popover invariant).\n      this._closeColorPopover();\n      this._closeLinkPopover();\n      this._closeFontPopover();\n      this._closeMoreMenu();\n      if (this._activePopover && typeof this._activePopover.close === 'function') {\n        try {\n          this._activePopover.close();\n        } catch (_) {}\n        this._activePopover = null;\n      }\n      var popover = new _AIRewritePopoverOverlay_js__WEBPACK_IMPORTED_MODULE_7__[\"default\"](this, {\n        anchorBtn: anchorBtn,\n        builder: this._builder\n      });\n      this._activePopover = popover;\n      popover.open();\n    }\n  }, {\n    key: \"_makeStubButton\",\n    value: function _makeStubButton(key, labelKey, shortcutHint) {\n      var _this9 = this;\n      var btn = this._makeIconBtn(key);\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t(labelKey);\n      var wave = STUB_WAVES[key] || '?';\n      btn.classList.add('is-stub');\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('data-stub-key', key);\n      var tooltip = \"\".concat(label, \" \\u2014 \").concat(_I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.coming_in').replace('{wave}', wave)).concat(shortcutHint ? \" (\".concat(shortcutHint, \")\") : '');\n      btn.setAttribute('data-tooltip', tooltip);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        // Fire bus event so future waves wire their popover without\n        // re-authoring the chrome. W1.1 ships with no subscribers —\n        // the click is a visible \"received but no-op\" to the user\n        // via the brief .is-active pulse (CSS handles the feedback).\n        _this9._bus.emit('text-inline-toolbar:open-' + key, {\n          elementUid: _this9._currentPayload && _this9._currentPayload.elementUid,\n          payload: _this9._currentPayload,\n          button: btn\n        });\n        // Ephemeral is-active pulse — confirms the click landed.\n        btn.classList.add('is-just-pressed');\n        setTimeout(function () {\n          return btn.classList.remove('is-just-pressed');\n        }, 220);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_makeParagraphStyleChip\",\n    value: function _makeParagraphStyleChip() {\n      var _this10 = this;\n      var btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = 'bjs-ovl-pill bjs-toolbar-btn bjs-toolbar-para-style is-stub';\n      btn.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.paragraph_style'));\n      btn.setAttribute('data-stub-key', 'paragraph-style');\n      var label = document.createElement('span');\n      label.className = 'bjs-toolbar-para-style-label';\n      label.textContent = '—';\n      btn.appendChild(label);\n      var caret = document.createElement('span');\n      caret.className = 'material-symbols-rounded bjs-toolbar-caret';\n      caret.setAttribute('aria-hidden', 'true');\n      caret.textContent = 'expand_more';\n      btn.appendChild(caret);\n      btn.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.paragraph_style') + ' — ' + _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.coming_in').replace('{wave}', STUB_WAVES['paragraph-style']));\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this10._bus.emit('text-inline-toolbar:open-paragraph-style', {\n          elementUid: _this10._currentPayload && _this10._currentPayload.elementUid,\n          payload: _this10._currentPayload,\n          button: btn\n        });\n        btn.classList.add('is-just-pressed');\n        setTimeout(function () {\n          return btn.classList.remove('is-just-pressed');\n        }, 220);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_makeAlignButton\",\n    value: function _makeAlignButton(side, shortcutHint) {\n      var _this11 = this;\n      var btn = this._makeIconBtn('align-' + side);\n      var label = _I18n_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"].t('inline_toolbar.align_' + side);\n      btn.setAttribute('aria-label', label);\n      btn.setAttribute('aria-pressed', 'false');\n      btn.setAttribute('data-align-key', side);\n      btn.setAttribute('data-tooltip', shortcutHint ? \"\".concat(label, \" (\").concat(shortcutHint, \")\") : label);\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this11._applyAlign(side, btn);\n      });\n      return btn;\n    }\n\n    /* ── Format apply ─────────────────────────────────────────────── */\n  }, {\n    key: \"_applyToggle\",\n    value: function _applyToggle(cmd, btn) {\n      this._applyExecCommand(cmd, null, btn);\n    }\n\n    /**\n     * Apply text-align to the current selection's host element via the\n     * formatter write path. TEXT_INLINE_PLAN D13 v5 (single write path):\n     *\n     *   1. `element.formatter.setFormat('text_align', side)` — writes the\n     *      element's serialised state. Sidebar `AlignControl` also writes\n     *      through this path via its `setValue` callback, so both surfaces\n     *      share a single source of truth. No execCommand, no `style=\"...\"`\n     *      DOM-scribble that bypasses the formatter.\n     *   2. `element.applyFormatStyles()` — patches the element's live DOM\n     *      inline style in place (no full re-render, caret stays put).\n     *      Elements that don't expose `applyFormatStyles()` yet (Label /\n     *      Alert / SubmitButton pre-W5.1) fall back to `render()`; caret\n     *      loss is acceptable on those because they're single-word\n     *      elements that rarely host selections.\n     *   3. `builder.events.emit('formatter:change', { elementUid, key,\n     *      value, source })` — broadcast so a future sidebar AlignControl\n     *      (or W4.1 Advanced popover's dual-mounted control) can subscribe\n     *      and re-read state without polling. `source` field lets\n     *      subscribers skip their own echoes.\n     *\n     * Retired 2026-04-20 (9d7df762) as an execCommand-based\n     * implementation that raced sidebar formatter writes; restored same\n     * day on the formatter path after the D13 decision was refined (v4\n     * → v5: the rule is single-write-path, not block-vs-range). See\n     * BUILDER.md Lesson 56.\n     */\n  }, {\n    key: \"_applyAlign\",\n    value: function _applyAlign(side, btn) {\n      var element = this._resolveCurrentElement();\n      if (!element || !element.formatter || typeof element.formatter.setFormat !== 'function') {\n        this._flashError(btn);\n        return;\n      }\n      try {\n        element.formatter.setFormat('text_align', side);\n        if (typeof element.applyFormatStyles === 'function') {\n          element.applyFormatStyles();\n        } else if (typeof element.render === 'function') {\n          element.render();\n        }\n        this._bus.emit('formatter:change', {\n          elementUid: element.id,\n          key: 'text_align',\n          value: side,\n          source: 'text-inline-toolbar'\n        });\n        // Re-read pill state so the segmented group reflects the new\n        // active button immediately (no bus round-trip needed for\n        // our own write).\n        this._updateButtonStates(this._currentPayload);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:applyAlign:' + side, err);\n        this._flashError(btn);\n      }\n    }\n\n    /**\n     * Resolve the current selection's elementUid to its live Element\n     * instance via `builder.uiManager.elements`. Returns null if the\n     * tracker has no active payload or the instance has been\n     * garbage-collected (e.g. user deleted the element mid-selection).\n     */\n  }, {\n    key: \"_resolveCurrentElement\",\n    value: function _resolveCurrentElement() {\n      if (!this._currentPayload) return null;\n      var uid = this._currentPayload.elementUid;\n      var uiMgr = this._builder && this._builder.uiManager;\n      if (!uiMgr || !Array.isArray(uiMgr.elements)) return null;\n      return uiMgr.elements.find(function (el) {\n        return el && el.id === uid;\n      }) || null;\n    }\n  }, {\n    key: \"_normalizeAlign\",\n    value: function _normalizeAlign(v) {\n      if (!v) return null;\n      var s = String(v).toLowerCase();\n      if (s === 'start' || s === 'left') return 'left';\n      if (s === 'center') return 'center';\n      if (s === 'end' || s === 'right') return 'right';\n      if (s === 'justify') return 'justify';\n      return null;\n    }\n\n    /**\n     * Apply an `execCommand` against the iframe document.\n     *\n     * Two correctness invariants drive this method:\n     *\n     *   (1) PRE-APPLY — the toolbar OWNS its operating range. The toolbar\n     *       lives in the parent document; clicking its button leaves the\n     *       iframe selection in an undefined state across browsers (mostly\n     *       fine on Chromium/macOS, but real-mouse gestures do occasionally\n     *       leave `iwin.getSelection()` collapsed by the time the click\n     *       handler runs — a focus/selection race that does NOT fire\n     *       `selectionchange` so the tracker can't see it). `execCommand`\n     *       reads the live selection silently and returns `false` when it's\n     *       collapsed → button red-flashes even though the user's intent\n     *       (`_currentPayload.range`, captured on the last `text-selection`\n     *       emit) is well-defined. Fix: SET the live selection to the\n     *       tracker's saved range immediately before `execCommand`. This is\n     *       the standard floating-toolbar pattern (TinyMCE / CKEditor /\n     *       Quill all do it). It makes the apply path deterministic and\n     *       independent of whatever the live selection happens to be.\n     *\n     *   (2) POST-APPLY — the element's `input` listener mirrors\n     *       `host.innerHTML` back into `element.text`, which on most\n     *       elements rewrites `target.innerHTML = text` and detaches the\n     *       range's text-node refs. We save char offsets BEFORE the apply\n     *       and restore via TreeWalker AFTER the rewrite (HARD RULE T2 +\n     *       Lesson 40 / Lesson 56 precedent). Pre-W5.1 caret-stable shim.\n     *\n     * Failure modes are tagged on `_flashError(...)` so the next surprise\n     * red flash points at the exact branch in BJS.warn output instead of\n     * forcing another investigation cycle.\n     */\n  }, {\n    key: \"_applyExecCommand\",\n    value: function _applyExecCommand(cmd, value, btn) {\n      var _this12 = this;\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      var iwin = idoc && idoc.defaultView;\n      if (!idoc || !iwin) {\n        this._flashError(btn, 'no-iframe-doc:' + cmd);\n        return false;\n      }\n      if (!this._currentPayload) {\n        this._flashError(btn, 'no-payload:' + cmd);\n        return false;\n      }\n      var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(this._currentPayload.elementUid, \"\\\"]\"));\n      if (!host) {\n        this._flashError(btn, 'no-host:' + cmd);\n        return false;\n      }\n      // (1) Sync live iframe selection to the tracker's saved range.\n      // The cloned range still references the same text nodes (no DOM\n      // rewrite happens between selection-change and click), so addRange\n      // is a no-op when the live selection already matches and a real\n      // restore when it doesn't. Either way, `execCommand` below sees a\n      // valid non-collapsed range inside contenteditable.\n      var savedRange = this._currentPayload.range;\n      try {\n        var sel = iwin.getSelection();\n        sel.removeAllRanges();\n        sel.addRange(savedRange);\n      } catch (err) {\n        // Range refs detached (host re-rendered between mount + click,\n        // e.g. via a sidebar control write) — fail visibly so the bug\n        // surfaces at the source instead of silently no-op'ing.\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].warn('text-inline-toolbar:pre-apply-restore:' + cmd, err);\n        this._flashError(btn, 'pre-restore-throw:' + cmd);\n        return false;\n      }\n      // (2) Char-offset snapshot for the post-apply restore.\n      var offsets = this._saveSelectionOffsets(host, savedRange);\n      var ok = false;\n      try {\n        ok = idoc.execCommand(cmd, false, value);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:execCommand:' + cmd, err);\n        this._flashError(btn, 'exec-throw:' + cmd);\n        return false;\n      }\n      if (!ok) {\n        // After (1) we know the live selection is non-collapsed and\n        // inside contenteditable, so `false` here means the browser\n        // genuinely rejected the command (e.g. `removeFormat` over a\n        // span with no inline format, or a vendor-specific edge case).\n        // Log enough context to debug without a re-run.\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].warn('text-inline-toolbar:execCommand-rejected:' + cmd, {\n          selectionText: iwin.getSelection().toString(),\n          hostTag: host.tagName\n        });\n        this._flashError(btn, 'exec-false:' + cmd);\n        return false;\n      }\n      this._normalizeHost();\n      this._notifyContentChanged();\n      // Defer selection restore to the next microtask so the native\n      // `input` event (+ element.setText → innerHTML rewrite) has\n      // finished first. Then the tracker can re-read the restored\n      // selection and re-emit change, keeping the toolbar mounted.\n      setTimeout(function () {\n        _this12._restoreSelectionOffsets(host, offsets);\n        _this12._refreshTracker();\n      }, 0);\n      return true;\n    }\n\n    /**\n     * Save current selection within `host` as `{start,end}` character\n     * offsets. Survives any innerHTML rebuild because offsets point to a\n     * text index, not a DOM node. Returns null when the range is not\n     * contained by host (caller owns the degrade).\n     */\n  }, {\n    key: \"_saveSelectionOffsets\",\n    value: function _saveSelectionOffsets(host, range) {\n      if (!host || !range) return null;\n      try {\n        var doc = host.ownerDocument;\n        var pre = doc.createRange();\n        pre.selectNodeContents(host);\n        pre.setEnd(range.startContainer, range.startOffset);\n        var start = pre.toString().length;\n        var end = start + range.toString().length;\n        return {\n          start: start,\n          end: end\n        };\n      } catch (_) {\n        return null;\n      }\n    }\n  }, {\n    key: \"_restoreSelectionOffsets\",\n    value: function _restoreSelectionOffsets(host, offsets) {\n      if (!host || !offsets) return;\n      try {\n        var doc = host.ownerDocument;\n        var win = doc.defaultView;\n        var sel = win.getSelection();\n        var range = doc.createRange();\n\n        // NodeFilter.SHOW_TEXT = 4\n        var walker = doc.createTreeWalker(host, 4, null, false);\n        var count = 0;\n        var startNode = null,\n          startOffset = 0;\n        var endNode = null,\n          endOffset = 0;\n        var node;\n        while (node = walker.nextNode()) {\n          var len = node.textContent.length;\n          var nextCount = count + len;\n          if (!startNode && nextCount >= offsets.start) {\n            startNode = node;\n            startOffset = offsets.start - count;\n          }\n          if (!endNode && nextCount >= offsets.end) {\n            endNode = node;\n            endOffset = offsets.end - count;\n            break;\n          }\n          count = nextCount;\n        }\n        // Fallback — clamp to host extents. Better to end with a\n        // valid (even if collapsed) selection than throw.\n        if (!startNode) {\n          startNode = host;\n          startOffset = 0;\n        }\n        if (!endNode) {\n          endNode = startNode;\n          endOffset = Math.min(startOffset, (startNode.textContent || '').length);\n        }\n        range.setStart(startNode, startOffset);\n        range.setEnd(endNode, endOffset);\n        sel.removeAllRanges();\n        sel.addRange(range);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:restore-selection', err);\n      }\n    }\n  }, {\n    key: \"_normalizeHost\",\n    value: function _normalizeHost() {\n      if (!this._currentPayload) return;\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) return;\n      var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(this._currentPayload.elementUid, \"\\\"]\"));\n      if (!host) return;\n      try {\n        _InlineSanitizer_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"].normalize(host);\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:normalize', err);\n      }\n    }\n  }, {\n    key: \"_notifyContentChanged\",\n    value: function _notifyContentChanged() {\n      if (!this._currentPayload) return;\n      // Mirrors what BaseElement._wireInlineEdit's `input` listener\n      // does for typing — the toolbar edits the same DOM directly so\n      // we must give subscribers (HistoryManager, element.text sync)\n      // the same signal.\n      this._bus.emit('text-inline-toolbar:content-change', {\n        elementUid: this._currentPayload.elementUid\n      });\n      // Fire a native input event on the host so W0.2b's auto-wired\n      // listener picks up the new text without the toolbar needing to\n      // reach into element internals.\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc) return;\n      var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(this._currentPayload.elementUid, \"\\\"]\"));\n      if (!host) return;\n      try {\n        host.dispatchEvent(new idoc.defaultView.Event('input', {\n          bubbles: true\n        }));\n      } catch (err) {\n        _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].error('text-inline-toolbar:input-dispatch', err);\n      }\n    }\n  }, {\n    key: \"_refreshTracker\",\n    value: function _refreshTracker() {\n      var tracker = this._builder.textSelectionTracker;\n      if (tracker && typeof tracker.refresh === 'function') {\n        tracker.refresh();\n      }\n    }\n  }, {\n    key: \"_flashError\",\n    value: function _flashError(btn, tag) {\n      // Always surface WHY the red flash fired so debugging the next\n      // surprise takes seconds. `tag` is a short branch identifier from\n      // the caller (e.g. 'exec-false:bold', 'no-host:italic'); falls\n      // back to a generic label for older callers without one.\n      _BJS_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].warn('text-inline-toolbar:flash-error', tag || 'unknown');\n      if (!btn) return;\n      btn.classList.add('is-error');\n      setTimeout(function () {\n        return btn.classList.remove('is-error');\n      }, 600);\n    }\n\n    /* ── State sync ───────────────────────────────────────────────── */\n  }, {\n    key: \"_updateButtonStates\",\n    value: function _updateButtonStates(payload) {\n      var _this13 = this;\n      if (!this.domNode || !payload) return;\n      var formats = payload.formats || {};\n\n      // Toggle buttons — active + mixed from queryCommandState /\n      // queryCommandIndeterm. We read `indeterm` directly from the\n      // iframe document because the tracker's payload only reports\n      // the start-of-selection state; indeterminate requires a live\n      // query at apply time.\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      this.domNode.querySelectorAll('[data-format-key]').forEach(function (btn) {\n        var key = btn.getAttribute('data-format-key');\n        var active = formats[key] === true;\n        var indeterm = false;\n        if (idoc && typeof idoc.queryCommandIndeterm === 'function') {\n          try {\n            indeterm = !!idoc.queryCommandIndeterm(key);\n          } catch (_) {\n            indeterm = false;\n          }\n        }\n        btn.classList.toggle('is-active', active && !indeterm);\n        btn.classList.toggle('is-mixed', indeterm);\n        if (indeterm) {\n          btn.setAttribute('aria-checked', 'mixed');\n          btn.removeAttribute('aria-pressed');\n        } else {\n          btn.setAttribute('aria-pressed', active ? 'true' : 'false');\n          btn.removeAttribute('aria-checked');\n        }\n      });\n\n      // Align segmented — read from element.formatter (single-write-path\n      // per D13 v5). We used to query DOM inline style via\n      // queryCommandState; that path was retired along with the\n      // execCommand-based apply in 9d7df762. Current pill state now\n      // reflects what the formatter actually serialises — the same\n      // source sidebar AlignControl reads.\n      var element = this._resolveCurrentElement();\n      var alignVal = element && element.formatter && typeof element.formatter.getFormat === 'function' ? element.formatter.getFormat('text_align') : null;\n      var align = this._normalizeAlign(alignVal);\n      this.domNode.querySelectorAll('[data-align-key]').forEach(function (btn) {\n        var k = btn.getAttribute('data-align-key');\n        var on = k === align;\n        btn.classList.toggle('is-active', on);\n        btn.setAttribute('aria-pressed', on ? 'true' : 'false');\n      });\n\n      // Color indicators — drive both text-color + highlight-color\n      // bars from the current selection's computed color. Runs on\n      // every mount + every re-selection via this same code path, so\n      // there's exactly one source of truth: `_readInitialColor(mode)`.\n      // No separate mount-time read needed in `_makeColorButton` — the\n      // first `_updateButtonStates` after mount does it. Theme fallback\n      // (light: --bjs-text #111, dark: #e5e7eb) kicks in via CSS when\n      // we remove the inline var (null color case, typical for a\n      // reset hiliteColor where backgroundColor is transparent).\n      this.domNode.querySelectorAll('[data-color-mode]').forEach(function (btn) {\n        var mode = btn.getAttribute('data-color-mode');\n        var hex = _this13._readInitialColor(mode);\n        if (hex) {\n          btn.style.setProperty('--bjs-color-current', hex);\n        } else {\n          btn.style.removeProperty('--bjs-color-current');\n        }\n      });\n\n      // Link button — reflect whether selection sits inside an <a>.\n      // Pre-W1.3 shipped as a stub with [data-stub-key]; W1.3 promotes\n      // to a wired button with [data-link-btn]. Both kept here for any\n      // transition window.\n      var linkBtn = this.domNode.querySelector('[data-link-btn], [data-stub-key=\"link\"]');\n      if (linkBtn) linkBtn.classList.toggle('is-active', !!formats.link);\n\n      // Paragraph-style chip label — only when the chip is rendered (W2.3).\n      if (this.domNode.querySelector('.bjs-toolbar-para-style-label')) {\n        this._updateParagraphStyleLabel(payload);\n      }\n    }\n  }, {\n    key: \"_updateParagraphStyleLabel\",\n    value: function _updateParagraphStyleLabel(payload) {\n      var label = this.domNode.querySelector('.bjs-toolbar-para-style-label');\n      if (!label) return;\n      var idoc = this._builder.iframe && this._builder.iframe.contentDocument;\n      if (!idoc || !payload) {\n        label.textContent = '—';\n        return;\n      }\n      var host = idoc.querySelector(\"[data-bjs-inline-text=\\\"\".concat(payload.elementUid, \"\\\"]\"));\n      if (!host) {\n        label.textContent = '—';\n        return;\n      }\n      // The inline-edit host is the block tag itself for P / H1-6 /\n      // Label / Alert-body / Link. For non-standard tags, fall back\n      // to \"Text\".\n      var tag = host.tagName.toLowerCase();\n      var map = {\n        p: 'Paragraph',\n        h1: 'Heading 1',\n        h2: 'Heading 2',\n        h3: 'Heading 3',\n        h4: 'Heading 4',\n        h5: 'Heading 5',\n        h6: 'Heading 6',\n        a: 'Link',\n        label: 'Label'\n      };\n      label.textContent = map[tag] || 'Text';\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TextInlineToolbarOverlay);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/overlays/TextInlineToolbarOverlay.js?");

/***/ }),

/***/ "./src/includes/pricingCardIcons.js":
/*!******************************************!*\
  !*** ./src/includes/pricingCardIcons.js ***!
  \******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   allNames: () => (/* binding */ allNames),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */   hasIcon: () => (/* binding */ hasIcon),\n/* harmony export */   render: () => (/* binding */ render)\n/* harmony export */ });\n/**\n * BuilderJS inline SVG icon registry (originally \"pricingCardIcons\").\n *\n * Replaces Material Symbols font (which doesn't load inside the builder iframe\n * theme and is unreliable in exported emails) with inline SVG paths so every\n * icon renders deterministically — builder canvas, preview iframe, exported\n * HTML, sidebar controls, and floating action bars all share one source.\n *\n * Contract:\n *   - `render(name, opts)` returns an SVG string (or `<span>` fallback for\n *     emoji / non-registry names), or empty string for empty input.\n *   - Opts: `{ size: number (px), color: string (CSS color) }`.\n *   - Icons are 24×24 viewBox, 1.75 stroke-width so they stay crisp at\n *     16px (chips), 20px (sidebar controls), 24px (overlay pills), 28-56px\n *     (pricing preset thumbnails).\n *\n * Scope (2026-04-19 expansion — BUTTON_UPGRADE_PLAN):\n *   Registry grew from 18 pricing-card icons to ~40 to cover every icon\n *   surface in the Button refactor — overlay pills (close/link/palette/\n *   settings), preset picker tick (check_circle), icon-led preset glyphs\n *   (arrow_forward, download, shopping_cart, mail, play_arrow, share, add,\n *   arrow_back, check, call, send, open_in_new), sidebar chevrons\n *   (expand_more / expand_less / chevron_right), widget toggles. Registry\n *   is generic — any element can import it.\n *\n * Each SVG is ~0.3-0.8 KB; total stays under 25 KB.\n */\n\nvar ICON_PATHS = {\n  // ─── Original pricing icons ───────────────────────────────────────────\n  bolt: '<path d=\"M13 3L4 14h6l-1 7 9-11h-6l1-7z\" fill=\"currentColor\" stroke=\"none\"/>',\n  diamond: '<path d=\"M12 3l4 4 4-4M12 3L8 7 4 3m4 4l4 14L4 7h16l-4 14z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  workspace_premium: '<circle cx=\"12\" cy=\"10\" r=\"6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M9 15l-2 6 5-2 5 2-2-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M12 7l1 2 2 .3-1.5 1.4.3 2L12 11.7l-1.8 1 .3-2L9 9.3 11 9z\" fill=\"currentColor\" stroke=\"none\"/>',\n  rocket_launch: '<path d=\"M14 4c2 0 4 0 6 2s2 4 2 6l-4 2-6-6 2-4zM8 10l-4 2-2 4 4 4 4-2 2-4-4-4zM10 12l6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  star: '<path d=\"M12 3l2.8 6 6.2.6-4.7 4.3 1.4 6.1L12 16.8 6.3 20l1.4-6.1L3 9.6 9.2 9z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  auto_awesome: '<path d=\"M12 3l1.4 3.6L17 8l-3.6 1.4L12 13l-1.4-3.6L7 8l3.6-1.4z\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M18 14l.8 2.2L21 17l-2.2.8L18 20l-.8-2.2L15 17l2.2-.8zM6 14l.6 1.6L8 16l-1.4.4L6 18l-.6-1.6L4 16l1.4-.4z\" fill=\"currentColor\" stroke=\"none\"/>',\n  terminal: '<rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M7 10l3 2-3 2M13 14h4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  rocket: '<path d=\"M12 3c3 2 5 5 5 9 0 3-2 5-5 7-3-2-5-4-5-7 0-4 2-7 5-9z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"12\" cy=\"10\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><path d=\"M9 16l-2 4 3-1M15 16l2 4-3-1\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  crown: '<path d=\"M3 17l2-9 4 5 3-8 3 8 4-5 2 9z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M3 17h18v2H3z\" fill=\"currentColor\" stroke=\"none\"/>',\n  favorite: '<path d=\"M12 20l-7-7a4 4 0 115.7-5.7L12 8.6l1.3-1.3a4 4 0 115.7 5.7z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  bubble_chart: '<circle cx=\"8\" cy=\"14\" r=\"4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"16\" cy=\"9\" r=\"3\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"17\" cy=\"17\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/>',\n  layers: '<path d=\"M12 3l9 5-9 5-9-5z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M3 13l9 5 9-5M3 18l9 5 9-5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  shield: '<path d=\"M12 3l8 3v6c0 5-4 8-8 9-4-1-8-4-8-9V6z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M9 12l2 2 4-4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  verified: '<path d=\"M12 2l2.5 2 3.5-.5.5 3.5L21 9.5 19 12l2 2.5-2.5 2-.5 3.5-3.5-.5L12 22l-2.5-2-3.5.5L5.5 17 3 14.5 5 12 3 9.5l2.5-2L6 4l3.5.5z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M8 12l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  flash_on: '<path d=\"M11 3L5 13h5l-1 8 8-12h-5l1-6z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"currentColor\" stroke-linejoin=\"round\"/>',\n  flare: '<circle cx=\"12\" cy=\"12\" r=\"4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M12 2v4M12 18v4M2 12h4M18 12h4M4.6 4.6l2.8 2.8M16.6 16.6l2.8 2.8M19.4 4.6l-2.8 2.8M7.4 16.6l-2.8 2.8\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  emoji_events: '<path d=\"M6 4h12v3a4 4 0 01-4 4h-4a4 4 0 01-4-4zM4 6h2v2a2 2 0 01-2-2zM20 6h-2v2a2 2 0 002-2z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M10 11v4h4v-4M8 19h8v2H8z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  local_fire_department: '<path d=\"M12 3c0 4-5 5-5 10a5 5 0 0010 0c0-2-1-3-2-4 0 2-2 2-2 0s2-4-1-6z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  // ─── Overlay + control UI ────────────────────────────────────────────\n  close: '<path d=\"M6 6l12 12M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  check: '<path d=\"M5 12l4 4 10-10\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  check_circle: '<circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M8 12l3 3 5-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  link: '<path d=\"M10 14l4-4M9 17H7a4 4 0 010-8h2M15 7h2a4 4 0 010 8h-2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  edit: '<path d=\"M4 20h4L19 9l-4-4L4 16v4z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M14 6l4 4\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  palette: '<path d=\"M12 3a9 9 0 109 9c0-1.5-1-2-2-2h-2a2 2 0 010-4 2 2 0 00-2-2 9 9 0 00-3-1z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><circle cx=\"7.5\" cy=\"10.5\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"11\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"15.5\" cy=\"9\" r=\"1.2\" fill=\"currentColor\" stroke=\"none\"/>',\n  settings: '<circle cx=\"12\" cy=\"12\" r=\"3\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M19.4 15a1.7 1.7 0 00.3 1.9l.1.1a2 2 0 11-2.9 2.9l-.1-.1a1.7 1.7 0 00-1.9-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 01-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.9.3l-.1.1a2 2 0 11-2.9-2.9l.1-.1a1.7 1.7 0 00.3-1.9 1.7 1.7 0 00-1.5-1H3a2 2 0 010-4h.1a1.7 1.7 0 001.5-1.1 1.7 1.7 0 00-.3-1.9l-.1-.1a2 2 0 112.9-2.9l.1.1a1.7 1.7 0 001.9.3H9a1.7 1.7 0 001-1.5V3a2 2 0 014 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.9-.3l.1-.1a2 2 0 112.9 2.9l-.1.1a1.7 1.7 0 00-.3 1.9V9a1.7 1.7 0 001.5 1H21a2 2 0 010 4h-.1a1.7 1.7 0 00-1.5 1z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  tune: '<path d=\"M3 7h10M17 7h4M3 12h4M11 12h10M3 17h14M19 17h2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/><circle cx=\"15\" cy=\"7\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"9\" cy=\"12\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"17\" cy=\"17\" r=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/>',\n  expand_more: '<path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  expand_less: '<path d=\"M6 15l6-6 6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  chevron_right: '<path d=\"M9 6l6 6-6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  chevron_left: '<path d=\"M15 6l-6 6 6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  // ─── Button presets — icon-led glyphs ────────────────────────────────\n  arrow_forward: '<path d=\"M5 12h14M13 6l6 6-6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  arrow_back: '<path d=\"M19 12H5M11 6l-6 6 6 6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  download: '<path d=\"M12 4v11M7 10l5 5 5-5M4 19h16\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  shopping_cart: '<path d=\"M3 4h2l2 12h12l2-8H6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><circle cx=\"9\" cy=\"20\" r=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"17\" cy=\"20\" r=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/>',\n  mail: '<rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M3 7l9 6 9-6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  play_arrow: '<path d=\"M7 4l13 8-13 8z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"currentColor\" stroke-linejoin=\"round\"/>',\n  share: '<circle cx=\"6\" cy=\"12\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"18\" cy=\"5\"  r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><circle cx=\"18\" cy=\"19\" r=\"2.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M8 11l8-4.5M8 13l8 4.5\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  add: '<path d=\"M12 5v14M5 12h14\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  remove: '<path d=\"M5 12h14\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  call: '<path d=\"M5 4h4l2 5-2.5 1.5a10 10 0 005 5L15 13l5 2v4a2 2 0 01-2 2A15 15 0 013 6a2 2 0 012-2z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/>',\n  send: '<path d=\"M4 20l17-8L4 4l3 8-3 8z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M7 12h14\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  open_in_new: '<path d=\"M14 4h6v6M10 14L20 4M19 13v6a1 1 0 01-1 1H5a1 1 0 01-1-1V6a1 1 0 011-1h6\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n  // ─── Common UI glyphs (reserved for future surfaces) ─────────────────\n  menu: '<path d=\"M3 6h18M3 12h18M3 18h18\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  more_horiz: '<circle cx=\"5\"  cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"19\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>',\n  more_vert: '<circle cx=\"12\" cy=\"5\"  r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"12\" cy=\"19\" r=\"1.5\" fill=\"currentColor\" stroke=\"none\"/>',\n  info: '<circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\"/><path d=\"M12 10v6M12 7v.01\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>',\n  warning: '<path d=\"M12 3l10 18H2z\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linejoin=\"round\"/><path d=\"M12 10v4M12 17v.01\" stroke=\"currentColor\" stroke-width=\"1.75\" fill=\"none\" stroke-linecap=\"round\"/>'\n};\nfunction render(name) {\n  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n  if (!name || typeof name !== 'string') return '';\n  var size = typeof opts.size === 'number' && opts.size > 0 ? opts.size : 24;\n  var color = typeof opts.color === 'string' && opts.color ? opts.color : 'currentColor';\n  var key = name.trim().toLowerCase();\n\n  // Emoji / non-ASCII passthrough\n  if (!/^[a-z][a-z0-9_]*$/i.test(key)) {\n    return '<span style=\"font-size: ' + size + 'px; line-height: 1; display: inline-block;\">' + name + '</span>';\n  }\n  var path = ICON_PATHS[key];\n  if (!path) {\n    // Fallback: first-letter circle (subtle, works for any unknown name).\n    var letter = (key.charAt(0) || '?').toUpperCase();\n    var r = size / 2 - 1;\n    return '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ' + size + ' ' + size + '\" width=\"' + size + '\" height=\"' + size + '\" style=\"display:inline-block;vertical-align:middle;color:' + color + ';\">' + '<circle cx=\"' + size / 2 + '\" cy=\"' + size / 2 + '\" r=\"' + r + '\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>' + '<text x=\"' + size / 2 + '\" y=\"' + (size / 2 + size * 0.13) + '\" text-anchor=\"middle\" font-size=\"' + size * 0.55 + '\" font-weight=\"700\" font-family=\"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif\" fill=\"currentColor\">' + letter + '</text>' + '</svg>';\n  }\n  return '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"' + size + '\" height=\"' + size + '\" style=\"display:inline-block;vertical-align:middle;color:' + color + ';\">' + path + '</svg>';\n}\nfunction hasIcon(name) {\n  if (!name || typeof name !== 'string') return false;\n  var key = name.trim().toLowerCase();\n  return Object.prototype.hasOwnProperty.call(ICON_PATHS, key);\n}\nfunction allNames() {\n  return Object.keys(ICON_PATHS);\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n  render: render,\n  hasIcon: hasIcon,\n  allNames: allNames\n});\n\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/pricingCardIcons.js?");

/***/ }),

/***/ "./src/includes/ui/ColorPalettePicker.js":
/*!***********************************************!*\
  !*** ./src/includes/ui/ColorPalettePicker.js ***!
  \***********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _I18n_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../I18n.js */ \"./src/includes/I18n.js\");\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError(\"Cannot call a class as a function\"); }\nfunction _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, \"value\" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }\nfunction _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, \"prototype\", { writable: !1 }), e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * ColorPalettePicker — shared, primitive palette+custom-color picker.\n *\n * Introduced 2026-04-21 as a dedupe primitive between the canvas\n * TextColorPopoverOverlay (W1.2) and the sidebar ColorPickerControl\n * (slated for migration in the W1.2-followup phase — see TEXT_INLINE_PLAN\n * §3 W1.2+). Both surfaces need the SAME rich palette + custom hex +\n * native picker + eyedropper + Reset semantics; diverging them would\n * mean a Google-style update here today that never reaches the sidebar\n * tomorrow.\n *\n * Rendering model: opinionated DOM + BuilderJS chrome (`.bjs-color-*`\n * classes, shared with W1.2 popover). Consumer owns positioning — the\n * picker itself produces a flat `.domNode` that any container can mount.\n *\n * Interaction model: callback pair (`onPick(hex)` + `onReset()`),\n * one-shot per user action. Consumer decides:\n *   - the popover closes on pick     (canvas: TextColorPopoverOverlay)\n *   - the sidebar stays open on pick (future sidebar ColorPickerControl)\n *\n * State model: the picker is *stateless per instance* — it renders the\n * value it was constructed with, and re-renders when `setValue(hex)` is\n * called. No internal history / selection tracking. Recent-LRU state is\n * owned by the consumer (for canvas: `builder._recentTextColors`; for\n * sidebar: future `builder._recentElementColors`), passed in as `recent`.\n *\n * Accessibility: palette grid is `role=\"group\"`; swatches are\n * `role=\"button\"` with `data-tooltip=<hex>` + `aria-label=<hex>`. Custom\n * hex input has `aria-label=\"Hex color\"`. Reset button has its own\n * aria-label. Reduced-motion-safe (no animations that imply commit).\n *\n * Whitelist for future customisation (plan §10 decision pending):\n *   - `palette`: replace the default 60-swatch Google-style palette with a\n *     theme-provided set. Accepts `{ main, standard, recent }` where\n *     `main` is a 2-D array (rows × cols) + `standard` is a 1-D array +\n *     `recent` is a 1-D array.\n *   - `showEyedropper`: default true (auto-hidden when `EyeDropper`\n *     unsupported); pass `false` to force-hide.\n *   - `showReset`: default true. Pass `false` when the consumer has its\n *     own reset affordance elsewhere.\n */\n\n\n\n// Google-style rich palette — 10 columns × 6 rows = 60 presets. Order:\n// grayscale → saturated → 2 tint rows → 2 shade rows. Mirror of the\n// spec used by Google Docs / Sheets / Slides, rendered in BuilderJS\n// chrome. The default export — consumers may override via `opts.palette`.\nvar DEFAULT_GRAYSCALE = Object.freeze(['#000000', '#434343', '#666666', '#999999', '#B7B7B7', '#CCCCCC', '#D9D9D9', '#EFEFEF', '#F3F3F3', '#FFFFFF']);\nvar DEFAULT_SATURATED = Object.freeze(['#980000', '#FF0000', '#FF9900', '#FFFF00', '#00FF00', '#00FFFF', '#4A86E8', '#0000FF', '#9900FF', '#FF00FF']);\n// Tint-4 (palest) — derived 2026-04-21 by mixing each TINT_3 value with\n// white at 50/50 so the hue column stays consistent (user rule: \"design\n// màu tone chuẩn theo hiện tại nha ko lệch á\"). Use case: background\n// washes where even TINT_3 reads too saturated — e.g., subtle callout\n// fills, disabled surface tints.\nvar DEFAULT_TINT_4 = Object.freeze(['#F3DBD7', '#F9E5E5', '#FDF2E6', '#FFF8E5', '#ECF4E9', '#E7EFF1', '#E4ECFB', '#E7F0F9', '#ECE8F4', '#F4E8EE']);\nvar DEFAULT_TINT_3 = Object.freeze(['#E6B8AF', '#F4CCCC', '#FCE5CD', '#FFF2CC', '#D9EAD3', '#D0E0E3', '#C9DAF8', '#CFE2F3', '#D9D2E9', '#EAD1DC']);\nvar DEFAULT_TINT_2 = Object.freeze(['#DD7E6B', '#EA9999', '#F9CB9C', '#FFE599', '#B6D7A8', '#A2C4C9', '#A4C2F4', '#9FC5E8', '#B4A7D6', '#D5A6BD']);\nvar DEFAULT_SHADE_1 = Object.freeze(['#CC4125', '#E06666', '#F6B26B', '#FFD966', '#93C47D', '#76A5AF', '#6D9EEB', '#6FA8DC', '#8E7CC3', '#C27BA0']);\nvar DEFAULT_SHADE_2 = Object.freeze(['#A61C00', '#CC0000', '#E69138', '#F1C232', '#6AA84F', '#45818E', '#3C78D8', '#3D85C6', '#674EA7', '#A64D79']);\nvar DEFAULT_MAIN_PALETTE = Object.freeze([DEFAULT_GRAYSCALE, DEFAULT_SATURATED, DEFAULT_TINT_4,\n// palest — best for page / callout background washes\nDEFAULT_TINT_3, DEFAULT_TINT_2, DEFAULT_SHADE_1, DEFAULT_SHADE_2]);\n// \"Standard\" row — BuilderJS curated brand hues at Tailwind 500 intensity.\nvar DEFAULT_STANDARD = Object.freeze(['#111827', '#EF4444', '#F59E0B', '#10B981', '#3B82F6', '#6366F1', '#EC4899', '#FFFFFF']);\nvar ColorPalettePicker = /*#__PURE__*/function () {\n  /**\n   * @param {object} opts\n   * @param {string|null}  opts.value                — current color as `#rrggbb` or null\n   * @param {function}     opts.onPick(hex)          — user picked a color via swatch / hex / eyedropper\n   * @param {function?}    opts.onReset()            — user hit Reset (null-color) — defaults to `onPick(null)`\n   * @param {string[]?}    opts.recent               — recent-LRU colors (caller-owned state)\n   * @param {{main?: string[][], standard?: string[]}?} opts.palette — override palette rows\n   * @param {string?}      opts.title                — header title; falls back to \"Palette\"\n   * @param {boolean?}     opts.showEyedropper       — default true (auto-hidden when API missing)\n   * @param {boolean?}     opts.showReset            — default true\n   * @param {boolean?}     opts.showCustomRow        — default true (hex input + native picker)\n   */\n  function ColorPalettePicker(opts) {\n    _classCallCheck(this, ColorPalettePicker);\n    if (!opts || typeof opts.onPick !== 'function') {\n      throw new Error('ColorPalettePicker: opts.onPick(hex) is required');\n    }\n    this._value = opts.value || null;\n    this._onPick = opts.onPick;\n    this._onReset = opts.onReset || function () {\n      return opts.onPick(null);\n    };\n    this._recent = Array.isArray(opts.recent) ? opts.recent.slice() : [];\n    var pal = opts.palette || {};\n    this._mainRows = Array.isArray(pal.main) ? pal.main : DEFAULT_MAIN_PALETTE;\n    this._standard = Array.isArray(pal.standard) ? pal.standard : DEFAULT_STANDARD;\n    this._title = opts.title || _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.palette');\n    this._showEyedropper = opts.showEyedropper !== false;\n    this._showReset = opts.showReset !== false;\n    this._showCustomRow = opts.showCustomRow !== false;\n    this.domNode = document.createElement('div');\n    this.domNode.className = 'bjs-color-palette-picker';\n    this._render();\n  }\n\n  /** Public entry — update the custom-row inputs to reflect the current\n   *  value. Does NOT change `.is-active` markers on the palette swatches\n   *  (the black swatch is the stable anchor — see `_makeSwatch`). */\n  return _createClass(ColorPalettePicker, [{\n    key: \"setValue\",\n    value: function setValue(hex) {\n      var normalized = this._parseHex(hex);\n      this._value = normalized || hex || null;\n      if (this._hexInput) this._hexInput.value = this._value || '';\n      if (this._nativePicker && this._value && /^#[0-9a-f]{6}$/i.test(this._value)) {\n        this._nativePicker.value = this._value;\n      }\n    }\n\n    /** Public entry — update recent-LRU row (consumer pushes, picker re-renders). */\n  }, {\n    key: \"setRecent\",\n    value: function setRecent(arr) {\n      this._recent = Array.isArray(arr) ? arr.slice() : [];\n      // Re-render whole domNode — recent section may appear/disappear\n      // between 0 and 1 entries, which is a structural change.\n      this.domNode.innerHTML = '';\n      this._render();\n    }\n\n    /* ── private render ─────────────────────────────────────────────── */\n  }, {\n    key: \"_render\",\n    value: function _render() {\n      this.domNode.appendChild(this._buildHeader());\n      if (this._recent.length) {\n        this.domNode.appendChild(this._buildSection(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.recent'), [this._recent.slice(0, 10)], 'bjs-color-popover-recent'));\n      }\n      this.domNode.appendChild(this._buildSection(this._title, this._mainRows, 'bjs-color-popover-palette bjs-color-popover-palette-rich'));\n      this.domNode.appendChild(this._buildSection(_I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.standard'), [this._standard], 'bjs-color-popover-standard'));\n      if (this._showCustomRow) {\n        this.domNode.appendChild(this._buildCustomRow());\n      }\n      if (this._showEyedropper && typeof window !== 'undefined' && 'EyeDropper' in window) {\n        this.domNode.appendChild(this._buildEyedropperRow());\n      }\n    }\n  }, {\n    key: \"_buildHeader\",\n    value: function _buildHeader() {\n      var _this = this;\n      var header = document.createElement('div');\n      header.className = 'bjs-color-popover-header';\n\n      // Title-LEFT, Reset-RIGHT. DOM order must match visual order so\n      // CSS's `margin-left: auto` on Reset cleanly pushes it to the\n      // right edge. Do NOT swap back to Reset-first — the layout would\n      // break in the reverse.\n      var title = document.createElement('span');\n      title.className = 'bjs-color-popover-title';\n      title.textContent = this._title;\n      header.appendChild(title);\n      if (this._showReset) {\n        var reset = document.createElement('button');\n        reset.type = 'button';\n        reset.className = 'bjs-color-popover-reset';\n        reset.setAttribute('data-role', 'reset');\n        reset.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.remove'));\n        reset.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.remove'));\n        var resetIcon = document.createElement('span');\n        resetIcon.className = 'material-symbols-rounded';\n        resetIcon.setAttribute('aria-hidden', 'true');\n        resetIcon.textContent = 'format_color_reset';\n        reset.appendChild(resetIcon);\n        var resetLabel = document.createElement('span');\n        resetLabel.className = 'bjs-color-popover-reset-label';\n        resetLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.reset');\n        reset.appendChild(resetLabel);\n        reset.addEventListener('click', function (e) {\n          e.preventDefault();\n          e.stopPropagation();\n          _this._onReset();\n        });\n        header.appendChild(reset);\n      }\n      return header;\n    }\n  }, {\n    key: \"_buildSection\",\n    value: function _buildSection(label, rows, extraClass) {\n      var _this2 = this;\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-color-popover-section ' + (extraClass || '');\n      var head = document.createElement('div');\n      head.className = 'bjs-color-popover-section-label';\n      head.textContent = label;\n      wrap.appendChild(head);\n      var colCount = rows[0] && rows[0].length ? rows[0].length : 8;\n      var grid = document.createElement('div');\n      grid.className = 'bjs-color-popover-grid';\n      grid.setAttribute('role', 'group');\n      grid.style.setProperty('--bjs-color-grid-cols', String(colCount));\n      rows.forEach(function (row) {\n        row.forEach(function (hex) {\n          return grid.appendChild(_this2._makeSwatch(hex));\n        });\n      });\n      wrap.appendChild(grid);\n      return wrap;\n    }\n  }, {\n    key: \"_makeSwatch\",\n    value: function _makeSwatch(hex) {\n      var _this3 = this;\n      var btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = 'bjs-color-swatch-btn';\n      btn.setAttribute('data-role', 'swatch');\n      btn.setAttribute('data-color', hex);\n      btn.setAttribute('aria-label', hex);\n      btn.setAttribute('data-tooltip', hex);\n      btn.style.setProperty('--bjs-color-swatch', hex);\n      // Stable visual anchor — always mark the black swatch active\n      // regardless of the currently-applied color (per user UX rule —\n      // \"ko highlight current color chọn, cứ highlight node màu đen\").\n      // Rationale: users scanning a 60-swatch palette want a stable\n      // visual starting point, not a marker that jumps around with\n      // whatever they picked last. The \"current color\" state is\n      // surfaced on the toolbar button's underline bar instead.\n      if (hex.toLowerCase() === '#000000') {\n        btn.classList.add('is-active');\n      }\n      btn.addEventListener('click', function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n        _this3._onPick(hex);\n      });\n      return btn;\n    }\n  }, {\n    key: \"_buildCustomRow\",\n    value: function _buildCustomRow() {\n      var _this4 = this;\n      var wrap = document.createElement('div');\n      wrap.className = 'bjs-color-popover-section bjs-color-popover-custom';\n      var head = document.createElement('div');\n      head.className = 'bjs-color-popover-section-label';\n      head.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.custom');\n      wrap.appendChild(head);\n      var row = document.createElement('div');\n      row.className = 'bjs-color-popover-custom-row';\n      var nativePicker = document.createElement('input');\n      nativePicker.type = 'color';\n      nativePicker.className = 'bjs-color-popover-native';\n      nativePicker.value = this._value && /^#[0-9a-f]{6}$/i.test(this._value) ? this._value : '#000000';\n      nativePicker.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.custom'));\n      nativePicker.addEventListener('change', function (e) {\n        _this4._onPick(e.target.value);\n      });\n      this._nativePicker = nativePicker;\n      var hexInput = document.createElement('input');\n      hexInput.type = 'text';\n      hexInput.className = 'bjs-color-popover-hex';\n      hexInput.value = this._value || '';\n      hexInput.placeholder = '#RRGGBB';\n      hexInput.setAttribute('aria-label', 'Hex color');\n      hexInput.setAttribute('spellcheck', 'false');\n      hexInput.setAttribute('autocomplete', 'off');\n      var commitHex = function commitHex() {\n        var v = _this4._parseHex(hexInput.value);\n        if (v) {\n          _this4._onPick(v);\n        } else if (hexInput.value && hexInput.value.trim() !== '') {\n          hexInput.classList.add('is-error');\n          setTimeout(function () {\n            return hexInput.classList.remove('is-error');\n          }, 600);\n        }\n      };\n      hexInput.addEventListener('keydown', function (e) {\n        if (e.key === 'Enter') {\n          e.preventDefault();\n          commitHex();\n        }\n      });\n      hexInput.addEventListener('blur', commitHex);\n      this._hexInput = hexInput;\n      row.appendChild(nativePicker);\n      row.appendChild(hexInput);\n      wrap.appendChild(row);\n      return wrap;\n    }\n  }, {\n    key: \"_buildEyedropperRow\",\n    value: function _buildEyedropperRow() {\n      var _this5 = this;\n      var foot = document.createElement('div');\n      foot.className = 'bjs-color-popover-footer';\n      var eye = document.createElement('button');\n      eye.type = 'button';\n      eye.className = 'bjs-color-popover-eyedropper';\n      eye.setAttribute('data-role', 'eyedropper');\n      eye.setAttribute('aria-label', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.eyedropper'));\n      eye.setAttribute('data-tooltip', _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.eyedropper'));\n      var icon = document.createElement('span');\n      icon.className = 'material-symbols-rounded';\n      icon.setAttribute('aria-hidden', 'true');\n      icon.textContent = 'colorize';\n      eye.appendChild(icon);\n      var eyeLabel = document.createElement('span');\n      eyeLabel.className = 'bjs-color-popover-eyedropper-label';\n      eyeLabel.textContent = _I18n_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t('color_popover.eyedropper');\n      eye.appendChild(eyeLabel);\n      eye.addEventListener('click', /*#__PURE__*/function () {\n        var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(e) {\n          var dropper, res;\n          return _regeneratorRuntime().wrap(function _callee$(_context) {\n            while (1) switch (_context.prev = _context.next) {\n              case 0:\n                e.preventDefault();\n                _context.prev = 1;\n                // eslint-disable-next-line no-undef\n                dropper = new window.EyeDropper();\n                _context.next = 5;\n                return dropper.open();\n              case 5:\n                res = _context.sent;\n                if (res && res.sRGBHex) _this5._onPick(res.sRGBHex);\n                _context.next = 12;\n                break;\n              case 9:\n                _context.prev = 9;\n                _context.t0 = _context[\"catch\"](1);\n                if (_context.t0 && _context.t0.name !== 'AbortError') {\n                  eye.classList.add('is-error');\n                  setTimeout(function () {\n                    return eye.classList.remove('is-error');\n                  }, 600);\n                }\n              case 12:\n              case \"end\":\n                return _context.stop();\n            }\n          }, _callee, null, [[1, 9]]);\n        }));\n        return function (_x) {\n          return _ref.apply(this, arguments);\n        };\n      }());\n      foot.appendChild(eye);\n      return foot;\n    }\n\n    /** Parse hex into canonical lowercase `#rrggbb`. */\n  }, {\n    key: \"_parseHex\",\n    value: function _parseHex(raw) {\n      if (!raw) return null;\n      var s = String(raw).trim();\n      if (s.charAt(0) === '#') s = s.slice(1);\n      if (/^[0-9a-f]{3}$/i.test(s)) {\n        s = s.split('').map(function (c) {\n          return c + c;\n        }).join('');\n      }\n      if (!/^[0-9a-f]{6}$/i.test(s)) return null;\n      return '#' + s.toLowerCase();\n    }\n  }]);\n}();\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ColorPalettePicker);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ui/ColorPalettePicker.js?");

/***/ }),

/***/ "./src/includes/ui/holedBoxClipPath.js":
/*!*********************************************!*\
  !*** ./src/includes/ui/holedBoxClipPath.js ***!
  \*********************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */   holedBoxClipPath: () => (/* binding */ holedBoxClipPath)\n/* harmony export */ });\n/*\n * holedBoxClipPath — 2026-04-19.\n *\n * Build a `clip-path: polygon(...)` string for a \"holed box\" — an outer\n * rectangle with a rectangular hole carved out. All measurements in px.\n *\n * Winding (CSS non-zero rule):\n *   outer rect CW   → +1 winding inside outer\n *   inner rect CCW  → -1 winding inside inner\n *   sum = 0 inside inner → HOLE\n *\n * Slit from (L,0) straight down to (L,B) is traversed twice (once going\n * into the hole, once coming back up the same line) so it renders as a\n * zero-width seam → visually invisible.\n *\n * Historical gotcha: the first implementation had both loops going CW\n * → winding +2 inside the hole → hole was FILLED → the overlay covered\n * the child element (\"ăn vào luôn cả element\"). Reversing the inner\n * loop order to CCW fixed it. Keep the ordering below as-is — the inner\n * corner sequence is: (L,0) → (L,B) → (R,B) → (R,T) → (L,T) → (L,0).\n *\n * The background painted on the holed box can be ANY CSS paint —\n * stripes, image, gradient, conic, emoji, whatever — because clip-path\n * is a purely geometric operation applied AFTER the browser renders\n * the background. See docs/plans/HOLED_BOX.md for the full primer + use cases.\n *\n * @param {{width: number, height: number}}              outer — outer rect dims in px\n * @param {{left: number, top: number, right: number, bottom: number}}\n *                                                       hole  — hole bounds in px,\n *                                                               right/bottom = absolute\n *                                                               coords (NOT widths)\n * @returns {string}  CSS `polygon(...)` string ready for `element.style.clipPath`\n */\nfunction holedBoxClipPath(outer, hole) {\n  var W = outer.width,\n    H = outer.height;\n  var L = hole.left,\n    T = hole.top;\n  var R = hole.right,\n    B = hole.bottom;\n  return \"polygon(\\n        0 0, \".concat(W, \"px 0, \").concat(W, \"px \").concat(H, \"px, 0 \").concat(H, \"px, 0 0,\\n        \").concat(L, \"px 0,\\n        \").concat(L, \"px \").concat(B, \"px,\\n        \").concat(R, \"px \").concat(B, \"px,\\n        \").concat(R, \"px \").concat(T, \"px,\\n        \").concat(L, \"px \").concat(T, \"px,\\n        \").concat(L, \"px 0\\n    )\");\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (holedBoxClipPath);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ui/holedBoxClipPath.js?");

/***/ }),

/***/ "./src/includes/ui/sortable.js":
/*!*************************************!*\
  !*** ./src/includes/ui/sortable.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   bjsSortable: () => (/* binding */ bjsSortable),\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../PointerCaptureRegistry.js */ \"./src/includes/PointerCaptureRegistry.js\");\n\n\n/**\n * bjsSortable — pointer-driven drag-reorder for any vertical list.\n *\n * Phase-3 W6.1 introduced the same primitive inline on GridControl's\n * horizontal cell strip. W6.2 extracts the shared behavior into a tiny\n * module that ListControl / SocialIconsControl / SelectControl can opt\n * into without each re-inventing the same pointer math.\n *\n * Contract: the caller owns the data model. The mixin just reports a\n * `from → to` index move; the caller's `onReorder(from, to)` callback\n * splices the underlying array and re-renders (or mutates in place).\n *\n * ```js\n *   import { bjsSortable } from './ui/sortable.js';\n *\n *   bjsSortable(olElement, {\n *     itemSelector: '.bjs-list-item',\n *     handleSelector: '.bjs-list-item-handle',\n *     onReorder: (from, to) => {\n *       const [item] = items.splice(from, 1);\n *       const adj = to > from ? to - 1 : to;\n *       items.splice(adj, 0, item);\n *       this.render();\n *       this.callback?.setItems(items);\n *     },\n *   });\n * ```\n *\n * Design notes (why this file exists instead of three copies):\n * 1. **Pointer capture goes through the shared registry** so UIManager's\n *    hover-suspend invariant (OVERLAY_PLAN §4.I5) survives a detached\n *    mid-drag. A rogue `setPointerCapture` in a leaf control breaks the\n *    entire builder's hover state until the next refresh.\n * 2. **The drop indicator is a DOM sibling of the list, not the item**\n *    so its absolute position measured against the list's\n *    `getBoundingClientRect()` survives item `innerHTML` rebuilds during\n *    the drag. If it lived inside an item, a caller that full-renders\n *    on every move would orphan it.\n * 3. **Auto-scroll is opt-in via `scrollContainer`** — most sidebar\n *    lists already scroll naturally with the panel. Only provide a\n *    container when the list sits inside its own scroll clip.\n * 4. **`destroy()` is returned** so the caller can bind fresh sortable\n *    behavior after a `render()` without leaking old listeners. Most\n *    controls re-`render()` which rebuilds DOM from scratch → old\n *    listeners are GC'd with their nodes, so `destroy()` is optional in\n *    that flow. Provided for the controls that patch DOM in place.\n */\n\nvar DROP_INDICATOR_CLASS = 'bjs-sortable-drop-indicator';\nvar GHOST_CLASS = 'bjs-sortable-ghost';\nvar DRAGGING_CLASS = 'is-sortable-dragging';\nvar DRAG_OVER_CLASS = 'is-sortable-drag-over';\nfunction bjsSortable(listEl) {\n  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n  if (!listEl || listEl.nodeType !== 1) {\n    throw new TypeError('bjsSortable: listEl must be a DOM element');\n  }\n  var _opts$itemSelector = opts.itemSelector,\n    itemSelector = _opts$itemSelector === void 0 ? '.bjs-list-item' : _opts$itemSelector,\n    _opts$handleSelector = opts.handleSelector,\n    handleSelector = _opts$handleSelector === void 0 ? '.bjs-list-item-handle' : _opts$handleSelector,\n    onReorder = opts.onReorder,\n    _opts$scrollContainer = opts.scrollContainer,\n    scrollContainer = _opts$scrollContainer === void 0 ? null : _opts$scrollContainer,\n    _opts$dragClass = opts.dragClass,\n    dragClass = _opts$dragClass === void 0 ? DRAGGING_CLASS : _opts$dragClass,\n    _opts$onDragStart = opts.onDragStart,\n    onDragStart = _opts$onDragStart === void 0 ? null : _opts$onDragStart,\n    _opts$onDragEnd = opts.onDragEnd,\n    onDragEnd = _opts$onDragEnd === void 0 ? null : _opts$onDragEnd;\n  if (typeof onReorder !== 'function') {\n    throw new TypeError('bjsSortable: opts.onReorder is required');\n  }\n\n  // Find or create the drop indicator inside the list's parent. Reuse across\n  // drags so we don't churn the DOM. The indicator is styled as an absolute\n  // vertical-gap line; caller's CSS owns its appearance.\n  var indicator = listEl.parentElement ? listEl.parentElement.querySelector(\":scope > .\".concat(DROP_INDICATOR_CLASS)) : null;\n  if (!indicator && listEl.parentElement) {\n    indicator = document.createElement('div');\n    indicator.className = DROP_INDICATOR_CLASS;\n    // Relative containment — the indicator lives OUTSIDE the ol (as a sibling)\n    // so sliding between <li>s doesn't disturb flex/grid math.\n    indicator.setAttribute('aria-hidden', 'true');\n    listEl.parentElement.appendChild(indicator);\n    if (getComputedStyle(listEl.parentElement).position === 'static') {\n      listEl.parentElement.style.position = 'relative';\n    }\n  }\n  var state = null;\n  function getItems() {\n    return Array.from(listEl.querySelectorAll(\":scope > \".concat(itemSelector)));\n  }\n  function hitTestSlot(clientY) {\n    var items = getItems();\n    if (!items.length) return 0;\n    var midpoints = items.map(function (it) {\n      var r = it.getBoundingClientRect();\n      return (r.top + r.bottom) / 2;\n    });\n    for (var i = 0; i < midpoints.length; i++) {\n      if (clientY < midpoints[i]) return i;\n    }\n    return items.length;\n  }\n  function paintIndicator(slot) {\n    if (!indicator) return;\n    var items = getItems();\n    if (slot === null || slot === undefined) {\n      indicator.classList.remove('is-visible');\n      return;\n    }\n    var parentRect = listEl.parentElement.getBoundingClientRect();\n    var yPx;\n    if (!items.length) {\n      yPx = listEl.getBoundingClientRect().top - parentRect.top;\n    } else if (slot === 0) {\n      yPx = items[0].getBoundingClientRect().top - parentRect.top - 2;\n    } else if (slot >= items.length) {\n      yPx = items[items.length - 1].getBoundingClientRect().bottom - parentRect.top + 2;\n    } else {\n      var prev = items[slot - 1].getBoundingClientRect();\n      var next = items[slot].getBoundingClientRect();\n      yPx = (prev.bottom + next.top) / 2 - parentRect.top;\n    }\n    var listRect = listEl.getBoundingClientRect();\n    indicator.style.left = \"\".concat(listRect.left - parentRect.left, \"px\");\n    indicator.style.width = \"\".concat(listRect.width, \"px\");\n    indicator.style.top = \"\".concat(yPx, \"px\");\n    indicator.classList.add('is-visible');\n  }\n  function autoScroll(clientY) {\n    var sc = scrollContainer;\n    if (!sc) return;\n    var rect = sc.getBoundingClientRect();\n    var EDGE = 32;\n    var SPEED = 8;\n    if (clientY < rect.top + EDGE) {\n      sc.scrollTop -= SPEED;\n    } else if (clientY > rect.bottom - EDGE) {\n      sc.scrollTop += SPEED;\n    }\n  }\n  function onHandlePointerDown(e) {\n    if (e.button !== undefined && e.button !== 0) return;\n    var handle = e.currentTarget;\n    var item = handle.closest(itemSelector);\n    if (!item || !listEl.contains(item)) return;\n    var items = getItems();\n    var sourceIdx = items.indexOf(item);\n    if (sourceIdx < 0) return;\n    e.preventDefault();\n    e.stopPropagation();\n    _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].acquire(handle, e.pointerId);\n    item.classList.add(dragClass);\n    listEl.classList.add(DRAGGING_CLASS);\n\n    // Create a floating ghost clone positioned with the pointer. Gives\n    // users the Figma-style \"piece follows cursor\" affordance without\n    // needing HTML5 DnD (which fights with our PointerCaptureRegistry).\n    var ghost = item.cloneNode(true);\n    ghost.classList.add(GHOST_CLASS);\n    ghost.classList.remove(dragClass);\n    // Strip interactive children so ghost can't be focused / clicked.\n    ghost.querySelectorAll('button, input, select, textarea').forEach(function (el) {\n      el.setAttribute('tabindex', '-1');\n      el.style.pointerEvents = 'none';\n    });\n    var rect = item.getBoundingClientRect();\n    ghost.style.width = \"\".concat(rect.width, \"px\");\n    ghost.style.height = \"\".concat(rect.height, \"px\");\n    document.body.appendChild(ghost);\n    state = {\n      handle: handle,\n      pointerId: e.pointerId,\n      sourceIdx: sourceIdx,\n      item: item,\n      ghost: ghost,\n      dropSlot: null,\n      offsetX: e.clientX - rect.left,\n      offsetY: e.clientY - rect.top\n    };\n    positionGhost(e.clientX, e.clientY);\n    var slot0 = hitTestSlot(e.clientY);\n    state.dropSlot = normaliseSlot(slot0, sourceIdx);\n    paintIndicator(state.dropSlot);\n    handle.addEventListener('pointermove', onMove);\n    handle.addEventListener('pointerup', onUp);\n    handle.addEventListener('pointercancel', onCancel);\n    handle.addEventListener('lostpointercapture', onCancel);\n    if (typeof onDragStart === 'function') {\n      try {\n        onDragStart(sourceIdx);\n      } catch (_e) {}\n    }\n  }\n  function positionGhost(x, y) {\n    if (!state || !state.ghost) return;\n    state.ghost.style.left = \"\".concat(x - state.offsetX, \"px\");\n    state.ghost.style.top = \"\".concat(y - state.offsetY, \"px\");\n  }\n\n  /** Drop slot indices adjacent to the source (`from` or `from + 1`) both\n   *  resolve back to the same position → treat as no-op and return null so\n   *  the indicator vanishes. */\n  function normaliseSlot(slot, sourceIdx) {\n    if (slot === sourceIdx || slot === sourceIdx + 1) return null;\n    return slot;\n  }\n  function onMove(e) {\n    if (!state) return;\n    positionGhost(e.clientX, e.clientY);\n    var slot = hitTestSlot(e.clientY);\n    state.dropSlot = normaliseSlot(slot, state.sourceIdx);\n    paintIndicator(state.dropSlot);\n    autoScroll(e.clientY);\n  }\n  function cleanup() {\n    if (!state) return;\n    var _state = state,\n      handle = _state.handle,\n      item = _state.item,\n      ghost = _state.ghost,\n      pointerId = _state.pointerId;\n    try {\n      handle.removeEventListener('pointermove', onMove);\n    } catch (_e) {}\n    try {\n      handle.removeEventListener('pointerup', onUp);\n    } catch (_e) {}\n    try {\n      handle.removeEventListener('pointercancel', onCancel);\n    } catch (_e) {}\n    try {\n      handle.removeEventListener('lostpointercapture', onCancel);\n    } catch (_e) {}\n    try {\n      _PointerCaptureRegistry_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"].release(handle, pointerId);\n    } catch (_e) {}\n    if (ghost && ghost.parentNode) ghost.parentNode.removeChild(ghost);\n    if (item) item.classList.remove(dragClass);\n    listEl.classList.remove(DRAGGING_CLASS);\n    paintIndicator(null);\n    state = null;\n  }\n  function onUp() {\n    var st = state;\n    var dest = st ? st.dropSlot : null;\n    var src = st ? st.sourceIdx : -1;\n    cleanup();\n    if (dest !== null && src >= 0) {\n      try {\n        onReorder(src, dest);\n      } catch (err) {\n        console.error('bjsSortable.onReorder threw', err);\n      }\n    }\n    if (typeof onDragEnd === 'function') {\n      try {\n        onDragEnd(src, dest);\n      } catch (_e) {}\n    }\n  }\n  function onCancel() {\n    var st = state;\n    var src = st ? st.sourceIdx : -1;\n    cleanup();\n    if (typeof onDragEnd === 'function') {\n      try {\n        onDragEnd(src, null);\n      } catch (_e) {}\n    }\n  }\n\n  // Wire every handle. Re-running bjsSortable on the same list rebinds\n  // cleanly because listeners were attached to the OLD DOM nodes which no\n  // longer exist (render() rebuilds innerHTML). Idempotence is a caller\n  // property in the render-every-change pattern.\n  var handles = Array.from(listEl.querySelectorAll(\"\".concat(itemSelector, \" \").concat(handleSelector)));\n  handles.forEach(function (h) {\n    h.addEventListener('dragstart', function (e) {\n      return e.preventDefault();\n    }); // block native DnD\n    h.addEventListener('pointerdown', onHandlePointerDown);\n  });\n  return {\n    destroy: function destroy() {\n      handles.forEach(function (h) {\n        try {\n          h.removeEventListener('pointerdown', onHandlePointerDown);\n        } catch (_e) {}\n      });\n      cleanup();\n      if (indicator && indicator.parentNode) {\n        indicator.parentNode.removeChild(indicator);\n      }\n    }\n  };\n}\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (bjsSortable);\n\n//# sourceURL=webpack://BuilderBundle/./src/includes/ui/sortable.js?");

/***/ }),

/***/ "./src/lang/en.json":
/*!**************************!*\
  !*** ./src/lang/en.json ***!
  \**************************/
/***/ ((module) => {

eval("module.exports = /*#__PURE__*/JSON.parse('{\"widgets.heading\":\"Heading\",\"widgets.paragraph\":\"Paragraph\",\"widgets.button\":\"Button\",\"widgets.image\":\"Image\",\"widgets.video\":\"Video Widget\",\"widgets.grid\":\"Grid\",\"widgets.list\":\"List\",\"widgets.menu\":\"Menu Bar\",\"widgets.pricing_cards\":\"Pricing Cards\",\"widgets.divider\":\"Divider\",\"widgets.alert\":\"Alert\",\"widgets.youtube\":\"Youtube\",\"widgets.rss\":\"RSS\",\"widgets.select\":\"Select\",\"widgets.radio\":\"Radio\",\"widgets.checkbox\":\"Checkbox\",\"widgets.checkout\":\"Checkout\",\"widgets.checkout_simple\":\"Checkout Simple\",\"widgets.welcome\":\"Welcome\",\"widgets.image_text_left\":\"Image Left & Text\",\"widgets.image_text_right\":\"Image Right & Text\",\"widgets.image_text_top\":\"Image Top & Text\",\"widgets.image_text_bottom\":\"Image Bottom & Text\",\"widgets.image_text_double\":\"Image Top & Text\",\"widgets.text_center\":\"Text Center\",\"widgets.text_left\":\"Text Left\",\"widgets.text_double\":\"Text Left\",\"widgets.terms_of_service\":\"Terms of Service\",\"elements.page\":\"Page\",\"elements.block\":\"Block\",\"elements.cell\":\"Cell\",\"elements.button\":\"Button\",\"elements.image\":\"Image\",\"elements.heading\":\"Heading\",\"elements.link\":\"Link\",\"elements.video\":\"Video\",\"elements.alert\":\"Alert\",\"elements.menu\":\"Menu\",\"elements.list\":\"List\",\"elements.label\":\"Label\",\"elements.text_input\":\"Text Input\",\"elements.select\":\"Select\",\"elements.radio\":\"Radio\",\"elements.checkbox\":\"Checkbox\",\"elements.social_icons\":\"Social Icons\",\"elements.divider\":\"Divider\",\"elements.html\":\"HTML\",\"elements.rss\":\"RSS\",\"elements.youtube\":\"YouTube\",\"elements.pricing_cards\":\"Pricing Cards\",\"elements.pricing_card\":\"Card\",\"elements.checkout\":\"Checkout\",\"elements.checkout_simple\":\"Checkout Simple\",\"elements.heading_1\":\"Heading 1\",\"elements.heading_2\":\"Heading 2\",\"elements.heading_3\":\"Heading 3\",\"elements.heading_4\":\"Heading 4\",\"elements.heading_5\":\"Heading 5\",\"elements.paragraph\":\"Paragraph\",\"elements.submit_button\":\"Submit Button\",\"elements.field\":\"Field\",\"elements.terms_of_service\":\"Terms of Service\",\"actions.copy\":\"Copy\",\"actions.remove\":\"Remove\",\"actions.select_parent\":\"Select Parent\",\"actions.unselect\":\"Unselect\",\"controls.text\":\"Text\",\"controls.url\":\"URL\",\"controls.font_family\":\"Font Family\",\"controls.font_weight\":\"Font Weight\",\"controls.font_size\":\"Font Size\",\"controls.text_color\":\"Text Color\",\"controls.link_color\":\"Link Color\",\"controls.alignment\":\"Alignment\",\"controls.background_settings\":\"Background Settings\",\"controls.border_settings\":\"Border Settings\",\"controls.radius\":\"Radius\",\"controls.padding\":\"Padding\",\"controls.margin\":\"Margin\",\"controls.block_padding\":\"Block Padding\",\"controls.page_padding\":\"Page Padding\",\"controls.width\":\"Width\",\"controls.height\":\"Height\",\"controls.max_width\":\"Max Width\",\"controls.max_height\":\"Max Height\",\"controls.min_width\":\"Min Width\",\"controls.min_height\":\"Min Height\",\"controls.display\":\"Display\",\"controls.direction\":\"Direction\",\"controls.justify\":\"Justify\",\"controls.align_items\":\"Align Items\",\"controls.gap\":\"Gap\",\"controls.content_gap\":\"Content Gap\",\"controls.line_height\":\"Line Height\",\"controls.letter_spacing\":\"Letter Spacing\",\"controls.paragraph_spacing\":\"Paragraph Spacing\",\"controls.text_direction\":\"Text Direction\",\"controls.color\":\"Color\",\"controls.size_pct\":\"Size (%)\",\"controls.default_block_background\":\"Default Block Background\",\"controls.block_gap\":\"Block Gap\",\"controls.container_width\":\"Container Width\",\"controls.cell_background\":\"Cell Background\",\"controls.cell_border\":\"Cell Border\",\"controls.cell_radius\":\"Cell Radius\",\"controls.cell_padding\":\"Cell Padding\",\"controls.cell_height\":\"Cell Height\",\"controls.optimized_mobile\":\"Optimized for mobile\",\"controls.optimized_mobile_desc\":\"Allow the element to display correctly on mobile devices\",\"controls.compat_mode\":\"Compatibility mode for legacy browser\",\"controls.compat_mode_desc\":\"Render compatible HTML for older browser like IE, Opera notice that in certain cases, it might generate JS and make sure your browser supports JS\",\"controls.social_icons\":\"Social Icons\",\"controls.items\":\"Items\",\"controls.plans\":\"Plans\",\"pricing.section_style\":\"Card style\",\"pricing.section_style_desc\":\"Pick one of 10 presets — applies to every card in this set.\",\"pricing.style_label\":\"Style\",\"pricing_style.minimal_label\":\"Minimal\",\"pricing_style.highlighted_label\":\"Highlighted\",\"pricing_style.featured_label\":\"Featured\",\"pricing_style.compact_label\":\"Compact\",\"pricing_style.glass_label\":\"Glass\",\"pricing_style.pill_label\":\"Pill\",\"pricing_style.neon_label\":\"Neon\",\"pricing_style.brutalist_label\":\"Brutalist\",\"pricing_style.editorial_label\":\"Editorial\",\"pricing_style.gradient_label\":\"Gradient\",\"pricing_style.banded_label\":\"Banded\",\"pricing_style.tier_label\":\"Tier\",\"pricing_style.neo_label\":\"Soft\",\"pricing.section_card_meta\":\"This card\",\"pricing.section_card_meta_desc\":\"Per-card accent — pick the one you want to stand out.\",\"pricing.highlighted_label\":\"Highlight this card\",\"pricing.highlighted_desc\":\"Apply the accent border + subtle lift so this plan stands out.\",\"pricing.badge_label\":\"Badge text\",\"pricing.badge_placeholder\":\"e.g. Most Popular\",\"pricing.icon_label\":\"Icon\",\"pricing.icon_placeholder\":\"e.g. bolt or 💎\",\"pricing.icon_help\":\"Use a Material Symbols name (bolt, diamond…) or any emoji.\",\"pricing.accent_label\":\"Accent color\",\"pricing.accent_placeholder\":\"#ffcc2a\",\"pricing.card_empty_title\":\"Empty plan\",\"pricing.card_empty_hint\":\"Drop a heading, price, or button to start this plan.\",\"pricing.highlight_label\":\"Recommended plan\",\"pricing.highlight_none\":\"None — no card highlighted\",\"pricing.highlight_card_n\":\"Card {n}\",\"pricing.show_icons_label\":\"Show card icons\",\"pricing.show_icons_desc\":\"Hide icons on every card without clearing the icon field.\",\"pricing.show_badges_label\":\"Show card badges\",\"pricing.show_badges_desc\":\"Hide badges (“Most Popular” pills) without clearing the badge text.\",\"pricing.style_switch_hint\":\"Switching style replaces every card’s accent, button, and text colors with the new style’s defaults. Your badge, icon, and highlight choices are preserved.\",\"pricing.card_style_hint\":\"This card inherits the {style} style defaults. Colors you pick here override the style.\",\"pricing.reset_all_label\":\"Reset all cards\",\"pricing.reset_all_hint\":\"Clears accent, badge, icon, and highlight on every card, then re-applies {style} defaults.\",\"pricing.reset_all_button\":\"Reset\",\"pricing.reset_card_label\":\"Reset this card\",\"pricing.reset_card_hint\":\"Clears this card’s accent, badge, icon, highlight, and re-applies {style} defaults.\",\"pricing.reset_card_button\":\"Reset\",\"icon_picker.none\":\"None\",\"icon_picker.custom\":\"Custom emoji\",\"icon_picker.custom_label\":\"Enter an emoji or glyph\",\"icon_picker.custom_placeholder\":\"e.g. 💎 or ✨\",\"controls.columns\":\"Columns\",\"controls.heading\":\"Heading\",\"controls.divider_style\":\"Divider Style\",\"controls.image_padding\":\"Image Padding\",\"controls.image_effects\":\"Image Effects\",\"controls.button_padding\":\"Button Padding\",\"controls.custom_block_padding\":\"Custom Block Padding\",\"controls.alert_padding\":\"Alert Padding\",\"controls.grid_background\":\"Grid Background\",\"controls.grid_padding\":\"Grid Padding\",\"controls.grid_height\":\"Grid Height\",\"controls.cells\":\"Cells\",\"controls.cell_gap\":\"Cell Gap\",\"controls.name\":\"Name\",\"controls.value\":\"Value\",\"controls.placeholder\":\"Placeholder\",\"controls.orientation\":\"Orientation\",\"controls.separator\":\"Separator\",\"controls.separator_gap\":\"Separator Gap\",\"separator.none\":\"No separator\",\"separator.custom\":\"Custom\",\"separator.placeholder\":\"e.g. ::\",\"controls.items_gap\":\"Items Gap\",\"controls.youtube_url\":\"Youtube URL\",\"controls.video_url\":\"Video URL\",\"video.url_placeholder\":\"https://example.com/video.mp4\",\"video.url_banner\":\"Paste a direct <b>.mp4</b>, <b>.webm</b>, or <b>.ogg</b> URL. YouTube / Vimeo links need the <b>YouTube</b> widget instead — they won\\'t play inside a native &lt;video&gt; tag.\",\"video.invalid_url\":\"Enter a valid URL (http://, https://, or /path).\",\"video.load_error\":\"This URL didn\\'t return a playable video. Check the link or use the YouTube widget for YouTube/Vimeo.\",\"video.load_ok\":\"Video loaded successfully.\",\"video.load_pending\":\"Checking video…\",\"video.err_aborted\":\"Loading was cancelled before the video finished downloading.\",\"video.err_network\":\"Network error — the video server didn\\'t respond. Check the URL, the server\\'s availability, and that it returns 200 OK.\",\"video.err_decode\":\"The video file is corrupted or uses a codec this browser can\\'t decode.\",\"video.err_src_unsupported\":\"The URL returned, but the content isn\\'t a supported video (wrong Content-Type, blocked by CORS, or a format this browser can\\'t play). YouTube / Vimeo links need the YouTube widget instead.\",\"video.clear\":\"Clear video URL\",\"video.empty_title\":\"No video yet\",\"video.empty_desc\":\"Paste a direct video URL in the right panel (Video URL field) to preview it here.\",\"video.fallback_error\":\"The video URL couldn\\'t be played. The file may be missing, blocked by CORS, or not a supported format (mp4/webm/ogg).\",\"controls.pricing_cards_padding\":\"Pricing Cards Padding\",\"controls.icons_items_list\":\"Icons/Items List\",\"controls.icon_gap\":\"Icon Gap\",\"controls.icon_size\":\"Icon Size\",\"controls.social_icons_padding\":\"Social Icons Padding\",\"controls.list_items\":\"List Items\",\"list.add\":\"Add\",\"list.edit\":\"Edit\",\"list.delete\":\"Delete\",\"list.reorder\":\"Drag to reorder\",\"list.label\":\"Label\",\"list.url\":\"URL\",\"list.item_fallback\":\"Item\",\"list.insert_here\":\"Insert here\",\"list.bulk_selected\":\"{n} selected\",\"list.bulk_delete\":\"Delete\",\"list.bulk_clear\":\"Clear\",\"select.reorder\":\"Drag to reorder\",\"controls.text_alignment\":\"Text alignment\",\"controls.block_alignment\":\"Block alignment\",\"controls.item_alignment\":\"Item alignment\",\"menu.banner\":\"List items become clickable links. Pick an <b>orientation</b> — horizontal rows or vertical stacks — and a per-item separator if you want dividers between labels. Item alignment appears for vertical stacks only.\",\"controls.heading_type\":\"Heading Type\",\"controls.field_label\":\"Field label\",\"controls.field_settings\":\"Field settings\",\"controls.field_settings_help\":\"Label visibility, placeholder, default value, required flag with indicator, and validation messages.\",\"controls.field_show_label\":\"Show field label\",\"controls.field_show_label_help\":\"When off, the input renders without a visible label. The required indicator hides too.\",\"controls.field_default\":\"Default value\",\"controls.field_required\":\"Required\",\"controls.field_required_help\":\"When on, the visitor must fill the field. Server-side validation always runs as a safety net.\",\"controls.field_required_indicator\":\"Required indicator\",\"controls.field_required_indicator_help\":\"Shown next to the label when the field is required. Pick a preset or type your own.\",\"controls.field_required_indicator_preset_none\":\"None\",\"controls.field_required_indicator_preset_star\":\"★\",\"controls.field_required_indicator_preset_asterisk\":\"*\",\"controls.field_required_indicator_preset_text\":\"(required)\",\"controls.field_required_indicator_preset_text_value\":\"(required)\",\"controls.field_required_indicator_preset_custom\":\"Custom\",\"controls.field_required_indicator_custom_placeholder\":\"e.g. (required)\",\"controls.field_required_indicator_color\":\"Indicator color\",\"controls.field_msg_required\":\"Required validation message\",\"controls.field_msg_required_help\":\"Custom message shown when the visitor leaves this field blank. Empty falls through to the default.\",\"controls.field_msg_required_placeholder\":\"This field is required.\",\"controls.field_msg_email\":\"Email format message\",\"controls.field_msg_email_help\":\"Shown when the value isn\\'t a valid email address. Empty falls through to the default.\",\"controls.field_msg_email_placeholder\":\"Please enter a valid email address.\",\"controls.field_inline_hint\":\"Tip: client-side validation gates submit; server-side rejects tampered POSTs.\",\"controls.checkbox_label\":\"Checkbox label\",\"controls.terms_required\":\"Block submit if unchecked\",\"controls.terms_required_help\":\"When on, the form rejects submission unless the visitor checks the box.\",\"controls.terms_settings\":\"Compliance settings\",\"controls.terms_settings_help\":\"Pick a preset or customise the legal copy and consent toggle.\",\"controls.terms_preset_label\":\"Preset\",\"controls.terms_preset_tos\":\"Terms\",\"controls.terms_preset_privacy\":\"Privacy\",\"controls.terms_preset_marketing\":\"Marketing\",\"controls.terms_preset_gdpr\":\"GDPR\",\"controls.terms_inline_hint\":\"Tip: click the legal text on the canvas to edit links and rich formatting inline.\",\"controls.terms_position_label\":\"Checkbox position\",\"controls.terms_position_below\":\"Below\",\"controls.terms_position_above\":\"Above\",\"controls.terms_position_inline_left\":\"Inline ←\",\"controls.terms_position_inline_right\":\"Inline →\",\"controls.terms_error_message\":\"Validation message\",\"controls.terms_error_message_help\":\"Custom message shown when the visitor submits without checking. Leave empty to use the default.\",\"controls.terms_error_message_placeholder\":\"Please accept the terms before submitting.\",\"elements.terms_preset_tos_text\":\"By submitting this form, you agree to our <a href=\\\\\"#\\\\\">Terms of Service</a> and <a href=\\\\\"#\\\\\">Privacy Policy</a>.\",\"elements.terms_preset_tos_label\":\"I agree to the terms above.\",\"elements.terms_preset_privacy_text\":\"We respect your privacy. See our <a href=\\\\\"#\\\\\">Privacy Policy</a> for how we handle your data.\",\"elements.terms_preset_privacy_label\":\"I have read and agree to the privacy policy.\",\"elements.terms_preset_marketing_text\":\"Want to receive product updates and offers? Tick the box to opt in (optional).\",\"elements.terms_preset_marketing_label\":\"Yes, send me marketing emails.\",\"elements.terms_preset_gdpr_text\":\"By checking this box, I consent to the processing of my personal data as described in our <a href=\\\\\"#\\\\\">Data Policy</a>.\",\"elements.terms_preset_gdpr_label\":\"I consent to data processing.\",\"controls.select_options\":\"Select Options\",\"controls.select_padding\":\"Select Padding\",\"controls.radio_options\":\"Radio Options\",\"controls.checkbox_options\":\"Checkbox Options\",\"controls.action_url\":\"Action URL\",\"controls.method\":\"Method\",\"controls.rss_url\":\"RSS URL\",\"controls.fixed\":\"Fixed\",\"controls.auto\":\"Auto\",\"controls.h1_main_title\":\"H1 - Main Title\",\"controls.h2_section_title\":\"H2 - Section Title\",\"controls.h3_subsection_title\":\"H3 - Subsection Title\",\"controls.h4_smaller_title\":\"H4 - Smaller Title\",\"controls.h5_even_smaller_title\":\"H5 - Even Smaller Title\",\"controls.h6_smallest_title\":\"H6 - Smallest Title\",\"section.configurations\":\"CONFIGURATIONS\",\"section.image_size\":\"IMAGE SIZE\",\"section.image_size_desc\":\"Adjust width, height and bounds.\",\"section.page_settings\":\"PAGE SETTINGS\",\"section.cell_settings\":\"CELL SETTINGS\",\"section.grid_settings\":\"GRID SETTINGS\",\"section.cells_width_settings\":\"CELLS WIDTH SETTINGS\",\"section.parent_grid\":\"PARENT GRID\",\"section.parent_grid_desc\":\"Settings below apply to the whole grid row (all cells).\",\"section.cell_widths\":\"CELL WIDTHS\",\"section.cell_widths_desc\":\"px, %, em, vw … or Auto (grow-share). Cells sum with gap to fill the row.\",\"section.grid_spacing\":\"GRID SPACING & ALIGNMENT\",\"section.grid_spacing_desc\":\"Horizontal gap between cells and vertical cell alignment.\",\"section.grid_background\":\"GRID BACKGROUND\",\"section.grid_background_desc\":\"Color, image, or filter applied to the whole grid row.\",\"controls.cell_n\":\"Cell\",\"controls.cell_alignment\":\"Cell alignment\",\"controls.cell_gap_desc\":\"Use 0 for flush cells or 8 / 16 / 24 for common gutters.\",\"align.stretch\":\"Stretch\",\"align.top\":\"Top\",\"align.center\":\"Center\",\"align.bottom\":\"Bottom\",\"grid.add_cell\":\"Add cell\",\"grid.remove_cell\":\"Remove cell\",\"grid.drag_cell\":\"Drag to reorder\",\"grid.insert_cell_at\":\"Insert cell at\",\"grid.cells\":\"Cells\",\"grid.layout_presets\":\"Layout presets\",\"grid.manager_hint\":\"Card widths mirror the live grid layout. Click a card to edit its width below.\",\"grid.preset_1col\":\"1 column\",\"grid.preset_1_1\":\"50 / 50\",\"grid.preset_1_1_1\":\"Three equal columns\",\"grid.preset_1_2\":\"33 / 67 — sidebar left\",\"grid.preset_2_1\":\"67 / 33 — sidebar right\",\"grid.preset_1_2_1\":\"25 / 50 / 25 — magazine\",\"grid.alert_overflow\":\"Cells sum to more than 100% — the row will overflow. Rebalance to fit, or equalize?\",\"grid.alert_underfill\":\"Cells don’t fill the row — empty space remaining. Rebalance to fill, or equalize?\",\"grid.alert_rebalance\":\"Rebalance\",\"grid.alert_rebalance_title\":\"Scale existing percents proportionally so the row sums to 100%\",\"grid.alert_equalize\":\"Equalize\",\"grid.alert_equalize_title\":\"Set every cell to 100 ∕ N percent\",\"grid.alert_dismiss\":\"Dismiss\",\"grid.ruler\":\"Row ruler\",\"grid.resize_between\":\"Resize between cells\",\"grid.bulk_selected\":\"{n} selected\",\"grid.bulk_delete\":\"Delete\",\"grid.bulk_clear\":\"Clear\",\"dropdown.auto_full\":\"Auto (Full)\",\"dropdown.narrow\":\"Narrow (600px)\",\"dropdown.medium\":\"Medium (800px)\",\"dropdown.wide\":\"Wide (1024px)\",\"dropdown.xl\":\"XL (1200px)\",\"dropdown.full_bleed\":\"Full Bleed (100%)\",\"dropdown.default\":\"Default\",\"dropdown.block\":\"Block\",\"dropdown.flex\":\"Flex\",\"dropdown.row\":\"Row\",\"dropdown.column\":\"Column\",\"dropdown.start\":\"Start\",\"dropdown.center\":\"Center\",\"dropdown.end\":\"End\",\"dropdown.space_between\":\"Space Between\",\"dropdown.space_around\":\"Space Around\",\"dropdown.space_evenly\":\"Space Evenly\",\"dropdown.stretch\":\"Stretch\",\"image.mode\":\"Image Mode\",\"image.upload_image\":\"Upload Image\",\"image.paste_url\":\"Paste Url\",\"image.loading\":\"Loading...\",\"image.upload\":\"Upload\",\"image.browse\":\"Browse\",\"image.replace\":\"Replace\",\"image.remove\":\"Remove\",\"image.url\":\"Image URL\",\"image.enter_url\":\"Enter image URL\",\"image.alt_text\":\"Alternate Text\",\"image.enter_alt\":\"Enter alternate text\",\"image.no_image\":\"No image selected\",\"image.image_selected\":\"Image selected\",\"image.invalid_image\":\"Invalid image\",\"image.embedded\":\"Embedded image\",\"image.uploaded_file\":\"(uploaded file)\",\"background.desc\":\"Color, image, gradient, size, position, repeat, and effects.\",\"background.repeat\":\"Repeat background\",\"background.repeat_desc\":\"Enable to repeat the background image\",\"background.position_h\":\"Position (Horizontal)\",\"background.position_v\":\"Position (Vertical)\",\"bbg.image\":\"Image\",\"bbg.no_image\":\"No image\",\"bbg.no_image_hint\":\"Upload or paste a URL\",\"bbg.preview_hint\":\"Drag inside the preview to set focus · Scroll to zoom\",\"bbg.upload\":\"Upload\",\"bbg.paste_url\":\"Paste URL\",\"bbg.url\":\"URL\",\"bbg.image_read_failed\":\"Could not read the file. Check format and try again.\",\"bbg.size\":\"Size\",\"bbg.size_cover\":\"Cover\",\"bbg.size_contain\":\"Contain\",\"bbg.size_custom\":\"Scale\",\"bbg.focus\":\"Focus point\",\"bbg.focus_x\":\"Focus X\",\"bbg.focus_y\":\"Focus Y\",\"bbg.repeat\":\"Repeat\",\"bbg.repeat_none\":\"None\",\"bbg.repeat_tile\":\"Tile\",\"bbg.repeat_x\":\"Row\",\"bbg.repeat_y\":\"Column\",\"bbg.gradient\":\"Gradient\",\"bbg.gradient_hint\":\"Enable CSS gradient overlay\",\"bbg.gradient_type\":\"Type\",\"bbg.gradient_linear\":\"Linear\",\"bbg.gradient_radial\":\"Radial\",\"bbg.gradient_angle\":\"Angle\",\"bbg.gradient_color_1\":\"Start color\",\"bbg.gradient_color_2\":\"End color\",\"bbg.gradient_presets\":\"Presets\",\"bbg.effects\":\"Effects\",\"bbg.effects_active\":\"Effects are applied\",\"bbg.active\":\"Active\",\"bbg.effects_email_warning\":\"Blend modes and CSS filters render in modern clients. Outlook and some legacy clients may drop these effects.\",\"bbg.opacity\":\"Opacity\",\"bbg.blend_mode\":\"Blend\",\"bbg.blend_normal\":\"Normal\",\"bbg.blend_multiply\":\"Multiply\",\"bbg.blend_screen\":\"Screen\",\"bbg.blend_overlay\":\"Overlay\",\"bbg.blend_darken\":\"Darken\",\"bbg.blend_lighten\":\"Lighten\",\"bbg.blend_color_dodge\":\"Color dodge\",\"bbg.blend_color_burn\":\"Color burn\",\"bbg.blend_soft_light\":\"Soft light\",\"bbg.blend_hard_light\":\"Hard light\",\"bbg.blend_difference\":\"Difference\",\"bbg.blend_exclusion\":\"Exclusion\",\"bbg.blend_hue\":\"Hue\",\"bbg.blend_saturation\":\"Saturation\",\"bbg.blend_color\":\"Color\",\"bbg.blend_luminosity\":\"Luminosity\",\"bbg.filter_blur\":\"Blur\",\"bbg.filter_brightness\":\"Brightness\",\"bbg.filter_contrast\":\"Contrast\",\"bbg.filter_saturate\":\"Saturation\",\"bbg.filter_grayscale\":\"Grayscale\",\"bbg.reset_effects\":\"Reset effects\",\"bbg.reset_all\":\"Reset all\",\"controls.link\":\"Link\",\"link.target_self\":\"Same tab\",\"link.target_blank\":\"New tab\",\"link.invalid_url\":\"Enter a valid URL (http://, https://, or /path)\",\"link.clear\":\"Clear link\",\"link_config.banner\":\"Pick where this link goes. Email / Phone / Anchor links use the right scheme automatically.\",\"link_config.type\":\"Type\",\"link_config.type_web\":\"Web URL\",\"link_config.type_email\":\"Email\",\"link_config.type_phone\":\"Phone\",\"link_config.type_anchor\":\"Anchor (in this email)\",\"link_config.url\":\"URL\",\"link_config.url_placeholder\":\"https://example.com\",\"link_config.clear\":\"Clear URL\",\"link_config.target\":\"Open\",\"link_config.target_self\":\"Same tab\",\"link_config.target_blank\":\"New tab\",\"link_config.email_to\":\"Email address\",\"link_config.email_to_placeholder\":\"[email protected]\",\"link_config.email_subject\":\"Subject (optional)\",\"link_config.email_body\":\"Body (optional)\",\"link_config.phone_number\":\"Phone number\",\"link_config.phone_placeholder\":\"+1 555 123 4567\",\"link_config.anchor_id\":\"Section ID\",\"link_config.anchor_placeholder\":\"section-name\",\"link_config.title\":\"Title (tooltip)\",\"link_config.title_placeholder\":\"Shown on hover; helps screen readers\",\"link_config.auto_rel_notice\":\"rel=\\\\\"noopener noreferrer\\\\\" will be added automatically (protects recipients against tab-hijacking when opening in a new tab).\",\"link_config.advanced\":\"ADVANCED\",\"link_config.advanced_desc\":\"rel attributes · aria-label · UTM · download filename\",\"link_config.rel\":\"Link relationship (rel)\",\"link_config.aria_label\":\"Screen-reader label (aria-label)\",\"link_config.aria_label_placeholder\":\"E.g. \\\\\"Download our 2025 report\\\\\" — overrides visible text for assistive tech\",\"link_config.download\":\"Download filename\",\"link_config.download_placeholder\":\"e.g. invoice.pdf (leave empty for normal links)\",\"link_config.utm\":\"UTM tracking parameters\",\"link_config.utm_clear\":\"Clear UTM\",\"link_config.utm_source_placeholder\":\"utm_source — e.g. newsletter\",\"link_config.utm_medium_placeholder\":\"utm_medium — e.g. email\",\"link_config.utm_campaign_placeholder\":\"utm_campaign — e.g. spring_sale\",\"link_config.utm_term_placeholder\":\"utm_term — e.g. paid_keyword\",\"link_config.utm_content_placeholder\":\"utm_content — e.g. cta_button_v2\",\"link_config.err_web_url\":\"Enter a valid URL (https://, /, ./, blob:, data:)\",\"link_config.err_email\":\"Enter a valid email address\",\"link_config.err_phone\":\"Use digits, spaces, +, -, (, ) only\",\"link_config.err_anchor\":\"ID must start with a letter; use letters, digits, -, _\",\"image.effects\":\"Image Effects\",\"border.settings\":\"Border Settings\",\"border.radius\":\"Radius\",\"richtext.bold\":\"Bold\",\"richtext.italic\":\"Italic\",\"richtext.underline\":\"Underline\",\"richtext.strikethrough\":\"Strikethrough\",\"richtext.superscript\":\"Superscript\",\"richtext.subscript\":\"Subscript\",\"richtext.text_color\":\"Text Color\",\"richtext.highlight\":\"Highlight\",\"richtext.clear_formatting\":\"Clear Formatting\",\"richtext.horizontal_rule\":\"Horizontal Line\",\"richtext.unlink\":\"Remove Link\",\"richtext.unselect\":\"Deselect\",\"richtext.select_all\":\"Select All\",\"richtext.undo\":\"Undo\",\"richtext.redo\":\"Redo\",\"richtext.bullet_list\":\"Bullet List\",\"richtext.numbered_list\":\"Numbered List\",\"richtext.indent\":\"Increase Indent\",\"richtext.outdent\":\"Decrease Indent\",\"richtext.link\":\"Insert Link (Ctrl+K)\",\"richtext.link_url_placeholder\":\"https://example.com\",\"richtext.link_apply\":\"Apply link\",\"richtext.link_remove\":\"Remove link\",\"ai.optimize\":\"Optimize content\",\"ai.rewrite_formal\":\"Rewrite formally\",\"ai.rewrite_casual\":\"Rewrite more casually\",\"ai.thinking\":\"Thinking...\",\"ai.failed\":\"Failed to connect to AI service. Please try again later.\",\"youtube.enter_url\":\"Enter YouTube URL\",\"youtube.invalid_url\":\"Enter a valid URL (http://, https://, or /path).\",\"youtube.url_banner\":\"Paste a YouTube <b>watch</b>, <b>embed</b>, <b>shorts</b>, or <b>youtu.be</b> URL. Direct video files belong in the <b>Video</b> widget instead.\",\"youtube.url_placeholder\":\"https://www.youtube.com/watch?v=…\",\"youtube.clear\":\"Clear YouTube URL\",\"youtube.extract_ok\":\"Valid YouTube URL — video embed is ready.\",\"youtube.extract_failed\":\"This URL doesn\\'t look like a YouTube link. Expected youtube.com/watch?v=…, youtu.be/…, youtube.com/embed/…, or youtube.com/shorts/…\",\"youtube.empty_title\":\"No YouTube video yet\",\"youtube.empty_desc\":\"Paste a YouTube URL in the right panel to embed it here.\",\"rss.enter_url\":\"Enter RSS URL\",\"rss.max_items\":\"Max Items\",\"rss.url_required\":\"URL is required.\",\"rss.invalid_url\":\"Please enter a valid RSS URL.\",\"rss.invalid_limit\":\"Please enter a valid limit.\",\"rss.fetch_failed\":\"Failed to fetch RSS feed.\",\"rss.invalid_format\":\"Invalid RSS feed format.\",\"rss.load_failed\":\"Failed to load RSS feed. Please check the URL.\",\"rss.see_more\":\"See more info\",\"rss.style\":\"Style\",\"rss.style_modern\":\"Modern (Cards)\",\"rss.style_classic\":\"Classic (List)\",\"rss.show_title\":\"Show Title\",\"rss.show_desc\":\"Show Description\",\"rss.show_date\":\"Show Date\",\"rss.show_image\":\"Show Image\",\"rss.show_link\":\"Show Read More Link\",\"rss.show_author\":\"Show Author\",\"rss.content_length\":\"Content Length\",\"rss.content_length_desc\":\"Max characters for description (0 = full)\",\"rss.fetch\":\"Fetch\",\"rss.apply\":\"Apply\",\"rss.fetching\":\"Fetching...\",\"rss.items_found\":\"items found\",\"rss.decrease\":\"Decrease\",\"rss.increase\":\"Increase\",\"rss.handler_missing\":\"RSS handler not configured.\",\"rss.no_items\":\"No items found in this feed.\",\"rss.configure_feed\":\"RSS Feed\",\"rss.configure_feed_desc\":\"Add an RSS URL in the settings panel to display your feed here.\",\"rss.loading\":\"Loading feed...\",\"rss.network_error\":\"Could not reach the feed URL. Please check the URL and try again.\",\"rss.parse_error\":\"The URL does not contain a valid RSS feed.\",\"rss.read_more\":\"Read more\",\"rss.by\":\"by\",\"section.rss_feed\":\"RSS FEED\",\"section.rss_display\":\"DISPLAY OPTIONS\",\"dialog.ok\":\"OK\",\"dialog.error\":\"Error\",\"dialog.success\":\"Success\",\"dialog.info\":\"Info\",\"dialog.close\":\"Close\",\"dialog.save\":\"Save\",\"dimension.preset_sm\":\"Small\",\"dimension.preset_md\":\"Medium\",\"dimension.preset_lg\":\"Large\",\"dimension.preset_full\":\"Full\",\"dimension.placeholder\":\"auto\",\"dimension.placeholder_fill\":\"fill\",\"dimension.help_fill\":\"Grows to absorb any remaining row space\",\"dimension.clear\":\"Clear value\",\"dimension.exact_value\":\"Exact value\",\"dimension.auto_active\":\"Using natural image size\",\"dimension.menu_unit\":\"Unit\",\"dimension.menu_quick\":\"Quick size\",\"dimension.banner\":\"Use <b>px</b> for fixed sizing (best for email), <b>%</b> for responsive layouts. Leave one side on <b>auto</b> to preserve aspect ratio.\",\"padding.help\":\"Use the controls below to set values for each side (Top, Left, Right, Bottom). All values are in pixels (px). Click ✕ to clear a value.\",\"padding.top\":\"Top\",\"padding.left\":\"Left\",\"padding.right\":\"Right\",\"padding.bottom\":\"Bottom\",\"padding.clear\":\"Clear value\",\"padding.pin_on\":\"Keep padding guides visible on canvas\",\"padding.pin_off\":\"Stop keeping padding guides visible\",\"padding.pin_label_off\":\"Pin preview\",\"padding.pin_label_on\":\"Pinned\",\"inner_padding.help\":\"Adjust inner spacing to shape this element — larger values make it bigger, smaller values make it more compact.\",\"social.add\":\"Add\",\"social.add_facebook\":\"Add Facebook\",\"social.add_instagram\":\"Add Instagram\",\"social.add_linkedin\":\"Add LinkedIn\",\"social.add_twitter\":\"Add Twitter (X)\",\"social.add_youtube\":\"Add YouTube\",\"social.add_tiktok\":\"Add TikTok\",\"social.add_pinterest\":\"Add Pinterest\",\"social.choose_platform\":\"Choose platform\",\"social.label\":\"Label\",\"social.url_label\":\"URL\",\"social.move_up\":\"Move up\",\"social.move_down\":\"Move down\",\"social.delete_item\":\"Delete item\",\"color.not_set\":\"not set\",\"page.untitled\":\"Untitled Page\",\"widgets_box.drag_hint\":\"Just drag & drop the widget into the page content to insert!\",\"widgets_box.field_required\":\"Required\",\"widgets_box.field_optional\":\"Optional\",\"widgets_box.field_visible\":\"Visible on form\",\"widgets_box.field_hidden\":\"Hidden field\",\"widgets_box.field_type_action\":\"action\",\"widgets_box.field_type_compliance\":\"compliance\",\"widgets_box.field_type_required_for_form\":\"Required for form\",\"widgets_box.submit_button\":\"Submit button\",\"widgets_box.list_subscribers\":\"subscribers\",\"widgets_box.list_fields\":\"fields\",\"widgets.ad_headline\":\"Ad Headline\",\"widgets.ad_primary_text\":\"Primary Text\",\"widgets.ad_description\":\"Description\",\"widgets.ad_cta\":\"Call to Action\",\"widgets.ad_image\":\"Ad Image\",\"widgets.ad_logo\":\"Brand Logo\",\"widgets.ad_carousel_card\":\"Carousel Card\",\"elements.ad_headline_default\":\"Your attention-grabbing headline\",\"elements.ad_primary_text_default\":\"Your body copy here. Keep it short, clear, and actionable — under 125 characters works best on most platforms.\",\"elements.ad_description_default\":\"One-line sub-text\",\"elements.ad_cta_default\":\"Learn More\",\"elements.ad_carousel_headline_default\":\"Card headline\",\"elements.ad_carousel_desc_default\":\"Short sub-text\",\"validation.url_required\":\"URL is required.\",\"font.system_inherit\":\"System (inherit)\",\"form_container.name\":\"Form Area\",\"form_container.empty_title\":\"Drop form fields here\",\"form_container.empty_hint\":\"Or click ← Load list defaults in the sidebar\",\"image_effects.grayscale\":\"Grayscale\",\"image_effects.sepia\":\"Sepia\",\"image_effects.invert\":\"Invert\",\"image_effects.blur\":\"Blur\",\"image_effects.brightness\":\"Brightness\",\"image_effects.contrast\":\"Contrast\",\"image_effects.saturation\":\"Saturation\",\"image_effects.hue_rotate\":\"Hue Rotate\",\"image_effects.opacity\":\"Opacity\",\"image_effects.grayscale_desc\":\"🖌️ Converts the image to black and white, with values from 0% (normal) to 100% (completely grayscale).\",\"image_effects.sepia_desc\":\"🏺 Adds a warm, yellowish-brown tone to create a vintage or antique look.\",\"image_effects.invert_desc\":\"🔄 Reverses all colors in the image, like a photo negative effect.\",\"image_effects.blur_desc\":\"🌫️ Creates a soft focus effect, higher values increase the blurriness.\",\"image_effects.brightness_desc\":\"☀️ Adjusts how bright the image appears, 100% is normal, higher values increase brightness.\",\"image_effects.contrast_desc\":\"⚖️ Controls the difference between dark and light areas, 100% is normal.\",\"image_effects.saturation_desc\":\"🌈 Changes color intensity, 100% is normal, higher values make colors more vivid.\",\"image_effects.hue_rotate_desc\":\"🎨 Shifts all colors in the image by rotating them around the color wheel.\",\"image_effects.opacity_desc\":\"👻 Controls how transparent the image is, 100% is fully visible, 0% is invisible.\",\"image_effects.preview\":\"Preview\",\"image_effects.reset\":\"Reset Effects\",\"image_effects.effects\":\"Effects\",\"image_crop.title\":\"Crop & Focus\",\"image_crop.toggle_hint\":\"Enable CSS crop & focus point\",\"image_crop.email_warning\":\"CSS-based crop. Modern email clients render correctly. Outlook 2007–2013 and a few legacy clients fall back to the original full image.\",\"image_crop.aspect_ratio\":\"Aspect ratio\",\"image_crop.preset_original\":\"Original\",\"image_crop.custom_ratio\":\"Custom ratio\",\"image_crop.ratio_x\":\"Ratio X (width)\",\"image_crop.ratio_y\":\"Ratio Y (height)\",\"image_crop.swap_hint\":\"Swap X ↔ Y (rotate 90°)\",\"image_crop.zoom\":\"Zoom\",\"image_crop.focus_x\":\"Focus X\",\"image_crop.focus_y\":\"Focus Y\",\"image_crop.preview_hint\":\"Drag inside the preview to set focus · Scroll wheel to zoom\",\"image_crop.reset\":\"Reset crop\",\"border.title\":\"BORDERS\",\"border.description\":\"Adjust border style, width, and color.\",\"border.content_area\":\"Content area border\",\"border.more_options\":\"More options\",\"border.all_sides\":\"All sides\",\"border.top\":\"Top\",\"border.right\":\"Right\",\"border.bottom\":\"Bottom\",\"border.left\":\"Left\",\"border.style_solid\":\"Solid\",\"border.style_dashed\":\"Dashed\",\"border.style_dotted\":\"Dotted\",\"border.style_double\":\"Double\",\"border.style_none\":\"None\",\"border.transparent\":\"transparent\",\"border.style_label\":\"Border style\",\"border.width_label\":\"Border width (px)\",\"border.width_unit\":\"px\",\"border.color_label\":\"Border color\",\"border.mode_label\":\"Mode\",\"border.mode_all\":\"All\",\"border.mode_split\":\"Split\",\"border.preset_label\":\"Preset\",\"border.preset_none\":\"None\",\"border.preset_thin\":\"Thin\",\"border.preset_medium\":\"Medium\",\"border.preset_thick\":\"Thick\",\"border.copy_to_all\":\"Copy this side to all sides\",\"border.reset\":\"Reset borders\",\"border.preview_aria\":\"Preview\",\"border.preview_announce\":\"Border: {style} {width}px {color}\",\"number.decrement\":\"Decrease\",\"number.increment\":\"Increase\",\"select.element_name\":\"Element Name\",\"select.element_name_ph\":\"field_name\",\"select.add_item\":\"Add item\",\"select.remove_item\":\"Remove item\",\"select.label\":\"Label\",\"select.value\":\"Value\",\"line_height.line_1_2\":\"Line 1.2\",\"line_height.line_1_5\":\"Line 1.5\",\"line_height.line_1_8\":\"Line 1.8\",\"line_height.line_2\":\"Line 2\",\"line_height.select\":\"Select\",\"line_height.custom\":\"Custom\",\"font_weight.not_set\":\"not set\",\"font.not_set\":\"not set\",\"social.social_item\":\"Social item\",\"social.item_number\":\"Item #\",\"overlay.drag\":\"Drag\",\"overlay.drag_block\":\"Drag block\",\"overlay.resize\":\"Resize\",\"overlay.resize_corner\":\"Resize corner\",\"overlay.action_bar\":\"Element actions\",\"overlay.upload\":\"Upload\",\"overlay.replace\":\"Replace\",\"overlay.effects\":\"Effects\",\"overlay.crop\":\"Crop\",\"overlay.crop_title\":\"Crop image\",\"overlay.crop_enable\":\"Enable crop\",\"overlay.crop_enable_hint\":\"Off keeps the original image.\",\"overlay.crop_sidebar_hint\":\"Need zoom, focus point, or email compatibility? Open the sidebar panel.\",\"overlay.crop_confirm\":\"Done\",\"overlay.crop_cancel\":\"Cancel\",\"overlay.resize_title\":\"Resize image\",\"overlay.resize_width\":\"Width\",\"overlay.resize_height\":\"Height\",\"overlay.resize_aspect_lock\":\"Lock aspect ratio\",\"overlay.resize_aspect_hint\":\"Editing one dimension updates the other proportionally.\",\"overlay.resize_advanced\":\"Advanced — max / min\",\"overlay.resize_crop_hint\":\"Crop is on. Resizing keeps the crop frame; the cropped area re-fits to your new dimensions.\",\"overlay.link\":\"Link\",\"overlay.insert_column_before\":\"Insert column before\",\"overlay.insert_column_after\":\"Insert column after\",\"overlay.cell_resize\":\"Resize cell\",\"overlay.edit_text\":\"Edit text\",\"overlay.style\":\"Style\",\"overlay.settings\":\"Settings\",\"overlay.close\":\"Close\",\"overlay.link_url_prompt\":\"Link URL\",\"overlay.link_done\":\"Done\",\"button.settings.title\":\"Button settings\",\"button.settings.hint\":\"Esc to cancel · Click outside to apply\",\"button.settings.reset\":\"Reset\",\"button.section.shape\":\"Shape & size\",\"button.section.shape_desc\":\"Baseline size and corner radius.\",\"button.section.style\":\"Style Settings\",\"button.section.style_desc\":\"Preset look, size, shape & modifiers.\",\"button.section.effects\":\"Effects\",\"button.section.effects_desc\":\"Depth and micro-interactions. Page mode only.\",\"button.section.icon\":\"Icon\",\"button.section.icon_desc\":\"Optional pictogram beside, before, or instead of the label.\",\"button.section.layout\":\"Layout\",\"button.section.layout_desc\":\"Width within the block row.\",\"button.section.advanced\":\"Advanced\",\"button.section.advanced_desc\":\"Color, border, padding, font, spacing overrides.\",\"button.style.label\":\"Style\",\"button.style.custom_name\":\"Custom\",\"button.style.custom_summary\":\"Custom · advanced\",\"button.style.change_tooltip\":\"Browse all styles\",\"button.size.label\":\"Size\",\"button.size.xs\":\"Extra small\",\"button.size.sm\":\"Small\",\"button.size.md\":\"Medium\",\"button.size.lg\":\"Large\",\"button.size.xl\":\"Extra large\",\"button.radius.label\":\"Radius\",\"button.radius.sharp\":\"Sharp\",\"button.radius.sm\":\"SM\",\"button.radius.md\":\"MD\",\"button.radius.lg\":\"LG\",\"button.radius.pill\":\"Pill\",\"button.shadow.label\":\"Shadow\",\"button.shadow.none\":\"None\",\"button.shadow.sm\":\"SM\",\"button.shadow.md\":\"MD\",\"button.shadow.lg\":\"LG\",\"button.shadow.xl\":\"XL\",\"button.shadow.inner\":\"Inner\",\"button.hover.label\":\"Hover effect\",\"button.hover.none\":\"None\",\"button.hover.lift\":\"Lift\",\"button.hover.glow\":\"Glow\",\"button.hover.scale\":\"Scale\",\"button.hover.sweep\":\"Sweep\",\"button.hover.push\":\"Push\",\"button.icon.label\":\"Icon\",\"button.icon_pos.label\":\"Position\",\"button.icon_pos.left\":\"Left\",\"button.icon_pos.right\":\"Right\",\"button.icon_pos.only\":\"Only\",\"button.icon_pos.none\":\"None\",\"button.width.label\":\"Width\",\"button.width.auto\":\"Auto\",\"button.width.half\":\"50%\",\"button.width.full\":\"Full\",\"button.picker.title\":\"Pick a button style\",\"button.picker.cat_solid\":\"Solid\",\"button.picker.cat_outline\":\"Outline\",\"button.picker.cat_tonal\":\"Tonal\",\"button.picker.cat_ghost\":\"Ghost\",\"button.picker.cat_gradient\":\"Gradient\",\"button.picker.cat_elevated\":\"Elevated\",\"button.picker.cat_glass\":\"Glass & Glow\",\"button.picker.cat_brutalist\":\"Brutalist\",\"button.picker.cat_icon\":\"Icon-Led\",\"button.picker.page_only_short\":\"Page\",\"button.picker.vml_short\":\"VML\",\"button.picker.empty\":\"No presets in this category yet.\",\"button.picker.sample_text\":\"Action\",\"button.picker.footer_hint\":\"Esc to cancel · Click outside to apply\",\"button.picker.reset\":\"Reset\",\"errors.template_not_found_title\":\"Template not found\",\"errors.template_not_found_msg\":\"Template \\\\\"{name}\\\\\" could not be located in the current theme.\",\"errors.unused_ejs_keys_title\":\"Unused EJS keys\",\"errors.unused_ejs_keys_msg\":\"The following template keys were not used during render:\",\"history.undo\":\"Undo\",\"history.redo\":\"Redo\",\"history.title\":\"History\",\"history.clear\":\"Clear\",\"history.tx\":\"transaction\",\"history.entries_count\":\":n entries\",\"history.entries_count_one\":\":n entry\",\"history.default_label\":\"Edit\",\"history.edit\":\"Edit\",\"history.edit_type\":\"Edit :type\",\"history.edit_type_region\":\"Edit :region on :type\",\"history.initial\":\"Initial state\",\"history.edit_text\":\"Edit text\",\"history.paste\":\"Paste\",\"history.empty_title\":\"Nothing to undo yet\",\"history.empty_note\":\"Your edits will appear here. Undo with\",\"history.format_text_color\":\"Change text color\",\"history.format_link_color\":\"Change link color\",\"history.format_background\":\"Change background\",\"history.format_background_color\":\"Change background color\",\"history.format_padding_top\":\"Adjust padding\",\"history.format_padding_bottom\":\"Adjust padding\",\"history.format_padding_left\":\"Adjust padding\",\"history.format_padding_right\":\"Adjust padding\",\"history.format_margin_top\":\"Adjust margin\",\"history.format_margin_bottom\":\"Adjust margin\",\"history.format_margin_left\":\"Adjust margin\",\"history.format_margin_right\":\"Adjust margin\",\"history.format_font_size\":\"Change font size\",\"history.format_font_family\":\"Change font\",\"history.format_font_weight\":\"Change font weight\",\"history.format_line_height\":\"Change line height\",\"history.format_letter_spacing\":\"Change letter spacing\",\"history.format_border\":\"Change border\",\"history.format_border_radius\":\"Change border radius\",\"history.format_align\":\"Change alignment\",\"history.format_size\":\"Resize\",\"history.format_width\":\"Change width\",\"history.format_height\":\"Change height\",\"history.format_filter_brightness\":\"Adjust brightness\",\"history.format_filter_contrast\":\"Adjust contrast\",\"history.format_aspect_lock\":\"Toggle aspect lock\",\"history.format_generic\":\"Change style\",\"history.content_text\":\"Edit text\",\"history.content_src\":\"Change image\",\"history.content_url\":\"Change link\",\"history.content_html\":\"Edit HTML\",\"history.content_alt\":\"Edit alt text\",\"history.structure_add\":\"Add :type\",\"history.structure_remove\":\"Delete :type\",\"history.structure_move\":\"Move :type\",\"history.structure_duplicate\":\"Duplicate :type\",\"history.page_title\":\"Change page title\",\"history.page_theme\":\"Change theme\",\"history.page_block_gap\":\"Change spacing\",\"history.page_clear\":\"Clear page\",\"history.ai_generate\":\"AI: :prompt\",\"history.ai_rewrite\":\"AI rewrite\",\"history.ai_translate\":\"AI translate\",\"history.ai_inline_rewrite\":\"AI :prompt\",\"history.ai_action_rewrite\":\"rewrite\",\"history.ai_action_improve\":\"improve\",\"history.ai_action_shorten\":\"shorten\",\"history.ai_action_expand\":\"expand\",\"history.ai_action_simplify\":\"simplify\",\"history.ai_action_fix_grammar\":\"fix grammar\",\"history.ai_action_cta_ify\":\"CTA-ify\",\"history.ai_action_translate\":\"translate\",\"history.ai_action_rewrite_on_brand\":\"rewrite on brand\",\"history.external\":\"External change\",\"history.relative_time.just_now\":\"just now\",\"history.relative_time.seconds_ago\":\":ns ago\",\"history.relative_time.minutes_ago\":\":nm ago\",\"history.relative_time.hours_ago\":\":nh ago\",\"history.element_type.PageElement\":\"Page\",\"history.element_type.BlockElement\":\"Block\",\"history.element_type.CellElement\":\"Cell\",\"history.element_type.HeadingElement\":\"Heading\",\"history.element_type.TextElement\":\"Text\",\"history.element_type.ParagraphElement\":\"Paragraph\",\"history.element_type.ImageElement\":\"Image\",\"history.element_type.ButtonElement\":\"Button\",\"history.element_type.DividerElement\":\"Divider\",\"history.element_type.SpacerElement\":\"Spacer\",\"history.element_type.VideoElement\":\"Video\",\"history.element_type.YoutubeElement\":\"YouTube\",\"history.element_type.AlertElement\":\"Alert\",\"history.element_type.HtmlElement\":\"HTML\",\"history.element_type.ListElement\":\"List\",\"history.element_type.TableElement\":\"Table\",\"history.element_type.CheckoutElement\":\"Checkout\",\"history.element_type.CheckoutSimpleElement\":\"Checkout\",\"history.element_type.FormElement\":\"Form\",\"history.element_type.FieldElement\":\"Field\",\"inline_toolbar.aria_label\":\"Text formatting\",\"inline_toolbar.bold\":\"Bold\",\"inline_toolbar.italic\":\"Italic\",\"inline_toolbar.underline\":\"Underline\",\"inline_toolbar.strikethrough\":\"Strikethrough\",\"inline_toolbar.text_color\":\"Text color\",\"inline_toolbar.highlight_color\":\"Highlight color\",\"inline_toolbar.link\":\"Link\",\"inline_toolbar.alignment\":\"Alignment\",\"inline_toolbar.align_left\":\"Align left\",\"inline_toolbar.align_center\":\"Align center\",\"inline_toolbar.align_right\":\"Align right\",\"inline_toolbar.align_justify\":\"Justify\",\"inline_toolbar.more\":\"More options\",\"inline_toolbar.font\":\"Font\",\"inline_toolbar.advanced\":\"Advanced text\",\"inline_toolbar.ai_rewrite\":\"AI rewrite\",\"inline_toolbar.paragraph_style\":\"Paragraph style\",\"inline_toolbar.coming_in\":\"ships in {wave}\",\"color_popover.recent\":\"Recent\",\"color_popover.palette\":\"Palette\",\"color_popover.standard\":\"Standard\",\"color_popover.custom\":\"Custom\",\"color_popover.reset\":\"Reset\",\"color_popover.remove\":\"Remove color\",\"color_popover.eyedropper\":\"Pick color from page\",\"link_popover.title\":\"Link\",\"link_popover.apply\":\"Apply\",\"link_popover.cancel\":\"Cancel\",\"link_popover.remove\":\"Remove link\",\"link_popover.remove_disabled_host_anchor\":\"This element is already a link — edit in the sidebar or delete the element to remove.\",\"link_popover.err_empty_url\":\"Enter a URL before applying.\",\"link_popover.err_remove_failed\":\"Couldn\\'t remove the link. Try selecting just the linked text and retry.\",\"font_popover.title\":\"Font\",\"font_popover.preview_text\":\"The quick brown fox\",\"font_popover.scope_note\":\"Font changes apply to the whole text block — not just the highlighted range.\",\"rich_menu.aria_label\":\"Menu\",\"more_menu.heading_clipboard\":\"Clipboard\",\"more_menu.heading_format\":\"Format\",\"more_menu.cut\":\"Cut\",\"more_menu.copy\":\"Copy\",\"more_menu.copy_format\":\"Copy format\",\"more_menu.paste_format\":\"Paste format\",\"more_menu.clear_format\":\"Clear format\",\"more_menu.remove_link\":\"Remove link\",\"ai_rewrite.dialog_title\":\"AI rewrite\",\"ai_rewrite.close\":\"Close\",\"ai_rewrite.cancel\":\"Cancel\",\"ai_rewrite.back\":\"Back\",\"ai_rewrite.rewrite\":\"Rewrite\",\"ai_rewrite.try_again\":\"Try again\",\"ai_rewrite.apply\":\"Apply\",\"ai_rewrite.loading\":\"Generating with AI…\",\"ai_rewrite.applied_toast\":\"Rewritten — ⌘Z to undo\",\"ai_rewrite.disabled_title\":\"AI features disabled\",\"ai_rewrite.disabled_msg\":\"Set AI_ENABLED=true on the server to enable inline AI rewrites.\",\"ai_rewrite.quick_actions\":\"Quick actions\",\"ai_rewrite.tone\":\"Tone\",\"ai_rewrite.length\":\"Length\",\"ai_rewrite.custom_prompt\":\"Custom instruction\",\"ai_rewrite.custom_placeholder\":\"Describe exactly what you want — e.g. \\\\\"more confident, fewer adjectives\\\\\"\",\"ai_rewrite.action_improve\":\"Improve\",\"ai_rewrite.action_shorten\":\"Shorten\",\"ai_rewrite.action_expand\":\"Expand\",\"ai_rewrite.action_simplify\":\"Simplify\",\"ai_rewrite.action_fix_grammar\":\"Fix grammar\",\"ai_rewrite.action_cta_ify\":\"CTA-ify\",\"ai_rewrite.action_translate\":\"Translate\",\"ai_rewrite.action_custom\":\"Rewrite\",\"ai_rewrite.tone_formal\":\"Formal\",\"ai_rewrite.tone_casual\":\"Casual\",\"ai_rewrite.tone_playful\":\"Playful\",\"ai_rewrite.tone_persuasive\":\"Persuasive\",\"ai_rewrite.tone_friendly\":\"Friendly\",\"ai_rewrite.tone_urgent\":\"Urgent\",\"ai_rewrite.length_shorter\":\"Shorter\",\"ai_rewrite.length_same\":\"Same\",\"ai_rewrite.length_longer\":\"Longer\",\"ai_rewrite.error_rate_limit\":\"Rate limited\",\"ai_rewrite.error_disabled\":\"AI disabled\",\"ai_rewrite.error_timeout\":\"Timeout\",\"ai_rewrite.error_engine\":\"AI engine error\",\"ai_rewrite.error_configuration\":\"Configuration error\",\"ai_rewrite.error_validation\":\"Validation error\",\"ai_rewrite.error_internal\":\"Server error\",\"ai_rewrite.error_task_not_found\":\"Feature not registered\",\"ai_rewrite.error_unknown\":\"Error\",\"ai_rewrite.error_no_variants\":\"AI returned no variants. Try again with different settings.\",\"ai_rewrite.error_empty_selection\":\"Select some text first to use AI rewrite.\"}');\n\n//# sourceURL=webpack://BuilderBundle/./src/lang/en.json?");

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module can't be inlined because the eval devtool is used.
/******/ 	var __webpack_exports__ = __webpack_require__("./src/builder.js");
/******/ 	BuilderBundle = __webpack_exports__;
/******/ 	
/******/ })()
;