/**
 * Browser reactive runtime (Point 2: reactive directives).
 *
 * Served verbatim at `/__wrnexus/reactive.js` for any page that contains a
 * `data-scope`. It is plain browser JS (no build step) and self-contained: it
 * inlines a tiny `signal()` so it has no imports to resolve.
 *
 * Supported directives (this is exactly what the `.wrn` compiler emits):
 *   data-scope="count: 0, name: 'x'"   declare reactive state on a subtree
 *   data-on-<event>="count++"          run a statement in scope on an event
 *   data-text="expr"                   element textContent follows an expression
 *   data-wrn-loop-locals="base64-json"   preserves SSR {#each} item/index values
 *   data-wrnexus-csr="id"                 target for generated CSR fetch bindings
 *   {{expr}} or {expr}                 interpolation inside text nodes
 *
 * Expressions are evaluated by a tiny parser instead of `eval`/`new Function`,
 * so production can use a strong CSP without `unsafe-eval`.
 */

export const REACTIVE_RUNTIME = String.raw`
(function () {
  var behaviorInstances = new WeakMap();
  var mountedBehaviorRoots = new Set();
  var pendingUpdateHooks = new Map();
  var updateHooksScheduled = false;
  var behaviorObserver;
  var clientModuleCache = new Map();

  /*
   * Globals the expression engine resolves for client code. Kept as explicit
   * tables rather than falling through to window[name]: an implicit fallback
   * would let any expression reach every global on the page (and would make a
   * typo silently resolve to some unrelated window property) -- these lists
   * say exactly what client code may reach.
   *
   * dialogGlobals must be bound to window or the browser throws
   * "Illegal invocation" when they are called detached.
   */
  var dialogGlobals = {
    alert: 1,
    confirm: 1,
    prompt: 1,
    fetch: 1,
    print: 1,
    open: 1,
    scrollTo: 1,
    scrollBy: 1,
    matchMedia: 1,
    getComputedStyle: 1,
    structuredClone: 1,
    queueMicrotask: 1,
    btoa: 1,
    atob: 1,
  };

  // Language builtins. Wrapped in thunks so referencing one that a given
  // engine lacks cannot throw at table-definition time.
  var jsGlobals = {
    Object: function () { return Object; },
    Boolean: function () { return Boolean; },
    RegExp: function () { return RegExp; },
    Promise: function () { return typeof Promise === "undefined" ? undefined : Promise; },
    Set: function () { return typeof Set === "undefined" ? undefined : Set; },
    Map: function () { return typeof Map === "undefined" ? undefined : Map; },
    Error: function () { return Error; },
    Symbol: function () { return typeof Symbol === "undefined" ? undefined : Symbol; },
    BigInt: function () { return typeof BigInt === "undefined" ? undefined : BigInt; },
    Intl: function () { return typeof Intl === "undefined" ? undefined : Intl; },
    parseInt: function () { return parseInt; },
    parseFloat: function () { return parseFloat; },
    isNaN: function () { return isNaN; },
    isFinite: function () { return isFinite; },
    encodeURIComponent: function () { return encodeURIComponent; },
    decodeURIComponent: function () { return decodeURIComponent; },
    encodeURI: function () { return encodeURI; },
    decodeURI: function () { return decodeURI; },
    NaN: function () { return NaN; },
    Infinity: function () { return Infinity; },
    undefined: function () { return undefined; },
  };

  /*
   * toast(...) -- raise a notification from any client expression.
   *
   * The core runtime deliberately knows nothing about the Toaster component:
   * it only dispatches a window event, and whatever toaster is mounted picks
   * it up. That keeps @wrnexus/ui out of the runtime's dependencies and lets
   * an app swap in its own toaster by listening for the same event.
   *
   * When nothing is listening the message would otherwise vanish silently,
   * which is a miserable thing to debug -- so fall back to the console and
   * say why once.
   */
  var toastFallbackWarned = false;

  // Construct from the page window rather than the ambient global: in a
  // non-browser DOM the two are different classes, and a listener added on
  // the page window then never matches an event built from the other one.
  function dispatchWindowEvent(name, detail) {
    var Ctor = window.CustomEvent || CustomEvent;
    window.dispatchEvent(new Ctor(name, { detail: detail || {} }));
  }

  function emitToast(message, options, tone) {
    var detail =
      message && typeof message === "object" && !(message instanceof Error)
        ? Object.assign({}, message)
        : { message: message instanceof Error ? message.message : String(message) };

    if (options && typeof options === "object") {
      Object.keys(options).forEach(function (key) { detail[key] = options[key]; });
    }
    if (tone && !detail.tone) detail.tone = tone;

    // Detected from the DOM rather than a flag the host has to set, so any
    // element marked data-toaster counts -- including a custom one.
    if (!document.querySelector("[data-toaster]")) {
      if (!toastFallbackWarned) {
        toastFallbackWarned = true;
        console.info(
          "[wrnexus] toast() was called but no <Toaster /> is mounted on this page; " +
            "falling back to the console. Add <Toaster /> to your layout to show toasts.",
        );
      }
      console.info("[wrnexus:toast]", detail.tone || "info", detail.title || "", detail.message);
      return detail;
    }

    dispatchWindowEvent("wrnexus:toast", detail);
    return detail;
  }

  var toastApi = function (message, options) { return emitToast(message, options); };
  toastApi.success = function (message, options) { return emitToast(message, options, "success"); };
  toastApi.error = function (message, options) { return emitToast(message, options, "danger"); };
  toastApi.danger = toastApi.error;
  toastApi.warning = function (message, options) { return emitToast(message, options, "warning"); };
  toastApi.info = function (message, options) { return emitToast(message, options, "info"); };
  toastApi.dismiss = function (id) { dispatchWindowEvent("wrnexus:toast:dismiss", { id: id }); };
  toastApi.clear = function () { dispatchWindowEvent("wrnexus:toast:clear", {}); };

  /*
   * Published as a real global, not just an identifier the expression engine
   * knows about. Client functions are compiled to an ES module and run as
   * ordinary JavaScript, so a bare toast(...) there is a global lookup that
   * the engine never sees -- without this it throws ReferenceError while the
   * identical call in an inline handler works, which is a maddening
   * inconsistency.
   *
   * wireToast is the stable name. toast is the ergonomic alias and defers to
   * an application that already defines one.
   */
  window.wireToast = toastApi;
  if (!window.toast) window.toast = toastApi;

  // Read straight off window, no binding needed (objects, not functions).
  var windowGlobals = {
    localStorage: 1,
    sessionStorage: 1,
    screen: 1,
    performance: 1,
    crypto: 1,
    CustomEvent: 1,
    Event: 1,
    FormData: 1,
    URLSearchParams: 1,
    AbortController: 1,
    Notification: 1,
    IntersectionObserver: 1,
    ResizeObserver: 1,
    MutationObserver: 1,
    devicePixelRatio: 1,
    innerWidth: 1,
    innerHeight: 1,
    scrollX: 1,
    scrollY: 1,
  };

  function reportDiagnostic(code, message, element, detail) {
    var payload = {
      code: code,
      message: message,
      hydrationId: element && element.getAttribute ? element.getAttribute("data-wrn-hydration") : null,
      detail: detail || null,
    };
    console.error("[wrnexus:" + code + "] " + message, detail || "");
    try {
      window.dispatchEvent(new CustomEvent("wrnexus:diagnostic", { detail: payload }));
    } catch (_) {
      // CustomEvent can be unavailable in minimal DOM test environments.
    }
  }

  /*__WRNEXUS_DEV_START__*/
  var developmentWarnings = Object.create(null);
  function warnOnce(code, message, element, detail) {
    var key = code + "\\n" + message;
    if (developmentWarnings[key]) return;
    developmentWarnings[key] = true;
    var payload = {
      code: code,
      message: message,
      hydrationId: element && element.getAttribute ? element.getAttribute("data-wrn-hydration") : null,
      detail: detail || null,
    };
    console.warn("[" + code + "] " + message, detail || "");
    try {
      window.dispatchEvent(new CustomEvent("wrnexus:diagnostic", { detail: payload }));
    } catch (_) {
      // CustomEvent can be unavailable in minimal DOM test environments.
    }
  }

  function warnMissingBindingFunction(statement, resolve, element) {
    var match = /^\s*([A-Za-z_$][\w$]*)\s*\(/.exec(statement || "");
    if (!match || typeof resolve(match[1]) === "function") return;
    warnOnce(
      "WRN-DEV-BINDING-MISSING",
      "Component binding calls '" + match[1] + "', but that function does not exist in the parent scope.",
      element,
      { binding: statement, functionName: match[1] },
    );
  }

  function warnMissingThemeTokens() {
    var referenced = Object.create(null);
    var declared = Object.create(null);
    function collect(rules) {
      Array.prototype.forEach.call(rules || [], function (rule) {
        var cssText = rule.cssText || "";
        var match;
        var pattern = /var\(\s*(--wire-[A-Za-z0-9_-]+)/g;
        while ((match = pattern.exec(cssText))) referenced[match[1]] = true;
        if (rule.style) {
          Array.prototype.forEach.call(rule.style, function (property) {
            if (String(property).indexOf("--wire-") === 0) declared[property] = true;
          });
        }
        try {
          if (rule.cssRules) collect(rule.cssRules);
        } catch (_) {
          // Cross-origin and disabled stylesheets can deny CSSOM access.
        }
      });
    }
    Array.prototype.forEach.call(document.styleSheets || [], function (sheet) {
      try { collect(sheet.cssRules); } catch (_) {}
    });
    Array.prototype.forEach.call(document.querySelectorAll("[style]") || [], function (element) {
      Array.prototype.forEach.call(element.style || [], function (property) {
        if (String(property).indexOf("--wire-") === 0) declared[property] = true;
      });
    });
    var rendered = window.getComputedStyle(document.documentElement);
    Object.keys(referenced).forEach(function (token) {
      if (declared[token] || rendered.getPropertyValue(token).trim()) return;
      warnOnce(
        "WRN-DEV-THEME-TOKEN-MISSING",
        "Theme token '" + token + "' is referenced by rendered CSS but is not defined.",
        document.documentElement,
        { token: token },
      );
    });
  }
  /*__WRNEXUS_DEV_END__*/

  function scheduleUpdateHook(element, callback) {
    pendingUpdateHooks.set(element, callback);
    if (updateHooksScheduled) return;
    updateHooksScheduled = true;
    queueMicrotask(function () {
      updateHooksScheduled = false;
      var pending = Array.from(pendingUpdateHooks.entries());
      pendingUpdateHooks.clear();
      pending.forEach(function (entry) {
        var root = entry[0];
        var hook = entry[1];
        if (!root.isConnected) return;
        try { hook(); } catch (error) {
          console.error("[wrnexus] component update hook failed", error);
        }
      });
    });
  }

  function decodeScopePayload(value) {
    var binary = window.atob(value);
    var bytes =
      new Uint8Array(binary.length);

    for (
      var index = 0;
      index < binary.length;
      index++
    ) {
      bytes[index] =
        binary.charCodeAt(index);
    }

    var decoded =
      new TextDecoder(
        "utf-8",
      ).decode(bytes);

    var parsed =
      JSON.parse(decoded);

    return parsed &&
      typeof parsed === "object"
      ? parsed
      : {};
  }

  function decodeBehaviorPayload(value) {
    var binary = window.atob(value);
    var bytes = new Uint8Array(binary.length);

    for (var index = 0; index < binary.length; index++) {
      bytes[index] = binary.charCodeAt(index);
    }

    return new TextDecoder("utf-8").decode(bytes);
  }

  function parseBehavior(element) {
    var raw = element.getAttribute(
      "data-wrn-behavior",
    );

    if (!raw) {
      return null;
    }

    try {
      var decoded =
        decodeBehaviorPayload(raw);

      var parsed = JSON.parse(decoded);

      if (
        !parsed ||
        typeof parsed !== "object"
      ) {
        return null;
      }

      return parsed;
    } catch (error) {
      console.error(
        "[wrnexus] failed to parse component behavior",
        error,
      );

      return null;
    }
  }

  function extractBehaviorFunctions(source) {
    var functions = [];
    var re = /(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(([^)]*)\)\s*\{/g;
    var match;
    while ((match = re.exec(source || ""))) {
      var start = re.lastIndex;
      var depth = 1;
      var quote = "";
      var i = start;
      for (; i < source.length; i++) {
        var ch = source[i];
        if (quote) {
          if (ch === "\\") i++;
          else if (ch === quote) quote = "";
          continue;
        }
        if (ch === '"' || ch === "'" || ch === "\`") {
          quote = ch;
          continue;
        }
        if (ch === "{") depth++;
        else if (ch === "}" && --depth === 0) break;
      }
      if (depth !== 0) break;
      functions.push({
        name: match[1],
        args: match[2].split(",").map(function (arg) { return arg.trim(); }).filter(Boolean),
        body: source.slice(start, i),
      });
      re.lastIndex = i + 1;
    }
    return functions;
  }

  /*
   * Remove comments before anything tries to read the code.
   *
   * Statement bodies reaching the interpreter -- a lifecycle mount hook, a
   * multi-line inline handler -- are ordinary authored code. A comment line
   * became its own "statement" and blew up the whole body, so the hook simply
   * never ran. Comments are replaced by a space rather than deleted so they
   * cannot glue two tokens together.
   */
  function stripComments(input) {
    var out = "";
    var quote = "";
    var index = 0;

    while (index < input.length) {
      var ch = input[index];

      if (quote) {
        out += ch;
        if (ch === "\\") {
          out += input[index + 1] || "";
          index += 2;
          continue;
        }
        if (ch === quote) quote = "";
        index++;
        continue;
      }

      if (ch === '"' || ch === "'" || ch === "\`") {
        quote = ch;
        out += ch;
        index++;
        continue;
      }

      if (ch === "/" && input[index + 1] === "/") {
        var lineEnd = input.indexOf("\n", index + 2);
        if (lineEnd === -1) break;
        out += "\n";
        index = lineEnd + 1;
        continue;
      }

      if (ch === "/" && input[index + 1] === "*") {
        var blockEnd = input.indexOf("*/", index + 2);
        out += " ";
        if (blockEnd === -1) break;
        index = blockEnd + 2;
        continue;
      }

      out += ch;
      index++;
    }

    return out;
  }

  function splitStatements(rawInput) {
    var input = stripComments(rawInput);
    var parts = [];
    var start = 0;
    var depth = 0;
    var quote = "";

    function continuesOnNextLine(index) {
      var previousIndex = index - 1;
      var nextIndex = index + 1;

      while (
        previousIndex >= start &&
        /\s/.test(input[previousIndex])
      ) {
        previousIndex--;
      }

      while (
        nextIndex < input.length &&
        /\s/.test(input[nextIndex])
      ) {
        nextIndex++;
      }

      var previous =
        previousIndex >= start
          ? input[previousIndex]
          : "";
      var next =
        nextIndex < input.length
          ? input[nextIndex]
          : "";

      var currentLine = input
        .slice(start, previousIndex + 1)
        .trim();

      // Postfix updates are complete statements. Treating their trailing + or
      // - as a multiline operator merges the following assignment into the
      // same statement (for example count++ followed by message = ...).
      if (/\+\+$|--$/.test(currentLine)) {
        return false;
      }

      // Newlines are formatting whitespace while either side is an
      // incomplete expression. This covers multiline assignments and
      // ternaries emitted by formatted .wrn component functions.
      return (
        /[=+\-*/%?:,.!&|<>]/.test(
          previous,
        ) ||
        /[.?+:*/%&|<>=]/.test(next)
      );
    }

    for (var i = 0; i < input.length; i++) {
      var ch = input[i];
      if (quote) {
        if (ch === "\\") i++;
        else if (ch === quote) quote = "";
        continue;
      }
      if (ch === '"' || ch === "'" || ch === "\`") {
        quote = ch;
        continue;
      }
      if (ch === "(" || ch === "[" || ch === "{") depth++;
      else if (ch === ")" || ch === "]" || ch === "}") depth--;
      else if (
        (
          ch === ";" ||
          ch === "\n" ||
          ch === "\r"
        ) &&
        depth === 0
      ) {
        if (
          ch !== ";" &&
          continuesOnNextLine(i)
        ) {
          continue;
        }

        var nextIndex = i + 1;

        while (
          nextIndex < input.length &&
          /\s/.test(input[nextIndex])
        ) {
          nextIndex++;
        }

        if (
          input.slice(
            nextIndex,
            nextIndex + 4,
          ) === "else"
        ) {
          continue;
        }

        var part = input
          .slice(start, i)
          .trim();

        if (part) {
          parts.push(part);
        }

        start = i + 1;
      }
    }
    var tail = input.slice(start).trim();
    if (tail) parts.push(tail);
    return parts;
  }

  function signal(initial) {
    var value = initial;
    var subscribers = new Set();
    var notifying = false;

    return {
      get: function () {
        return value;
      },

      set: function (nextValue) {
        if (
          Object.is(
            nextValue,
            value,
          )
        ) {
          return;
        }

        var previous = value;
        value = nextValue;

        /*
        * Prevent nested synchronous notification of the
        * same signal.
        */
        if (notifying) {
          return;
        }

        notifying = true;

        try {
          /*
          * Always iterate a snapshot. A renderer can read
          * this signal and subscribe again while it runs.
          */
          var snapshot =
            Array.from(subscribers);

          for (
            var index = 0;
            index < snapshot.length;
            index++
          ) {
            var subscriber =
              snapshot[index];

            if (
              subscribers.has(
                subscriber,
              )
            ) {
              subscriber(
                value,
                previous,
              );
            }
          }
        } finally {
          notifying = false;
        }
      },

      subscribe: function (
        subscriber,
      ) {
        subscribers.add(
          subscriber,
        );

        return function () {
          subscribers.delete(
            subscriber,
          );
        };
      },
    };
  }

  function routeSnapshot() {
    var url = new URL(window.location.href);
    var params = window.__wrnexusRouteParams || {};
    var marker = document.querySelector("[data-wrn-route-params]");
    if (marker) {
      try { params = JSON.parse(marker.getAttribute("data-wrn-route-params") || "{}"); }
      catch (_) { params = {}; }
      window.__wrnexusRouteParams = params;
      marker.remove();
    }
    return {
      url: url.href,
      pathname: url.pathname,
      search: url.search,
      hash: url.hash,
      searchParams: url.searchParams,
      params: params,
    };
  }
  function sanitizeReactiveUrl(value) {
    var raw = String(value == null ? "" : value);
    var compact = raw.trim().replace(/[\u0000-\u0020]+/g, "").toLowerCase();
    if (/^(?:javascript|vbscript|file):/.test(compact)) return "about:blank";
    if (/^data:(?!image\/(?:png|gif|jpeg|webp|avif);)/.test(compact)) return "about:blank";
    return raw;
  }

  function applyReactiveAttribute(node, name, value) {
    var lowerName = String(name || "").toLowerCase();
    if (
      value != null &&
      ["href", "src", "action", "formaction", "poster", "cite", "background", "xlink:href"].indexOf(lowerName) !== -1
    ) {
      value = sanitizeReactiveUrl(value);
    }

    if (
      lowerName === "value" &&
      (
        node instanceof HTMLInputElement ||
        node instanceof HTMLTextAreaElement ||
        node instanceof HTMLSelectElement
      )
    ) {
      var nextValue =
        value == null ? "" : String(value);

      if (node.value !== nextValue) {
        node.value = nextValue;
      }

      if (value == null) {
        node.removeAttribute("value");
      } else {
        node.setAttribute(
          "value",
          nextValue,
        );
      }

      return;
    }

    if (
      lowerName === "checked" &&
      node instanceof HTMLInputElement
    ) {
      var checked = !!value;

      if (node.checked !== checked) {
        node.checked = checked;
      }

      if (checked) {
        node.setAttribute(
          "checked",
          "",
        );
      } else {
        node.removeAttribute(
          "checked",
        );
      }

      return;
    }

    if (
      lowerName === "selected" &&
      node instanceof HTMLOptionElement
    ) {
      var selected = !!value;

      node.selected = selected;

      if (selected) {
        node.setAttribute(
          "selected",
          "",
        );
      } else {
        node.removeAttribute(
          "selected",
        );
      }

      return;
    }

    if (
      lowerName === "disabled" ||
      lowerName === "required" ||
      lowerName === "readonly" ||
      lowerName === "multiple"
    ) {
      var enabled = !!value;

      if (lowerName in node) {
        try {
          node[lowerName] = enabled;
        } catch (_) {
          // Fall through to attribute handling.
        }
      }

      if (enabled) {
        node.setAttribute(
          name,
          "",
        );
      } else {
        node.removeAttribute(name);
      }

      return;
    }

    if (
      lowerName.startsWith("data-") ||
      lowerName.startsWith("aria-")
    ) {
      if (value == null) {
        node.removeAttribute(name);
      } else {
        node.setAttribute(name, String(value));
      }

      return;
    }

    if (value === false || value == null) {
      node.removeAttribute(name);
    } else {
      node.setAttribute(
        name,
        value === true ? "" : String(value),
      );
    }
  }

  function loadClientModule(element) {
    var url = element.getAttribute("data-wrn-client-module");
    if (!url) return Promise.resolve(null);
    var promise = clientModuleCache.get(url);
    if (!promise) {
      promise = import(url).catch(function (error) {
        clientModuleCache.delete(url);
        reportDiagnostic("WRN-CLIENT-MODULE", "Failed to load browser function module '" + url + "'.", element, error);
        return null;
      });
      clientModuleCache.set(url, promise);
    }
    return promise;
  }

  function setupScope(el) {
    if (el.__wrnexusScope) return;

    el.__wrnexusScope = true;
    el.__wrnexusHydrated = true;

    var encodedScope =
      el.getAttribute(
        "data-wrn-scope",
      );

    var initial;

    if (encodedScope) {
      try {
        initial =
          decodeScopePayload(
            encodedScope,
          );
      } catch (error) {
        reportDiagnostic(
          "WRN-HYDRATE-SCOPE",
          "Failed to decode the server-rendered scope payload.",
          el,
          error,
        );

        initial = {};
      }
    } else {
      var declaration =
        el.getAttribute(
          "data-scope",
        ) || "";

      initial =
        parseScopeDecl(
          declaration,
        );
    }

    var signals = {};
    Object.keys(initial).forEach(function (k) { signals[k] = signal(initial[k]); });
    var behavior = parseBehavior(el);
    var computedDefinitions = {};
    var computing = new Set();
    if (behavior && Array.isArray(behavior.computed)) {
      behavior.computed.forEach(function (entry) {
        if (entry && typeof entry.name === "string" && typeof entry.expr === "string") {
          computedDefinitions[entry.name] = entry.expr;
        }
      });
    }

    var renderers = [];
    // Dependency-tracked rendering: while a renderer runs, every signal it reads
    // subscribes THAT renderer (not a blanket "re-render everything"). A signal
    // change then re-runs only the renderers that actually read it. The Set in
    // signal.subscribe dedupes, so re-subscribing each run is cheap and bounded.
    var currentRenderer = null;
    var pendingRenderers = new Set();
    var batchDepth = 0;
    var flushingRenderers = false;

    function flushRenderers() {
      if (flushingRenderers || batchDepth > 0) return;

      flushingRenderers = true;

      try {
        while (pendingRenderers.size > 0) {
          var queue = Array.from(pendingRenderers);
          pendingRenderers.clear();
          queue.forEach(function (run) { run(); });
        }
      } finally {
        flushingRenderers = false;
      }
    }

    function scheduleRenderer(renderer) {
      pendingRenderers.add(renderer);
      flushRenderers();
    }

    function batchUpdates(callback) {
      batchDepth++;

      try {
        return callback();
      } finally {
        batchDepth--;
        flushRenderers();
      }
    }

    function reactive(fn) {
      var running = false;

      function run() {
        if (running) {
          return;
        }

        running = true;

        var previousRenderer =
          currentRenderer;

        currentRenderer = schedule;

        try {
          fn();
        } finally {
          currentRenderer =
            previousRenderer;

          running = false;
        }
      }

      function schedule() {
        scheduleRenderer(run);
      }

      renderers.push(run);

      return run;
    }
    /*
     * An index loop, deliberately, not forEach.
     *
     * forEach fixes its range before the first callback, so an effect
     * registered WHILE the sweep is running was never executed -- and an
     * effect that never runs never subscribes, so it stayed dead for the life
     * of the page. Every binding inside a data-for row registers exactly then,
     * from inside its loop render, which is why a row attribute could not
     * react to anything its list expression did not already read. Re-reading
     * length each step picks those up in the same sweep.
     *
     * The cap is a guard against an effect that registers another effect on
     * every run; it is far above any real component.
     */
    function renderAll() {
      for (var index = 0; index < renderers.length && index < 10000; index++) {
        renderers[index]();
      }
    }
    function decodeLoopLocals(node) {
      if (!node) {
        return {};
      }

      var element =
        node.nodeType === 1
          ? node
          : node.parentElement;

      var owner =
        element &&
        element.closest &&
        element.closest(
          "[data-wrn-loop-locals]",
        );

      if (!owner) {
        return {};
      }

      var encoded =
        owner.getAttribute(
          "data-wrn-loop-locals",
        );

      if (!encoded) {
        return {};
      }

      try {
        var binary =
          window.atob(encoded);

        var bytes =
          new Uint8Array(binary.length);

        for (
          var index = 0;
          index < binary.length;
          index++
        ) {
          bytes[index] =
            binary.charCodeAt(index);
        }

        var decoded =
          new TextDecoder("utf-8").decode(
            bytes,
          );

        var parsed =
          JSON.parse(decoded);

        return parsed &&
          typeof parsed === "object"
          ? parsed
          : {};
      } catch (error) {
        console.error(
          "[wrnexus] failed to decode loop locals",
          error,
        );

        return {};
      }
    }

    var behaviorFunctions = {};
    var moduleBindings = {};
    var componentEventTarget = el.hasAttribute("data-wrn-events")
      ? el
      : el.querySelector("[data-wrn-events]") || el;
    var declaredEvents = new Set(
      String(componentEventTarget.getAttribute("data-wrn-events") || "")
        .split(",")
        .map(function (name) { return name.trim(); })
        .filter(Boolean),
    );
    var outputHandlers = componentEventTarget.__wrnexusOutputHandlers || (componentEventTarget.__wrnexusOutputHandlers = {});
    var outputProxy = new Proxy({}, {
      get: function (_target, property) {
        return function (payload) {
          return invokeComponentOutput(componentEventTarget, String(property), payload);
        };
      },
    });
    var componentRpcName = componentEventTarget.getAttribute("data-wrn-component") || componentEventTarget.getAttribute("data-wrn-hydration") || "component";
    var serverProxy = new Proxy({}, {
      get: function (_target, property) {
        return function () {
          return callServerFunction(componentRpcName, String(property), Array.prototype.slice.call(arguments));
        };
      },
    });
    var propsProxy = new Proxy({}, {
      get: function (_target, property) { return peekScope(String(property)); },
      set: function () { throw new TypeError("WRN-PROP-READONLY: props are readonly"); },
    });
    var refsProxy = new Proxy({}, {
      get: function (_target, property) { return el.querySelector('[data-ref="' + String(property).replace(/"/g, '\"') + '"]'); },
    });
    var stateWatchers = {};
    var anyStateListeners = new Set();
    var cleanupCallbacks = [];
    var disposed = false;
    var routeValue = signal(routeSnapshot());

    function updateRouteValue() {
      routeValue.set(routeSnapshot());
    }

    window.addEventListener("wrnexus:navigated", updateRouteValue);
    window.addEventListener("popstate", updateRouteValue);
    window.addEventListener("hashchange", updateRouteValue);
    cleanupCallbacks.push(function () {
      window.removeEventListener("wrnexus:navigated", updateRouteValue);
      window.removeEventListener("popstate", updateRouteValue);
      window.removeEventListener("hashchange", updateRouteValue);
    });

    function readGlobal(name) {
      if (declaredEvents.has(name)) {
        return function (detail) {
          return dispatchComponentEvent(componentEventTarget, name, detail);
        };
      }
      if (name === "output") return outputProxy;
      if (name === "server") return serverProxy;
      if (name === "props") return propsProxy;
      if (name === "refs") return refsProxy;
      if (Object.prototype.hasOwnProperty.call(moduleBindings, name)) return moduleBindings[name];
      if (name === "$emit") {
        return function (eventName, detail) {
          return dispatchComponentEvent(componentEventTarget, eventName, detail);
        };
      }
      if (name === "window") return window;
      if (name === "document") return document;
      if (name === "console") return console;
      if (name === "Array") return Array;
      if (name === "Number") return Number;
      if (name === "String") return String;
      if (name === "Math") return Math;
      if (name === "JSON") return JSON;
      if (name === "Date") return Date;
      if (name === "URL") return URL;
      if (name === "location") return window.location;
      if (name === "history") return window.history;
      if (name === "navigator") return window.navigator;
      if (name === "$route" || name === "route") {
        if (currentRenderer) routeValue.subscribe(currentRenderer);
        return routeValue.get();
      }
      if (name === "setTimeout") return window.setTimeout.bind(window);
      if (name === "clearTimeout") return window.clearTimeout.bind(window);
      if (name === "setInterval") return window.setInterval.bind(window);
      if (name === "clearInterval") return window.clearInterval.bind(window);
      if (name === "requestAnimationFrame") return window.requestAnimationFrame.bind(window);
      if (name === "cancelAnimationFrame") return window.cancelAnimationFrame.bind(window);
      /*
       * Ordinary browser and language globals.
       *
       * This engine resolves identifiers itself rather than handing the
       * expression to eval/new Function, which is what lets a page run under
       * a strict CSP with no unsafe-eval. The cost is that an unknown
       * identifier quietly evaluates to undefined -- so an author who writes
       * alert(...) or Object.keys(...) in a client function gets
       * "undefined is not a function" and no clue why. Resolving the normal
       * globals here makes client code behave the way its author expects.
       *
       * Bound where the callee needs a window receiver (illegal-invocation
       * otherwise), and read lazily so a server-side or minimal DOM that
       * lacks one of these does not break the rest.
       */
      if (name === "toast") return toastApi;
      if (dialogGlobals[name] && typeof window[name] === "function") {
        return window[name].bind(window);
      }
      if (jsGlobals[name]) {
        var builtin = jsGlobals[name]();
        if (builtin !== undefined) return builtin;
      }
      if (windowGlobals[name]) {
        try {
          return window[name];
        } catch (error) {
          return undefined;
        }
      }
      return undefined;
    }

    function readScope(name) {
      if (Object.prototype.hasOwnProperty.call(computedDefinitions, name)) {
        if (computing.has(name)) {
          reportDiagnostic("WRN-COMPUTED-CYCLE", "Computed value '" + name + "' has a dependency cycle.", el);
          return undefined;
        }
        computing.add(name);
        try {
          return evalExpr(computedDefinitions[name]);
        } finally {
          computing.delete(name);
        }
      }
      var sig = signals[name];
      if (sig) {
        if (currentRenderer) sig.subscribe(currentRenderer);
        return sig.get();
      }
      if (Object.prototype.hasOwnProperty.call(behaviorFunctions, name)) {
        return behaviorFunctions[name];
      }
      return readGlobal(name);
    }

    function peekScope(name) {
      if (Object.prototype.hasOwnProperty.call(computedDefinitions, name)) {
        return readScope(name);
      }
      if (signals[name]) return signals[name].get();
      if (Object.prototype.hasOwnProperty.call(behaviorFunctions, name)) {
        return behaviorFunctions[name];
      }
      return readGlobal(name);
    }

    function notifyState(name, value, previous) {
      var watchers = stateWatchers[name];
      if (watchers) {
        watchers.slice().forEach(function (watcher) {
          try { watcher(value, previous); } catch (error) {
            console.error("[wrnexus] watcher for '" + name + "' failed", error);
          }
        });
      }
      anyStateListeners.forEach(function (listener) {
        try { listener(name, value, previous); } catch (error) {
          console.error("[wrnexus] state subscriber failed", error);
        }
      });
    }

    function writeScope(
      name,
      value,
    ) {
      if (!signals[name]) {
        signals[name] =
          signal(value);

        notifyState(
          name,
          value,
          undefined,
        );

        renderAll();
        return;
      }

      var previous =
        signals[name].get();

      if (
        Object.is(
          previous,
          value,
        )
      ) {
        return;
      }

      signals[name].set(value);

      notifyState(
        name,
        value,
        previous,
      );
    }

    function evalExpr(expr, locals) {
      return evaluateExpression(expr, function (name) {
        if (locals && Object.prototype.hasOwnProperty.call(locals, name)) {
          return locals[name];
        }
        return readScope(name);
      });
    }

    function runStmt(
      source,
      locals,
    ) {
      return batchUpdates(function () {
        var statements =
          splitStatements(source);

        for (
          var statementIndex = 0;
          statementIndex <
          statements.length;
          statementIndex++
        ) {
          var result = runStatement(
            statements[statementIndex],
            function (expression) {
              return evalExpr(
                expression,
                locals,
              );
            },
            function (name) {
              if (
                locals &&
                Object.prototype
                  .hasOwnProperty.call(
                    locals,
                    name,
                  )
              ) {
                return locals[name];
              }

              return peekScope(name);
            },
            function (name, value) {
              if (
                locals &&
                Object.prototype
                  .hasOwnProperty.call(
                    locals,
                    name,
                  )
              ) {
                locals[name] = value;
              } else {
                writeScope(name, value);
              }
            },
            function (body) {
              return runStmt(
                body,
                locals,
              );
            },
          );

          if (result.returned) {
            return result;
          }
        }

        return {
          returned: false,
          value: undefined,
        };
      });
    }

    function installBehaviorFunctions(source) {
      extractBehaviorFunctions(source || "").forEach(function (definition) {
        // A generated browser module contains the real JavaScript implementation
        // of client/shared functions. Keep that implementation when it has already
        // been installed instead of replacing it with the small CSP-safe fallback
        // interpreter. The fallback intentionally supports only a bounded subset of
        // JavaScript and must never shadow the compiled function.
        if (typeof behaviorFunctions[definition.name] === "function") return;
        behaviorFunctions[
          definition.name
        ] = function () {
          var locals = {};

          for (
            var i = 0;
            i < definition.args.length;
            i++
          ) {
            locals[definition.args[i]] =
              arguments[i];
          }

          var result = runStmt(
            definition.body,
            locals,
          );

          return result.returned
            ? result.value
            : undefined;
        };
      });
    }

    function installClientModule(module) {
      if (!module) return;
      var stateProxy = new Proxy({}, {
        get: function (_target, property) { return readScope(String(property)); },
        set: function (_target, property, value) { writeScope(String(property), value); return true; },
        ownKeys: function () { return Object.keys(signals); },
        getOwnPropertyDescriptor: function () { return { enumerable: true, configurable: true }; },
      });
      var context = {
        state: stateProxy,
        output: outputProxy,
        server: serverProxy,
        props: propsProxy,
        refs: refsProxy,
      };
      var importedBindings = module.__wrnexusImportedBindings;
      if (importedBindings && typeof importedBindings === "object") {
        Object.keys(importedBindings).forEach(function (name) {
          var binding = importedBindings[name];
          moduleBindings[name] = binding;
          if (binding && typeof binding.subscribe === "function") {
            cleanupCallbacks.push(binding.subscribe(function () { renderAll(); }));
          }
        });
      }
      var functions = typeof module.bindClientScope === "function"
        ? module.bindClientScope(context)
        : module.__wrnexusClientFunctions;
      if (!functions || typeof functions !== "object") return;
      Object.keys(functions).forEach(function (name) {
        if (typeof functions[name] === "function") behaviorFunctions[name] = functions[name];
      });
    }

    installClientModule(el.__wrnexusClientModule);

    // A binding belongs to THIS scope only when el is the node's *owning*
    // scope. Normally that is the nearest [data-scope] ancestor, so an outer
    // scope never clobbers an inner one's values.
    //
    // Slot content is the exception. Children written between a component's
    // open and close tags are authored
    // in the PARENT's source but SSR splices them inside the child
    // component's [data-scope] root, so the nearest-ancestor rule would hand
    // them to the child -- where the page's state and functions do not exist,
    // and the child's same-named state silently shadows them. The server
    // wraps spliced slot content in [data-wrn-slot], which acts as an
    // ownership boundary: crossing it means stepping *out* of the component
    // that received the slot and continuing the search from its mount point.
    // The loop repeats so slots nested through several components resolve to
    // the scope that actually wrote the markup.
    function ownerScope(node) {
      var cursor = node.nodeType === 1 ? node : node.parentNode;
      for (var guard = 0; cursor && cursor.closest && guard < 32; guard++) {
        var found = cursor.closest(
          "[data-scope], [data-wrn-scope], [data-wrn-slot]",
        );
        if (!found) return null;
        if (!found.hasAttribute("data-wrn-slot")) return found;
        // Step out of the component whose slot this content filled, then keep
        // looking from just above that component's root.
        var componentRoot =
          found.parentNode && found.parentNode.closest
            ? found.parentNode.closest("[data-scope], [data-wrn-scope]")
            : null;
        cursor = componentRoot ? componentRoot.parentNode : found.parentNode;
      }
      return null;
    }

    function owns(node) {
      return ownerScope(node) === el;
    }

    // --- data-for list rendering -------------------------------------------
    // Each [data-for="item in list"] element is a per-item template. Add
    // data-key="item.id" or a key item.id suffix preserves DOM nodes when
    // a list is reordered. Unkeyed loops retain the legacy full-rerender path.
    function parseFor(value) {
      var m = /^\s*([A-Za-z_$][\w$]*)\s*(?:,\s*([A-Za-z_$][\w$]*)\s*)?\s+in\s+([\s\S]+?)(?:\s+key\s+([\s\S]+?))?\s*$/.exec(
        value || "",
      );
      return m ? { item: m[1], index: m[2], list: m[3].trim(), key: m[4] && m[4].trim() } : null;
    }

    function unwrapForKey(value) {
      var expression = String(value || "").trim();
      if (expression.charAt(0) === "{" && expression.charAt(expression.length - 1) === "}") {
        expression = expression.slice(1, -1).trim();
      }
      return expression;
    }

    function stableForKey(value) {
      if (value === null) return "null:";
      var type = typeof value;
      if (type === "object") {
        try { return "object:" + JSON.stringify(value); } catch (_) { return "object:" + String(value); }
      }
      return type + ":" + String(value);
    }
    function fillMustache(str, itemEval) {
      return str.replace(/\{\{\s*([^}]+?)\s*\}\}|\{([^{}]+)\}/g, function (_, d, s) {
        var e = (d || s).trim();
        try { return String(itemEval(e)); } catch (err) { return ""; }
      });
    }
    function hydrateItem(
      root,
      locals,
    ) {
      function localRead(name) {
        if (
          Object.prototype.hasOwnProperty.call(
            locals,
            name,
          )
        ) {
          return locals[name];
        }

        return readScope(name);
      }

      function itemEval(expression) {
        return evaluateExpression(
          expression,
          localRead,
        );
      }

      function applyItemTemplate(
        template,
      ) {
        return String(template).replace(
          /\{\{\s*([^}]+?)\s*\}\}|\{([^{}]+)\}/g,
          function (
            _,
            doubleExpression,
            singleExpression,
          ) {
            var expression = (
              doubleExpression ||
              singleExpression
            ).trim();

            try {
              var value =
                itemEval(expression);

              return value == null
                ? ""
                : String(value);
            } catch (_) {
              return "";
            }
          },
        );
      }

      /*
       * A nested [data-for] inside this item is a TEMPLATE for its own loop,
       * not content of this one. Interpolating it here would bake the inner
       * mustaches against the outer locals -- where the inner item name is
       * undefined -- and the nested rows would render blank. Skip those
       * subtrees; setupForLoop below takes them over with this item's locals
       * in scope.
       */
      function insideNestedLoop(node) {
        var cursor = node;
        while (cursor && cursor !== root) {
          if (cursor.nodeType === 1 && cursor.hasAttribute("data-for")) return true;
          cursor = cursor.parentNode;
        }
        return false;
      }

      var elements = [root];

      if (root.querySelectorAll) {
        Array.prototype.push.apply(
          elements,
          root.querySelectorAll("*"),
        );
      }

      elements.forEach(function (node) {
        if (
          !node ||
          node.nodeType !== 1
        ) {
          return;
        }

        if (node !== root && insideNestedLoop(node)) return;

        var attributes =
          Array.prototype.slice.call(
            node.attributes,
          );

        attributes.forEach(function (
          attribute,
        ) {
          /*
          * data-text must be handled using itemEval(),
          * because item/index only exist in loop locals.
          */
          if (
            attribute.name === "data-text"
          ) {
            try {
              var textValue =
                itemEval(attribute.value);

              node.textContent =
                textValue == null
                  ? ""
                  : String(textValue);
            } catch (error) {
              console.error(
                "[wrnexus] data-for text binding failed for '" +
                  attribute.value +
                  "'",
                error,
              );

              node.textContent = "";
            }

            return;
          }

          /*
          * Conditional classes:
          * data-wrn-class-*='["class","expression"]'
          */
          if (
            attribute.name.indexOf(
              "data-wrn-class-",
            ) === 0
          ) {
            var classBinding;

            try {
              classBinding = JSON.parse(
                attribute.value,
              );
            } catch (_) {
              return;
            }

            if (
              !classBinding ||
              classBinding.length !== 2
            ) {
              return;
            }

            var className =
              classBinding[0];

            var classExpression =
              classBinding[1];

            var classEnabled = false;

            try {
              classEnabled = !!itemEval(
                classExpression,
              );
            } catch (_) {
              classEnabled = false;
            }

            node.classList.toggle(
              className,
              classEnabled,
            );

            return;
          }

          /*
          * Reactive ordinary attributes:
          * data-wrn-bind-*='["aria-expanded","{isOpen(index)}"]'
          */
          if (
            attribute.name.indexOf(
              "data-wrn-bind-",
            ) === 0
          ) {
            var binding;

            try {
              binding = JSON.parse(
                attribute.value,
              );
            } catch (_) {
              return;
            }

            if (
              !binding ||
              binding.length !== 2
            ) {
              return;
            }

            var attributeName =
              binding[0];

            var attributeTemplate =
              binding[1];

            /*
             * Reactive, not resolved once. The expression can read component
             * state the row never mentions -- a selection set, the current sort
             * -- and the row must stay in step with it after it is built.
             * Resolving at clone time froze every such attribute at whatever it
             * was on first render.
             */
            (function (bindNode, bindName, bindTemplate) {
              var exact = /^\{([^{}]+)\}$/.exec(bindTemplate);
              // Run immediately for the same reason as data-show above.
              var runBind = reactive(function () {
                var rawValue;
                if (exact) {
                  try {
                    rawValue = itemEval(exact[1].trim());
                  } catch (_) {
                    return;
                  }
                } else {
                  rawValue = bindTemplate.replace(/\{([^{}]+)\}/g, function (_, expression) {
                    try {
                      var value = itemEval(expression.trim());
                      return value == null ? "" : String(value);
                    } catch (_) {
                      return "";
                    }
                  });
                }
                applyReactiveAttribute(bindNode, bindName, rawValue);
              });
              runBind();
            })(node, attributeName, attributeTemplate);

            return;
          }

          /*
          * Event handlers inside data-for.
          */
          if (
            attribute.name.indexOf(
              "data-on-",
            ) === 0
          ) {
            var eventName =
              attribute.name.slice(
                "data-on-".length,
              );

            var statement =
              attribute.value;

            node.addEventListener(
              eventName,
              function (event) {
                var eventLocals = {};

                Object.keys(
                  locals,
                ).forEach(function (key) {
                  eventLocals[key] =
                    locals[key];
                });

                eventLocals.event = event;
                eventLocals.$event = event;
                eventLocals.payload = event && Object.prototype.hasOwnProperty.call(event, "detail") ? event.detail : undefined;

                try {
                  runStmt(
                    statement,
                    eventLocals,
                  );
                } catch (error) {
                  console.error(
                    "[wrnexus] data-for handler error in '" +
                      statement +
                      "'",
                    error,
                  );
                }
              },
            );

            return;
          }

          /*
          * data-show inside data-for.
          *
          * The page-level data-show pass runs once over the DOM at hydration,
          * long before these clones exist, so a row's data-show was never
          * evaluated: the attribute kept its literal expression text and the
          * element stayed visible no matter what. That silently rendered
          * every conditional part of every row -- an empty action button drawn
          * as a stray outline, blank headings taking up space.
          *
          * Evaluated here against the row's own locals. A row is rebuilt when
          * its item changes, so evaluating once per clone is correct and
          * needs no separate subscription.
          */
          /*
           * data-html inside a loop row. The page-level scan happens once at
           * hydration, long before these clones exist, so a row that renders
           * markup would otherwise never have it applied.
           */
          if (attribute.name === "data-html") {
            (function (htmlNode, htmlExpr) {
              var runHtml = reactive(function () {
                var markup;

                try {
                  markup = itemEval(htmlExpr);
                } catch (_) {
                  return;
                }

                var next = markup == null ? "" : String(markup);

                if (htmlNode.innerHTML !== next) {
                  htmlNode.innerHTML = next;
                }
              });
              runHtml();
            })(node, attribute.value);

            return;
          }

          if (attribute.name === "data-show") {
            // Reactive, not resolved once: the expression can read component
            // state the row itself knows nothing about (a selection set, a
            // sort key), and those must keep the row in step after it is
            // built.
            (function (showNode, showExpr) {
              /*
               * Run it now, do not wait to be swept. reactive() only
               * registers; the initial renderAll picks registrations up, but a
               * row rebuilt LATER (a re-sort, a filter) registers outside any
               * sweep, and nothing would ever run it. The attribute then stays
               * as the raw expression and the element defaults to visible --
               * which is why sorting a column made a second copy of every
               * header label appear.
               */
              var runShow = reactive(function () {
                var shown = true;

                try {
                  shown = !!itemEval(showExpr);
                } catch (_) {
                  // Unresolvable expression: leave the element visible rather
                  // than hiding content because of an authoring slip.
                }

                showNode.setAttribute(
                  "data-show",
                  shown ? "true" : "false",
                );

                showNode.style.display = shown ? "" : "none";
              });
              runShow();
            })(node, attribute.value);

            return;
          }

          /*
          * Static attributes containing interpolation.
          */
          if (
            attribute.value &&
            attribute.value.indexOf("{") !== -1
          ) {
            node.setAttribute(
              attribute.name,
              applyItemTemplate(
                attribute.value,
              ),
            );
          }
        });
      });

      /*
      * Text interpolation inside loop content:
      *
      * <span>{item.title}</span>
      */
      var walker =
        document.createTreeWalker(
          root,
          NodeFilter.SHOW_TEXT,
          null,
        );

      var textNode;

      while (
        (textNode = walker.nextNode())
      ) {
        var template =
          textNode.nodeValue || "";

        if (
          template.indexOf("{") === -1
        ) {
          continue;
        }

        if (insideNestedLoop(textNode)) continue;

        textNode.nodeValue =
          applyItemTemplate(template);
      }

      // Hand every nested loop its own renderer, with this item in scope.
      if (root.querySelectorAll) {
        Array.prototype.slice
          .call(root.querySelectorAll("[data-for]"))
          .forEach(function (nested) {
            // Only the outermost nested templates: deeper ones are set up by
            // their own parent when it renders.
            var parentTemplate = nested.parentNode;
            while (parentTemplate && parentTemplate !== root) {
              if (
                parentTemplate.nodeType === 1 &&
                parentTemplate.hasAttribute("data-for")
              ) {
                return;
              }
              parentTemplate = parentTemplate.parentNode;
            }
            setupForLoop(nested, locals);
          });
      }
    }

    /*
     * Set up one [data-for] template. Extracted from an inline forEach so it
     * can recurse: hydrateItem calls it for every loop nested inside a rendered
     * item, passing that item as outerLocals. Without that a table -- rows
     * containing cells -- could not render at all, because the inner loop was
     * never given a renderer and its template was left in the DOM unexpanded.
     *
     * outerLocals are the enclosing item bindings; they are visible to the
     * list expression, the key, and everything the nested rows interpolate.
     */
    function setupForLoop(tpl, outerLocals) {
      var inherited = outerLocals || {};

      function withInherited(extra) {
        var merged = {};
        Object.keys(inherited).forEach(function (name) {
          merged[name] = inherited[name];
        });
        if (extra) {
          Object.keys(extra).forEach(function (name) {
            merged[name] = extra[name];
          });
        }
        return merged;
      }

      function loopRead(name) {
        if (Object.prototype.hasOwnProperty.call(inherited, name)) {
          return inherited[name];
        }
        return readScope(name);
      }

      function loopEval(expression) {
        return evaluateExpression(expression, loopRead);
      }

        /*
         * A nested template is hydrated while its row is still detached from
         * the document, so owns() cannot walk up to a [data-scope] ancestor
         * and would reject it. Ownership is already settled in that case: the
         * enclosing loop only renders rows it owns.
         */
        if (!tpl.parentNode || (!outerLocals && !owns(tpl))) {
          return;
        }

        var spec =
          parseFor(
            tpl.getAttribute(
              "data-for",
            ),
          );

        if (!spec) {
          return;
        }

        var template =
          tpl.cloneNode(true);

        template.removeAttribute(
          "data-for",
        );

        var keyExpression =
          spec.key ||
          unwrapForKey(
            tpl.getAttribute(
              "data-key",
            ),
          );

        template.removeAttribute(
          "data-key",
        );

        var parent =
          tpl.parentNode;

        var marker =
          document.createComment(
            "wrn-for",
          );

        parent.insertBefore(
          marker,
          tpl,
        );

        parent.removeChild(tpl);

        var clones = [];
        var keyedRecords = new Map();

        /*
         * reactive() only REGISTERS the effect; the initial renderAll() sweep
         * runs the renderers array, and forEach fixes its range before the
         * first callback -- so an effect registered while that sweep is
         * already running is never executed. A nested loop registers at
         * exactly that moment, from inside its parent row's render, which is
         * why nested rows came out empty. Run it once by hand.
         */
        var runLoop = reactive(function () {
          var list =
            loopEval(spec.list);

          if (!Array.isArray(list)) {
            console.error(
              "[wrnexus] data-for expected an array for '" +
                spec.list +
                "', received",
              list,
            );

            list = [];
          }

          if (!keyExpression) {
            for (
              var cloneIndex = 0;
              cloneIndex <
              clones.length;
              cloneIndex++
            ) {
              var existingClone =
                clones[cloneIndex];

              if (
                existingClone.parentNode
              ) {
                existingClone.parentNode
                  .removeChild(
                    existingClone,
                  );
              }
            }

            clones = [];

            var fragment =
              document.createDocumentFragment();

            for (
              var itemIndex = 0;
              itemIndex < list.length;
              itemIndex++
            ) {
              var clone =
                template.cloneNode(true);

              var locals = withInherited(null);

              locals[spec.item] =
                list[itemIndex];

              if (spec.index) {
                locals[spec.index] =
                  itemIndex;
              }

              hydrateItem(
                clone,
                locals,
              );

              fragment.appendChild(
                clone,
              );

              clones.push(clone);
            }

            parent.insertBefore(
              fragment,
              marker.nextSibling,
            );

            return;
          }

          var nextRecords = new Map();
          var orderedNodes = [];

          for (
            var keyedIndex = 0;
            keyedIndex < list.length;
            keyedIndex++
          ) {
            var keyedItem = list[keyedIndex];
            var keyedLocals = withInherited(null);

            keyedLocals[spec.item] = keyedItem;
            if (spec.index) keyedLocals[spec.index] = keyedIndex;

            var rawKey;
            try {
              rawKey = evaluateExpression(
                keyExpression,
                function (name) {
                  return Object.prototype.hasOwnProperty.call(keyedLocals, name)
                    ? keyedLocals[name]
                    : loopRead(name);
                },
              );
            } catch (error) {
              reportDiagnostic(
                "WRN-HYDRATE-KEY-001",
                "Unable to evaluate data-for key '" + keyExpression + "'.",
                el,
                error,
              );
              rawKey = keyedIndex;
            }

            var normalizedKey = stableForKey(rawKey);
            if (nextRecords.has(normalizedKey)) {
              reportDiagnostic(
                "WRN-HYDRATE-KEY-002",
                "Duplicate data-for key '" + String(rawKey) + "'; falling back to its index.",
                el,
                { key: rawKey, index: keyedIndex },
              );
              normalizedKey += ":index:" + keyedIndex;
            }

            var record = keyedRecords.get(normalizedKey);
            if (
              !record ||
              record.item !== keyedItem ||
              (spec.index && record.index !== keyedIndex)
            ) {
              if (record && record.node.parentNode) {
                record.node.parentNode.removeChild(record.node);
              }

              var keyedClone = template.cloneNode(true);
              hydrateItem(keyedClone, keyedLocals);
              record = {
                node: keyedClone,
                item: keyedItem,
                index: keyedIndex,
              };
            }

            nextRecords.set(normalizedKey, record);
            orderedNodes.push(record.node);
          }

          keyedRecords.forEach(function (record, key) {
            if (!nextRecords.has(key) && record.node.parentNode) {
              record.node.parentNode.removeChild(record.node);
            }
          });

          var keyedFragment = document.createDocumentFragment();
          orderedNodes.forEach(function (node) {
            keyedFragment.appendChild(node);
          });

          parent.insertBefore(
            keyedFragment,
            marker.nextSibling,
          );

          keyedRecords = nextRecords;
          clones = orderedNodes;
        });

        if (outerLocals) runLoop();
    
    }

    Array.prototype.slice
      .call(el.querySelectorAll("[data-for]"))
      .forEach(function (tpl) {
        // Only top-level templates here; nested ones are wired by the item
        // that contains them, once it has values to give them.
        if (tpl.parentNode && tpl.parentNode.closest && tpl.parentNode.closest("[data-for]")) {
          return;
        }
        setupForLoop(tpl, null);
      });

    // data-text bindings. Server-rendered {#each} nodes recover their item/index
    // values from the nearest data-wrn-loop-locals marker.
    /*
     * data-html="expr" -- render the value as markup instead of text.
     *
     * Deliberately a separate directive from data-text rather than an option
     * on it: this is the one place the runtime stops escaping, so it should be
     * impossible to reach by accident. Only ever point it at markup your own
     * application produced. Anything derived from user input has to be
     * sanitised first -- data-text is the safe default and stays that way.
     */
    el.querySelectorAll("[data-html]").forEach(function (node) {
      if (!owns(node)) return;

      var htmlExpr = node.getAttribute("data-html");

      reactive(function () {
        var value;

        try {
          value = evalExpr(htmlExpr, decodeLoopLocals(node));
        } catch (error) {
          reportDiagnostic("WRN-HTML-EXPR", "data-html expression failed.", node, error);
          return;
        }

        var markup = value == null ? "" : String(value);

        if (node.innerHTML !== markup) {
          node.innerHTML = markup;
        }
      });
    });

    el.querySelectorAll("[data-text]").forEach(function (node) {
      if (!owns(node)) return;

      var expr = node.getAttribute("data-text");

      reactive(function () {
        try {
          var value = evalExpr(
            expr,
            decodeLoopLocals(node),
          );

          node.textContent =
            value == null ? "" : String(value);
        } catch (_) {
          // Keep the server-rendered value when evaluation is unavailable.
        }
      });
    });

    // data-show="expr" — toggle visibility on truthiness. This directive is
    // intentionally non-destructive because popovers, selects and remote data
    // controls keep event wiring and state while closed. Use a compiled {#if}
    // block when the inactive branch must not be rendered.
    el.querySelectorAll("[data-show]").forEach(function (node) {
      if (!owns(node)) return;

      var showExpr = node.getAttribute("data-show");

      reactive(function () {
        var visible = true;

        try {
          visible = !!evalExpr(
            showExpr,
            decodeLoopLocals(node),
          );
        } catch (_) {
          // Keep visible when evaluation is unavailable.
        }

        node.setAttribute(
          "data-show",
          visible ? "true" : "false",
        );
        node.style.display = visible ? "" : "none";
      });
    });

    // Conditional class bindings emitted as:
    // data-wrn-class-*='["class-name","expression"]'
    var classBindNodes = [el].concat(
      Array.prototype.slice.call(el.querySelectorAll("*")),
    );

    classBindNodes.forEach(function (node) {
      if (!owns(node)) return;

      Array.prototype.slice.call(node.attributes).forEach(function (marker) {
        if (marker.name.indexOf("data-wrn-class-") !== 0) return;

        var binding;

        try {
          binding = JSON.parse(marker.value);
        } catch (e) {
          return;
        }

        if (!binding || binding.length !== 2) return;

        var className = binding[0];
        var expression = binding[1];

        reactive(function () {
          var enabled = false;

          try {
            enabled = !!evalExpr(
              expression,
              decodeLoopLocals(node),
            );
          } catch (error) {
            enabled = false;
          }

          node.classList.toggle(
            className,
            enabled,
          );
        });
      });
    });

    // Reactive ordinary attributes emitted by the compiler. Each marker stores
    // [attributeName, originalTemplate], preserving an SSR value while allowing
    // state changes to update type, aria-*, class, href, and other attributes.
    var bindNodes = [el].concat(
      Array.prototype.slice.call(
        el.querySelectorAll("*"),
      ),
    );

    bindNodes.forEach(function (node) {
      if (!owns(node)) return;

      Array.prototype.slice
        .call(node.attributes)
        .forEach(function (marker) {
          if (
            marker.name.indexOf(
              "data-wrn-bind-",
            ) !== 0
          ) {
            return;
          }

          var binding;

          try {
            binding = JSON.parse(
              marker.value,
            );
          } catch (error) {
            return;
          }

          if (
            !binding ||
            binding.length !== 2
          ) {
            return;
          }

          var name = binding[0];
          var template = binding[1];

          reactive(function () {
            var locals =
              decodeLoopLocals(node);

            var exact =
              /^\{([^{}]+)\}$/.exec(
                template,
              );

            var raw;

            if (exact) {
              try {
                raw = evalExpr(
                  exact[1].trim(),
                  locals,
                );
              } catch (error) {
                return;
              }
            } else {
              raw = template.replace(
                /\{([^{}]+)\}/g,
                function (
                  _,
                  expression,
                ) {
                  try {
                    var value =
                      evalExpr(
                        expression.trim(),
                        locals,
                      );

                    return value == null
                      ? ""
                      : String(value);
                  } catch (error) {
                    return "";
                  }
                },
              );
            }

            applyReactiveAttribute(
              node,
              name,
              raw,
            );
          });
        });
    });

    // {{expr}} / {expr} interpolation in text nodes
    var walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null);
    var textNode;
    while ((textNode = walker.nextNode())) {
      var template = textNode.nodeValue;
      if (template.indexOf("{") === -1) continue;
      // Text in these is data, not a template: a JSON sample sitting in a
      // textarea would otherwise be read as mustaches and eaten.
      var owner = textNode.parentNode;
      var ownerName = owner ? owner.nodeName : "";
      if (ownerName === "TEXTAREA" || ownerName === "SCRIPT" || ownerName === "STYLE") continue;
      if (!owns(textNode)) continue;
      (function (node, tpl) {
        reactive(function () {
          node.nodeValue = tpl.replace(/\{\{\s*([^}]+?)\s*\}\}|\{([^{}]+)\}/g, function (_, doubleExpr, singleExpr) {
            var expr = doubleExpr || singleExpr;
            try {
              var value = evalExpr(
                expr.trim(),
                decodeLoopLocals(
                  node.parentNode,
                ),
              );

              return value == null
                ? ""
                : String(value);
            } catch (err) { return ""; }
          });
        });
      })(textNode, template);
    }

    // Event handlers on elements, window, and document.
    var nodes = [el].concat(Array.prototype.slice.call(el.querySelectorAll("*")));
    nodes.forEach(function (node) {
      if (!owns(node)) return;
      Array.prototype.slice.call(node.attributes).forEach(function (attr) {
        if (attr.name.indexOf("data-on-") !== 0) return;

        var rawName = attr.name.slice("data-on-".length);
        var target = node;
        var evt = rawName;

        if (rawName.indexOf("window-") === 0) {
          target = window;
          evt = rawName.slice("window-".length);
        } else if (rawName.indexOf("document-") === 0) {
          target = document;
          evt = rawName.slice("document-".length);
        }

        var stmt = attr.value;
        var listener = function (event) {
          var locals =
            decodeLoopLocals(node);

          locals.event = event;
          locals.$event = event;
          locals.payload = event && Object.prototype.hasOwnProperty.call(event, "detail") ? event.detail : undefined;

          try {
            runStmt(
              stmt,
              locals,
            );
          } catch (error) {
            console.error(
              "[wrnexus] handler error in '" +
                stmt +
                "'",
              error,
            );
          }
        };

        var options =
          target === window && (evt === "scroll" || evt === "touchstart" || evt === "touchmove")
            ? { passive: true }
            : undefined;

        if (target === componentEventTarget && declaredEvents.has(evt)) {
          var directHandler = function (payload) {
            var locals = decodeLoopLocals(node);
            locals.payload = payload;
            locals.event = undefined;
            locals.$event = undefined;
            return runStmt(stmt, locals);
          };
          (outputHandlers[evt] || (outputHandlers[evt] = new Set())).add(directHandler);
          cleanupCallbacks.push(function () {
            if (outputHandlers[evt]) outputHandlers[evt].delete(directHandler);
          });
        }
        target.addEventListener(evt, listener, options);
        cleanupCallbacks.push(function () {
          target.removeEventListener(evt, listener, options);
        });
      });
    });

    // Handlers a parent wrote on a component tag, e.g. a Modal tag carrying
    // an @confirm="save()" attribute.
    // The statement belongs to the PARENT's scope but the attribute rides
    // through to the child's view root, so the child must not bind it: that
    // function only exists out here. The compiler emits these as data-wrn-out-* so the
    // two cases stay distinguishable, and this scope claims every one that
    // sits on a component it directly mounts.
    Array.prototype.slice
      .call(el.querySelectorAll("[data-wrn-events]"))
      .forEach(function (node) {
        var componentRoot =
          node.closest("[data-scope], [data-wrn-scope]");
        if (!componentRoot || componentRoot === el) return;
        // Only the scope that mounted this component owns its outputs.
        if (
          !componentRoot.parentNode ||
          !componentRoot.parentNode.closest ||
          ownerScope(componentRoot.parentNode) !== el
        ) {
          return;
        }

        var registry =
          node.__wrnexusOutputHandlers ||
          (node.__wrnexusOutputHandlers = {});

        Array.prototype.slice.call(node.attributes).forEach(function (attr) {
          if (attr.name.indexOf("data-wrn-out-") !== 0) return;

          var outName = attr.name.slice("data-wrn-out-".length);
          var outStmt = attr.value;

          var outHandler = function (payload) {
            var locals = decodeLoopLocals(componentRoot);
            locals.payload = payload;
            locals.event = undefined;
            locals.$event = undefined;
            try {
              /*__WRNEXUS_DEV_START__*/
              warnMissingBindingFunction(outStmt, function (name) { return peekScope(name); }, componentRoot);
              /*__WRNEXUS_DEV_END__*/
              return runStmt(outStmt, locals);
            } catch (error) {
              console.error(
                "[wrnexus] component output handler error in '" + outStmt + "'",
                error,
              );
            }
          };

          (registry[outName] || (registry[outName] = new Set())).add(outHandler);
          cleanupCallbacks.push(function () {
            if (registry[outName]) registry[outName].delete(outHandler);
          });

          // A component tag can also carry plain DOM events such as click. Those
          // are not declared outputs, so nothing calls the registry entry --
          // listen for the bubbling event too. Declared outputs never reach
          // here: invokeComponentOutput short-circuits once a handler exists.
          var domListener = function (event) {
            var locals = decodeLoopLocals(componentRoot);
            locals.event = event;
            locals.$event = event;
            locals.payload =
              event && Object.prototype.hasOwnProperty.call(event, "detail")
                ? event.detail
                : undefined;
            try {
              runStmt(outStmt, locals);
            } catch (error) {
              console.error(
                "[wrnexus] component handler error in '" + outStmt + "'",
                error,
              );
            }
          };
          node.addEventListener(outName, domListener);
          cleanupCallbacks.push(function () {
            node.removeEventListener(outName, domListener);
          });
        });
      });

    // Prop expressions belong to the parent that mounted the component. The
    // server forwards these markers onto the rendered child root; evaluate
    // them here and write changes into the child's prop signals.
    Array.prototype.slice
      .call(el.querySelectorAll("[data-scope], [data-wrn-scope]"))
      .forEach(function (node) {
        if (!node.parentNode || ownerScope(node.parentNode) !== el) return;
        Array.prototype.slice.call(node.attributes).forEach(function (attr) {
          if (attr.name.indexOf("data-wrn-prop-bind-") !== 0) return;
          var binding;
          try { binding = JSON.parse(attr.value); } catch (_) { return; }
          if (!binding || binding.length !== 2) return;
          var propName = binding[0];
          var template = binding[1];
          reactive(function () {
            var exact = /^\{([^{}]+)\}$/.exec(template);
            var value;
            try {
              value = exact
                ? evalExpr(exact[1].trim(), decodeLoopLocals(node))
                : template.replace(/\{([^{}]+)\}/g, function (_, expression) {
                    var part = evalExpr(expression.trim(), decodeLoopLocals(node));
                    return part == null ? "" : String(part);
                  });
            } catch (_) { return; }
            var apply = function () {
              if (node.__wrnexusScopeApi) node.__wrnexusScopeApi.set(propName, value);
            };
            if (node.__wrnexusScopeApi) apply();
            else queueMicrotask(apply);
          });
        });
      });

    // Every hydrated scope exposes state writes. Prop-only components need the
    // same API even when they have no behavior block.
    var publicScopeApi = {
        get: peekScope,
        set: writeScope,
        call: function (name) {
          var fn = behaviorFunctions[name];
          if (typeof fn !== "function") return undefined;
          return fn.apply(null, Array.prototype.slice.call(arguments, 1));
        },
    };
    el.__wrnexusScopeApi = publicScopeApi;
    el.querySelectorAll("[data-wrn-select]").forEach(function (select) {
      select.__wrnexusScopeApi = publicScopeApi;
    });

    if (behavior) {
      installBehaviorFunctions(behavior.functions);

      (behavior.effects || []).forEach(function (source) {
        if (typeof source !== "string" || !source.trim()) return;
        reactive(function () {
          try { runStmt(source); } catch (error) {
            reportDiagnostic("WRN-EFFECT-ERROR", "Reactive effect failed.", el, error);
          }
        });
      });

      (behavior.watches || []).forEach(function (watch) {
        if (!watch || typeof watch.state !== "string" || typeof watch.body !== "string") return;
        if (!stateWatchers[watch.state]) stateWatchers[watch.state] = [];
        stateWatchers[watch.state].push(function (value, previous) {
          runStmt(watch.body, { value: value, previous: previous });
        });
      });

      var updateSource =
        behavior.lifecycle && typeof behavior.lifecycle.update === "string"
          ? behavior.lifecycle.update.trim()
          : "";

      if (updateSource) {
        anyStateListeners.add(function () {
          scheduleUpdateHook(el, function () {
            if (!disposed) runStmt(updateSource);
          });
        });
      }

      var mountSource =
        behavior.lifecycle && typeof behavior.lifecycle.mount === "string"
          ? behavior.lifecycle.mount.trim()
          : "";

      var unmountSource =
        behavior.lifecycle && typeof behavior.lifecycle.unmount === "string"
          ? behavior.lifecycle.unmount.trim()
          : "";

      var instance = {
        dispose: function () {
          if (disposed) return;
          disposed = true;
          cleanupCallbacks.splice(0).reverse().forEach(function (cleanup) {
            try { cleanup(); } catch (_) { /* ignore cleanup errors */ }
          });
          pendingUpdateHooks.delete(el);
          if (unmountSource) {
            try { runStmt(unmountSource); } catch (error) {
              console.error("[wrnexus] component unmount hook failed", error);
            }
          }
          mountedBehaviorRoots.delete(el);
          behaviorInstances.delete(el);
          delete el.__wrnexusScopeApi;
          el.querySelectorAll("[data-wrn-select]").forEach(function (select) {
            delete select.__wrnexusScopeApi;
          });
          el.__wrnexusScope = false;
        },
      };

      behaviorInstances.set(el, instance);
      mountedBehaviorRoots.add(el);

      if (mountSource) {
        queueMicrotask(function () {
          if (!disposed && el.isConnected) {
            try { runStmt(mountSource); } catch (error) {
              console.error("[wrnexus] component mount hook failed", error);
            }
          }
        });
      }
    }

    renderAll();
  }

  function disposeBehaviors(root) {
    var elements = [];
    if (root && root.nodeType === 1 && root.hasAttribute("data-wrn-behavior")) {
      elements.push(root);
    }
    if (root && root.querySelectorAll) {
      Array.prototype.push.apply(elements, root.querySelectorAll("[data-wrn-behavior]"));
    }
    elements.reverse().forEach(function (element) {
      var instance = behaviorInstances.get(element);
      if (instance) instance.dispose();
    });
  }

  function ensureBehaviorObserver() {
    if (behaviorObserver || typeof MutationObserver === "undefined") return;
    behaviorObserver = new MutationObserver(function (records) {
      records.forEach(function (record) {
        Array.prototype.forEach.call(record.removedNodes, function (node) {
          if (node && node.nodeType === 1) disposeBehaviors(node);
        });
      });
    });
    behaviorObserver.observe(document.documentElement, { childList: true, subtree: true });
  }

  function queueScopeHydration(element) {
    if (!element || element.__wrnexusScope || element.__wrnexusHydrationQueued) return;
    var runtime = element.getAttribute("data-wrn-runtime") || "universal";
    var strategy = element.getAttribute("data-wrn-hydrate") || "load";
    if (runtime === "server" || strategy === "none") return;
    element.__wrnexusHydrationQueued = true;

    function hydrate() {
      if (element.__wrnexusScope || !element.isConnected) return;
      var started = performance.now ? performance.now() : Date.now();
      function complete(module) {
        if (element.__wrnexusScope || !element.isConnected) return;
        if (module) element.__wrnexusClientModule = module;
        setupScope(element);
        var ended = performance.now ? performance.now() : Date.now();
        try {
          element.dispatchEvent(new CustomEvent("wrnexus:hydrated", {
            bubbles: true,
            detail: {
              id: element.getAttribute("data-wrn-hydration") || null,
              strategy: strategy,
              durationMs: Math.max(0, ended - started),
            },
          }));
        } catch (_) {}
      }
      var moduleUrl = element.getAttribute("data-wrn-client-module");
      if (!moduleUrl || moduleUrl === "__WRNEXUS_CLIENT_MODULE__") {
        complete(null);
        return;
      }
      loadClientModule(element).then(complete);
    }

    if (strategy === "load") {
      hydrate();
      return;
    }
    if (strategy === "idle") {
      var idle = window.requestIdleCallback || function (callback) { return window.setTimeout(callback, 1); };
      idle(hydrate);
      return;
    }
    if (strategy === "visible" && typeof IntersectionObserver !== "undefined") {
      var observer = new IntersectionObserver(function (entries) {
        if (!entries.some(function (entry) { return entry.isIntersecting; })) return;
        observer.disconnect();
        hydrate();
      });
      observer.observe(element);
      return;
    }
    if (strategy === "interaction") {
      var activate = function () {
        element.removeEventListener("pointerdown", activate, true);
        element.removeEventListener("keydown", activate, true);
        element.removeEventListener("focusin", activate, true);
        hydrate();
      };
      element.addEventListener("pointerdown", activate, true);
      element.addEventListener("keydown", activate, true);
      element.addEventListener("focusin", activate, true);
      return;
    }
    if (strategy.indexOf("media:") === 0 && typeof window.matchMedia === "function") {
      var query = strategy.slice(6);
      var media = window.matchMedia(query);
      if (media.matches) hydrate();
      else {
        var onChange = function (event) {
          if (!event.matches) return;
          if (media.removeEventListener) media.removeEventListener("change", onChange);
          else media.removeListener(onChange);
          hydrate();
        };
        if (media.addEventListener) media.addEventListener("change", onChange);
        else media.addListener(onChange);
      }
      return;
    }

    reportDiagnostic(
      "WRN-HYDRATE-STRATEGY",
      "Unknown hydration strategy '" + strategy + "'. Falling back to load.",
      element,
    );
    hydrate();
  }

  /*
   * Keep anchored overlays inside the viewport.
   *
   * A popover, tooltip or menu is positioned purely in CSS, relative to its
   * trigger. That is correct until the trigger sits near an edge: the panel
   * then hangs off the side of the screen and is unreadable and unclickable.
   * Every one of these components had that problem, so the nudge lives here
   * once rather than five times.
   *
   * The offset is applied through the standalone translate property, NOT
   * transform: several placements already use transform to centre themselves
   * with translateX(-50%), and the two properties compose instead of
   * overwriting each other. Measurement always happens with the offset
   * cleared, so repositioning is idempotent -- re-running it on a panel that
   * is already on screen changes nothing and cannot drift.
   */
  /*__WRNEXUS_CONTROLLERS_PRIMARY_START__*/
  var ANCHORED_SELECTOR = "[data-wrn-anchored]";
  var ANCHOR_MARGIN = 8;
  var anchoredScheduled = false;
  // True while the clamp is writing, so its own style writes are not mistaken
  // for a change that needs repositioning. Without this the observer and the
  // clamp chase each other forever and the offset ends up cleared as often as
  // it is applied.
  var anchoredWriting = false;

  function isRenderedElement(element) {
    if (!element || !element.getBoundingClientRect) return false;
    var rect = element.getBoundingClientRect();
    return rect.width > 0 && rect.height > 0;
  }

  function clampAnchored(element) {
    // Measure the untouched position; the offset is recomputed from scratch.
    element.style.translate = "";
    var arrow = element.querySelector("[data-wrn-anchor-arrow]");
    if (arrow) arrow.style.translate = "";
    if (!isRenderedElement(element)) return;

    var rect = element.getBoundingClientRect();
    var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
    var viewportHeight = window.innerHeight || document.documentElement.clientHeight;

    /*
     * Clamp only while the overlay's own trigger is on screen.
     *
     * Judging by the PANEL alone gets both cases wrong. An overlay whose
     * trigger has scrolled away sits far outside the viewport quite
     * legitimately, and dragging it back tore it off its trigger. But a menu
     * that has only just opened can also start fully outside -- a top-placed
     * dropdown near the top of a phone screen renders above y=0 -- and that
     * one very much does need moving; skipping it left the menu invisible
     * with no way to reach it. The trigger tells the two apart.
     */
    var host = element.closest("[data-ui-component]") || element.parentElement;
    var anchor = host ? host.getBoundingClientRect() : rect;
    var anchorVisible =
      anchor.bottom > 0 &&
      anchor.top < viewportHeight &&
      anchor.right > 0 &&
      anchor.left < viewportWidth;

    if (!anchorVisible) {
      return;
    }

    var shiftX = 0;
    var shiftY = 0;

    if (rect.width < viewportWidth - ANCHOR_MARGIN * 2) {
      if (rect.left < ANCHOR_MARGIN) shiftX = ANCHOR_MARGIN - rect.left;
      else if (rect.right > viewportWidth - ANCHOR_MARGIN) {
        shiftX = viewportWidth - ANCHOR_MARGIN - rect.right;
      }
    }

    if (rect.height < viewportHeight - ANCHOR_MARGIN * 2) {
      if (rect.top < ANCHOR_MARGIN) shiftY = ANCHOR_MARGIN - rect.top;
      else if (rect.bottom > viewportHeight - ANCHOR_MARGIN) {
        shiftY = viewportHeight - ANCHOR_MARGIN - rect.bottom;
      }
    }

    if (!shiftX && !shiftY) return;

    element.style.translate = shiftX + "px " + shiftY + "px";

    /*
     * The arrow lives inside the panel, so it travels with it and stops
     * pointing at the trigger. Move it back by the same amount -- but keep it
     * inside the panel, an arrow detached from its own bubble looks worse
     * than one slightly off-centre.
     */
    if (!arrow) return;
    var arrowRect = arrow.getBoundingClientRect();
    var limitX = Math.max(0, rect.width / 2 - arrowRect.width);
    var limitY = Math.max(0, rect.height / 2 - arrowRect.height);
    var arrowX = Math.max(-limitX, Math.min(limitX, -shiftX));
    var arrowY = Math.max(-limitY, Math.min(limitY, -shiftY));
    if (arrowX || arrowY) {
      arrow.style.translate = arrowX + "px " + arrowY + "px";
    }
  }

  function repositionAnchored(root) {
    var host = root && root.querySelectorAll ? root : document;
    anchoredWriting = true;
    try {
      Array.prototype.slice
        .call(host.querySelectorAll(ANCHORED_SELECTOR))
        .forEach(clampAnchored);
    } finally {
      // Released on a timer, not requestAnimationFrame. rAF does not fire in
      // a background or non-compositing tab, and this flag gates every future
      // reposition -- releasing it from rAF would latch it on and silently
      // disable the whole feature for the life of the page.
      window.setTimeout(function () {
        anchoredWriting = false;
      }, 0);
    }
  }

  function scheduleAnchoredReposition() {
    if (anchoredWriting || anchoredScheduled) return;
    anchoredScheduled = true;
    // setTimeout rather than requestAnimationFrame for the same reason: an
    // overlay opened while the tab is in the background must still be placed
    // correctly, and rAF simply never runs there.
    window.setTimeout(function () {
      anchoredScheduled = false;
      repositionAnchored(document);
      /*
       * A second pass shortly after. The mutation that opens an overlay is
       * usually the same one that makes it visible, so on the very next frame
       * it can still measure as hidden (zero-sized) -- the clamp then skips it
       * and, with no further mutation coming, nothing would ever reposition
       * it. Re-running once the panel has actually been laid out fixes that,
       * and because the clamp recomputes from a cleared offset the repeat is
       * free of side effects.
       */
      window.setTimeout(function () {
        repositionAnchored(document);
      }, 60);
    });
  }

  /*
   * One document observer, several subscribers. The filter stays explicit:
   * observing every attribute would see the tabindex the roving code writes
   * and loop on its own output.
   */
  var documentWatchers = [];

  function watchDocument(handler) {
    documentWatchers.push(handler);
  }

  function startDocumentWatch() {
    if (window.__wrnexusDocWatchBound || typeof MutationObserver !== "function") return;
    window.__wrnexusDocWatchBound = true;
    new MutationObserver(function () {
      for (var index = 0; index < documentWatchers.length; index += 1) documentWatchers[index]();
    }).observe(document.documentElement, {
      subtree: true,
      childList: true,
      attributes: true,
      // prettier-ignore
      attributeFilter: ["data-open","data-show","class","style","hidden",
        "data-placement","aria-selected","aria-current","disabled","aria-disabled"],
    });
  }

  function setupAnchoredOverlays() {
    if (window.__wrnexusAnchoredBound) return;
    window.__wrnexusAnchoredBound = true;

    // Opening is expressed differently by each component (data-open on the
    // root, data-show on the panel, a class), so watch for any attribute or
    // structural change and re-measure on the next frame instead of trying to
    // enumerate every signal.
    watchDocument(scheduleAnchoredReposition);

    window.addEventListener("resize", scheduleAnchoredReposition);
    window.addEventListener("scroll", scheduleAnchoredReposition, true);
  }

  /*
   * Modal dialog focus, focus restore, Tab trap and scroll lock. Shared by
   * Modal and Drawer, and here rather than in them because a client function
   * cannot hold the previously focused element across a close.
   *
   * Fixing focus also repairs Escape: both bind @keydown on their own root,
   * so until focus moved inside, closeOnEscape did nothing.
   */
  var DIALOG_SELECTOR = '[role="dialog"][aria-modal="true"]';
  var FOCUSABLE_SELECTOR =
    "a[href], button:not([disabled]), input:not([disabled]), select:not([disabled])," +
    ' textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
  var openDialogs = [];
  var dialogRestoreFocus = null;
  var dialogScrollLock = null;

  // data-show, not measured size: the test DOM reports everything as
  // zero-sized, which is what left the trap uncovered.
  function isDialogVisible(dialog) {
    if (!dialog || !dialog.isConnected) return false;
    if (dialog.hasAttribute("hidden")) return false;
    if (dialog.closest('[data-show="false"]')) return false;
    /*
     * data-open is the signal Modal and Drawer actually publish, and it is the
     * only one Drawer can publish: its panel animates open, so it cannot be
     * toggled with data-show, which sets display:none. Treating every dialog
     * without a data-show="false" ancestor as open meant a closed Drawer held
     * the body scroll lock forever and the page could not be scrolled.
     */
    var owner = dialog.closest("[data-open]");
    if (owner) return owner.getAttribute("data-open") === "true";
    return true;
  }

  function focusableWithin(dialog) {
    var found = [];
    var candidates = dialog.querySelectorAll(FOCUSABLE_SELECTOR);
    for (var index = 0; index < candidates.length; index += 1) {
      var candidate = candidates[index];
      // Markers, not measurement.
      if (candidate.hasAttribute("hidden")) continue;
      if (candidate.closest('[data-show="false"]')) continue;
      found.push(candidate);
    }
    return found;
  }

  function lockDialogScroll() {
    if (dialogScrollLock) return;
    var body = document.body;
    if (!body) return;
    dialogScrollLock = { overflow: body.style.overflow };
    body.style.overflow = "hidden";
  }

  function unlockDialogScroll() {
    if (!dialogScrollLock || !document.body) return;
    document.body.style.overflow = dialogScrollLock.overflow;
    dialogScrollLock = null;
  }

  function onDialogOpened(dialog) {
    // Only the first dialog records the restore target; a dialog opened from
    // inside another must not overwrite the page element we came from.
    if (!openDialogs.length) {
      var active = document.activeElement;
      dialogRestoreFocus = active && active !== document.body ? active : null;
      lockDialogScroll();
    }
    openDialogs.push(dialog);

    // Prefer a real control; the panel carries tabindex="-1" as a fallback.
    var targets = focusableWithin(dialog);
    var target = targets.length ? targets[0] : dialog;
    if (target && target.focus) target.focus();
  }

  function onDialogClosed(dialog) {
    var at = openDialogs.indexOf(dialog);
    if (at !== -1) openDialogs.splice(at, 1);
    if (openDialogs.length) return;
    unlockDialogScroll();
    if (dialogRestoreFocus && dialogRestoreFocus.focus && dialogRestoreFocus.isConnected) {
      dialogRestoreFocus.focus();
    }
    dialogRestoreFocus = null;
  }

  function syncDialogs() {
    var dialogs = document.querySelectorAll(DIALOG_SELECTOR);
    for (var index = 0; index < dialogs.length; index += 1) {
      var dialog = dialogs[index];
      var visible = isDialogVisible(dialog);
      var tracked = openDialogs.indexOf(dialog) !== -1;
      if (visible && !tracked) onDialogOpened(dialog);
      else if (!visible && tracked) onDialogClosed(dialog);
    }
    // A dialog can be removed from the document outright rather than hidden.
    for (var open = openDialogs.length - 1; open >= 0; open -= 1) {
      if (!openDialogs[open].isConnected) onDialogClosed(openDialogs[open]);
    }
  }

  function trapDialogTab(event) {
    if (event.key !== "Tab" || !openDialogs.length) return;
    var dialog = openDialogs[openDialogs.length - 1];
    var targets = focusableWithin(dialog);
    if (!targets.length) {
      // Nothing to cycle; keep focus on the panel rather than the page behind.
      event.preventDefault();
      if (dialog.focus) dialog.focus();
      return;
    }
    var first = targets[0];
    var last = targets[targets.length - 1];
    var active = document.activeElement;
    if (event.shiftKey && (active === first || !dialog.contains(active))) {
      event.preventDefault();
      last.focus();
    } else if (!event.shiftKey && active === last) {
      event.preventDefault();
      first.focus();
    }
  }

  function setupModalDialogs() {
    if (window.__wrnexusDialogsBound) return;
    window.__wrnexusDialogsBound = true;

    // Deferred: the mutation that opens a dialog is the one that makes it
    // visible, so it is not laid out yet when the record arrives.
    watchDocument(function () {
      window.setTimeout(syncDialogs, 0);
    });

    document.addEventListener("keydown", trapDialogTab, true);
    syncDialogs();
  }

  /*
   * Roving arrow-key focus. A container marked data-wrn-roving owns its
   * [data-wrn-roving-item] descendants: one carries tabindex="0" so Tab
   * reaches the group once, and the arrows move within it. Here rather than
   * in five components because focus bookkeeping cannot live in component
   * state.
   */
  var ROVING_SELECTOR = "[data-wrn-roving]";
  var ROVING_ITEM_SELECTOR = "[data-wrn-roving-item]";

  // Templates stringify these: "" and "false" mean opted out, and a bare
  // [attr] selector matches either, so the value must be checked.
  // Bare means yes; only an explicit "false" opts out.
  function rovingItemOff(value) {
    return value === null || value === "false";
  }

  // The container must name an axis; empty is what {cond ? "x" : ""} emits.
  function rovingOrientation(container) {
    var value = container.getAttribute("data-wrn-roving");
    if (value === null || value === "" || value === "false") return "";
    return value;
  }

  function rovingItems(container) {
    var found = [];
    var candidates = container.querySelectorAll(ROVING_ITEM_SELECTOR);
    for (var index = 0; index < candidates.length; index += 1) {
      var candidate = candidates[index];
      if (rovingItemOff(candidate.getAttribute("data-wrn-roving-item"))) continue;
      // A nested group owns its own items; do not steal them.
      if (candidate.closest(ROVING_SELECTOR) !== container) continue;
      if (candidate.hasAttribute("disabled")) continue;
      if (candidate.getAttribute("aria-disabled") === "true") continue;
      // Markers, not measurement (see isDialogVisible).
      if (candidate.hasAttribute("hidden")) continue;
      if (candidate.closest('[data-show="false"]')) continue;
      found.push(candidate);
    }
    return found;
  }

  function rovingActiveIndex(items) {
    for (var index = 0; index < items.length; index += 1) {
      var item = items[index];
      if (item.getAttribute("aria-selected") === "true") return index;
      var current = item.getAttribute("aria-current");
      if (current === "page" || current === "step" || current === "true") return index;
    }
    return 0;
  }

  function applyRovingTabindex(items, activeIndex) {
    for (var index = 0; index < items.length; index += 1) {
      items[index].setAttribute("tabindex", index === activeIndex ? "0" : "-1");
    }
  }

  function syncRovingGroup(container) {
    if (!rovingOrientation(container)) return;
    var items = rovingItems(container);
    if (!items.length) return;
    applyRovingTabindex(items, rovingActiveIndex(items));
  }

  function syncRovingGroups() {
    var groups = document.querySelectorAll(ROVING_SELECTOR);
    for (var index = 0; index < groups.length; index += 1) syncRovingGroup(groups[index]);
  }

  function handleRovingKeydown(event) {
    var target = event.target;
    if (!target || !target.closest) return;
    var item = target.closest(ROVING_ITEM_SELECTOR);
    if (!item) return;
    var container = item.closest(ROVING_SELECTOR);
    if (!container) return;

    var items = rovingItems(container);
    var index = items.indexOf(item);
    if (index === -1) return;

    var orientation = rovingOrientation(container);
    if (!orientation) return;
    var horizontal = orientation === "horizontal" || orientation === "both";
    var vertical = orientation === "vertical" || orientation === "both";
    var key = event.key;
    var next = -1;

    if ((horizontal && key === "ArrowRight") || (vertical && key === "ArrowDown")) {
      next = (index + 1) % items.length;
    } else if ((horizontal && key === "ArrowLeft") || (vertical && key === "ArrowUp")) {
      next = (index - 1 + items.length) % items.length;
    } else if (key === "Home") {
      next = 0;
    } else if (key === "End") {
      next = items.length - 1;
    } else {
      return;
    }

    event.preventDefault();
    applyRovingTabindex(items, next);
    if (items[next].focus) items[next].focus();
  }

  function setupRovingFocus() {
    if (window.__wrnexusRovingBound) return;
    window.__wrnexusRovingBound = true;

    document.addEventListener("keydown", handleRovingKeydown, true);

    watchDocument(function () {
      window.setTimeout(syncRovingGroups, 0);
    });

    syncRovingGroups();
  }

  // Scrollspy. The marker goes onto the links, not into state: an observer
  // callback fires after the client function returned, so that write is lost.
  function applyScrollspyCurrent(nav, href) {
    var links = nav.querySelectorAll('a[href^="#"]');
    var changed = false;
    var label = "";
    for (var index = 0; index < links.length; index += 1) {
      var link = links[index];
      var current = link.getAttribute("href") === href;
      if (current) label = (link.textContent || "").trim();
      if ((link.getAttribute("data-active") === "true") !== current) changed = true;
      link.setAttribute("data-active", current ? "true" : "false");
      link.setAttribute("aria-current", current ? "location" : "false");
    }
    if (!changed) return;
    // Named for the component output so a parent @change binding receives it.
    nav.dispatchEvent(new CustomEvent("change", { detail: { href: href, label: label } }));
  }

  function wireScrollspy(nav) {
    if (nav.__wrnScrollspyWired) return;
    nav.__wrnScrollspyWired = true;

    nav.addEventListener("click", function (event) {
      var t = event.target;
      var link = t && t.closest ? t.closest('a[href^="#"]') : null;
      if (link && nav.contains(link)) applyScrollspyCurrent(nav, link.getAttribute("href"));
    });

    if (typeof IntersectionObserver === "undefined") return;

    var links = nav.querySelectorAll('a[href^="#"]');
    var targets = [];
    for (var index = 0; index < links.length; index += 1) {
      var href = links[index].getAttribute("href");
      var section = document.getElementById(href.slice(1));
      if (section) targets.push({ section: section, href: href });
    }
    if (!targets.length) return;

    var visible = {};
    var observer = new IntersectionObserver(
      function (entries) {
        for (var entryIndex = 0; entryIndex < entries.length; entryIndex += 1) {
          visible[entries[entryIndex].target.id] = entries[entryIndex].isIntersecting;
        }
        // First visible section in document order wins, so up and down
        // settle on the same link.
        for (var pick = 0; pick < targets.length; pick += 1) {
          if (visible[targets[pick].section.id]) {
            applyScrollspyCurrent(nav, targets[pick].href);
            return;
          }
        }
      },
      // Biased to the upper third: the current section is the one being read.
      { rootMargin: "-80px 0px -55% 0px" },
    );
    for (var watch = 0; watch < targets.length; watch += 1) observer.observe(targets[watch].section);
  }

  function setupScrollspy() {
    if (window.__wrnexusScrollspyBound) return;
    window.__wrnexusScrollspyBound = true;
    var wireAll = function () {
      var navs = document.querySelectorAll("[data-wrn-scrollspy]");
      for (var index = 0; index < navs.length; index += 1) wireScrollspy(navs[index]);
    };
    wireAll();
    watchDocument(function () {
      window.setTimeout(wireAll, 0);
    });
  }

  /*
   * Resizable split panes.
   *
   * The resolved size is written onto the container as a --wrn-split custom
   * property and the component styles from it. Pointer moves fire far too
   * often to route through a client function, and a state write made inside a
   * pointermove callback is dropped, so the DOM holds the answer.
   */
  var SPLITTER_SELECTOR = "[data-wrn-splitter]";

  function splitterNumber(element, name, fallback) {
    var raw = Number(element.getAttribute(name));
    return isFinite(raw) && raw !== 0 ? raw : fallback;
  }

  function splitterBounds(root) {
    var min = splitterNumber(root, "data-wrn-splitter-min", 10);
    return { min: min, max: 100 - min };
  }

  function applySplit(root, handle, size) {
    var bounds = splitterBounds(root);
    var next = Math.min(bounds.max, Math.max(bounds.min, size));
    next = Math.round(next * 100) / 100;
    root.style.setProperty("--wrn-split", next + "%");
    if (handle) {
      handle.setAttribute("aria-valuenow", String(next));
      handle.setAttribute("aria-valuemin", String(bounds.min));
      handle.setAttribute("aria-valuemax", String(bounds.max));
    }
    /*
     * Deliberately not named "resize". That collides with the native event, and
     * the component output binding never ran for it. The component listens for
     * this and re-emits its own declared output.
     */
    root.dispatchEvent(
      new CustomEvent("wrnexus:splitter:resize", { detail: { size: next } }),
    );
    return next;
  }

  function currentSplit(root, handle) {
    var fromHandle = Number(handle && handle.getAttribute("aria-valuenow"));
    if (isFinite(fromHandle) && fromHandle) return fromHandle;
    var raw = String(root.style.getPropertyValue("--wrn-split") || "").replace("%", "");
    var parsed = Number(raw);
    return isFinite(parsed) && parsed ? parsed : 50;
  }

  function handleSplitterKeydown(event) {
    var target = event.target;
    if (!target || !target.closest) return;
    var handle = target.closest("[data-wrn-splitter-handle]");
    if (!handle) return;
    var root = handle.closest(SPLITTER_SELECTOR);
    if (!root) return;

    var vertical = root.getAttribute("data-wrn-splitter") === "vertical";
    var step = splitterNumber(root, "data-wrn-splitter-step", 5);
    var bounds = splitterBounds(root);
    var size = currentSplit(root, handle);
    var key = event.key;
    var next = size;

    if (key === (vertical ? "ArrowDown" : "ArrowRight")) next = size + step;
    else if (key === (vertical ? "ArrowUp" : "ArrowLeft")) next = size - step;
    else if (key === "Home") next = bounds.min;
    else if (key === "End") next = bounds.max;
    else return;

    event.preventDefault();
    applySplit(root, handle, next);
  }

  function setupSplitters() {
    if (window.__wrnexusSplitterBound) return;
    window.__wrnexusSplitterBound = true;

    document.addEventListener("keydown", handleSplitterKeydown, true);

    var dragging = null;

    document.addEventListener("pointerdown", function (event) {
      var target = event.target;
      var handle = target && target.closest ? target.closest("[data-wrn-splitter-handle]") : null;
      if (!handle) return;
      var root = handle.closest(SPLITTER_SELECTOR);
      if (!root) return;
      dragging = { root: root, handle: handle };
      root.setAttribute("data-wrn-splitter-dragging", "true");
      if (handle.setPointerCapture && event.pointerId !== undefined) {
        handle.setPointerCapture(event.pointerId);
      }
      event.preventDefault();
    });

    document.addEventListener("pointermove", function (event) {
      if (!dragging) return;
      var rect = dragging.root.getBoundingClientRect();
      var vertical = dragging.root.getAttribute("data-wrn-splitter") === "vertical";
      var span = vertical ? rect.height : rect.width;
      if (!span) return;
      var offset = vertical ? event.clientY - rect.top : event.clientX - rect.left;
      applySplit(dragging.root, dragging.handle, (offset / span) * 100);
    });

    var endDrag = function () {
      if (!dragging) return;
      dragging.root.removeAttribute("data-wrn-splitter-dragging");
      dragging = null;
    };
    document.addEventListener("pointerup", endDrag);
    document.addEventListener("pointercancel", endDrag);
  }

  /*__WRNEXUS_CONTROLLERS_PRIMARY_END__*/

  function hydrateScopes(root) {
    var host = root || document;

    var scopeSelector =
      "[data-scope], [data-wrn-scope]";

    if (
      host.nodeType === 1 &&
      host.matches &&
      host.matches(scopeSelector)
    ) {
      queueScopeHydration(host);
    }

    if (host.querySelectorAll) {
      host
        .querySelectorAll(scopeSelector)
        .forEach(queueScopeHydration);
    }

    ensureBehaviorObserver();
    hydrateNavbarControllers(host);
    hydratePreferenceControllers(host);
    hydrateSelectControllers(host);
    hydratePinInputControllers(host);
    /*__WRNEXUS_DEV_START__*/
    warnMissingThemeTokens();
    /*__WRNEXUS_DEV_END__*/
  }

  /*__WRNEXUS_CONTROLLERS_UI_START__*/
  var navbarOutsideClickBound = false;
  var preferenceOutsideClickBound = false;

  function hydratePreferenceControllers(root) {
    var host = root || document;
    var switchers = [];
    if (host.nodeType === 1 && host.matches && host.matches("[data-wrn-preferences]")) {
      switchers.push(host);
    }
    if (host.querySelectorAll) {
      Array.prototype.push.apply(
        switchers,
        host.querySelectorAll("[data-wrn-preferences]"),
      );
    }
    switchers.forEach(function (switcher) {
      if (switcher.dataset.wrnPreferencesBound === "true") return;
      switcher.dataset.wrnPreferencesBound = "true";
      switcher.addEventListener("toggle", function (event) {
        var opened = event.target;
        if (!opened || opened.tagName !== "DETAILS" || !opened.open) return;
        switcher.querySelectorAll(".wire-preferences__menu[open]").forEach(function (menu) {
          if (menu !== opened) menu.removeAttribute("open");
        });
      }, true);
    });
    if (!preferenceOutsideClickBound) {
      preferenceOutsideClickBound = true;
      document.addEventListener("pointerdown", function (event) {
        document.querySelectorAll("[data-wrn-preferences]").forEach(function (switcher) {
          if (switcher.contains(event.target)) return;
          switcher.querySelectorAll(".wire-preferences__menu[open]").forEach(function (menu) {
            menu.removeAttribute("open");
          });
        });
      });
      document.addEventListener("keydown", function (event) {
        if (event.key !== "Escape") return;
        document.querySelectorAll("[data-wrn-preferences] .wire-preferences__menu[open]").forEach(function (menu) {
          menu.removeAttribute("open");
          var summary = menu.querySelector(":scope > summary");
          if (summary) summary.focus();
        });
      });
    }
  }

  function hydrateNavbarControllers(root) {
    var host = root || document;
    var navbars = [];
    if (host.nodeType === 1 && host.matches && host.matches("[data-wrn-navbar]")) {
      navbars.push(host);
    }
    if (host.querySelectorAll) {
      Array.prototype.push.apply(
        navbars,
        host.querySelectorAll("[data-wrn-navbar]"),
      );
    }

    navbars.forEach(function (navbar) {
      var current = window.location.pathname.replace(/\/+$/, "") || "/";
      var best = null;
      var bestLength = -1;
      navbar.querySelectorAll(".wire-navbar__menus a[href]").forEach(function (link) {
        var url;
        try { url = new URL(link.getAttribute("href"), window.location.origin); } catch (_) { return; }
        if (url.origin !== window.location.origin) return;
        var path = url.pathname.replace(/\/+$/, "") || "/";
        var matches = path === current || (path !== "/" && current.indexOf(path + "/") === 0);
        if (!matches || path.length <= bestLength) return;
        best = link;
        bestLength = path.length;
      });
      navbar.querySelectorAll(".wire-navbar__menus [aria-current='page']").forEach(function (item) {
        item.removeAttribute("aria-current");
      });
      if (best) {
        best.setAttribute("aria-current", "page");
        var parentMenu = best.closest(".wire-navbar__dropdown");
        var parentSummary = parentMenu && parentMenu.querySelector(":scope > summary");
        if (parentSummary) parentSummary.setAttribute("aria-current", "page");
      }

      if (navbar.dataset.wrnNavbarBound === "true") return;
      navbar.dataset.wrnNavbarBound = "true";
      var hoverEnabled = navbar.getAttribute("data-open-on-hover") === "true";
      var hoverCapable =
        typeof window.matchMedia !== "function" ||
        window.matchMedia("(hover: hover) and (pointer: fine)").matches;
      if (hoverEnabled && hoverCapable) {
        navbar.querySelectorAll(".wire-navbar__dropdown").forEach(function (menu) {
          menu.addEventListener("pointerenter", function () {
            if (menu.__wrnNavbarCloseTimer) {
              clearTimeout(menu.__wrnNavbarCloseTimer);
              menu.__wrnNavbarCloseTimer = null;
            }
            navbar.querySelectorAll(".wire-navbar__dropdown[open]").forEach(function (candidate) {
              if (candidate !== menu) candidate.removeAttribute("open");
            });
            menu.setAttribute("open", "");
          });
          menu.addEventListener("pointerleave", function () {
            if (menu.__wrnNavbarCloseTimer) clearTimeout(menu.__wrnNavbarCloseTimer);
            menu.__wrnNavbarCloseTimer = setTimeout(function () {
              menu.removeAttribute("open");
              menu.__wrnNavbarCloseTimer = null;
            }, 240);
          });
        });
      }
      navbar.addEventListener("toggle", function (event) {
        var opened = event.target;
        if (!opened || opened.tagName !== "DETAILS" || !opened.open) return;
        navbar.querySelectorAll(".wire-navbar__dropdown[open]").forEach(function (menu) {
          if (menu !== opened) menu.removeAttribute("open");
        });
      }, true);
    });

    if (!navbarOutsideClickBound) {
      navbarOutsideClickBound = true;
      document.addEventListener("pointerdown", function (event) {
        document.querySelectorAll("[data-wrn-navbar]").forEach(function (navbar) {
          if (navbar.contains(event.target)) return;
          navbar.querySelectorAll(".wire-navbar__dropdown[open]").forEach(function (menu) {
            menu.removeAttribute("open");
          });
        });
      });
      document.addEventListener("keydown", function (event) {
        if (event.key !== "Escape") return;
        document.querySelectorAll("[data-wrn-navbar] .wire-navbar__dropdown[open]").forEach(function (menu) {
          menu.removeAttribute("open");
          var summary = menu.querySelector(":scope > summary");
          if (summary) summary.focus();
        });
      });
    }
  }

  var selectOutsideClickBound = false;

  function selectScopeApi(root) {
    var scope = root;
    while (scope) {
      if (scope.__wrnexusScopeApi) return scope.__wrnexusScopeApi;
      scope = scope.parentElement;
    }
    return null;
  }

  function selectPayloadOptions(payload) {
    if (Array.isArray(payload)) return payload;
    if (!payload || typeof payload !== "object") return [];
    if (Array.isArray(payload.options)) return payload.options;
    if (Array.isArray(payload.items)) return payload.items;
    if (Array.isArray(payload.results)) return payload.results;
    if (Array.isArray(payload.data)) return payload.data;
    return [];
  }

  function syncComboboxInput(root) {
    if (!root || !root.hasAttribute("data-wrn-combobox")) return;
    var input = root.querySelector(".wire-next__combobox-input");
    var api = selectScopeApi(root);
    if (!input || !api) return;
    var value = api.call("inputText") || "";
    input.value = String(value);
    input.setAttribute("value", String(value));
  }

  function selectEventDetail(root, extra) {
    var api = selectScopeApi(root);
    var multiple = !!(api && api.get("multiple"));
    var detail = {
      component: root.hasAttribute("data-wrn-combobox") ? "ComboBox" : "AdvancedSelect",
      query: api ? (api.get("query") || "") : "",
      value: api ? (api.get("selectedValue") || "") : "",
      values: api && Array.isArray(api.get("selectedValues")) ? api.get("selectedValues") : [],
      multiple: multiple,
      selectedOptions: api ? (api.call("selectedOptions") || []) : [],
    };
    if (extra && typeof extra === "object") {
      Object.keys(extra).forEach(function (key) { detail[key] = extra[key]; });
    }
    return detail;
  }

  function emitSelectEvent(root, name, extra) {
    try {
      dispatchComponentEvent(root, name, selectEventDetail(root, extra));
    } catch (_) {
      // CustomEvent can be unavailable in minimal DOM environments.
    }
  }

  function renderRemoteSelectOptions(root, options) {
    var list = root.querySelector(".wire-next__select-list");
    if (!list) return;

    list.querySelectorAll(".wire-next__option-group, .wire-next__select-option, .wire-next__select-message")
      .forEach(function (node) { node.remove(); });

    options.forEach(function (option) {
      if (!option || option.value == null) return;
      var button = document.createElement("button");
      button.type = "button";
      button.className = "wire-next__select-option";
      button.setAttribute("role", "option");
      button.setAttribute("data-option-value", String(option.value));
      button.disabled = !!option.disabled;

      if (option.icon) {
        var icon = document.createElement("i");
        icon.className = String(option.icon);
        icon.setAttribute("aria-hidden", "true");
        button.appendChild(icon);
      } else if (option.avatar) {
        var avatar = document.createElement("img");
        avatar.src = String(option.avatar);
        avatar.alt = "";
        button.appendChild(avatar);
      } else if (option.color) {
        var dot = document.createElement("i");
        dot.className = "wire-next__color-dot";
        dot.style.setProperty("--option-color", String(option.color));
        button.appendChild(dot);
      }

      var copy = document.createElement("span");
      var label = document.createElement("strong");
      label.textContent = String(option.label == null ? option.value : option.label);
      copy.appendChild(label);
      if (option.description) {
        var description = document.createElement("small");
        description.textContent = String(option.description);
        copy.appendChild(description);
      }
      button.appendChild(copy);

      var check = document.createElement("i");
      check.className = "wire-next__check icon-[lucide--check]";
      check.setAttribute("aria-hidden", "true");
      check.style.display = "none";
      button.appendChild(check);

      button.addEventListener("click", function () {
        var api = selectScopeApi(root);
        if (!api || button.disabled) return;
        api.call("chooseOption", option);
        window.setTimeout(function () {
          var selected = api.call("isSelected", option);
          button.classList.toggle("wire-next__select-option--selected", !!selected);
          button.setAttribute("aria-selected", selected ? "true" : "false");
          check.style.display = selected ? "" : "none";
          syncComboboxInput(root);
        }, 0);
      });
      list.appendChild(button);
    });
  }

  function setupSelectController(root) {
    if (!root || root.__wrnexusSelectController) return;
    root.__wrnexusSelectController = { attempts: 0 };

    var remote = root.getAttribute("data-remote") === "true";
    var remoteUrl = root.getAttribute("data-remote-url") || "";
    var input = root.querySelector(".wire-next__select-search input, .wire-next__combobox-input");
    var list = root.querySelector(".wire-next__select-list");
    var loadMore = root.querySelector("[data-wrn-select-load-more]");
    var timer = 0;
    var requestId = 0;
    var loadedOptions = [];
    var retainedSelections = [];
    var currentPage = Number(root.getAttribute("data-page") || 1);

    function setLoading(loading) {
      root.setAttribute("data-loading", loading ? "true" : "false");
      if (list) list.setAttribute("aria-busy", loading ? "true" : "false");
      var api = selectScopeApi(root);
      if (api) api.set("loading", loading);
    }

    function load(append, allowEmptyQuery) {
      root.__wrnexusSelectController.attempts++;
      if (!remote || !remoteUrl) return;
      var api = selectScopeApi(root);
      if (!api) return;
      var query = input ? input.value : "";
      var minimum = Number(api.get("minSearchLength") || 0);
      if (!allowEmptyQuery && query.length < minimum) return;

      var url;
      try {
        url = new URL(remoteUrl, window.location.href);
      } catch (_) {
        return;
      }
      var parameter = root.getAttribute("data-remote-query-param") || "q";
      if (query) url.searchParams.set(parameter, query);
      var nextPage = append ? currentPage + 1 : 1;
      url.searchParams.set("page", String(nextPage));

      var thisRequest = ++requestId;
      setLoading(true);
      fetch(url.toString(), { headers: { accept: "application/json" } })
        .then(function (response) {
          if (!response.ok) throw new Error("HTTP " + response.status);
          return response.json();
        })
        .then(function (payload) {
          if (thisRequest !== requestId) return;
          var nextOptions = selectPayloadOptions(payload);
          loadedOptions = append ? loadedOptions.concat(nextOptions) : nextOptions;
          currentPage = nextPage;
          var selectedValues = api.get("selectedValues");
          var selectedValue = api.get("selectedValue");
          var selectedKeys = api.get("multiple")
            ? (Array.isArray(selectedValues) ? selectedValues : [])
            : (selectedValue ? [selectedValue] : []);
          var previousOptions = api.call("allOptions") || [];
          retainedSelections = retainedSelections
            .concat(previousOptions)
            .concat(loadedOptions)
            .filter(function (option, index, list) {
              return option && selectedKeys.includes(option.value) &&
                list.findIndex(function (item) { return item && item.value === option.value; }) === index;
            });
          var stateOptions = retainedSelections.concat(loadedOptions).filter(function (option, index, list) {
            return option && list.findIndex(function (item) { return item && item.value === option.value; }) === index;
          });
          api.set("options", stateOptions);
          api.set("groups", []);
          api.set("page", currentPage);
          api.set("hasMore", !!(payload && (payload.hasMore || payload.nextPage || payload.next)));
          renderRemoteSelectOptions(root, loadedOptions);
          emitSelectEvent(root, "load", {
            options: nextOptions,
            page: currentPage,
            hasMore: !!(payload && (payload.hasMore || payload.nextPage || payload.next)),
            append: !!append,
            url: url.toString(),
            payload: payload,
          });
        })
        .catch(function (error) {
          console.error("[wrnexus] advanced select remote request failed", error);
          emitSelectEvent(root, "error", {
            error: error,
            message: error && error.message ? error.message : String(error),
            url: url.toString(),
          });
        })
        .then(function () {
          if (thisRequest === requestId) setLoading(false);
        });
    }

    if (input) {
      input.addEventListener("input", function () {
        emitSelectEvent(root, "search", { query: input.value });
        if (!remote) return;
        window.clearTimeout(timer);
        var debounce = Number(root.getAttribute("data-remote-debounce") || 250);
        timer = window.setTimeout(function () { load(false); }, debounce);
      });
    }

    if (loadMore) {
      loadMore.addEventListener("click", function () { load(true); });
    }

    if (list && root.getAttribute("data-infinite") === "true") {
      list.addEventListener("scroll", function () {
        if (list.scrollTop + list.clientHeight < list.scrollHeight - 24) return;
        var api = selectScopeApi(root);
        if (api && api.get("hasMore") && root.getAttribute("data-loading") !== "true") load(true);
      });
    }

    root.addEventListener("click", function (event) {
      if (!remote || !remoteUrl) return;
      if (!event.target.closest(".wire-next__select-trigger")) return;
      if (loadedOptions.length === 0) load(false);
    });
    root.__wrnexusSelectController.load = load;

    var dropdown = root.querySelector(".wire-next__select-dropdown");
    var lastOpen = !!(selectScopeApi(root) && selectScopeApi(root).get("open"));
    function emitOpenStateIfChanged() {
      var api = selectScopeApi(root);
      var nextOpen = !!(api && api.get("open"));
      if (nextOpen === lastOpen) return;
      lastOpen = nextOpen;
      emitSelectEvent(root, nextOpen ? "open" : "close");
    }
    var ObserverConstructor =
      root.ownerDocument &&
      root.ownerDocument.defaultView &&
      root.ownerDocument.defaultView.MutationObserver
        ? root.ownerDocument.defaultView.MutationObserver
        : (typeof MutationObserver !== "undefined" ? MutationObserver : null);
    if (ObserverConstructor) {
      new ObserverConstructor(function () {
        emitOpenStateIfChanged();
      }).observe(dropdown || root, {
        attributes: true,
        attributeFilter: dropdown ? ["data-show", "style"] : ["class"],
      });
    }

    root.addEventListener("click", function (event) {
      var optionButton = event.target.closest(".wire-next__select-option");
      if (optionButton) {
        window.setTimeout(function () {
          var api = selectScopeApi(root);
          var optionValue = optionButton.getAttribute("data-option-value");
          var options = api ? (api.call("allOptions") || []) : [];
          var option = options.find(function (item) {
            return item && String(item.value) === String(optionValue);
          });
          emitSelectEvent(root, "select", { option: option || null });
          emitSelectEvent(root, "change", { option: option || null, reason: "select" });
          emitOpenStateIfChanged();
        }, 0);
      }
      if (event.target.closest(".wire-next__clear-select")) {
        window.setTimeout(function () {
          emitSelectEvent(root, "clear");
          emitSelectEvent(root, "change", { reason: "clear" });
        }, 0);
      }
    }, true);
    root.addEventListener("keydown", function (event) {
      if (event.key !== "Enter") return;
      var before = selectEventDetail(root);
      window.setTimeout(function () {
        var after = selectEventDetail(root);
        var beforeSelection = before.multiple ? JSON.stringify(before.values) : before.value;
        var afterSelection = after.multiple ? JSON.stringify(after.values) : after.value;
        if (afterSelection === beforeSelection) return;
        syncComboboxInput(root);
        emitSelectEvent(root, "select", { source: "keyboard" });
        emitSelectEvent(root, "change", { reason: "select", source: "keyboard" });
        emitOpenStateIfChanged();
      }, 0);
    }, true);

    if (root.hasAttribute("data-wrn-combobox")) {
      root.wrnexusCombobox = {
        open: function () {
          var api = selectScopeApi(root);
          if (api) api.call("openDropdown");
          emitOpenStateIfChanged();
        },
        close: function () {
          var api = selectScopeApi(root);
          if (api) api.call("closeDropdown");
          emitOpenStateIfChanged();
        },
        clear: function () {
          var api = selectScopeApi(root);
          if (api) api.call("clearValue");
          syncComboboxInput(root);
          emitSelectEvent(root, "clear", { source: "method" });
          emitSelectEvent(root, "change", { reason: "clear", source: "method" });
        },
        setValue: function (value) {
          var api = selectScopeApi(root);
          if (api) api.call("setValue", value);
          syncComboboxInput(root);
          emitSelectEvent(root, "change", { reason: "setValue", source: "method" });
        },
        reload: function () {
          load(false, true);
        },
      };
      root.addEventListener("click", function (event) {
        if (!event.target.closest(".wire-next__select-option, .wire-next__clear-select")) return;
        window.setTimeout(function () { syncComboboxInput(root); }, 0);
      });
      if (input) {
        input.addEventListener("keydown", function (event) {
          if (event.key === "Enter") {
            window.setTimeout(function () { syncComboboxInput(root); }, 0);
          }
        });
      }
    }

    if (remote && remoteUrl && root.getAttribute("data-remote-auto-load") !== "false") {
      load(false, true);
    }
  }

  function hydrateSelectControllers(root) {
    var host = root || document;
    var selects = [];
    if (host.nodeType === 1 && host.matches && host.matches("[data-wrn-select]")) selects.push(host);
    if (host.querySelectorAll) {
      Array.prototype.push.apply(selects, host.querySelectorAll("[data-wrn-select]"));
    }
    selects.forEach(setupSelectController);

    if (!selectOutsideClickBound) {
      selectOutsideClickBound = true;
      document.addEventListener("pointerdown", function (event) {
        document.querySelectorAll("[data-wrn-select].wire-next--open").forEach(function (select) {
          if (select.contains(event.target)) return;
          var api = selectScopeApi(select);
          if (api) api.set("open", false);
        });
      });
    }
  }

  /*__WRNEXUS_CONTROLLERS_UI_END__*/

  function invokeComponentOutput(root, name, payload) {
    if (!root || !name) return undefined;
    var registry = root.__wrnexusOutputHandlers;
    var handlers = registry && registry[name];
    /*
     * A parent writes @sizeChange, but HTML lowercases attribute names, so the
     * handler is registered under "sizechange" while the component emits
     * "sizeChange". Without this the lookup misses, the call falls through to
     * dispatchComponentEvent, and the binding is never invoked -- silently.
     * Every camelCase output in the library was undeliverable because of it.
     */
    if ((!handlers || !handlers.size) && registry) {
      var lower = String(name).toLowerCase();
      if (lower !== name) handlers = registry[lower];
      if (!handlers || !handlers.size) {
        for (var key in registry) {
          if (key.toLowerCase() === lower && registry[key] && registry[key].size) {
            handlers = registry[key];
            break;
          }
        }
      }
    }
    if (handlers && handlers.size) {
      var values = [];
      handlers.forEach(function (handler) { values.push(handler(payload)); });
      return values.some(function (value) { return value && typeof value.then === "function"; })
        ? Promise.all(values)
        : values[values.length - 1];
    }
    /*__WRNEXUS_DEV_START__*/
    warnOnce(
      "WRN-DEV-OUTPUT-UNHANDLED",
      "Output '" + name + "' has no parent binding. Registered bindings: " +
        (registry ? Object.keys(registry).join(", ") || "none" : "none") + ".",
      root,
      { output: name, registeredBindings: registry ? Object.keys(registry) : [] },
    );
    /*__WRNEXUS_DEV_END__*/
    return dispatchComponentEvent(root, name, payload);
  }

  function callServerFunction(component, functionName, args) {
    var csrf = document.querySelector('meta[name="wrnexus-csrf"]');
    return fetch("/__wrnexus/rpc", {
      method: "POST",
      credentials: "same-origin",
      headers: {
        "content-type": "application/json",
        "x-csrf-token": csrf ? csrf.getAttribute("content") || "" : "",
      },
      body: JSON.stringify({ component: component, function: functionName, args: args || [] }),
    }).then(function (response) {
      return response.json().catch(function () { return null; }).then(function (payload) {
        if (!response.ok || !payload || !payload.ok) {
          var error = new Error(payload && payload.error && payload.error.message || "Server function call failed");
          error.code = payload && payload.error && payload.error.code || "WRN-RPC-FAILED";
          error.status = response.status;
          throw error;
        }
        return payload.value;
      });
    });
  }

  function dispatchComponentEvent(root, name, detail) {
    if (!root || !name) return null;
    var EventConstructor =
      root.ownerDocument &&
      root.ownerDocument.defaultView &&
      root.ownerDocument.defaultView.CustomEvent
        ? root.ownerDocument.defaultView.CustomEvent
        : CustomEvent;
    var event = new EventConstructor(String(name), {
      bubbles: true,
      detail: detail || {},
    });
    root.dispatchEvent(event);
    // Compatibility for applications using the former prefixed contract.
    root.dispatchEvent(new EventConstructor("wrnexus:" + String(name), {
      bubbles: true,
      detail: detail || {},
    }));
    return event;
  }

  function emitPinInputEvent(root, name, extra) {
    var hidden = root.querySelector("[data-pin-value]");
    var cells = Array.prototype.slice.call(root.querySelectorAll("[data-pin-cell]"));
    var value = hidden ? hidden.value : "";
    var detail = {
      component: "PinInput",
      value: value,
      digits: cells.map(function (cell) { return cell.value; }),
      complete: value.length === cells.length,
      length: cells.length,
    };
    if (extra && typeof extra === "object") {
      Object.keys(extra).forEach(function (key) { detail[key] = extra[key]; });
    }
    try {
      dispatchComponentEvent(root, name, detail);
    } catch (_) {
      // CustomEvent can be unavailable in minimal DOM environments.
    }
  }

  /*__WRNEXUS_CONTROLLERS_PIN_START__*/
  function setupPinInputController(root) {
    if (!root || root.__wrnexusPinInputController) return;
    var cells = Array.prototype.slice.call(root.querySelectorAll("[data-pin-cell]"));
    var hidden = root.querySelector("[data-pin-value]");
    var clearButton = root.querySelector("[data-pin-clear]");
    var patternSource = root.getAttribute("data-pattern") || "[0-9]";
    var allowPaste = root.getAttribute("data-allow-paste") !== "false";
    var autoSubmit = root.getAttribute("data-auto-submit") === "true";
    var matcher;
    var exactMatcher;
    var NativeEventConstructor =
      root.ownerDocument &&
      root.ownerDocument.defaultView &&
      root.ownerDocument.defaultView.Event
        ? root.ownerDocument.defaultView.Event
        : Event;

    try {
      exactMatcher = new RegExp("^(?:" + patternSource + ")$");
      matcher = new RegExp("^(?:" + patternSource + ")$", "i");
    } catch (error) {
      matcher = /$a/;
      emitPinInputEvent(root, "error", {
        error: error,
        message: "Invalid PIN pattern: " + patternSource,
      });
    }

    function acceptedCharacters(value) {
      return Array.from(String(value || "")).map(function (character) {
        matcher.lastIndex = 0;
        if (!matcher.test(character)) return "";
        exactMatcher.lastIndex = 0;
        if (exactMatcher.test(character)) return character;
        var upper = character.toUpperCase();
        exactMatcher.lastIndex = 0;
        if (exactMatcher.test(upper)) return upper;
        var lower = character.toLowerCase();
        exactMatcher.lastIndex = 0;
        return exactMatcher.test(lower) ? lower : character;
      }).filter(Boolean);
    }

    function currentValue() {
      return cells.map(function (cell) { return cell.value; }).join("");
    }

    function updateClearButton(value) {
      if (!clearButton) return;
      clearButton.style.display = value ? "" : "none";
    }

    function syncValue(reason, index) {
      var previous = hidden ? hidden.value : "";
      var value = currentValue();
      if (hidden) {
        hidden.value = value;
        hidden.setAttribute("value", value);
        hidden.dispatchEvent(new NativeEventConstructor("input", { bubbles: true }));
        hidden.dispatchEvent(new NativeEventConstructor("change", { bubbles: true }));
      }
      root.setAttribute("data-value", value);
      root.setAttribute("data-complete", value.length === cells.length ? "true" : "false");
      updateClearButton(value);
      emitPinInputEvent(root, "input", { reason: reason, index: index });
      if (value !== previous) {
        emitPinInputEvent(root, "change", { reason: reason, index: index });
      }
      if (value.length === cells.length && previous.length !== cells.length) {
        emitPinInputEvent(root, "complete", { reason: reason, index: index });
        if (autoSubmit) {
          var form = root.closest("form");
          if (form && typeof form.requestSubmit === "function") form.requestSubmit();
        }
      }
    }

    function setValue(value, reason) {
      var characters = acceptedCharacters(value).slice(0, cells.length);
      cells.forEach(function (cell, index) {
        cell.value = characters[index] || "";
        cell.setAttribute("value", cell.value);
      });
      syncValue(reason || "setValue", characters.length ? characters.length - 1 : -1);
    }

    function focusCell(index) {
      var cell = cells[Math.max(0, Math.min(cells.length - 1, index))];
      if (cell && !cell.disabled) {
        cell.focus();
        if (typeof cell.select === "function") cell.select();
      }
    }

    cells.forEach(function (cell, index) {
      cell.addEventListener("focus", function () {
        if (typeof cell.select === "function") cell.select();
      });
      cell.addEventListener("input", function () {
        var characters = acceptedCharacters(cell.value);
        cell.value = characters.length ? characters[characters.length - 1] : "";
        cell.setAttribute("value", cell.value);
        syncValue("input", index);
        if (cell.value && index < cells.length - 1) focusCell(index + 1);
      });
      cell.addEventListener("keydown", function (event) {
        if (event.key === "Backspace" && !cell.value && index > 0) {
          event.preventDefault();
          cells[index - 1].value = "";
          cells[index - 1].setAttribute("value", "");
          syncValue("backspace", index - 1);
          focusCell(index - 1);
        } else if (event.key === "ArrowLeft" && index > 0) {
          event.preventDefault();
          focusCell(index - 1);
        } else if (event.key === "ArrowRight" && index < cells.length - 1) {
          event.preventDefault();
          focusCell(index + 1);
        } else if (event.key === "Home") {
          event.preventDefault();
          focusCell(0);
        } else if (event.key === "End") {
          event.preventDefault();
          focusCell(cells.length - 1);
        }
      });
      cell.addEventListener("paste", function (event) {
        if (!allowPaste) return;
        var clipboard = event.clipboardData;
        if (!clipboard) return;
        event.preventDefault();
        var characters = acceptedCharacters(clipboard.getData("text")).slice(0, cells.length - index);
        characters.forEach(function (character, offset) {
          cells[index + offset].value = character;
          cells[index + offset].setAttribute("value", character);
        });
        syncValue("paste", index);
        emitPinInputEvent(root, "paste", { index: index, pasted: characters.join("") });
        focusCell(Math.min(index + characters.length, cells.length - 1));
      });
    });

    if (clearButton) {
      clearButton.addEventListener("click", function () {
        setValue("", "clear");
        emitPinInputEvent(root, "clear");
        focusCell(0);
      });
    }

    root.wrnexusPinInput = {
      focus: function (index) { focusCell(Number(index || 0)); },
      clear: function () {
        setValue("", "clear");
        emitPinInputEvent(root, "clear", { source: "method" });
      },
      setValue: function (value) { setValue(value, "setValue"); },
      getValue: function () { return currentValue(); },
    };
    root.__wrnexusPinInputController = root.wrnexusPinInput;
    setValue(hidden ? hidden.value : root.getAttribute("data-value"), "initial");
  }

  function hydratePinInputControllers(root) {
    var host = root || document;
    var inputs = [];
    if (host.nodeType === 1 && host.matches && host.matches("[data-wrn-pin-input]")) {
      inputs.push(host);
    }
    if (host.querySelectorAll) {
      Array.prototype.push.apply(inputs, host.querySelectorAll("[data-wrn-pin-input]"));
    }
    inputs.forEach(setupPinInputController);
  }

  /*__WRNEXUS_CONTROLLERS_PIN_END__*/

  function parseScopeDecl(decl) {
    var initial = {};
    splitTopLevel(decl, ",").forEach(function (part) {
      var idx = findTopLevel(part, ":");
      if (idx < 0) return;
      var name = part.slice(0, idx).trim();
      var expr = part.slice(idx + 1).trim();
      if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name)) return;
      try {
        initial[name] = evaluateExpression(expr, function () { return undefined; });
      } catch (e) {
        console.error("[wrnexus] invalid data-scope value for '" + name + "'", e);
      }
    });
    return initial;
  }

  function skipStatementWhitespace(
    source,
    index,
  ) {
    while (
      index < source.length &&
      /\s/.test(source[index])
    ) {
      index++;
    }

    return index;
  }

  function findClosingDelimiter(
    source,
    start,
    opening,
    closing,
  ) {
    if (source[start] !== opening) {
      return -1;
    }

    var depth = 1;
    var quote = "";
    var escaped = false;

    for (
      var index = start + 1;
      index < source.length;
      index++
    ) {
      var character = source[index];

      if (quote) {
        if (escaped) {
          escaped = false;
          continue;
        }

        if (character === "\\") {
          escaped = true;
          continue;
        }

        if (character === quote) {
          quote = "";
        }

        continue;
      }

      if (
        character === '"' ||
        character === "'" ||
        character === "\`"
      ) {
        quote = character;
        continue;
      }

      if (character === opening) {
        depth++;
        continue;
      }

      if (character === closing) {
        depth--;

        if (depth === 0) {
          return index;
        }
      }
    }

    return -1;
  }

  function parseIfStatement(source) {
    source = String(source || "").trim();

    if (
      source.slice(0, 2) !== "if" ||
      /[A-Za-z0-9_$]/.test(
        source.charAt(2),
      )
    ) {
      return null;
    }

    var branches = [];
    var index = 0;
    var firstBranch = true;

    while (index < source.length) {
      index = skipStatementWhitespace(
        source,
        index,
      );

      var branchType;

      if (
        firstBranch &&
        source.slice(index, index + 2) ===
          "if" &&
        !/[A-Za-z0-9_$]/.test(
          source.charAt(index + 2),
        )
      ) {
        branchType = "if";
        index += 2;
      } else if (
        source.slice(index, index + 7) ===
          "else if" &&
        !/[A-Za-z0-9_$]/.test(
          source.charAt(index + 7),
        )
      ) {
        branchType = "else-if";
        index += 7;
      } else if (
        source.slice(index, index + 4) ===
          "else" &&
        !/[A-Za-z0-9_$]/.test(
          source.charAt(index + 4),
        )
      ) {
        branchType = "else";
        index += 4;
      } else {
        break;
      }

      firstBranch = false;

      index = skipStatementWhitespace(
        source,
        index,
      );

      var condition = null;

      if (branchType !== "else") {
        if (source.charAt(index) !== "(") {
          throw new Error(
            "Expected '(' after " +
              (
                branchType === "if"
                  ? "if"
                  : "else if"
              ),
          );
        }

        var conditionEnd =
          findClosingDelimiter(
            source,
            index,
            "(",
            ")",
          );

        if (conditionEnd < 0) {
          throw new Error(
            "Unclosed " +
              (
                branchType === "if"
                  ? "if"
                  : "else if"
              ) +
              " condition",
          );
        }

        condition = source
          .slice(
            index + 1,
            conditionEnd,
          )
          .trim();

        index = skipStatementWhitespace(
          source,
          conditionEnd + 1,
        );
      }

      if (source.charAt(index) !== "{") {
        throw new Error(
          "Expected '{' after " +
            branchType,
        );
      }

      var bodyEnd =
        findClosingDelimiter(
          source,
          index,
          "{",
          "}",
        );

      if (bodyEnd < 0) {
        throw new Error(
          "Unclosed " +
            branchType +
            " body",
        );
      }

      branches.push({
        condition: condition,
        body: source.slice(
          index + 1,
          bodyEnd,
        ),
      });

      index = skipStatementWhitespace(
        source,
        bodyEnd + 1,
      );

      if (
        source.slice(index, index + 7) ===
          "else if" ||
        source.slice(index, index + 4) ===
          "else"
      ) {
        continue;
      }

      break;
    }

    return branches.length > 0
      ? branches
      : null;
  }

  function runStatement(
    stmt,
    evalExpr,
    read,
    write,
    runBlock,
  ) {
    stmt = String(stmt || "").trim();

    if (!stmt) {
      return {
        returned: false,
        value: undefined,
      };
    }

    var returnMatch =
      /^return(?:\s+([\s\S]+))?$/.exec(
        stmt,
      );

    if (returnMatch) {
      return {
        returned: true,
        value: returnMatch[1]
          ? evalExpr(returnMatch[1])
          : undefined,
      };
    }

    var ifBranches =
      parseIfStatement(stmt);

    if (ifBranches) {
      for (
        var branchIndex = 0;
        branchIndex < ifBranches.length;
        branchIndex++
      ) {
        var branch =
          ifBranches[branchIndex];

        if (
          branch.condition === null ||
          !!evalExpr(branch.condition)
        ) {
          return runBlock(branch.body);
        }
      }

      return {
        returned: false,
        value: undefined,
      };
    }

    var increment = stmt.match(
      /^([A-Za-z_$][A-Za-z0-9_$]*)\s*(\+\+|--)$/,
    );

    if (increment) {
      write(
        increment[1],
        Number(read(increment[1]) || 0) +
          (increment[2] === "++"
            ? 1
            : -1),
      );

      return {
        returned: false,
        value: undefined,
      };
    }

    var assignment = stmt.match(
      /^([A-Za-z_$][A-Za-z0-9_$]*)\s*(\+=|-=|\*=|\/=|%=|=)\s*([\s\S]+)$/,
    );

    if (!assignment) {
      evalExpr(stmt);

      return {
        returned: false,
        value: undefined,
      };
    }

    var name = assignment[1];
    var operator = assignment[2];
    var nextValue =
      evalExpr(assignment[3]);
    var currentValue = read(name);

    if (operator === "+=") {
      nextValue =
        currentValue + nextValue;
    } else if (operator === "-=") {
      nextValue =
        Number(currentValue || 0) -
        Number(nextValue || 0);
    } else if (operator === "*=") {
      nextValue =
        Number(currentValue || 0) *
        Number(nextValue || 0);
    } else if (operator === "/=") {
      nextValue =
        Number(currentValue || 0) /
        Number(nextValue || 0);
    } else if (operator === "%=") {
      nextValue =
        Number(currentValue || 0) %
        Number(nextValue || 0);
    }

    write(name, nextValue);

    return {
      returned: false,
      value: nextValue,
    };
  }

  function evaluateSpecialExpression(
    expression,
    read,
  ) {
    var source = String(
      expression || "",
    ).trim();

    // Remove an optional trailing semicolon.
    if (
      source.charAt(
        source.length - 1,
      ) === ";"
    ) {
      source = source
        .slice(0, -1)
        .trim();
    }

    /*
    * Array literals containing spreads:
    *
    * [...openIndexes, index]
    * [first, ...otherItems]
    */
    if (
      source.charAt(0) === "[" &&
      source.charAt(
        source.length - 1,
      ) === "]" &&
      source.indexOf("...") !== -1
    ) {
      var arraySource = source.slice(
        1,
        -1,
      );

      var arrayParts = splitTopLevel(
        arraySource,
        ",",
      );

      var arrayResult = [];

      arrayParts.forEach(function (
        part,
      ) {
        var partSource =
          part.trim();

        if (!partSource) {
          return;
        }

        if (
          partSource.slice(0, 3) ===
          "..."
        ) {
          var spreadResult =
            evaluateExpression(
              partSource
                .slice(3)
                .trim(),
              read,
            );

          if (
            Array.isArray(
              spreadResult,
            )
          ) {
            Array.prototype.push.apply(
              arrayResult,
              spreadResult,
            );
          }

          return;
        }

        arrayResult.push(
          evaluateExpression(
            partSource,
            read,
          ),
        );
      });

      return {
        matched: true,
        value: arrayResult,
      };
    }

    /*
    * First recognize the array method call without
    * trying to parse the callback in the same regex.
    */
    var methodMatch =
      /^([\s\S]+)\.(filter|map|flatMap|some|every|find|findIndex)\(\s*([\s\S]*)\s*\)$/.exec(
        source,
      );

    if (!methodMatch) {
      return {
        matched: false,
        value: undefined,
      };
    }

    var collectionSource =
      methodMatch[1].trim();

    var method =
      methodMatch[2];

    var callbackSource =
      methodMatch[3].trim();

    /*
    * Supported callbacks:
    *
    * item => item.active
    * (item) => item.active
    * (item, index) => index > 0
    */
    var callbackMatch =
      /^(?:\(\s*([A-Za-z_$][A-Za-z0-9_$]*)\s*(?:,\s*([A-Za-z_$][A-Za-z0-9_$]*)\s*)?\)|([A-Za-z_$][A-Za-z0-9_$]*))\s*=>\s*([\s\S]+)$/.exec(
        callbackSource,
      );

    if (!callbackMatch) {
      return {
        matched: false,
        value: undefined,
      };
    }

    var itemName =
      callbackMatch[1] ||
      callbackMatch[3];

    var indexName =
      callbackMatch[2];

    var callbackBody =
      callbackMatch[4].trim();

    /*
    * Support expression bodies wrapped in parentheses:
    *
    * item => (
    *   item.active
    * )
    */
    if (
      callbackBody.charAt(0) ===
        "(" &&
      callbackBody.charAt(
        callbackBody.length - 1,
      ) === ")"
    ) {
      callbackBody = callbackBody
        .slice(1, -1)
        .trim();
    }

    var collection =
      evaluateExpression(
        collectionSource,
        read,
      );

    if (!Array.isArray(collection)) {
      collection = [];
    }

    var callback = function (
      itemValue,
      itemIndex,
    ) {
      return evaluateExpression(
        callbackBody,
        function (name) {
          if (name === itemName) {
            return itemValue;
          }

          if (
            indexName &&
            name === indexName
          ) {
            return itemIndex;
          }

          return read(name);
        },
      );
    };

    var result;

    if (method === "filter") {
      result =
        collection.filter(callback);
    } else if (
      method === "map"
    ) {
      result =
        collection.map(callback);
    } else if (
      method === "flatMap"
    ) {
      result =
        collection.flatMap(callback);
    } else if (
      method === "some"
    ) {
      result =
        collection.some(callback);
    } else if (
      method === "every"
    ) {
      result =
        collection.every(callback);
    } else if (
      method === "find"
    ) {
      result =
        collection.find(callback);
    } else {
      result =
        collection.findIndex(
          callback,
        );
    }

    return {
      matched: true,
      value: result,
    };
  }

  // A small, eval-free expression evaluator (so a strict CSP needs no
  // 'unsafe-eval'). Supports: literals, identifiers, member access (a.b, a[b]),
  // function/method calls, arrays, objects, arithmetic, comparison, equality,
  // logical (&& ||), unary (! - +), and the ternary operator.
  function evaluateExpression(
    expr,
    read,
  ) {
    expr = String(
      expr || "",
    ).trim();

    var special =
      evaluateSpecialExpression(
        expr,
        read,
      );

    if (special.matched) {
      return special.value;
    }

    function evaluateTemplateLiteral(source) {
      var template = source.slice(1, -1);
      var rendered = "";
      var cursor = 0;

      while (cursor < template.length) {
        if (template[cursor] === "\\") {
          cursor++;
          var escaped = template[cursor++];
          rendered += escaped === "n" ? "\n" : escaped === "t" ? "\t" : escaped || "";
          continue;
        }

        if (template[cursor] === "$" && template[cursor + 1] === "{") {
          var expressionStart = cursor + 2;
          var expressionEnd = expressionStart;
          var depth = 1;
          var quote = "";

          for (; expressionEnd < template.length; expressionEnd++) {
            var character = template[expressionEnd];
            if (quote) {
              if (character === "\\") expressionEnd++;
              else if (character === quote) quote = "";
              continue;
            }
            if (character === '"' || character === "'") quote = character;
            else if (character === "{") depth++;
            else if (character === "}" && --depth === 0) break;
          }

          if (depth !== 0) throw new Error("Unclosed template interpolation in '" + source + "'");
          rendered += String(evaluateExpression(template.slice(expressionStart, expressionEnd), read));
          cursor = expressionEnd + 1;
          continue;
        }

        rendered += template[cursor++];
      }

      return rendered;
    }

    // Template literals are evaluated without eval so they remain compatible
    // with a strict CSP. Each interpolation uses the same bounded expression
    // evaluator as every other reactive binding. They are accepted both as a
    // complete expression and as a primary inside a larger expression.
    if (
      expr.length >= 2 &&
      expr[0] === "\`" &&
      expr[expr.length - 1] === "\`"
    ) {
      return evaluateTemplateLiteral(expr);
    }

    var tokens =
      tokenizeExpression(expr);
      
    var index = 0;
    function peek() { return tokens[index]; }
    function next() { return tokens[index++]; }
    /*
     * Punctuation only. is/match are asked exclusively about operators and
     * brackets, but they used to compare the token *value* alone -- so a
     * string literal that happens to spell an operator was mistaken for one.
     * That silently broke the most ordinary calls in the language:
     * join('-'), split(','), replace('.', '') all died on "Unexpected token".
     * Requiring an operator token keeps a quoted '-' a value.
     */
    function is(v) {
      var t = peek();
      return !!t && (t.type === "op" || t.type === "operator") && t.value === v;
    }
    function match(v) { if (is(v)) { index++; return true; } return false; }
    function expect(v) {
      if (!match(v)) throw new Error("Expected '" + v + "' in '" + expr + "'");
    }

    function parsePrimary() {
      var t = next();
      if (!t) throw new Error("Unexpected end of expression in '" + expr + "'");
      if (t.type === "number" || t.type === "string") return { value: t.value };
      // A fresh RegExp per evaluation: a shared instance carries lastIndex
      // between calls, so a /g pattern would return alternating results for
      // the same input.
      if (t.type === "regex") return { value: new RegExp(t.value.source, t.value.flags) };
      if (t.type === "template") return { value: evaluateTemplateLiteral(t.value) };
      if (t.type === "ident") {
        if (t.value === "true") return { value: true };
        if (t.value === "false") return { value: false };
        if (t.value === "null") return { value: null };
        if (t.value === "undefined") return { value: undefined };
        return { value: read(t.value) };
      }
      if (t.value === "(") { var v = parseTernary(); expect(")"); return { value: v }; }
      if (t.value === "[") {
        var arr = [];
        if (!is("]")) { arr.push(parseTernary()); while (match(",")) arr.push(parseTernary()); }
        expect("]");
        return { value: arr };
      }
      if (t.value === "{") {
        var obj = {};
        if (!is("}")) {
          do {
            var kt = next();
            var key = kt.value;
            expect(":");
            obj[key] = parseTernary();
          } while (match(","));
        }
        expect("}");
        return { value: obj };
      }
      throw new Error("Unexpected token '" + t.value + "'");
    }

    function parsePostfix() {
      var node = parsePrimary();
      for (;;) {
        if (match(".")) {
          var prop = next().value;
          node = { value: node.value == null ? undefined : node.value[prop], obj: node.value };
        } else if (match("[")) {
          var key = parseTernary();
          expect("]");
          node = { value: node.value == null ? undefined : node.value[key], obj: node.value };
        } else if (is("(")) {
          next();
          var args = [];
          if (!is(")")) { args.push(parseTernary()); while (match(",")) args.push(parseTernary()); }
          expect(")");
          var fn = node.value;
          node = { value: typeof fn === "function" ? fn.apply(node.obj, args) : undefined };
        } else break;
      }
      return node;
    }

    function parseUnary() {
      if (match("!")) return !parseUnary();
      if (match("-")) return -parseUnary();
      if (match("+")) return +parseUnary();
      return parsePostfix().value;
    }
    function parseMul() {
      var l = parseUnary();
      while (peek() && (is("*") || is("/") || is("%"))) {
        var op = next().value, r = parseUnary();
        l = op === "*" ? l * r : op === "/" ? l / r : l % r;
      }
      return l;
    }
    function parseAdd() {
      var l = parseMul();
      while (peek() && (is("+") || is("-"))) {
        var op = next().value, r = parseMul();
        l = op === "+" ? l + r : l - r;
      }
      return l;
    }
    function parseCmp() {
      var l = parseAdd();
      while (peek() && (is("<") || is(">") || is("<=") || is(">="))) {
        var op = next().value, r = parseAdd();
        l = op === "<" ? l < r : op === ">" ? l > r : op === "<=" ? l <= r : l >= r;
      }
      return l;
    }
    function parseEq() {
      var l = parseCmp();
      while (peek() && (is("==") || is("!=") || is("===") || is("!=="))) {
        var op = next().value, r = parseCmp();
        l = op === "==" ? l == r : op === "!=" ? l != r : op === "===" ? l === r : l !== r;
      }
      return l;
    }
    function parseAnd() {
      var l = parseEq();
      while (match("&&")) {
        var r = parseEq();
        l = l && r;
      }
      return l;
    }
    function parseOr() {
      var l = parseAnd();
      while (match("||")) {
        var r = parseAnd();
        l = l || r;
      }
      return l;
    }
    function parseTernary() {
      var c = parseOr();
      if (match("?")) { var a = parseTernary(); expect(":"); var b = parseTernary(); return c ? a : b; }
      return c;
    }

    var value = parseTernary();
    if (index < tokens.length) throw new Error("Unexpected token '" + tokens[index].value + "'");
    return value;
  }

  function tokenizeExpression(input) {
    var tokens = [];
    var i = 0;
    while (i < input.length) {
      var ch = input[i];
      if (/\s/.test(ch)) { i++; continue; }

      /*
       * Comments. Statement bodies handed to this engine -- a lifecycle mount
       * hook, an inline handler -- are ordinary authored code and routinely
       * contain them. Without this the leading slash fell through to the
       * regex-literal branch and the whole body died with "Unclosed regular
       * expression", naming nothing useful.
       */
      if (ch === "/" && input[i + 1] === "/") {
        var lineEnd = input.indexOf("\n", i + 2);
        i = lineEnd === -1 ? input.length : lineEnd + 1;
        continue;
      }

      if (ch === "/" && input[i + 1] === "*") {
        var blockEnd = input.indexOf("*/", i + 2);
        i = blockEnd === -1 ? input.length : blockEnd + 2;
        continue;
      }
      if (/[0-9]/.test(ch) || (ch === "." && /[0-9]/.test(input[i + 1]))) {
        var start = i++;
        while (i < input.length && /[0-9.]/.test(input[i])) i++;
        tokens.push({ type: "number", value: Number(input.slice(start, i)) });
        continue;
      }
      if (ch === '"' || ch === "'") {
        var quote = ch, value = "";
        i++;
        while (i < input.length) {
          ch = input[i++];
          if (ch === quote) break;
          if (ch === "\\") {
            var esc = input[i++];
            value += esc === "n" ? "\n" : esc === "t" ? "\t" : esc || "";
          } else value += ch;
        }
        tokens.push({ type: "string", value: value });
        continue;
      }
      if (ch === "\`") {
        var templateStart = i++;
        var templateDepth = 0;
        var templateQuote = "";
        while (i < input.length) {
          ch = input[i++];
          if (templateQuote) {
            if (ch === "\\") i++;
            else if (ch === templateQuote) templateQuote = "";
            continue;
          }
          if (ch === "\\") {
            i++;
            continue;
          }
          if (ch === "\`" && templateDepth === 0) break;
          if (ch === "$" && input[i] === "{") {
            templateDepth++;
            i++;
            continue;
          }
          if (templateDepth > 0) {
            if (ch === '"' || ch === "'") templateQuote = ch;
            else if (ch === "{") templateDepth++;
            else if (ch === "}") templateDepth--;
          }
        }
        if (input[i - 1] !== "\`") throw new Error("Unclosed template literal");
        tokens.push({ type: "template", value: input.slice(templateStart, i) });
        continue;
      }
      if (/[A-Za-z_$]/.test(ch)) {
        var s = i++;
        while (i < input.length && /[A-Za-z0-9_$]/.test(input[i])) i++;
        tokens.push({ type: "ident", value: input.slice(s, i) });
        continue;
      }
      /*
       * Regex literal. Validating input is the single most common reason a
       * client function reaches for one, and without this the leading '/' fell
       * through to the division operator and the pattern body then died on
       * "Unexpected character '^'" -- taking the whole handler with it.
       *
       * '/' is ambiguous: it starts a regex only where a *value* may begin,
       * and is division after one. The preceding token decides -- after a
       * value-producing token (number, string, identifier, or a closing
       * bracket) it is division; anywhere else it opens a literal. This is
       * the standard lexer disambiguation and is why plain division keeps working.
       */
      if (ch === "/") {
        var previous = tokens[tokens.length - 1];
        var afterValue =
          previous &&
          (previous.type === "number" ||
            previous.type === "string" ||
            previous.type === "template" ||
            (previous.type === "ident" &&
              previous.value !== "return" &&
              previous.value !== "typeof" &&
              previous.value !== "in" &&
              previous.value !== "of") ||
            ((previous.type === "op" || previous.type === "operator") &&
              (previous.value === ")" || previous.value === "]" || previous.value === "}")));

        if (!afterValue) {
          var regexStart = i++;
          var inClass = false;
          var closed = false;
          while (i < input.length) {
            var rc = input[i];
            if (rc === "\\") {
              i += 2;
              continue;
            }
            if (rc === "[") inClass = true;
            else if (rc === "]") inClass = false;
            else if (rc === "/" && !inClass) {
              closed = true;
              i++;
              break;
            } else if (rc === "\n") break;
            i++;
          }
          if (!closed) throw new Error("Unclosed regular expression");
          var body = input.slice(regexStart + 1, i - 1);
          var flagStart = i;
          while (i < input.length && /[a-z]/.test(input[i])) i++;
          tokens.push({
            type: "regex",
            value: new RegExp(body, input.slice(flagStart, i)),
          });
          continue;
        }
      }
      var three = input.slice(i, i + 3);

      if (
        three === "===" ||
        three === "!=="
      ) {
        tokens.push({
          type: "operator",
          value: three,
        });

        i += 3;
        continue;
      }

      var two = input.slice(i, i + 2);

      if (
        two === "==" ||
        two === "!=" ||
        two === ">=" ||
        two === "<=" ||
        two === "&&" ||
        two === "||"
      ) {
        tokens.push({
          type: "operator",
          value: two,
        });

        i += 2;
        continue;
      }
      if ("()+-*/%!<>.,?:[]{}".indexOf(ch) !== -1) { tokens.push({ type: "op", value: ch }); i++; continue; }
      throw new Error("Unexpected character '" + ch + "'");
    }
    return tokens;
  }

  function splitTopLevel(input, separator) {
    var parts = [];
    var start = 0;
    var depth = 0;
    var quote = "";
    for (var i = 0; i < input.length; i++) {
      var ch = input[i];
      if (quote) {
        if (ch === "\\") i++;
        else if (ch === quote) quote = "";
        continue;
      }
      if (ch === '"' || ch === "'") {
        quote = ch;
        continue;
      }
      if (ch === "(" || ch === "[" || ch === "{") depth++;
      else if (ch === ")" || ch === "]" || ch === "}") depth--;
      else if (ch === separator && depth === 0) {
        parts.push(input.slice(start, i).trim());
        start = i + 1;
      }
    }
    parts.push(input.slice(start).trim());
    return parts.filter(Boolean);
  }

  function findTopLevel(input, needle) {
    var depth = 0;
    var quote = "";
    for (var i = 0; i < input.length; i++) {
      var ch = input[i];
      if (quote) {
        if (ch === "\\") i++;
        else if (ch === quote) quote = "";
        continue;
      }
      if (ch === '"' || ch === "'") quote = ch;
      else if (ch === "(" || ch === "[" || ch === "{") depth++;
      else if (ch === ")" || ch === "]" || ch === "}") depth--;
      else if (ch === needle && depth === 0) return i;
    }
    return -1;
  }

  function safeCsrUrl(id) {
    try {
      if (!/^[A-Za-z0-9_-]+$/.test(id)) return null;
      return "/__wrnexus/csr?route=" + encodeURIComponent(location.pathname) + "&id=" + encodeURIComponent(id);
    } catch (_) {
      return null;
    }
  }

  function setupCsrFetch(el) {
    if (el.__wrnexusCsrFetch) return;
    el.__wrnexusCsrFetch = true;

    var id = el.getAttribute("data-wrnexus-csr") || "";
    var url = safeCsrUrl(id);
    if (!url) {
      console.error("[wrnexus] blocked unsafe CSR binding '" + id + "'");
      return;
    }

    var headers = { "accept": "text/plain" };
    var storage = localStorageSnapshotHeader();
    if (storage) headers["x-wrnexus-local-storage"] = storage;

    fetch(url, { headers: headers })
      .then(function (res) {
        if (!res.ok) throw new Error("HTTP " + res.status);
        return res.text();
      })
      .then(function (text) {
        el.textContent = text;
      })
      .catch(function (err) {
        console.error("[wrnexus] CSR fetch failed for binding '" + id + "'", err);
        el.textContent = "Failed to load";
      });
  }

  function hydrateCsrFetches(root) {
    (root || document).querySelectorAll("[data-wrnexus-csr]").forEach(setupCsrFetch);
  }

  function localStorageSnapshotHeader() {
    try {
      if (!("localStorage" in window)) return "";
      var values = {};
      for (var i = 0; i < window.localStorage.length; i++) {
        var key = window.localStorage.key(i);
        if (!key) continue;
        var value = window.localStorage.getItem(key);
        if (typeof value === "string") values[key] = value;
      }
      var encoded = encodeURIComponent(JSON.stringify(values));
      return encoded.length <= 12000 ? encoded : "";
    } catch (_) {
      return "";
    }
  }

  var asyncLoads = new Map();
  function asyncValueAt(value, path) {
    var current = value;
    var parts = String(path || "").split(".").filter(Boolean);
    for (var i = 0; i < parts.length; i++) {
      if (current == null || typeof current !== "object") return "";
      current = current[parts[i]];
    }
    return current == null ? "" : current;
  }
  function interpolateAsync(root, model, prefix) {
    function visit(node) {
      if (node.nodeType === 3) {
        node.textContent = String(node.textContent || "").replace(/\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*\}/g, function (whole, path) {
          var parts = path.split(".");
          if (parts[0] === prefix) parts.shift();
          if (prefix === "error" && parts[0] !== "message") return whole;
          var value = asyncValueAt(model, parts.join("."));
          return typeof value === "object" ? JSON.stringify(value) : String(value);
        });
      }
      Array.from(node.childNodes || []).forEach(visit);
    }
    visit(root);
    root.querySelectorAll("*").forEach(function (node) {
      Array.from(node.attributes || []).forEach(function (attribute) {
        if (attribute.name.indexOf("data-wrn-async-") === 0) return;
        if (attribute.value.indexOf("{") === -1) return;
        var nextValue = String(attribute.value).replace(/\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*\}/g, function (whole, path) {
          var parts = path.split(".");
          if (parts[0] === prefix) parts.shift();
          if (prefix === "error" && parts[0] !== "message") return whole;
          var value = asyncValueAt(model, parts.join("."));
          return typeof value === "object" ? JSON.stringify(value) : String(value);
        });
        if (/^(?:href|src|action|formaction)$/i.test(attribute.name)) {
          nextValue = sanitizeReactiveUrl(nextValue);
        }
        node.setAttribute(attribute.name, nextValue);
      });
    });
    root.querySelectorAll("[data-wrn-async-value]").forEach(function (node) {
      var path = node.getAttribute("data-wrn-async-value") || "";
      var value = asyncValueAt(model, path);
      node.textContent = typeof value === "object" ? JSON.stringify(value, null, 2) : String(value);
    });
  }
  function showAsync(boundary, state, model) {
    var template = boundary.querySelector("template[data-wrn-async-" + state + "]");
    var content = boundary.querySelector("[data-wrn-async-content]");
    if (!template || !content) return;
    var fragment = template.content.cloneNode(true);
    var alias = template.getAttribute("data-wrn-async-alias") ||
      (state === "error" ? "error" : boundary.getAttribute("data-wrn-async"));
    interpolateAsync(fragment, model, alias);
    content.replaceChildren(fragment);
    boundary.setAttribute("aria-busy", state === "loading" ? "true" : "false");
    boundary.setAttribute("data-wrn-async-state", state);
  }
  function setupAsyncBoundary(boundary) {
    if (boundary.__wrnexusAsync) return;
    boundary.__wrnexusAsync = true;
    if (boundary.getAttribute("data-wrn-async-resolved") === "true") {
      boundary.setAttribute("data-wrn-async-state", "success");
      boundary.setAttribute("aria-busy", "false");
      return;
    }
    var name = boundary.getAttribute("data-wrn-async") || "";
    if (!/^[A-Za-z_$][\w$]{0,63}$/.test(name)) return showAsync(boundary, "error", { message: "Invalid data source" });
    var url = "/__wrnexus/client-load?route=" + encodeURIComponent(location.pathname) + "&search=" + encodeURIComponent(location.search) + "&name=" + encodeURIComponent(name);
    var attempts = Math.min(5, Math.max(0, Number(boundary.getAttribute("data-wrn-async-retries")) || 0));
    var controller = new AbortController();
    boundary.__wrnexusAsyncAbort = controller;
    window.addEventListener("wrnexus:navigation-start", function () { controller.abort(); }, { once: true });
    function request(remaining) {
      var pending = asyncLoads.get(url);
      if (!pending) {
        pending = fetch(url, { headers: { accept: "application/json" }, signal: controller.signal }).then(function (response) {
          if (!response.ok) throw new Error("Client load returned " + response.status);
          return response.json();
        }).finally(function () { asyncLoads.delete(url); });
        asyncLoads.set(url, pending);
      }
      pending.then(function (result) {
        showAsync(boundary, "success", result.data);
      }).catch(function (error) {
        if (controller.signal.aborted) return;
        if (remaining > 0) return setTimeout(function () { request(remaining - 1); }, 100 * (attempts - remaining + 1));
        showAsync(boundary, "error", { message: error && error.message ? error.message : "Loading failed" });
      });
    }
    showAsync(boundary, "loading", {});
    request(attempts);
  }
  function hydrateAsyncBoundaries(root) {
    (root || document).querySelectorAll("[data-wrn-async]").forEach(setupAsyncBoundary);
  }

  var invalidationRefreshPending = false;
  function asyncBoundaryTags(boundary) {
    var raw = boundary.getAttribute("data-wrn-async-tags") || boundary.getAttribute("data-wrn-async") || "";
    return raw.split(",").map(function (tag) { return tag.trim(); }).filter(Boolean);
  }
  function refreshAsyncBoundary(boundary) {
    if (boundary.__wrnexusAsyncAbort) {
      try { boundary.__wrnexusAsyncAbort.abort(); } catch (_) {}
    }
    boundary.__wrnexusAsync = false;
    boundary.removeAttribute("data-wrn-async-resolved");
    setupAsyncBoundary(boundary);
  }
  function handleCacheInvalidation(event) {
    var detail = event && event.detail && typeof event.detail === "object" ? event.detail : {};
    var tags = Array.isArray(detail.tags) ? detail.tags.map(String) : [];
    if (!tags.length) return;
    var matchedServerBoundary = false;
    document.querySelectorAll("[data-wrn-async]").forEach(function (boundary) {
      var matches = asyncBoundaryTags(boundary).some(function (tag) { return tags.indexOf(tag) !== -1; });
      if (!matches) return;
      if (boundary.getAttribute("data-wrn-async-resolved") === "true") {
        matchedServerBoundary = true;
        return;
      }
      refreshAsyncBoundary(boundary);
    });
    if (matchedServerBoundary && !invalidationRefreshPending) {
      invalidationRefreshPending = true;
      Promise.resolve().then(function () {
        invalidationRefreshPending = false;
        if (typeof window.__wrnexusRefresh === "function") window.__wrnexusRefresh();
        else window.location.reload();
      });
    }
  }
  window.addEventListener("wrnexus:cache:invalidate", handleCacheInvalidation);

  function mountClientRoots(root) {
    (root || document).querySelectorAll("template[data-wrn-client-template]").forEach(function (template) {
      var id = template.getAttribute("data-wrn-client-template");
      var mount = null;
      (root || document).querySelectorAll("[data-wrn-client-root]").forEach(function (candidate) {
        if (!mount && candidate.getAttribute("data-wrn-client-root") === id) mount = candidate;
      });
      if (!mount || !template.content) return;
      var fragment = template.content.cloneNode(true);
      mount.replaceWith(fragment);
      template.remove();
      window.dispatchEvent(new window.CustomEvent("wrnexus:client-mounted", { detail: { id: id } }));
    });
  }

  function hydrateDeclarativeUi(root) {
    var host = root || document;
    host.querySelectorAll("[data-wrn-portal]").forEach(function (portal) {
      if (portal.__wrnPortalMounted) return;
      var selector = portal.getAttribute("data-wrn-portal") || "body";
      var target = null; try { target = document.querySelector(selector); } catch (_) {}
      if (!target || target === portal || portal.contains(target)) return;
      portal.__wrnPortalMounted = true;
      var marker = document.createComment("wrnexus-portal");
      portal.parentNode && portal.parentNode.insertBefore(marker, portal);
      target.appendChild(portal);
    });
    host.querySelectorAll("[data-wrn-transition]").forEach(function (element) {
      if (element.__wrnTransitionMounted) return;
      element.__wrnTransitionMounted = true;
      var name = element.getAttribute("data-wrn-transition") || "wrn-transition";
      element.classList.add(name + "-enter", name + "-enter-active");
      requestAnimationFrame(function () { element.classList.remove(name + "-enter"); element.classList.add(name + "-enter-to"); });
      element.addEventListener("transitionend", function () { element.classList.remove(name + "-enter-active", name + "-enter-to"); }, { once: true });
    });
    host.querySelectorAll("[data-wrn-dynamic-component]").forEach(function (element) {
      if (element.__wrnDynamicMounted) return;
      element.__wrnDynamicMounted = true;
      var cases = Array.prototype.slice.call(element.children).filter(function (candidate) {
        return candidate.hasAttribute("data-component-case");
      }).map(function (candidate) {
        var marker = document.createComment("wrnexus-component-case:" + (candidate.getAttribute("data-component-case") || ""));
        element.insertBefore(marker, candidate);
        return { candidate: candidate, marker: marker };
      });
      var update = function () {
        var selected = element.getAttribute("data-wrn-dynamic-component") || "";
        cases.forEach(function (record) {
          var candidate = record.candidate;
          var active = candidate.getAttribute("data-component-case") === selected;
          candidate.hidden = false;
          if (active && !candidate.isConnected && record.marker.parentNode) {
            record.marker.parentNode.insertBefore(candidate, record.marker.nextSibling);
          } else if (!active && candidate.parentNode) {
            candidate.parentNode.removeChild(candidate);
          }
        });
        window.dispatchEvent(new window.CustomEvent("wrnexus:dynamic-component", { detail: { component: selected } }));
      };
      update();
      new MutationObserver(update).observe(element, { attributes: true, attributeFilter: ["data-wrn-dynamic-component"] });
    });
  }

  window.__wrnexusMountClientRoots = mountClientRoots;
  window.__wrnexusHydrateAsyncBoundaries = hydrateAsyncBoundaries;
  setupAnchoredOverlays();
  setupModalDialogs();
  setupRovingFocus();
  setupScrollspy();
  setupSplitters();
  startDocumentWatch();
  window.__wrnexusRepositionAnchored = repositionAnchored;
  window.__wrnexusHydrateScopes = hydrateScopes;
  window.__wrnexusInvalidateClientModule = function (url) { clientModuleCache.delete(url); };
  window.__wrnexusHydrateCsrFetches = hydrateCsrFetches;
  window.__wrnexusDisposeBehaviors = disposeBehaviors;
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", function () {
      mountClientRoots(document);
      hydrateScopes(document);
      hydrateCsrFetches(document);
      hydrateAsyncBoundaries(document);
      hydrateDeclarativeUi(document);
    });
  } else {
    mountClientRoots(document);
    hydrateScopes(document);
    hydrateCsrFetches(document);
    hydrateAsyncBoundaries(document);
    hydrateDeclarativeUi(document);
  }
})();
`.trim();
