/*!
 * BlockWriteAI Plugin
 * Adds an optional AI inline toolbar button, drawer, and server-proxied actions.
 */
(function (global, factory) {
  if (typeof module === "object" && module.exports) {
    module.exports = factory(require("../blockwriteai"));
  } else {
    factory(global.BlockWriteAI);
  }
})(typeof window !== "undefined" ? window : this, function (BlockWriteAI) {
  "use strict";

  if (!BlockWriteAI || BlockWriteAI.__aiPluginInstalled) return BlockWriteAI || null;
  BlockWriteAI.__aiPluginInstalled = true;

  var H = BlockWriteAI.helpers || {};
  var el = H.el || function (tag, className, attrs) {
    var node = document.createElement(tag);
    if (className) node.className = className;
    Object.keys(attrs || {}).forEach(function (key) {
      if (key === "html") node.innerHTML = attrs[key];
      else if (key === "text") node.textContent = attrs[key];
      else if (key === "dataset") {
        Object.keys(attrs[key] || {}).forEach(function (dataKey) {
          node.dataset[dataKey] = attrs[key][dataKey];
        });
      } else if (attrs[key] !== false && attrs[key] != null) {
        node.setAttribute(key, attrs[key] === true ? "" : attrs[key]);
      }
    });
    return node;
  };
  var esc = H.escapeHTML || function (value) {
    return String(value == null ? "" : value).replace(/[&<>"]/g, function (ch) {
      return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[ch];
    });
  };
  var svgIcon = H.svgIcon || function (name, label) {
    name = String(name || "circle").trim();
    return '<svg class="rbe-svg-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false" data-rbe-icon="' + esc(name) + '"><circle cx="12" cy="12" r="8"/></svg><span class="rbe-sr-only">' + esc(label || name) + "</span>";
  };

  var ACTIONS = [
    ["improve", "wand-magic-sparkles", "Improve writing", "Make selected writing clearer and smoother."],
    ["grammar", "spell-check", "Fix grammar", "Correct grammar, spelling, and punctuation."],
    ["summarize", "compress", "Summarize", "Create a shorter version of the selected text."],
    ["expand", "up-right-and-down-left-from-center", "Expand", "Add helpful detail while keeping the meaning."],
    ["professional", "briefcase", "Make professional", "Rewrite in a polished business tone."]
  ];

  function injectStyles() {
    if (document.querySelector("style[data-blockwriteai-ai]")) return;
    var style = document.createElement("style");
    style.dataset.blockwriteaiAi = "true";
    style.textContent =
      ".rbe-ai-inline-btn{width:34px;height:34px;border:1px solid #cbd5e1;border-radius:8px;background:#eef6ff;color:#155eef;display:inline-grid;place-items:center;cursor:pointer;font-weight:800;}" +
      ".rbe-ai-inline-btn,.rbe-ai-toolbar-btn{position:relative;}" +
      ".rbe-ai-inline-btn:hover,.rbe-ai-inline-btn:focus-visible{border-color:#2563eb;background:#dbeafe;color:#1d4ed8;}" +
      ".rbe-ai-inline-btn.is-open{border-color:#16a34a;background:#eafaf1;color:#087443;}" +
      ".rbe-ai-toolbar-btn{position:absolute;left:50%;top:0;transform:translateX(-50%);width:38px;min-width:38px;padding-left:0;padding-right:0;justify-content:center;border-color:#bfdbfe;background:#eff6ff;color:#1d4ed8;box-shadow:0 8px 24px rgba(37,99,235,.14);}" +
      ".rbe-ai-toolbar-btn:hover:not(:disabled),.rbe-ai-toolbar-btn:focus-visible{border-color:#2563eb;background:#dbeafe;color:#1d4ed8;}" +
      ".rbe-ai-toolbar-btn.is-open{border-color:#16a34a;background:#eafaf1;color:#087443;}" +
      ".rbe-ai-lock-icon{position:absolute;right:-5px;top:-5px;width:16px;height:16px;border:1px solid #fbbf24;border-radius:999px;background:#fff7ed;color:#92400e;display:none;place-items:center;font-size:8px;box-shadow:0 2px 8px rgba(146,64,14,.2);}" +
      ".rbe-ai-inline-btn.is-premium-locked .rbe-ai-lock-icon,.rbe-ai-toolbar-btn.is-premium-locked .rbe-ai-lock-icon{display:grid;}" +
      ".rbe-ai-drawer{position:fixed;right:18px;top:18px;z-index:11000;width:390px;max-width:calc(100vw - 24px);height:calc(100vh - 36px);display:grid;grid-template-rows:auto 1fr auto;border:1px solid #cbd5e1;border-radius:14px;background:#fff;box-shadow:0 28px 80px rgba(15,23,42,.25);overflow:hidden;opacity:0;pointer-events:none;transform:translateX(calc(100% + 34px));transition:transform .28s cubic-bezier(.22,1,.36,1),opacity .2s ease,width .22s ease,height .22s ease,top .22s ease,right .22s ease;will-change:transform,opacity;}" +
      ".rbe-ai-drawer.is-open{opacity:1;pointer-events:auto;transform:translateX(0);}" +
      ".rbe-ai-drawer[hidden]{display:none!important;}" +
      ".rbe-ai-drawer.is-minimized{height:auto;grid-template-rows:auto;cursor:pointer;}" +
      ".rbe-ai-drawer.is-minimized .rbe-ai-body,.rbe-ai-drawer.is-minimized .rbe-ai-foot{display:none;}" +
      ".rbe-ai-drawer.is-maximized{top:50%;right:50%;width:min(860px,calc(100vw - 32px));height:min(760px,calc(100dvh - 32px));max-width:calc(100vw - 32px);transform:translate(50%,-50%);}" +
      ".rbe-ai-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;border-bottom:1px solid #e2e8f0;background:linear-gradient(135deg,#f8fbff,#eef6ff);}" +
      ".rbe-ai-window-actions{display:flex;align-items:center;gap:8px;flex:0 0 auto;}" +
      ".rbe-ai-title{display:flex;align-items:center;gap:10px;font-weight:850;color:#0f172a;}" +
      ".rbe-ai-title-icon{width:34px;height:34px;border-radius:10px;background:#eafaf2;color:#12a865;display:grid;place-items:center;}" +
      ".rbe-ai-window-btn,.rbe-ai-close{width:32px;height:32px;border:1px solid #cbd5e1;border-radius:999px;background:#fff;color:#172033;display:grid;place-items:center;cursor:pointer;}" +
      ".rbe-ai-window-btn .rbe-svg-icon,.rbe-ai-close .rbe-svg-icon{display:block;line-height:1;margin:0;}" +
      ".rbe-ai-window-btn[data-action='minimize'] .rbe-svg-icon{margin-bottom:8px;}" +
      ".rbe-ai-window-btn:hover,.rbe-ai-window-btn:focus-visible,.rbe-ai-close:hover,.rbe-ai-close:focus-visible{border-color:#2563eb;background:#eff6ff;color:#1d4ed8;}" +
      ".rbe-ai-body{padding:14px 16px;overflow:auto;display:grid;gap:14px;align-content:start;}" +
      ".rbe-ai-section{display:grid;gap:8px;}" +
      ".rbe-ai-label{font-size:12px;font-weight:850;text-transform:uppercase;letter-spacing:.03em;color:#667085;}" +
      ".rbe-ai-selection,.rbe-ai-result{border:1px solid #d7dee8;border-radius:10px;background:#f8fafc;color:#172033;padding:10px 12px;min-height:54px;max-height:132px;overflow:auto;font:13px/1.45 Arial,sans-serif;white-space:pre-wrap;}" +
      ".rbe-ai-result{position:relative;padding:38px 12px 12px;min-height:112px;max-height:260px;user-select:none;}" +
      ".rbe-ai-result-body{display:grid;gap:8px;}" +
      ".rbe-ai-result-body h4{margin:0;font-size:13px;line-height:1.3;color:#172033;}" +
      ".rbe-ai-result-body p{margin:0;}" +
      ".rbe-ai-result-body ul,.rbe-ai-result-body ol{margin:0;padding-left:18px;}" +
      ".rbe-ai-result-body pre{margin:0;max-height:190px;overflow:auto;border:1px solid #d7dee8;border-radius:8px;background:#eef2f7;padding:10px;font:12px/1.45 Consolas,'Liberation Mono',monospace;white-space:pre-wrap;}" +
      ".rbe-ai-result-copy{position:absolute;right:8px;top:7px;width:28px;height:28px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;color:#172033;display:grid;place-items:center;cursor:pointer;}" +
      ".rbe-ai-result-copy:hover,.rbe-ai-result-copy:focus-visible{border-color:#2563eb;background:#eff6ff;color:#1d4ed8;}" +
      ".rbe-ai-history-modal{position:fixed;inset:0;z-index:12050;background:rgba(15,23,42,.48);display:grid;place-items:center;padding:20px;}" +
      ".rbe-ai-history-modal[hidden]{display:none!important;}" +
      ".rbe-ai-history-dialog{width:min(860px,calc(100vw - 28px));height:min(720px,calc(100dvh - 28px));display:grid;grid-template-rows:auto auto 1fr auto;border:1px solid #cbd5e1;border-radius:14px;background:#fff;box-shadow:0 28px 80px rgba(15,23,42,.3);overflow:hidden;}" +
      ".rbe-ai-history-head,.rbe-ai-history-tools{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;border-bottom:1px solid #e2e8f0;background:#f8fafc;}" +
      ".rbe-ai-history-head h3{margin:0;font-size:16px;color:#172033;}" +
      ".rbe-ai-history-tools{justify-content:space-between;}" +
      ".rbe-ai-history-select-wrap{display:inline-flex;align-items:center;gap:8px;font-weight:700;color:#172033;}" +
      ".rbe-ai-history-actions{display:flex;align-items:center;gap:8px;margin-left:auto;}" +
      ".rbe-ai-history-list{overflow:auto;padding:12px;display:grid;gap:10px;background:#fff;}" +
      ".rbe-ai-history-check,.rbe-ai-history-select-all{appearance:none;-webkit-appearance:none;width:16px;height:16px;border:2px solid #94a3b8;border-radius:999px;background:#fff;display:inline-grid;place-items:center;cursor:pointer;vertical-align:middle;}" +
      ".rbe-ai-history-check:checked,.rbe-ai-history-select-all:checked{border-color:#16a34a;background:#16a34a;}" +
      ".rbe-ai-history-check:checked:after,.rbe-ai-history-select-all:checked:after{content:'';width:7px;height:4px;border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg);margin-top:-1px;}" +
      ".rbe-ai-history-delete{width:36px;height:36px;min-width:36px;padding:0;border-color:#fecaca;color:#b42318;}" +
      ".rbe-ai-history-delete:hover{border-color:#fca5a5;background:#fff1f2;color:#991b1b;}" +
      ".rbe-ai-history-item{display:grid;grid-template-columns:auto 1fr;gap:12px;border:1px solid #d7dee8;border-radius:10px;background:#fff;padding:12px;}" +
      ".rbe-ai-history-item input{margin-top:4px;}" +
      ".rbe-ai-history-item strong{display:block;font-size:13px;color:#172033;}" +
      ".rbe-ai-history-item small{display:block;margin-top:3px;color:#667085;}" +
      ".rbe-ai-history-item pre{margin:8px 0 0;max-height:120px;overflow:auto;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;padding:8px;white-space:pre-wrap;font:12px/1.45 Arial,sans-serif;}" +
      ".rbe-ai-selection.is-empty{color:#98a2b3;}" +
      ".rbe-ai-mode{display:flex;align-items:flex-start;gap:10px;border:1px solid #d7dee8;border-radius:10px;background:#fff;padding:10px 12px;cursor:pointer;}" +
      ".rbe-ai-mode:hover{border-color:#93c5fd;background:#eff6ff;}" +
      ".rbe-ai-mode input{width:18px;height:18px;margin:1px 0 0;accent-color:#16a34a;flex:0 0 auto;}" +
      ".rbe-ai-mode strong{display:block;font-size:13px;line-height:1.2;color:#172033;}" +
      ".rbe-ai-mode small{display:block;margin-top:3px;color:#667085;font-size:11px;line-height:1.3;}" +
      ".rbe-ai-action-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;}" +
      ".rbe-ai-action{border:1px solid #d7dee8;border-radius:10px;background:#fff;color:#172033;padding:10px;display:flex;gap:9px;align-items:flex-start;text-align:left;cursor:pointer;}" +
      ".rbe-ai-action:hover,.rbe-ai-action:focus-visible{border-color:#2563eb;background:#eff6ff;}" +
      ".rbe-ai-action .rbe-svg-icon{margin-top:2px;color:#1d4ed8;flex:0 0 auto;}" +
      ".rbe-ai-action strong{display:block;font-size:13px;line-height:1.2;}" +
      ".rbe-ai-action small{display:block;margin-top:3px;color:#667085;font-size:11px;line-height:1.25;}" +
      ".rbe-ai-prompt{width:100%;min-height:110px;resize:vertical;border:1px solid #d7dee8;border-radius:10px;padding:10px 12px;color:#172033;font:14px/1.45 Arial,sans-serif;}" +
      ".rbe-ai-prompt:focus{outline:none;border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.12);}" +
      ".rbe-ai-primary,.rbe-ai-secondary{border:1px solid #cbd5e1;border-radius:9px;background:#fff;color:#172033;font-weight:850;padding:9px 12px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;gap:8px;}" +
      ".rbe-ai-primary{border-color:#2563eb;background:#2563eb;color:#fff;}" +
      ".rbe-ai-primary:hover{background:#1d4ed8;}" +
      ".rbe-ai-secondary:hover{border-color:#2563eb;color:#1d4ed8;background:#eff6ff;}" +
      ".rbe-ai-primary[disabled],.rbe-ai-secondary[disabled],.rbe-ai-action[disabled]{opacity:.55;cursor:not-allowed;}" +
      ".rbe-ai-foot{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:12px 16px;border-top:1px solid #e2e8f0;background:#f8fafc;}" +
      ".rbe-ai-foot-actions{display:flex;gap:8px;align-items:center;justify-content:flex-end;min-width:0;width:100%;}" +
      ".rbe-ai-apply{flex:0 1 112px;min-width:96px;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark,.rbe.rbe-theme-dark .rbe-ai-drawer,.rbe-shell.rbe-theme-dark .rbe-ai-drawer,body:has(.rbe.rbe-theme-dark) .rbe-ai-drawer,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-drawer{border-color:#334155;background:#0f172a;color:#e5edf8;box-shadow:0 30px 90px rgba(2,6,23,.62);}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-head,.rbe.rbe-theme-dark .rbe-ai-head,.rbe-shell.rbe-theme-dark .rbe-ai-head,body:has(.rbe.rbe-theme-dark) .rbe-ai-head,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-head{border-bottom-color:#263449;background:linear-gradient(135deg,#101827,#1d293b);}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-title,.rbe.rbe-theme-dark .rbe-ai-title,.rbe-shell.rbe-theme-dark .rbe-ai-title,body:has(.rbe.rbe-theme-dark) .rbe-ai-title,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-title{color:#f8fafc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-title-icon,.rbe.rbe-theme-dark .rbe-ai-title-icon,.rbe-shell.rbe-theme-dark .rbe-ai-title-icon,body:has(.rbe.rbe-theme-dark) .rbe-ai-title-icon,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-title-icon{background:linear-gradient(135deg,rgba(14,165,233,.18),rgba(45,212,191,.18));color:#38d9ff;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-window-btn,.rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-close,.rbe.rbe-theme-dark .rbe-ai-window-btn,.rbe.rbe-theme-dark .rbe-ai-close,.rbe-shell.rbe-theme-dark .rbe-ai-window-btn,.rbe-shell.rbe-theme-dark .rbe-ai-close,body:has(.rbe.rbe-theme-dark) .rbe-ai-window-btn,body:has(.rbe.rbe-theme-dark) .rbe-ai-close,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-window-btn,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-close{border-color:#334155;background:#111827;color:#f8fafc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-window-btn:hover,.rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-window-btn:focus-visible,.rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-close:hover,.rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-close:focus-visible,.rbe.rbe-theme-dark .rbe-ai-window-btn:hover,.rbe.rbe-theme-dark .rbe-ai-window-btn:focus-visible,.rbe.rbe-theme-dark .rbe-ai-close:hover,.rbe.rbe-theme-dark .rbe-ai-close:focus-visible,.rbe-shell.rbe-theme-dark .rbe-ai-window-btn:hover,.rbe-shell.rbe-theme-dark .rbe-ai-window-btn:focus-visible,.rbe-shell.rbe-theme-dark .rbe-ai-close:hover,.rbe-shell.rbe-theme-dark .rbe-ai-close:focus-visible,body:has(.rbe.rbe-theme-dark) .rbe-ai-window-btn:hover,body:has(.rbe.rbe-theme-dark) .rbe-ai-window-btn:focus-visible,body:has(.rbe.rbe-theme-dark) .rbe-ai-close:hover,body:has(.rbe.rbe-theme-dark) .rbe-ai-close:focus-visible,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-window-btn:hover,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-window-btn:focus-visible,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-close:hover,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-close:focus-visible{border-color:#60a5fa;background:#172033;color:#93c5fd;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-body,.rbe.rbe-theme-dark .rbe-ai-body,.rbe-shell.rbe-theme-dark .rbe-ai-body,body:has(.rbe.rbe-theme-dark) .rbe-ai-body,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-body{background:#0f172a;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-label,.rbe.rbe-theme-dark .rbe-ai-label,.rbe-shell.rbe-theme-dark .rbe-ai-label,body:has(.rbe.rbe-theme-dark) .rbe-ai-label,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-label{color:#aab8cf;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-selection,.rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-result,.rbe.rbe-theme-dark .rbe-ai-selection,.rbe.rbe-theme-dark .rbe-ai-result,.rbe-shell.rbe-theme-dark .rbe-ai-selection,.rbe-shell.rbe-theme-dark .rbe-ai-result,body:has(.rbe.rbe-theme-dark) .rbe-ai-selection,body:has(.rbe.rbe-theme-dark) .rbe-ai-result,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-selection,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-result{border-color:#334155;background:#111827;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-result-body h4,.rbe.rbe-theme-dark .rbe-ai-result-body h4,.rbe-shell.rbe-theme-dark .rbe-ai-result-body h4,body:has(.rbe.rbe-theme-dark) .rbe-ai-result-body h4,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-result-body h4{color:#f8fafc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-result-body pre,.rbe.rbe-theme-dark .rbe-ai-result-body pre,.rbe-shell.rbe-theme-dark .rbe-ai-result-body pre,body:has(.rbe.rbe-theme-dark) .rbe-ai-result-body pre,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-result-body pre{border-color:#334155;background:#0f172a;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-result-copy,.rbe.rbe-theme-dark .rbe-ai-result-copy,.rbe-shell.rbe-theme-dark .rbe-ai-result-copy,body:has(.rbe.rbe-theme-dark) .rbe-ai-result-copy,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-result-copy{border-color:#334155;background:#111827;color:#f8fafc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-selection.is-empty,.rbe.rbe-theme-dark .rbe-ai-selection.is-empty,.rbe-shell.rbe-theme-dark .rbe-ai-selection.is-empty,body:has(.rbe.rbe-theme-dark) .rbe-ai-selection.is-empty,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-selection.is-empty{color:#94a3b8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-mode,.rbe.rbe-theme-dark .rbe-ai-mode,.rbe-shell.rbe-theme-dark .rbe-ai-mode,body:has(.rbe.rbe-theme-dark) .rbe-ai-mode,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-mode{border-color:#334155;background:#111827;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-mode:hover,.rbe.rbe-theme-dark .rbe-ai-mode:hover,.rbe-shell.rbe-theme-dark .rbe-ai-mode:hover,body:has(.rbe.rbe-theme-dark) .rbe-ai-mode:hover,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-mode:hover{border-color:#38bdf8;background:#172033;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-mode strong,.rbe.rbe-theme-dark .rbe-ai-mode strong,.rbe-shell.rbe-theme-dark .rbe-ai-mode strong,body:has(.rbe.rbe-theme-dark) .rbe-ai-mode strong,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-mode strong{color:#f8fafc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-mode small,.rbe.rbe-theme-dark .rbe-ai-mode small,.rbe-shell.rbe-theme-dark .rbe-ai-mode small,body:has(.rbe.rbe-theme-dark) .rbe-ai-mode small,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-mode small{color:#aab8cf;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-action,.rbe.rbe-theme-dark .rbe-ai-action,.rbe-shell.rbe-theme-dark .rbe-ai-action,body:has(.rbe.rbe-theme-dark) .rbe-ai-action,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-action{border-color:#334155;background:#111827;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-action:hover,.rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-action:focus-visible,.rbe.rbe-theme-dark .rbe-ai-action:hover,.rbe.rbe-theme-dark .rbe-ai-action:focus-visible,.rbe-shell.rbe-theme-dark .rbe-ai-action:hover,.rbe-shell.rbe-theme-dark .rbe-ai-action:focus-visible,body:has(.rbe.rbe-theme-dark) .rbe-ai-action:hover,body:has(.rbe.rbe-theme-dark) .rbe-ai-action:focus-visible,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-action:hover,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-action:focus-visible{border-color:#38bdf8;background:#172033;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-action .rbe-svg-icon,.rbe.rbe-theme-dark .rbe-ai-action .rbe-svg-icon,.rbe-shell.rbe-theme-dark .rbe-ai-action .rbe-svg-icon,body:has(.rbe.rbe-theme-dark) .rbe-ai-action .rbe-svg-icon,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-action .rbe-svg-icon{color:#38bdf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-action strong,.rbe.rbe-theme-dark .rbe-ai-action strong,.rbe-shell.rbe-theme-dark .rbe-ai-action strong,body:has(.rbe.rbe-theme-dark) .rbe-ai-action strong,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-action strong{color:#f8fafc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-action small,.rbe.rbe-theme-dark .rbe-ai-action small,.rbe-shell.rbe-theme-dark .rbe-ai-action small,body:has(.rbe.rbe-theme-dark) .rbe-ai-action small,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-action small{color:#aab8cf;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-prompt,.rbe.rbe-theme-dark .rbe-ai-prompt,.rbe-shell.rbe-theme-dark .rbe-ai-prompt,body:has(.rbe.rbe-theme-dark) .rbe-ai-prompt,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-prompt{border-color:#334155;background:#111827;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-prompt::placeholder,.rbe.rbe-theme-dark .rbe-ai-prompt::placeholder,.rbe-shell.rbe-theme-dark .rbe-ai-prompt::placeholder,body:has(.rbe.rbe-theme-dark) .rbe-ai-prompt::placeholder,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-prompt::placeholder{color:#94a3b8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-prompt:focus,.rbe.rbe-theme-dark .rbe-ai-prompt:focus,.rbe-shell.rbe-theme-dark .rbe-ai-prompt:focus,body:has(.rbe.rbe-theme-dark) .rbe-ai-prompt:focus,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-prompt:focus{border-color:#38bdf8;box-shadow:0 0 0 3px rgba(56,189,248,.18);}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-secondary,.rbe.rbe-theme-dark .rbe-ai-secondary,.rbe-shell.rbe-theme-dark .rbe-ai-secondary,body:has(.rbe.rbe-theme-dark) .rbe-ai-secondary,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-secondary{border-color:#334155;background:#111827;color:#e5edf8;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-secondary:hover,.rbe.rbe-theme-dark .rbe-ai-secondary:hover,.rbe-shell.rbe-theme-dark .rbe-ai-secondary:hover,body:has(.rbe.rbe-theme-dark) .rbe-ai-secondary:hover,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-secondary:hover{border-color:#38bdf8;background:#172033;color:#7dd3fc;}" +
      ".rbe-ai-drawer.rbe-ai-theme-dark .rbe-ai-foot,.rbe.rbe-theme-dark .rbe-ai-foot,.rbe-shell.rbe-theme-dark .rbe-ai-foot,body:has(.rbe.rbe-theme-dark) .rbe-ai-foot,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-foot{border-top-color:#263449;background:#111827;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-dialog,.rbe.rbe-theme-dark~.rbe-ai-history-modal .rbe-ai-history-dialog,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-dialog,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-dialog{border-color:#334155;background:#0f172a;color:#e5edf8;box-shadow:0 30px 90px rgba(2,6,23,.62);}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-head,.rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-tools,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-head,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-tools,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-head,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-tools{border-bottom-color:#263449;background:#111827;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-head h3,.rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-select-wrap,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-head h3,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-select-wrap,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-head h3,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-select-wrap{color:#f8fafc;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-list,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-list,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-list{background:#0f172a;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-item,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-item,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-item{border-color:#334155;background:#111827;color:#e5edf8;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-item strong,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-item strong,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-item strong{color:#f8fafc;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-item small,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-item small,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-item small{color:#aab8cf;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-item pre,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-item pre,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-item pre{border-color:#334155;background:#0f172a;color:#e5edf8;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-check,.rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-select-all,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-check,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-select-all,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-check,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-select-all{border-color:#64748b;background:#0f172a;}" +
      ".rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-check:checked,.rbe-ai-history-modal.rbe-ai-theme-dark .rbe-ai-history-select-all:checked,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-check:checked,body:has(.rbe.rbe-theme-dark) .rbe-ai-history-select-all:checked,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-check:checked,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-history-select-all:checked{border-color:#22c55e;background:#22c55e;}" +
      ".rbe.rbe-theme-dark .rbe-ai-inline-btn,.rbe.rbe-theme-dark .rbe-ai-toolbar-btn,.rbe-shell.rbe-theme-dark .rbe-ai-inline-btn,.rbe-shell.rbe-theme-dark .rbe-ai-toolbar-btn,body:has(.rbe.rbe-theme-dark) .rbe-ai-inline-btn,body:has(.rbe.rbe-theme-dark) .rbe-ai-toolbar-btn,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-inline-btn,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-toolbar-btn{border-color:#334155;background:#111827;color:#38d9ff;box-shadow:0 8px 24px rgba(2,6,23,.32);}" +
      ".rbe.rbe-theme-dark .rbe-ai-inline-btn:hover,.rbe.rbe-theme-dark .rbe-ai-toolbar-btn:hover:not(:disabled),.rbe-shell.rbe-theme-dark .rbe-ai-inline-btn:hover,.rbe-shell.rbe-theme-dark .rbe-ai-toolbar-btn:hover:not(:disabled),body:has(.rbe.rbe-theme-dark) .rbe-ai-inline-btn:hover,body:has(.rbe.rbe-theme-dark) .rbe-ai-toolbar-btn:hover:not(:disabled),body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-inline-btn:hover,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-toolbar-btn:hover:not(:disabled){border-color:#38bdf8;background:#172033;color:#7dd3fc;}" +
      ".rbe.rbe-theme-dark .rbe-ai-inline-btn.is-open,.rbe.rbe-theme-dark .rbe-ai-toolbar-btn.is-open,.rbe-shell.rbe-theme-dark .rbe-ai-inline-btn.is-open,.rbe-shell.rbe-theme-dark .rbe-ai-toolbar-btn.is-open,body:has(.rbe.rbe-theme-dark) .rbe-ai-inline-btn.is-open,body:has(.rbe.rbe-theme-dark) .rbe-ai-toolbar-btn.is-open,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-inline-btn.is-open,body:has(.rbe-shell.rbe-theme-dark) .rbe-ai-toolbar-btn.is-open{border-color:#22c55e;background:#10251c;color:#86efac;}" +
      ".rbe-toast-stack{position:fixed;right:18px;bottom:18px;z-index:12000;display:grid;gap:10px;width:min(360px,calc(100vw - 24px));pointer-events:none;}" +
      ".rbe-toast{display:flex;align-items:flex-start;gap:10px;border:1px solid #d7dee8;border-radius:12px;background:#fff;color:#172033;padding:12px 14px;box-shadow:0 18px 48px rgba(15,23,42,.18);opacity:0;transform:translateY(12px) scale(.98);transition:opacity .24s ease,transform .24s ease;pointer-events:auto;}" +
      ".rbe-toast.is-show{opacity:1;transform:translateY(0) scale(1);}" +
      ".rbe-toast.is-hiding{opacity:0;transform:translateY(10px) scale(.98);}" +
      ".rbe-toast i{margin-top:2px;}" +
      ".rbe-toast strong{display:block;font-size:13px;line-height:1.25;}" +
      ".rbe-toast span{display:block;margin-top:2px;font-size:12px;line-height:1.4;color:#475467;}" +
      ".rbe-toast.is-error{border-color:#fecaca;background:#fff7f7;}" +
      ".rbe-toast.is-error i,.rbe-toast.is-error strong{color:#b42318;}" +
      ".rbe-toast.is-warning{border-color:#fedf89;background:#fffbeb;}" +
      ".rbe-toast.is-warning i,.rbe-toast.is-warning strong{color:#b54708;}" +
      ".rbe-toast.is-info{border-color:#bfdbfe;background:#eff6ff;}" +
      ".rbe-toast.is-info i,.rbe-toast.is-info strong{color:#1d4ed8;}" +
      "@media (max-width:900px){.rbe-ai-toolbar-btn{position:static;transform:none;order:-1;}}" +
      "@media (max-width:700px){.rbe-ai-drawer{inset:10px;width:auto;height:auto;max-height:calc(100dvh - 20px);border-radius:12px;}.rbe-ai-drawer.is-maximized{inset:10px;width:auto;height:auto;max-height:calc(100dvh - 20px);transform:translateX(0);}.rbe-ai-action-grid{grid-template-columns:1fr;}.rbe-ai-head,.rbe-ai-body,.rbe-ai-foot{padding-left:12px;padding-right:12px;}}" +
      "@media (max-width:520px){.rbe-ai-foot-actions{justify-content:stretch;width:100%;}.rbe-ai-primary,.rbe-ai-secondary{width:100%;}.rbe-ai-apply{flex:1 1 auto;min-width:0;}.rbe-ai-title{min-width:0;}.rbe-ai-title span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.rbe-toast-stack{right:10px;bottom:10px;width:calc(100vw - 20px);}}";
    document.head.appendChild(style);
  }

  function closestBlock(node) {
    if (!node) return null;
    var element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
    return element && element.closest ? element.closest(".rbe-block") : null;
  }

  function isRangeInsideEditor(editor, range) {
    if (!editor || !editor.root || !range) return false;
    var node = range.commonAncestorContainer;
    if (node && node.nodeType !== Node.ELEMENT_NODE) node = node.parentElement;
    return !!(node && editor.root.contains(node));
  }

  function captureSelection(editor) {
    var selection = window.getSelection();
    if (selection && selection.rangeCount && !selection.isCollapsed) {
      var range = selection.getRangeAt(0);
      if (isRangeInsideEditor(editor, range)) {
        editor.savedRange = range.cloneRange();
        return editor.savedRange;
      }
    }
    return editor.savedRange && isRangeInsideEditor(editor, editor.savedRange) ? editor.savedRange : null;
  }

  function selectedText(editor) {
    var range = captureSelection(editor);
    return range ? range.toString().trim() : "";
  }

  var BLOCK_SCHEMA_CATALOG = [
    { type: "paragraph", label: "Text", schema: "{text,alignment}" },
    { type: "heading", label: "Heading", schema: "{level,text,alignment}" },
    { type: "list", label: "List", schema: "{style,items:[{text,level,alignment,style}]}" },
    { type: "checklist", label: "Checklist", schema: "{items:[{text,checked,level}]}" },
    { type: "quote", label: "Quote", schema: "{text,caption,alignment}" },
    { type: "callout", label: "Callout", schema: "{tone,text,alignment}" },
    { type: "table", label: "Table", schema: "{rows,withHeadings,align,width}" },
    { type: "delimiter", label: "Divider", schema: "{style}" },
    { type: "code", label: "Code", schema: "{language,code}" },
    { type: "raw", label: "Raw HTML", schema: "{html}" },
    { type: "image", label: "Image", schema: "{items:[{url,alt,caption,alignment,width}]}" },
    { type: "attaches", label: "Attachment", schema: "{items:[{name,url,type,size,alignment}]}" },
    { type: "audio", label: "Audio", schema: "{title,url}" },
    { type: "drawing", label: "Drawing", schema: "{image,color,size}" },
    { type: "linkPreview", label: "Link Preview", schema: "{url,title,description}" },
    { type: "button", label: "Button", schema: "{text,url,background,color,alignment}" },
    { type: "embed", label: "Embed", schema: "{source,caption}" },
    { type: "chart", label: "Chart", schema: "{type,title,labels,values,caption}" },
    { type: "latex", label: "LaTeX", schema: "{code,display}" },
    { type: "mermaid", label: "Mermaid", schema: "{code,alignment,openOnInsert}" },
    { type: "columns", label: "Columns", schema: "{count,headers,columns,headerAlignments,columnAlignments}" },
    { type: "signatureRow", label: "Multiple blocks in a row", schema: "{blocks:[{type,data}]}" },
    { type: "toggle", label: "Toggle", schema: "{title,open,blocks:[{type,data}]}" },
    { type: "signature", label: "Signature", schema: "{label,width,alignment}" },
    { type: "signatureFlow", label: "Signature Flow", schema: "{title,steps:[{id,label}]}" },
    { type: "letterHead", label: "Letter Head", schema: "{companyName,address,email,mobile,logoUrl,watermarkUrl,timestamp,blocks:[{type,data}]}" }
  ];

  function clonePlain(value) {
    try {
      return JSON.parse(JSON.stringify(value == null ? null : value));
    } catch (error) {
      return null;
    }
  }

  function limitText(value, limit) {
    value = String(value == null ? "" : value);
    return value.length > limit ? value.slice(0, limit) : value;
  }

  function compactBlockData(data) {
    data = clonePlain(data || {}) || {};
    Object.keys(data).forEach(function (key) {
      if (typeof data[key] === "string") data[key] = limitText(data[key], key === "code" || key === "html" ? 1600 : 700);
      if (Array.isArray(data[key]) && data[key].length > 12) data[key] = data[key].slice(0, 12);
    });
    if (Array.isArray(data.blocks) && data.blocks.length > 10) data.blocks = data.blocks.slice(0, 10);
    return data;
  }

  function compactBlock(block, index) {
    if (!block || typeof block !== "object") return null;
    return {
      index: index,
      id: String(block.id || ""),
      type: String(block.type || "paragraph"),
      data: compactBlockData(block.data || {})
    };
  }

  function contextWindow(blocks, currentIndex) {
    blocks = Array.isArray(blocks) ? blocks : [];
    if (!blocks.length) return [];
    if (currentIndex < 0) currentIndex = blocks.length - 1;
    var start = Math.max(0, currentIndex - 4);
    var end = Math.min(blocks.length, currentIndex + 5);
    return blocks.slice(start, end).map(function (block, offset) {
      return compactBlock(block, start + offset);
    }).filter(Boolean);
  }

  function toolCatalogFor(editor) {
    var available = editor && Array.isArray(editor.availableTools) ? editor.availableTools : null;
    return BLOCK_SCHEMA_CATALOG.filter(function (tool) {
      return !available || available.indexOf(tool.type) !== -1;
    }).map(function (tool) {
      var feature = "";
      var enabled = true;
      if (editor && typeof editor.getPremiumFeatureForTool === "function") {
        feature = editor.getPremiumFeatureForTool.call(editor, tool.type) || "";
      }
      if (feature && editor && typeof editor.isPremiumFeatureEnabled === "function") {
        try {
          enabled = !!editor.isPremiumFeatureEnabled.call(editor, feature);
        } catch (error) {
          enabled = false;
        }
      }
      return Object.assign({}, tool, {
        premiumFeature: feature,
        available: enabled
      });
    });
  }

  function editorAIContext(editor, selected) {
    var data = typeof editor.getData === "function" ? editor.getData() : null;
    var blocks = data && Array.isArray(data.blocks) ? data.blocks : [];
    var current = typeof editor.getCurrentBlock === "function" ? editor.getCurrentBlock() : null;
    var currentIndex = current && typeof editor.indexOfBlock === "function" ? editor.indexOfBlock(current) : blocks.length - 1;
    return {
      editor: "BlockWriteAI",
      mode: "universal_block_agent",
      selectedText: limitText(selected || "", 3000),
      currentBlockIndex: currentIndex,
      currentBlockType: current && current.dataset ? String(current.dataset.type || "") : "",
      availableBlocks: toolCatalogFor(editor),
      nearbyBlocks: contextWindow(blocks, currentIndex),
      documentSummary: {
        blockCount: blocks.length,
        blockTypes: blocks.map(function (block) { return block && block.type ? block.type : "paragraph"; }).slice(0, 80)
      }
    };
  }

  function textToFragment(text) {
    var fragment = document.createDocumentFragment();
    String(text || "").split(/\n/).forEach(function (line, index) {
      if (index) fragment.appendChild(document.createElement("br"));
      fragment.appendChild(document.createTextNode(line));
    });
    return fragment;
  }

  function replaceSelection(editor, text, range) {
    range = range || editor.__blockwriteaiAI && editor.__blockwriteaiAI.lastRange || editor.savedRange;
    if (!range || !isRangeInsideEditor(editor, range)) return false;
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range);
    range.deleteContents();
    var fragment = textToFragment(text);
    var last = fragment.lastChild;
    range.insertNode(fragment);
    if (last && last.parentNode) {
      var next = document.createRange();
      next.setStartAfter(last);
      next.collapse(true);
      selection.removeAllRanges();
      selection.addRange(next);
      editor.savedRange = next.cloneRange();
    }
    if (typeof editor.changed === "function") editor.changed(true);
    if (typeof editor.updateInlineToolbarState === "function") editor.updateInlineToolbarState();
    return true;
  }

  function endpointFor(editor) {
    var ai = editor && editor.options ? editor.options.ai : null;
    if (ai && typeof ai.endpoint === "string" && ai.endpoint) return ai.endpoint;
    if (BlockWriteAI.ai && typeof BlockWriteAI.ai.endpoint === "string" && BlockWriteAI.ai.endpoint) return BlockWriteAI.ai.endpoint;
    if (BlockWriteAI.platformEndpoints && typeof BlockWriteAI.platformEndpoints.aiGenerate === "string") return BlockWriteAI.platformEndpoints.aiGenerate;
    return "api/ai.php";
  }

  function qualityEndpointFor(editor, action) {
    var root = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : {};
    action = "ai_quality_" + String(action || "rules");
    if (root.BlockWriteAIExamplePremium && typeof root.BlockWriteAIExamplePremium.action === "function") {
      return root.BlockWriteAIExamplePremium.action(action);
    }
    var endpoint = endpointFor(editor);
    if (/[?&](route|action)=ai_generate(?:_stream)?(?:[&#]|$)/i.test(endpoint)) {
      return endpoint.replace(/([?&](?:route|action)=)ai_generate(?:_stream)?([&#]?)/i, "$1" + action + "$2");
    }
    if (/\/api\/ai(?:\.php)?(?:[?#].*)?$/i.test(endpoint)) {
      return endpoint.replace(/\/api\/ai(?:\.php)?(?:[?#].*)?$/i, "/api/blockwriteai-premium.php?action=" + encodeURIComponent(action));
    }
    return "api/blockwriteai-premium.php?action=" + encodeURIComponent(action);
  }

  function qualityRulesText(rules) {
    rules = Array.isArray(rules) ? rules : [];
    return rules.map(function (rule, index) {
      return (index + 1) + ". " + String(rule.instruction || rule.intent_type || rule.pattern || "").trim();
    }).filter(function (line) {
      return /\.\s+\S/.test(line);
    }).join("\n");
  }

  function promptModeContract(prompt) {
    var original = String(prompt || "").trim();
    var working = original;
    var prefixes = [];
    var suffixes = [];
    var prefixMap = {
      "EXPOSE": {
        id: "expose",
        instruction: "EXPOSE mode: reveal hidden assumptions, gaps, contradictions, risks, missing information, unsupported claims, and validation issues before finalizing the answer."
      },
      "IQ200": {
        id: "deep_reasoning",
        instruction: "DEEP THINK mode: use structured multi-angle reasoning; consider objectives, constraints, alternatives, edge cases, tradeoffs, and verification checks before producing concise output."
      },
      "DEEP THINK": {
        id: "deep_reasoning",
        instruction: "DEEP THINK mode: use structured multi-angle reasoning; consider objectives, constraints, alternatives, edge cases, tradeoffs, and verification checks before producing concise output."
      },
      "DEEP DIVE": {
        id: "deep_reasoning",
        instruction: "DEEP DIVE mode: analyze deeply across causes, evidence, tradeoffs, risks, and recommended next actions."
      },
      "AUTOPSY": {
        id: "autopsy",
        instruction: "AUTOPSY mode: diagnose the subject systematically: what works, what fails, root causes, evidence, impact, missing information, and specific fixes."
      },
      "KILL CRITIC": {
        id: "kill_critic",
        instruction: "KILL CRITIC mode: act as a skeptical expert; challenge assumptions, identify failure scenarios, objections, weak evidence, risks, and concrete improvements."
      }
    };
    var changed = true;
    while (changed) {
      changed = false;
      Object.keys(prefixMap).forEach(function (name) {
        var re = new RegExp("^\\s*" + name.replace(/\s+/g, "\\s+") + "\\s*:\\s*", "i");
        if (re.test(working)) {
          var mode = prefixMap[name];
          if (!prefixes.some(function (item) { return item.id === mode.id; })) prefixes.push(mode);
          working = working.replace(re, "");
          changed = true;
        }
      });
    }
    if (/\s*:?\s*10X\s*$/i.test(working)) {
      suffixes.push({
        id: "10x",
        instruction: "10X suffix: after satisfying the base request, improve usefulness, clarity, completeness, depth, structure, and actionability. Rebuild weak output into production-ready content."
      });
      working = working.replace(/\s*:?\s*10X\s*$/i, "").trim();
    }
    var modes = prefixes.concat(suffixes);
    return {
      originalPrompt: original,
      cleanPrompt: working || original,
      modes: modes.map(function (mode) { return mode.id; }),
      instructions: modes.map(function (mode) { return mode.instruction; })
    };
  }

  function promptModeInstructions(contract) {
    contract = contract || {};
    if (!contract.instructions || !contract.instructions.length) return "";
    return "Prompt Power Modes detected: " + contract.modes.join(", ") + "\n" + contract.instructions.map(function (item, index) {
      return (index + 1) + ". " + item;
    }).join("\n");
  }

  function fetchQualityRules(editor, feature, prompt) {
    if (typeof fetch !== "function") return Promise.resolve([]);
    return fetch(qualityEndpointFor(editor, "rules"), {
      method: "POST",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: JSON.stringify({ feature: feature || "generate_blocks", prompt: String(prompt || "") })
    }).then(function (response) {
      return response.json().catch(function () { return {}; });
    }).then(function (payload) {
      return Array.isArray(payload.rules) ? payload.rules : [];
    }).catch(function () {
      return [];
    });
  }

  function logQualityEvent(editor, payload) {
    if (typeof fetch !== "function") return;
    try {
      fetch(qualityEndpointFor(editor, "event"), {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        body: JSON.stringify(payload || {})
      }).catch(function () {});
    } catch (error) {}
  }

  function streamEndpointFor(editor) {
    var ai = editor && editor.options ? editor.options.ai : null;
    if (ai && typeof ai.streamEndpoint === "string" && ai.streamEndpoint) return ai.streamEndpoint;
    if (BlockWriteAI.ai && typeof BlockWriteAI.ai.streamEndpoint === "string" && BlockWriteAI.ai.streamEndpoint) return BlockWriteAI.ai.streamEndpoint;
    var endpoint = endpointFor(editor);
    if (/\/api\/ai_generate\.php(?:[?#].*)?$/i.test(endpoint)) return endpoint.replace(/\/api\/ai_generate\.php(\?.*)?$/i, "/api/ai_generate_stream.php$1");
    if (/[?&](route|action)=ai_generate(?:[&#]|$)/i.test(endpoint)) return endpoint.replace(/([?&](?:route|action)=)ai_generate([&#]?)/i, "$1ai_generate_stream$2");
    if (BlockWriteAI.platformEndpoints && typeof BlockWriteAI.platformEndpoints.aiGenerateStream === "string") return BlockWriteAI.platformEndpoints.aiGenerateStream;
    return "";
  }

  function isPlatformAIEndpoint(endpoint) {
    endpoint = String(endpoint || "");
    return /\/api\/ai_generate(?:_stream)?\.php(?:[?#].*)?$/i.test(endpoint) || /[?&](route|action)=ai_generate(?:_stream)?(?:[&#]|$)/i.test(endpoint);
  }

  function attachPremiumCredentials(editor, payload, endpoint) {
    payload = Object.assign({}, payload || {});
    if (!isPlatformAIEndpoint(endpoint)) return payload;
    var premium = editor && editor.premiumOptions ? editor.premiumOptions : {};
    if (premium.serverMode) {
      if (premium.sessionToken && !payload.session_token) payload.session_token = premium.sessionToken;
      return payload;
    }
    var root = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : {};
    var licenseKey = premium.licenseKey || premium.license_key || root.BlockWriteAILicenseKey || "";
    var authorizationToken = licenseKey ? "" : premium.authorizationToken || premium.authorization_token || root.BlockWriteAIAuthorizationToken || "";
    var sessionToken = premium.sessionToken || premium.session_token || "";
    try {
      authorizationToken = licenseKey ? "" : authorizationToken ||
        root.sessionStorage && root.sessionStorage.getItem("bwai_authorization_token") ||
        root.localStorage && root.localStorage.getItem("bwai_authorization_token") ||
        "";
      licenseKey = licenseKey ||
        root.sessionStorage && (root.sessionStorage.getItem("blockwriteai_license_key") || root.sessionStorage.getItem("bwai_license_key")) ||
        root.localStorage && (root.localStorage.getItem("blockwriteai_license_key") || root.localStorage.getItem("bwai_license_key")) ||
        "";
      sessionToken = sessionToken ||
        root.sessionStorage && (root.sessionStorage.getItem("blockwriteai_session_token") || root.sessionStorage.getItem("bwai_session_token")) ||
        root.localStorage && (root.localStorage.getItem("blockwriteai_session_token") || root.localStorage.getItem("bwai_session_token")) ||
        "";
    } catch (error) {}
    if (licenseKey) authorizationToken = "";
    if (authorizationToken && !payload.authorization_token) payload.authorization_token = authorizationToken;
    else if (licenseKey && !payload.license_key) payload.license_key = licenseKey;
    if (sessionToken && !payload.session_token) payload.session_token = sessionToken;
    return payload;
  }

  function aiEnabled(editor) {
    if (!editor || typeof editor.isPremiumFeatureEnabled !== "function") return true;
    try {
      return editor.isPremiumFeatureEnabled.call(editor, "ai");
    } catch (error) {
      return false;
    }
  }

  function aiLockedMessage(editor) {
    if (editor && typeof editor.premiumMessage === "function") {
      try {
        return editor.premiumMessage.call(editor, "ai");
      } catch (error) {}
    }
    return "AI is locked. Please add an active BlockWriteAI premium license.";
  }

  function requireAI(editor) {
    if (aiEnabled(editor)) return true;
    showToast(editor, aiLockedMessage(editor), "warning");
    if (editor && typeof editor.showPremiumUpgradeModal === "function") {
      try {
        editor.showPremiumUpgradeModal.call(editor, "ai", "locked");
      } catch (error) {}
    }
    return false;
  }

  function consumeAIUsage(editor, payload) {
    if (isPlatformAIEndpoint(endpointFor(editor))) return Promise.resolve();
    if (editor && typeof editor.consumePremiumUsage === "function") {
      try {
        return Promise.resolve(
          editor.consumePremiumUsage.call(editor, "ai", {
            action: payload && payload.action ? payload.action : "generate",
            source: "ai_plugin",
            prompt: payload && payload.prompt ? payload.prompt : "",
            selected_text: payload && payload.text ? payload.text : "",
            prompt_modes: payload && payload.prompt_modes ? payload.prompt_modes : promptModeContract(payload && payload.prompt ? payload.prompt : "")
          })
        );
      } catch (error) {
        return Promise.reject(error);
      }
    }
    return Promise.resolve();
  }

  function usageDetailEndpointFor(editor) {
    var premium = editor && editor.premiumOptions ? editor.premiumOptions : {};
    if (premium.usageDetailEndpoint) return premium.usageDetailEndpoint;
    if (premium.usageEndpoint) return premium.usageEndpoint.replace(/ai_usage\.php(?:\?.*)?$/i, "ai_usage_detail.php");
    return "";
  }

  function historyEndpointFor(editor) {
    var premium = editor && editor.premiumOptions ? editor.premiumOptions : {};
    if (premium.aiHistoryEndpoint) return premium.aiHistoryEndpoint;
    if (premium.historyEndpoint) return premium.historyEndpoint;
    if (premium.usageEndpoint && /[?&](route|action)=ai_usage(?:[&#]|$)/i.test(premium.usageEndpoint)) {
      return premium.usageEndpoint.replace(/([?&](?:route|action)=)ai_usage([&#]?)/i, "$1ai_history$2");
    }
    if (premium.usageDetailEndpoint && /[?&](route|action)=ai_usage_detail(?:[&#]|$)/i.test(premium.usageDetailEndpoint)) {
      return premium.usageDetailEndpoint.replace(/([?&](?:route|action)=)ai_usage_detail([&#]?)/i, "$1ai_history$2");
    }
    var endpoint = endpointFor(editor);
    if (/[?&](route|action)=ai_generate_stream(?:[&#]|$)/i.test(endpoint)) return endpoint.replace(/([?&](?:route|action)=)ai_generate_stream([&#]?)/i, "$1ai_history$2");
    if (/[?&](route|action)=ai_generate(?:[&#]|$)/i.test(endpoint)) return endpoint.replace(/([?&](?:route|action)=)ai_generate([&#]?)/i, "$1ai_history$2");
    if (/\/api\/ai_generate_stream\.php(?:[?#].*)?$/i.test(endpoint)) return endpoint.replace(/\/api\/ai_generate_stream\.php(\?.*)?$/i, "/api/ai_history.php$1");
    if (/\/api\/ai_generate\.php(?:[?#].*)?$/i.test(endpoint)) return endpoint.replace(/\/api\/ai_generate\.php(\?.*)?$/i, "/api/ai_history.php$1");
    return "";
  }

  function trimUsageText(value, limit) {
    value = String(value == null ? "" : value).trim();
    return value.length > limit ? value.slice(0, limit) : value;
  }

  function usageEventId(editor, usageState) {
    if (usageState && usageState.usage_event_id) return usageState.usage_event_id;
    if (usageState && usageState.usage_result && usageState.usage_result.event_id) return usageState.usage_result.event_id;
    if (editor && editor.lastPremiumUsageResult && editor.lastPremiumUsageResult.event_id) return editor.lastPremiumUsageResult.event_id;
    return null;
  }

  function responseSummary(body) {
    if (!body) return "";
    if (typeof body.result === "string") return body.result;
    if (Array.isArray(body.blocks)) return "Generated " + body.blocks.length + " block(s).";
    if (typeof body.error === "string") return body.error;
    try {
      return JSON.stringify(body);
    } catch (error) {
      return "";
    }
  }

  function blockText(block) {
    if (!block || !block.data) return "";
    var data = block.data;
    if (typeof data.text === "string") return data.text;
    if (typeof data.code === "string") return data.code;
    if (Array.isArray(data.items)) {
      return data.items.map(function (item) {
        return typeof item === "string" ? item : String(item && item.text || "");
      }).filter(Boolean).join("\n");
    }
    if (Array.isArray(data.rows)) return data.rows.map(function (row) { return (row || []).join(" | "); }).join("\n");
    if (Array.isArray(data.blocks)) return data.blocks.map(blockText).filter(Boolean).join("\n");
    if (data.title) return String(data.title);
    return "";
  }

  function readableFromBlocks(blocks) {
    blocks = Array.isArray(blocks) ? blocks : [];
    if (!blocks.length) return "";
    return blocks.map(function (block, index) {
      var type = String(block && block.type || "block");
      var text = blockText(block);
      var label = type === "paragraph" ? "Text" : type.charAt(0).toUpperCase() + type.slice(1);
      return (index + 1) + ". " + label + (text ? "\n" + text : "");
    }).join("\n\n");
  }

  function readableResult(value) {
    if (value && typeof value === "object") {
      if (Array.isArray(value.blocks)) return readableFromBlocks(value.blocks);
      if (typeof value.result === "string") return value.result;
      return responseSummary(value);
    }
    var text = String(value == null ? "" : value).trim();
    if (!text) return "";
    if ((text.charAt(0) === "{" || text.charAt(0) === "[") && text.length < 60000) {
      try {
        var parsed = JSON.parse(text);
        if (parsed && Array.isArray(parsed.blocks)) return readableFromBlocks(parsed.blocks);
      } catch (error) {}
    }
    return text;
  }

  function resultHTML(text) {
    text = String(text || "").trim();
    if (!text) return "";
    var parts = text.split(/\n{2,}/).slice(0, 18);
    return parts.map(function (part) {
      part = part.trim();
      if (!part) return "";
      if (/^\d+\.\s+\w+/.test(part)) {
        var lines = part.split(/\n/);
        return "<section><h4>" + esc(lines.shift()) + "</h4>" + (lines.length ? "<pre>" + esc(lines.join("\n")) + "</pre>" : "") + "</section>";
      }
      if (part.length > 280 || /[{};]\s*$/.test(part)) return "<pre>" + esc(part) + "</pre>";
      return "<p>" + esc(part) + "</p>";
    }).join("");
  }

  function protectedResultMarkup(text) {
    var body = resultHTML(text);
    return '<button type="button" class="rbe-ai-result-copy" title="Copy result">' + svgIcon("copy", "Copy result") + '</button><div class="rbe-ai-result-body">' + body + "</div>";
  }

  function recordAIUsageResult(editor, usageState, payload, details) {
    var eventId = usageEventId(editor, usageState);
    var premium = editor && editor.premiumOptions ? editor.premiumOptions : {};
    var endpoint = usageDetailEndpointFor(editor);
    if (!eventId || !endpoint || (!premium.serverMode && !premium.licenseKey && !premium.authorizationToken) || typeof fetch !== "function") return Promise.resolve();
    var body = Object.assign(
      {
        action: "update",
        authorization_token: premium.serverMode ? undefined : premium.authorizationToken || undefined,
        license_key: premium.serverMode || premium.authorizationToken ? undefined : premium.licenseKey,
        event_id: eventId,
        route: trimUsageText(payload && payload.route, 80),
        prompt: trimUsageText(payload && payload.prompt, 4000),
        selected_text: trimUsageText(payload && payload.text, 3000)
      },
      details || {}
    );
    if (premium.sessionToken) body.session_token = premium.sessionToken;
    return fetch(endpoint, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Accept": "application/json"
      },
      body: JSON.stringify(body)
    }).catch(function () {});
  }

  function historyRequest(editor, body) {
    var premium = editor && editor.premiumOptions ? editor.premiumOptions : {};
    var endpoint = historyEndpointFor(editor);
    if (!endpoint || (!premium.serverMode && !premium.licenseKey && !premium.authorizationToken) || typeof fetch !== "function") return Promise.resolve({ ok: false, items: [] });
    body = Object.assign({
      authorization_token: premium.serverMode ? undefined : premium.authorizationToken || undefined,
      license_key: premium.serverMode || premium.authorizationToken ? undefined : premium.licenseKey
    }, body || {});
    if (premium.sessionToken) body.session_token = premium.sessionToken;
    return fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json", "Accept": "application/json" },
      body: JSON.stringify(body)
    }).then(function (response) {
      return response.json().catch(function () { return {}; });
    }).catch(function () {
      return { ok: false, items: [] };
    });
  }

  function saveAIHistory(editor, payload, responseText, responsePayload, status) {
    payload = payload || {};
    responsePayload = responsePayload || {};
    return historyRequest(editor, {
      action: "save",
      request_action: payload.action || "generate_blocks",
      route: responsePayload.route || payload.route || "",
      prompt: trimUsageText(payload.prompt || "", 12000),
      selected_text: trimUsageText(payload.text || "", 6000),
      response_text: trimUsageText(responseText || responseSummary(responsePayload), 50000),
      response_json: responsePayload,
      response_type: responsePayload.type || (Array.isArray(responsePayload.blocks) ? "blocks" : "text"),
      blocks_generated: Array.isArray(responsePayload.blocks) ? responsePayload.blocks.length : undefined,
      usage_event_id: responsePayload.usage_event_id || undefined,
      status: status || "completed"
    });
  }

  function refreshAIAvailability(editor) {
    if (!editor || !editor.root) return;
    var locked = !aiEnabled(editor);
    Array.prototype.slice.call(editor.root.querySelectorAll(".rbe-ai-inline-btn,.rbe-ai-toolbar-btn")).forEach(function (button) {
      button.classList.toggle("is-premium-locked", locked);
      button.setAttribute("aria-disabled", locked ? "true" : "false");
      button.title = locked ? aiLockedMessage(editor) : "BlockWriteAI";
      var lockIcon = button.querySelector(".rbe-ai-lock-icon");
      if (locked && !lockIcon) button.insertAdjacentHTML("beforeend", '<span class="rbe-ai-lock-icon">' + svgIcon("lock", "Locked premium feature") + "</span>");
      else if (!locked && lockIcon) lockIcon.remove();
    });
    if (locked && isDrawerOpen(editor)) closeDrawer(editor);
  }

  function callAI(editor, payload) {
    var endpoint = endpointFor(editor);
    var startedAt = Date.now();
    payload = attachPremiumCredentials(editor, payload, endpoint);
    var usageState = null;
    return consumeAIUsage(editor, payload).then(function (state) {
      usageState = state;
      var usageResult = state && (state.usage_result || state.lastPremiumUsageResult);
      if (usageResult) {
        if (usageResult.model) payload.model = usageResult.model;
        if (usageResult.route) payload.route = usageResult.route;
        if (usageResult.credits_required !== undefined) payload.credits_required = usageResult.credits_required;
      }
      return fetch(endpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Accept": "application/json"
        },
        body: JSON.stringify(payload)
      }).then(function (response) {
        return response.json().catch(function () {
          return {};
        }).then(function (body) {
          if (!response.ok || body.ok === false) {
            var requestError = new Error(body.error || "AI request failed");
            requestError.httpStatus = response.status;
            throw requestError;
          }
          recordAIUsageResult(editor, usageState, payload, {
            status: "completed",
            duration_ms: Date.now() - startedAt,
            model: body.model || "",
            model_used: body.model_used || body.model || "",
            input_tokens: body.input_tokens || 0,
            output_tokens: body.output_tokens || 0,
            total_tokens: body.total_tokens || 0,
            estimated_cost: body.estimated_cost || 0,
            response_source: body.response_source || "",
            response_type: body.type || (Array.isArray(body.blocks) ? "blocks" : "text"),
            response: trimUsageText(responseSummary(body), 6000),
            response_character_count: body.response_character_count || undefined,
            response_token_count: body.response_token_count || undefined,
            blocks_generated: Array.isArray(body.blocks) ? body.blocks.length : undefined
          });
          return body;
        });
      });
    }).catch(function (error) {
      recordAIUsageResult(editor, usageState, payload, {
        status: "failed",
        duration_ms: Date.now() - startedAt,
        http_status: error && error.httpStatus ? error.httpStatus : 0,
        response_type: "error",
        error_reason: trimUsageText(error && error.message ? error.message : "AI request failed", 1200)
      });
      throw error;
    });
  }

  function parseSSEFrames(buffer, onFrame) {
    var match;
    while ((match = /\r?\n\r?\n/.exec(buffer))) {
      var frame = buffer.slice(0, match.index);
      buffer = buffer.slice(match.index + match[0].length);
      var eventName = "message";
      var data = [];
      frame.split(/\r?\n/).forEach(function (line) {
        if (line.indexOf("event:") === 0) eventName = line.slice(6).trim() || "message";
        else if (line.indexOf("data:") === 0) data.push(line.slice(5).replace(/^\s/, ""));
      });
      if (data.length) onFrame(eventName, data.join("\n"));
    }
    return buffer;
  }

  function callAIStream(editor, payload, handlers) {
    handlers = handlers || {};
    var endpoint = streamEndpointFor(editor);
    if (!endpoint || typeof fetch !== "function" || typeof TextDecoder === "undefined") return callAI(editor, payload);
    var startedAt = Date.now();
    payload = attachPremiumCredentials(editor, payload, endpoint);
    var usageState = null;
    var finalPayload = null;
    return consumeAIUsage(editor, payload).then(function (state) {
      usageState = state;
      var usageResult = state && (state.usage_result || state.lastPremiumUsageResult);
      if (usageResult) {
        if (usageResult.model) payload.model = usageResult.model;
        if (usageResult.route) payload.route = usageResult.route;
        if (usageResult.credits_required !== undefined) payload.credits_required = usageResult.credits_required;
      }
      return fetch(endpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "Accept": "text/event-stream"
        },
        body: JSON.stringify(payload)
      });
    }).then(function (response) {
      if (!response.ok || !response.body || !response.body.getReader) {
        return callAI(editor, payload);
      }
      var reader = response.body.getReader();
      var decoder = new TextDecoder();
      var buffer = "";
      function read() {
        return reader.read().then(function (chunk) {
          if (chunk.done) return finalPayload || {};
          buffer += decoder.decode(chunk.value, { stream: true });
          buffer = parseSSEFrames(buffer, function (eventName, rawData) {
            var data = {};
            try { data = JSON.parse(rawData); } catch (error) { data = {}; }
            if (eventName === "preview") {
              if (typeof handlers.preview === "function") handlers.preview(data.text || "", data.delta || "");
            } else if (eventName === "status") {
              if (typeof handlers.status === "function") handlers.status(data.message || "");
            } else if (eventName === "blocks" || eventName === "text") {
              finalPayload = data;
            } else if (eventName === "error") {
              var streamError = new Error(data.error || "AI request failed");
              streamError.httpStatus = data.status || response.status || 0;
              throw streamError;
            }
          });
          return read();
        });
      }
      return read();
    }).then(function (body) {
      if (!body || body.ok === false) {
        var requestError = new Error(body && body.error || "AI request failed");
        requestError.httpStatus = body && body.status || 0;
        throw requestError;
      }
      recordAIUsageResult(editor, usageState, payload, {
        status: "completed",
        duration_ms: Date.now() - startedAt,
        model: body.model || "",
        model_used: body.model_used || body.model || "",
        input_tokens: body.input_tokens || 0,
        output_tokens: body.output_tokens || 0,
        total_tokens: body.total_tokens || 0,
        estimated_cost: body.estimated_cost || 0,
        response_source: body.response_source || "stream",
        response_type: body.type || (Array.isArray(body.blocks) ? "blocks" : "text"),
        response: trimUsageText(responseSummary(body), 6000),
        response_character_count: body.response_character_count || undefined,
        response_token_count: body.response_token_count || undefined,
        blocks_generated: Array.isArray(body.blocks) ? body.blocks.length : undefined
      });
      return body;
    }).catch(function (error) {
      recordAIUsageResult(editor, usageState, payload, {
        status: "failed",
        duration_ms: Date.now() - startedAt,
        http_status: error && error.httpStatus ? error.httpStatus : 0,
        response_type: "error",
        error_reason: trimUsageText(error && error.message ? error.message : "AI request failed", 1200)
      });
      throw error;
    });
  }

  function ensureState(editor) {
    if (!editor.__blockwriteaiAI) {
      editor.__blockwriteaiAI = {
        drawer: null,
        lastRange: null,
        lastText: "",
        result: "",
        loading: false,
        view: "normal",
        closeTimer: null,
        progressTimer: null,
        themeObserver: null,
        historyModal: null,
        historyItems: []
      };
    }
    return editor.__blockwriteaiAI;
  }

  function isEditorDark(editor) {
    if (!editor || !editor.root) return false;
    var root = editor.root;
    var doc = root.ownerDocument || document;
    return !!(
      root.classList.contains("rbe-theme-dark") ||
      (root.closest && root.closest(".rbe-theme-dark")) ||
      (doc.documentElement && doc.documentElement.classList.contains("rbe-theme-dark")) ||
      (doc.body && doc.body.classList.contains("rbe-theme-dark")) ||
      (doc.querySelector && doc.querySelector(".rbe.rbe-theme-dark,.rbe-shell.rbe-theme-dark"))
    );
  }

  function syncDrawerTheme(editor) {
    var state = ensureState(editor);
    if (!state.drawer) return;
    state.drawer.classList.toggle("rbe-ai-theme-dark", isEditorDark(editor));
  }

  function observeTheme(editor) {
    if (!editor || !editor.root || typeof MutationObserver === "undefined") return;
    var state = ensureState(editor);
    if (state.themeObserver) return;
    state.themeObserver = new MutationObserver(function () {
      syncDrawerTheme(editor);
    });
    state.themeObserver.observe(editor.root, { attributes: true, attributeFilter: ["class"] });
  }

  function emitProgress(editor, active, message) {
    if (!editor || !editor.root || typeof CustomEvent !== "function") return;
    editor.root.dispatchEvent(
      new CustomEvent("rbe:ai-progress", {
        bubbles: true,
        detail: { active: !!active, message: message || "" }
      })
    );
  }

  function setProgress(editor, active, message, delay) {
    var state = ensureState(editor);
    if (state.progressTimer) {
      clearTimeout(state.progressTimer);
      state.progressTimer = null;
    }
    if (active) {
      emitProgress(editor, true, message || "Working with BlockWriteAI...");
      return;
    }
    state.progressTimer = setTimeout(function () {
      emitProgress(editor, false, "");
      state.progressTimer = null;
    }, typeof delay === "number" ? delay : 0);
  }

  function showToast(editor, message, type) {
    if (!message || typeof document === "undefined") return;
    injectStyles();
    var stack = document.querySelector(".rbe-toast-stack");
    if (!stack) {
      stack = el("div", "rbe-toast-stack", {
        role: "status",
        "aria-live": "polite"
      });
      document.body.appendChild(stack);
    }
    var toastType = type === "error" ? "error" : (type === "info" ? "info" : "warning");
    var toast = el("div", "rbe-toast is-" + toastType, {});
    toast.innerHTML =
      svgIcon(toastType === "error" ? "circle-exclamation" : (toastType === "info" ? "circle-info" : "triangle-exclamation"), toastType) +
      "<div><strong>" +
      esc(toastType === "error" ? "BlockWriteAI error" : (toastType === "info" ? "BlockWriteAI" : "BlockWriteAI warning")) +
      "</strong><span>" +
      esc(message) +
      "</span></div>";
    stack.appendChild(toast);
    requestAnimationFrame(function () {
      toast.classList.add("is-show");
    });
    setTimeout(function () {
      toast.classList.remove("is-show");
      toast.classList.add("is-hiding");
      setTimeout(function () {
        if (toast.parentNode) toast.parentNode.removeChild(toast);
        if (stack && !stack.children.length && stack.parentNode) stack.parentNode.removeChild(stack);
      }, 260);
    }, 5000);
  }

  function setStatus(editor, message, error) {
    if (message && error) showToast(editor, message, "error");
  }

  function setLoading(editor, loading) {
    var state = ensureState(editor);
    state.loading = !!loading;
    if (!state.drawer) return;
    Array.prototype.slice.call(state.drawer.querySelectorAll("button")).forEach(function (button) {
      if (button.classList.contains("rbe-ai-close") || button.classList.contains("rbe-ai-window-btn")) return;
      button.disabled = !!loading || (button.classList.contains("rbe-ai-apply") && !state.result);
    });
  }

  function updateDrawerViewButtons(state) {
    if (!state.drawer) return;
    var minButton = state.drawer.querySelector(".rbe-ai-minimize");
    var maxButton = state.drawer.querySelector(".rbe-ai-maximize");
    var isMinimized = state.view === "minimized";
    var isMaximized = state.view === "maximized";
    if (minButton) {
      minButton.setAttribute("aria-pressed", isMinimized ? "true" : "false");
      minButton.title = isMinimized ? "Restore AI" : "Minimize AI";
    }
    if (maxButton) {
      maxButton.setAttribute("aria-pressed", isMaximized ? "true" : "false");
      maxButton.title = isMaximized ? "Restore AI" : "Maximize AI";
      maxButton.innerHTML = svgIcon(isMaximized ? "down-left-and-up-right-to-center" : "up-right-and-down-left-from-center", isMaximized ? "Restore" : "Maximize");
    }
  }

  function setDrawerView(editor, view) {
    var state = ensureState(editor);
    if (!state.drawer) return;
    state.view = view === "minimized" || view === "maximized" ? view : "normal";
    state.drawer.classList.toggle("is-minimized", state.view === "minimized");
    state.drawer.classList.toggle("is-maximized", state.view === "maximized");
    if (state.view === "minimized") setResult(editor, "");
    updateDrawerViewButtons(state);
  }

  function updateDrawerSelection(editor) {
    var state = ensureState(editor);
    if (!state.drawer) return;
    var selection = selectedText(editor);
    state.lastRange = editor.savedRange && isRangeInsideEditor(editor, editor.savedRange) ? editor.savedRange.cloneRange() : null;
    state.lastText = selection;
    var box = state.drawer.querySelector(".rbe-ai-selection");
    if (box) {
      box.textContent = selection || "Select text in the editor, then choose an AI action.";
      box.classList.toggle("is-empty", !selection);
    }
  }

  function ensureDrawer(editor) {
    var state = ensureState(editor);
    if (state.drawer) return state.drawer;
    injectStyles();
    var drawer = el("aside", "rbe-ai-drawer", {
      hidden: true,
      role: "dialog",
      "aria-label": "BlockWriteAI"
    });
    drawer.innerHTML =
      '<div class="rbe-ai-head"><div class="rbe-ai-title"><span class="rbe-ai-title-icon">' +
      svgIcon("wand-magic-sparkles", "BlockWriteAI") +
      '</span><span>BlockWriteAI</span></div><div class="rbe-ai-window-actions"><button type="button" class="rbe-ai-window-btn rbe-ai-history" title="AI history">' +
      svgIcon("comments", "AI history") +
      '</button><button type="button" class="rbe-ai-window-btn rbe-ai-minimize" title="Minimize AI" aria-pressed="false">' +
      svgIcon("window-minimize", "Minimize") +
      '</button><button type="button" class="rbe-ai-window-btn rbe-ai-maximize" title="Maximize AI" aria-pressed="false">' +
      svgIcon("up-right-and-down-left-from-center", "Maximize") +
      '</button><button type="button" class="rbe-ai-close" title="Close AI">' +
      svgIcon("xmark", "Close") +
      '</button></div></div><div class="rbe-ai-body">' +
      '<section class="rbe-ai-section"><div class="rbe-ai-label">Selection</div><div class="rbe-ai-selection is-empty"></div></section>' +
      '<section class="rbe-ai-section"><div class="rbe-ai-label">Actions</div><div class="rbe-ai-action-grid">' +
      ACTIONS.map(function (action) {
        return (
          '<button type="button" class="rbe-ai-action" data-ai-action="' +
          esc(action[0]) +
          '">' +
          svgIcon(action[1], action[2]) +
          "<span><strong>" +
          esc(action[2]) +
          "</strong><small>" +
          esc(action[3]) +
          "</small></span></button>"
        );
      }).join("") +
      '</div></section><section class="rbe-ai-section"><div class="rbe-ai-label">Generate blocks from prompt</div>' +
      '<textarea class="rbe-ai-prompt" placeholder="Example: Create a short project proposal with a heading, summary, checklist, and next steps."></textarea>' +
      '<button type="button" class="rbe-ai-primary rbe-ai-generate">' +
      svgIcon("sparkles", "Generate") +
      "<span>Generate blocks</span></button></section>" +
      '<section class="rbe-ai-section"><div class="rbe-ai-label">Result</div><div class="rbe-ai-result"></div></section>' +
      '</div><div class="rbe-ai-foot"><div class="rbe-ai-foot-actions"><button type="button" class="rbe-ai-secondary rbe-ai-apply" disabled>' +
      svgIcon("check", "Apply") +
      "<span>Apply</span></button></div></div>";
    editor.root.appendChild(drawer);
    drawer.addEventListener("copy", function (event) {
      if (event.target && event.target.closest && event.target.closest(".rbe-ai-result")) event.preventDefault();
    });
    drawer.addEventListener("cut", function (event) {
      if (event.target && event.target.closest && event.target.closest(".rbe-ai-result")) event.preventDefault();
    });
    drawer.addEventListener("contextmenu", function (event) {
      if (event.target && event.target.closest && event.target.closest(".rbe-ai-result")) event.preventDefault();
    });
    state.drawer = drawer;
    setDrawerView(editor, state.view);
    syncDrawerTheme(editor);
    observeTheme(editor);
    return drawer;
  }

  function setAIButtonsOpen(editor, open) {
    if (!editor || !editor.root) return;
    Array.prototype.slice.call(editor.root.querySelectorAll(".rbe-ai-inline-btn,.rbe-ai-toolbar-btn")).forEach(function (button) {
      button.classList.toggle("is-open", !!open);
    });
  }

  function isDrawerOpen(editor) {
    var state = ensureState(editor);
    return !!(state.drawer && !state.drawer.hidden && state.drawer.classList.contains("is-open"));
  }

  function openDrawer(editor) {
    if (!requireAI(editor)) return;
    var state = ensureState(editor);
    var drawer = ensureDrawer(editor);
    syncDrawerTheme(editor);
    setDrawerView(editor, state.view || "normal");
    updateDrawerSelection(editor);
    if (state.closeTimer) {
      clearTimeout(state.closeTimer);
      state.closeTimer = null;
    }
    drawer.hidden = false;
    drawer.getBoundingClientRect();
    requestAnimationFrame(function () {
      drawer.classList.add("is-open");
    });
    setAIButtonsOpen(editor, true);
    setStatus(editor, "");
    if (!state.lastText) {
      setTimeout(function () {
        var prompt = drawer.querySelector(".rbe-ai-prompt");
        if (prompt) prompt.focus();
      }, 0);
    }
  }

  function closeDrawer(editor) {
    var state = ensureState(editor);
    if (!state.drawer) return;
    if (state.closeTimer) clearTimeout(state.closeTimer);
    setDrawerView(editor, "normal");
    state.drawer.classList.remove("is-open");
    setAIButtonsOpen(editor, false);
    state.closeTimer = setTimeout(function () {
      if (!state.drawer) return;
      state.drawer.hidden = true;
      state.closeTimer = null;
      setResult(editor, "");
    }, 300);
  }

  function toggleDrawer(editor) {
    if (!requireAI(editor)) return;
    if (isDrawerOpen(editor)) closeDrawer(editor);
    else openDrawer(editor);
  }

  function scrollResultToBottom(result) {
    if (!result) return;
    requestAnimationFrame(function () {
      result.scrollTop = result.scrollHeight;
      Array.prototype.slice.call(result.querySelectorAll("pre")).forEach(function (pre) {
        pre.scrollTop = pre.scrollHeight;
      });
    });
  }

  function setResult(editor, text) {
    var state = ensureState(editor);
    state.result = readableResult(text);
    if (!state.drawer) return;
    var result = state.drawer.querySelector(".rbe-ai-result");
    var apply = state.drawer.querySelector(".rbe-ai-apply");
    if (result) {
      result.innerHTML = state.result ? protectedResultMarkup(state.result) : "";
      scrollResultToBottom(result);
    }
    if (apply) apply.disabled = state.loading || !state.result;
  }

  function runTextAction(editor, action) {
    if (!requireAI(editor)) return;
    var state = ensureState(editor);
    updateDrawerSelection(editor);
    if (!state.lastText) {
      showToast(editor, "Select text first, then run an AI action.", "warning");
      return;
    }
    setLoading(editor, true);
    setResult(editor, "");
    setProgress(editor, true, "Improving selected text with BlockWriteAI...");
    callAIStream(editor, {
      action: action,
      text: state.lastText,
      ai_mode: "universal",
      editor_context: editorAIContext(editor, state.lastText),
      document: typeof editor.getData === "function" ? editor.getData() : null
    }, {
      preview: function (text) {
        setResult(editor, text);
      },
      status: function (message) {
        if (message) setProgress(editor, true, message);
      }
    })
      .then(function (payload) {
        setResult(editor, payload.result || "");
        saveAIHistory(editor, { action: action, text: state.lastText }, ensureState(editor).result, payload, "completed");
      })
      .catch(function (error) {
        showToast(editor, error.message || "AI request failed", "error");
      })
      .finally(function () {
        setLoading(editor, false);
        setProgress(editor, false, "", 250);
      });
  }

  function cleanGeneratedBlock(block) {
    if (!block || typeof block !== "object") return null;
    var type = String(block.type || "paragraph");
    var data = block.data && typeof block.data === "object" ? block.data : {};
    return { type: type, data: data };
  }

  function promptWantsLatex(prompt) {
    prompt = String(prompt || "").toLowerCase();
    return /\b(latex|tex|formula|equation|derivation|theorem|gradient descent|scientific notation|mathematical notation|math block)\b/.test(prompt);
  }

  function looksLikeLatex(text) {
    text = String(text || "");
    return /\\(begin|frac|sum|prod|int|nabla|theta|alpha|beta|eta|partial|left|right|mathbf|mathbb|cdot|quad)\b|\$\$|\\\[|\\\(|[_^]\{/.test(text);
  }

  function stripLatexFence(text) {
    text = String(text || "").trim();
    var fenced = text.match(/^```(?:latex|tex)?\s*([\s\S]*?)\s*```$/i);
    if (fenced) return fenced[1].trim();
    return text.replace(/^\$\$([\s\S]*)\$\$$/, "$1").trim();
  }

  function coerceLatexBlocks(prompt, blocks) {
    blocks = Array.isArray(blocks) ? blocks : [];
    if (!promptWantsLatex(prompt)) return blocks;
    return blocks.map(function (block) {
      block = cleanGeneratedBlock(block);
      if (!block) return null;
      if (block.type === "latex") {
        block.data = Object.assign({ display: true }, block.data || {});
        if (!block.data.code && block.data.text) block.data.code = stripLatexFence(block.data.text);
        return block;
      }
      var data = block.data || {};
      var text = data.code || data.text || data.html || "";
      if ((block.type === "paragraph" || block.type === "code" || block.type === "raw") && (looksLikeLatex(text) || promptWantsLatex(prompt))) {
        return {
          type: "latex",
          data: {
            code: stripLatexFence(text),
            display: true
          }
        };
      }
      return block;
    }).filter(Boolean);
  }

  function requestedGeneratedChartType(prompt) {
    prompt = String(prompt || "").toLowerCase();
    if (/\bscatter(?:\s+chart)?\b/.test(prompt)) return "scatter";
    if (/\bstacked\s+(?:bar\s+)?chart\b|\bstackedbar\b/.test(prompt)) return "stackedBar";
    if (/\bcomparison\s+chart\b|\bcompare\b/.test(prompt)) return "comparison";
    if (/\bdoughnut|donut\b/.test(prompt)) return "doughnut";
    if (/\bpie(?:\s+chart)?\b/.test(prompt)) return "pie";
    if (/\bline(?:\s+chart| graph)?\b/.test(prompt)) return "line";
    if (/\barea(?:\s+chart)?\b/.test(prompt)) return "area";
    if (/\btrend(?:\s+chart)?\b/.test(prompt)) return "trend";
    if (/\bkpi(?:\s+card| chart)?\b/.test(prompt)) return "kpi";
    if (/\bbar(?:\s+chart| graph)?\b|\bcolumn\s+chart\b/.test(prompt)) return "bar";
    return "";
  }

  function generatedBlockText(block) {
    var data = block && block.data || {};
    return String(data.text || data.title || data.caption || data.code || data.html || data.items || "");
  }

  function generatedChartBlocks(blocks) {
    var charts = [];
    function walk(list) {
      (Array.isArray(list) ? list : []).forEach(function (block) {
        if (!block || typeof block !== "object") return;
        if (block.type === "chart") charts.push(block);
        var data = block.data || {};
        if (Array.isArray(data.blocks)) walk(data.blocks);
      });
    }
    walk(blocks);
    return charts;
  }

  function validateGeneratedBlocks(prompt, blocks, qualityRules) {
    prompt = String(prompt || "");
    blocks = Array.isArray(blocks) ? blocks : [];
    var lower = prompt.toLowerCase();
    var issues = [];
    if (!blocks.length) issues.push("No editor blocks were returned.");
    var typeSet = {};
    blocks.forEach(function (block) { if (block && block.type) typeSet[block.type] = true; });
    var charts = generatedChartBlocks(blocks);
    var chartType = requestedGeneratedChartType(prompt);
    if (/\b(chart|graph|plot|trend|kpi)\b/i.test(prompt) && !charts.length) {
      issues.push("Prompt asks for a chart/graph, but no chart block was returned.");
    }
    if (chartType && !charts.some(function (chart) { return String(chart.data && chart.data.type || "").toLowerCase() === chartType.toLowerCase(); })) {
      issues.push("Prompt explicitly asks for " + chartType + " chart, but the returned chart type does not match.");
    }
    if (/\btable\b/i.test(prompt) && !typeSet.table) issues.push("Prompt asks for a table, but no table block was returned.");
    if (/\bchecklist|todo|to-do\b/i.test(prompt) && !typeSet.checklist) issues.push("Prompt asks for a checklist, but no checklist block was returned.");
    if (/\bmermaid|flowchart|sequence diagram|gantt\b/i.test(prompt) && !typeSet.mermaid) issues.push("Prompt asks for a Mermaid diagram, but no Mermaid block was returned.");
    if (promptWantsLatex(prompt) && !typeSet.latex) issues.push("Prompt asks for LaTeX/math output, but no LaTeX block was returned.");
    if (/\btoggle|collapsible|accordion\b/i.test(prompt) && !typeSet.toggle) issues.push("Prompt asks for a toggle/collapsible block, but no toggle block was returned.");
    var outputText = blocks.map(function (block) {
      var data = block && block.data || {};
      return JSON.stringify(data);
    }).join(" ").toLowerCase();
    var negativeMatches = prompt.match(/\b(?:do not use|exclude|without|not by|do not include|no)\s+([A-Za-z0-9_ -]{2,40})/ig) || [];
    negativeMatches.forEach(function (match) {
      var field = String(match).replace(/\b(?:do not use|exclude|without|not by|do not include|no)\s+/i, "").trim();
      field = field.replace(/\b(?:as|in|for|from|with)\b.*$/i, "").trim();
      if (field && outputText.indexOf(field.toLowerCase()) >= 0) {
        issues.push("Prompt explicitly excludes `" + field + "`, but generated output still contains it.");
      }
    });
    var onlyMatch = prompt.match(/\b(?:show|include|use|return)\s+only\s+([A-Za-z0-9_, %&/-]+?)(?:\.|$)/i);
    if (onlyMatch) {
      var allowed = onlyMatch[1].split(/,| and /i).map(function (item) { return item.trim().toLowerCase(); }).filter(Boolean);
      if (allowed.length) {
        var headings = [];
        blocks.forEach(function (block) {
          if (!block || block.type !== "table") return;
          var rows = block.data && Array.isArray(block.data.rows) ? block.data.rows : [];
          (rows[0] || []).forEach(function (heading) { headings.push(String(heading || "").toLowerCase()); });
        });
        headings.forEach(function (heading) {
          if (heading && !allowed.some(function (field) { return heading.indexOf(field) >= 0 || field.indexOf(heading) >= 0; })) {
            issues.push("Prompt asks for only specific fields, but table includes extra column `" + heading + "`.");
          }
        });
      }
    }
    charts.forEach(function (chart) {
      var data = chart.data || {};
      var labels = String(data.labels || "").split(",").filter(function (item) { return item.trim(); });
      if (labels.length > 80) issues.push("Chart has too many labels to read; aggregate, limit, or use a table instead.");
      if ((data.type === "comparison" || data.type === "stackedBar") && String(data.values || "").indexOf(";") >= 0 && !String(data.seriesLabels || "").trim()) {
        issues.push("Multi-series chart is missing series labels.");
      }
    });
    (Array.isArray(qualityRules) ? qualityRules : []).forEach(function (rule) {
      var intent = String(rule.intent_type || "");
      if (intent === "chart_type" && chartType && !charts.some(function (chart) { return String(chart.data && chart.data.type || "").toLowerCase() === chartType.toLowerCase(); })) {
        issues.push("Quality rule requires exact requested chart type.");
      }
      if (intent === "block_contract" && /\b(table|chart|toggle|mermaid|latex|letterhead|signature)\b/i.test(prompt)) {
        var required = String(prompt.match(/\b(table|chart|toggle|mermaid|latex|letterhead|signature)\b/i) || "").toLowerCase();
        if (required === "chart" && !charts.length) issues.push("Quality rule requires the requested chart block.");
      }
    });
    var vs = prompt.match(/([A-Za-z0-9_ -]+?)\s+v(?:s|ersus)\.?\s+([A-Za-z0-9_ -]+)/i);
    if (vs && charts.length) {
      var xPhrase = vs[1].trim().toLowerCase();
      var yPhrase = vs[2].trim().toLowerCase();
      var chartText = charts.map(function (chart) {
        var data = chart.data || {};
        return [data.title, data.xAxisLabel, data.yAxisLabel, data.caption].join(" ").toLowerCase();
      }).join(" ");
      if (xPhrase && chartText.indexOf(xPhrase) < 0) issues.push("Relationship chart does not clearly use X-axis field: " + vs[1].trim() + ".");
      if (yPhrase && chartText.indexOf(yPhrase) < 0) issues.push("Relationship chart does not clearly use Y-axis field: " + vs[2].trim() + ".");
    }
    return { ok: !issues.length, issues: issues };
  }

  function repairPromptForGeneratedBlocks(prompt, validation, attempt, qualityRules) {
    var ruleText = qualityRulesText(qualityRules);
    return [
      "Repair the generated BlockWriteAI blocks so they match the user's prompt exactly.",
      "Original user prompt: " + String(prompt || ""),
      ruleText ? "Stored quality rules from previous validations:\n" + ruleText : "",
      "Validation failures:",
      (validation.issues || []).map(function (issue, index) { return (index + 1) + ". " + issue; }).join("\n"),
      "Return only valid BlockWriteAI JSON blocks. Preserve useful correct content, but fix the failed requirements.",
      "Repair attempt: " + attempt
    ].join("\n\n");
  }

  function callAIBlocksWithValidation(editor, basePayload, prompt, handlers) {
    var maxAttempts = 3;
    var modeContract = promptModeContract(prompt);
    return fetchQualityRules(editor, "generate_blocks", prompt).then(function (qualityRules) {
      var ruleText = [qualityRulesText(qualityRules), promptModeInstructions(modeContract)].filter(Boolean).join("\n\n");
      basePayload = Object.assign({}, basePayload || {}, {
        prompt_modes: modeContract,
        quality_rules: qualityRules,
        quality_instructions: ruleText
      });
    function run(attempt, payload, useStream) {
      if (attempt > 1 && handlers && typeof handlers.status === "function") handlers.status("Reviewing output and repairing mismatched blocks...");
      return (useStream ? callAIStream(editor, payload, handlers) : callAI(editor, payload)).then(function (body) {
        body = body || {};
        body.blocks = coerceLatexBlocks(prompt, body.blocks || []);
        var validation = validateGeneratedBlocks(prompt, body.blocks || [], qualityRules);
        body.validation = validation;
        body.ai_validation_attempts = attempt;
        if (validation.ok || attempt >= maxAttempts) {
          logQualityEvent(editor, {
            feature: "generate_blocks",
            status: validation.ok ? "passed" : "failed",
            route: payload && payload.route || "",
            prompt: prompt,
            validation: validation,
            metadata: { attempts: attempt, block_count: Array.isArray(body.blocks) ? body.blocks.length : 0, prompt_modes: modeContract.modes }
          });
          return body;
        }
        var repairPayload = Object.assign({}, basePayload, {
          prompt: repairPromptForGeneratedBlocks(prompt, validation, attempt + 1, qualityRules),
          original_prompt: prompt,
          ai_validation_loop: true,
          ai_validation_attempt: attempt + 1,
          validation_issues: validation.issues
        });
        return run(attempt + 1, repairPayload, false);
      });
    }
    return run(1, basePayload, true);
    });
  }

  function isBlankParagraphBlock(block) {
    if (!block || !block.dataset || block.dataset.type !== "paragraph") return false;
    var editable = block.querySelector(".rbe-paragraph");
    var text = editable ? editable.textContent : block.textContent;
    return !String(text || "").trim();
  }

  function insertGeneratedBlocks(editor, blocks, prompt) {
    blocks = coerceLatexBlocks(prompt, blocks).map(cleanGeneratedBlock).filter(Boolean);
    if (!blocks.length) return Promise.resolve(0);
    var current = typeof editor.getCurrentBlock === "function" ? editor.getCurrentBlock() : null;
    var index = current && typeof editor.indexOfBlock === "function" ? editor.indexOfBlock(current) + 1 : editor.canvas.children.length;
    var onlyBlock = editor.canvas && editor.canvas.children.length === 1 ? editor.canvas.children[0] : null;
    if (onlyBlock && isBlankParagraphBlock(onlyBlock)) {
      index = 0;
      onlyBlock.remove();
    }
    var insertedCount = 0;
    var skippedReason = "";
    function premiumFeatureForGeneratedType(type) {
      if (!editor || typeof editor.getPremiumFeatureForTool !== "function") return "";
      return editor.getPremiumFeatureForTool.call(editor, type) || "";
    }
    function canInsertGeneratedType(type) {
      if (!editor || typeof editor.getPremiumFeatureForTool !== "function" || typeof editor.isPremiumFeatureEnabled !== "function") return true;
      var feature = premiumFeatureForGeneratedType(type);
      if (!feature || editor.isPremiumFeatureEnabled.call(editor, feature)) return true;
      if (typeof editor.showPremiumLocked === "function") editor.showPremiumLocked.call(editor, feature);
      skippedReason = skippedReason || (typeof editor.premiumMessage === "function" ? editor.premiumMessage.call(editor, feature) : "Generated block is not available for this license.");
      return false;
    }
    function reserveGeneratedPremiumUsage(block) {
      var feature = premiumFeatureForGeneratedType(block.type);
      if (!feature || feature === "ai" || typeof editor.consumePremiumUsage !== "function") return Promise.resolve(true);
      return Promise.resolve(editor.consumePremiumUsage.call(editor, feature, {
        action: "ai_generate",
        source: "ai_plugin",
        tool: block.type
      })).then(function () {
        return true;
      }).catch(function (error) {
        skippedReason = error && error.message ? error.message : "Premium usage limit check failed.";
        showToast(editor, skippedReason, "warning");
        return false;
      });
    }
    return blocks.reduce(function (chain, block) {
      return chain.then(function () {
        if (!canInsertGeneratedType(block.type)) return;
        return reserveGeneratedPremiumUsage(block).then(function (allowed) {
          if (!allowed) return;
      try {
        var inserted = null;
        if (typeof editor.insertBlock === "function") {
          inserted = editor.insertBlock.call(editor, block.type, block.data, index);
          if (inserted) index += 1;
        } else if (typeof editor.createBlock === "function") {
          inserted = editor.createBlock.call(editor, block.type, block.data);
          editor.canvas.appendChild(inserted);
        }
        if (inserted) insertedCount += 1;
      } catch (error) {
        showToast(editor, error && error.message ? error.message : "Unable to insert generated block.", "error");
      }
        });
      });
    }, Promise.resolve()).then(function () {
      if (insertedCount && typeof editor.changed === "function") editor.changed(true);
      return { count: insertedCount, reason: skippedReason };
    });
  }

  function generateBlocks(editor) {
    if (!requireAI(editor)) return;
    var state = ensureState(editor);
    var prompt = state.drawer && state.drawer.querySelector(".rbe-ai-prompt");
    var value = prompt ? prompt.value.trim() : "";
    if (!value) {
      showToast(editor, "Write a prompt before generating blocks.", "warning");
      return;
    }
    setLoading(editor, true);
    setResult(editor, "");
    setProgress(editor, true, "Generating BlockWriteAI blocks...");
    var generationPayload = {
      action: "generate_blocks",
      prompt: value,
      text: selectedText(editor),
      ai_mode: "universal",
      editor_context: editorAIContext(editor, selectedText(editor)),
      document: typeof editor.getData === "function" ? editor.getData() : null
    };
    callAIBlocksWithValidation(editor, generationPayload, value, {
      preview: function (text) {
        setResult(editor, text);
      },
      status: function (message) {
        if (message) setProgress(editor, true, message);
      }
    })
      .then(function (payload) {
        return insertGeneratedBlocks(editor, payload.blocks || [], value).then(function (result) {
          var count = result && typeof result === "object" ? result.count : result;
          var reason = result && typeof result === "object" ? result.reason : "";
          if (!count) {
            recordAIUsageResult(editor, { usage_event_id: payload.usage_event_id }, { action: "generate_blocks", prompt: value }, {
              status: "failed",
              response_type: "blocks",
              error_reason: reason || "Generated blocks could not be inserted.",
              blocks_generated: Array.isArray(payload.blocks) ? payload.blocks.length : 0
            });
            saveAIHistory(editor, { action: "generate_blocks", prompt: value }, reason || "Generated blocks could not be inserted.", payload, "failed");
            showToast(editor, reason || "Generated blocks could not be inserted.", "warning");
          } else {
            setResult(editor, payload);
            saveAIHistory(editor, { action: "generate_blocks", prompt: value }, ensureState(editor).result, payload, "completed");
          }
        });
      })
      .catch(function (error) {
        showToast(editor, error.message || "AI generation failed", "error");
      })
      .finally(function () {
        setLoading(editor, false);
        setProgress(editor, false, "", 250);
      });
  }

  function historyItemHTML(item) {
    var prompt = String(item && item.prompt || item && item.selected_text || "AI action").trim();
    var response = readableResult(item && (item.response_json || item.response || ""));
    return (
      '<article class="rbe-ai-history-item" data-history-id="' + esc(item.id) + '">' +
      '<input type="checkbox" class="rbe-ai-history-check" value="' + esc(item.id) + '">' +
      '<div><strong>' + esc(prompt || "AI action") + '</strong>' +
      '<small>' + esc((item.created_at || "") + (item.response_type ? " | " + item.response_type : "")) + '</small>' +
      '<pre>' + esc(response || "No response saved.") + '</pre></div></article>'
    );
  }

  function renderHistoryModal(editor) {
    var state = ensureState(editor);
    if (!state.historyModal) return;
    var list = state.historyModal.querySelector(".rbe-ai-history-list");
    if (!list) return;
    if (state.historyError) {
      list.innerHTML = '<div class="rbe-ai-history-empty">' + esc(state.historyError) + '</div>';
      return;
    }
    if (!state.historyItems.length) {
      list.innerHTML = '<div class="rbe-ai-history-empty">No AI history yet.</div>';
      return;
    }
    list.innerHTML = state.historyItems.map(historyItemHTML).join("");
  }

  function selectedHistoryIds(modal) {
    return Array.prototype.slice.call(modal.querySelectorAll(".rbe-ai-history-check:checked")).map(function (input) {
      return parseInt(input.value, 10);
    }).filter(Boolean);
  }

  function refreshHistory(editor) {
    var state = ensureState(editor);
    state.historyError = "";
    return historyRequest(editor, { action: "list", limit: 80 }).then(function (payload) {
      if (payload && payload.ok === false && payload.error) {
        state.historyItems = [];
        state.historyError = payload.error;
        renderHistoryModal(editor);
        return;
      }
      state.historyItems = Array.isArray(payload.items) ? payload.items : [];
      renderHistoryModal(editor);
    }).catch(function (error) {
      state.historyItems = [];
      state.historyError = error && error.message ? error.message : "Unable to load AI history.";
      renderHistoryModal(editor);
    });
  }

  function openHistoryModal(editor) {
    if (!requireAI(editor)) return;
    var state = ensureState(editor);
    injectStyles();
    if (!state.historyModal) {
      var modal = el("div", "rbe-ai-history-modal", { role: "dialog", "aria-label": "AI history" });
      modal.classList.toggle("rbe-ai-theme-dark", isEditorDark(editor));
      modal.innerHTML =
        '<div class="rbe-ai-history-dialog">' +
        '<div class="rbe-ai-history-head"><h3>AI history</h3><button type="button" class="rbe-ai-window-btn rbe-ai-history-close" title="Close">' + svgIcon("xmark", "Close") + '</button></div>' +
        '<div class="rbe-ai-history-tools"><label class="rbe-ai-history-select-wrap"><input type="checkbox" class="rbe-ai-history-select-all"> <span>Select all</span></label><div class="rbe-ai-history-actions"><button type="button" class="rbe-ai-secondary rbe-ai-history-delete" title="Delete selected">' + svgIcon("trash-can", "Delete selected") + '</button></div></div>' +
        '<div class="rbe-ai-history-list">Loading...</div>' +
        '</div>';
      modal.addEventListener("click", function (event) {
        var target = event.target;
        if (target.closest && target.closest(".rbe-ai-history-close")) {
          event.preventDefault();
          closeHistoryModal(editor);
          return;
        }
        if (target.closest && target.closest(".rbe-ai-history-select-all")) {
          Array.prototype.slice.call(modal.querySelectorAll(".rbe-ai-history-check")).forEach(function (input) {
            input.checked = target.checked;
          });
          return;
        }
        if (target.closest && target.closest(".rbe-ai-history-delete")) {
          event.preventDefault();
          var ids = selectedHistoryIds(modal);
          if (!ids.length) {
            showToast(editor, "Select at least one history item.", "warning");
            return;
          }
          historyRequest(editor, { action: "delete", ids: ids }).then(function () {
            refreshHistory(editor);
          });
          return;
        }
      });
      document.body.appendChild(modal);
      state.historyModal = modal;
    }
    state.historyModal.classList.toggle("rbe-ai-theme-dark", isEditorDark(editor));
    state.historyModal.hidden = false;
    refreshHistory(editor);
  }

  function closeHistoryModal(editor) {
    var state = ensureState(editor);
    if (state.historyModal) state.historyModal.hidden = true;
  }

  function copyAIResult(editor) {
    var text = ensureState(editor).result || "";
    if (!text) return;
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(function () {
        showToast(editor, "Result copied to clipboard.", "info");
      }).catch(function () {
        showToast(editor, "Unable to copy result.", "error");
      });
    } else {
      showToast(editor, "Clipboard copy is not available in this browser.", "warning");
    }
  }

  function ensureAIRefreshListener(editor) {
    if (!editor || !editor.root || editor.__blockwriteaiAIRefreshBound) return;
    editor.root.addEventListener("rbe:premium-change", refreshAIAvailability.bind(null, editor));
    editor.__blockwriteaiAIRefreshBound = true;
  }

  function ensureTopToolbarAIButton(editor, toolbar) {
    toolbar = toolbar || (editor && editor.topToolbar);
    if (!editor || editor.options.ai === false || !toolbar) return toolbar;
    injectStyles();
    if (!toolbar.querySelector(".rbe-ai-toolbar-btn")) {
      toolbar.appendChild(
        el("button", "rbe-toolbar-btn rbe-ai-toolbar-btn", {
          type: "button",
          title: "BlockWriteAI",
          html: svgIcon("wand-magic-sparkles", "BlockWriteAI"),
          dataset: { aiToolbar: "true", premiumFeature: "ai", unlockedTitle: "BlockWriteAI" }
        })
      );
    }
    ensureAIRefreshListener(editor);
    refreshAIAvailability(editor);
    return toolbar;
  }

  function ensureInlineAIButton(editor, toolbar) {
    toolbar = toolbar || (editor && editor.inlineToolbar);
    if (!editor || editor.options.ai === false || !toolbar) return toolbar;
    injectStyles();
    if (!toolbar.querySelector(".rbe-ai-inline-btn")) {
      toolbar.appendChild(
        el("button", "rbe-ai-inline-btn", {
          type: "button",
          title: "BlockWriteAI",
          html: svgIcon("wand-magic-sparkles", "AI"),
          dataset: { aiInline: "true", premiumFeature: "ai", unlockedTitle: "BlockWriteAI" }
        })
      );
    }
    ensureAIRefreshListener(editor);
    refreshAIAvailability(editor);
    return toolbar;
  }

  function hydrateExistingEditors() {
    if (typeof document === "undefined") return;
    Array.prototype.slice.call(document.querySelectorAll(".rbe")).forEach(function (root) {
      var editor = root.__blockwriteaiInstance;
      if (!editor) return;
      ensureTopToolbarAIButton(editor);
      ensureInlineAIButton(editor);
    });
  }

  var originalCreateTopToolbar = BlockWriteAI.prototype.createTopToolbar;
  BlockWriteAI.prototype.createTopToolbar = function () {
    var toolbar = originalCreateTopToolbar.call(this);
    return ensureTopToolbarAIButton(this, toolbar);
  };

  var originalCreateInlineToolbar = BlockWriteAI.prototype.createInlineToolbar;
  BlockWriteAI.prototype.createInlineToolbar = function () {
    var toolbar = originalCreateInlineToolbar.call(this);
    return ensureInlineAIButton(this, toolbar);
  };

  BlockWriteAI.prototype.openAI = function () {
    if (this.options.ai === false) return null;
    if (!requireAI(this)) return null;
    openDrawer(this);
    return this;
  };

  var originalHandleRootClick = BlockWriteAI.prototype.handleRootClick;
  BlockWriteAI.prototype.handleRootClick = function (event) {
    var target = event.target;
    if (target.closest && target.closest(".rbe-ai-inline-btn,.rbe-ai-toolbar-btn")) {
      event.preventDefault();
      event.stopPropagation();
      toggleDrawer(this);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-close")) {
      event.preventDefault();
      event.stopPropagation();
      closeDrawer(this);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-result-copy")) {
      event.preventDefault();
      event.stopPropagation();
      copyAIResult(this);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-history")) {
      event.preventDefault();
      event.stopPropagation();
      openHistoryModal(this);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-history-close")) {
      event.preventDefault();
      event.stopPropagation();
      closeHistoryModal(this);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-history-select-all")) {
      Array.prototype.slice.call(document.querySelectorAll(".rbe-ai-history-check")).forEach(function (input) {
        input.checked = target.checked;
      });
      return;
    }
    if (target.closest && target.closest(".rbe-ai-history-delete")) {
      event.preventDefault();
      event.stopPropagation();
      var modal = ensureState(this).historyModal;
      var ids = modal ? selectedHistoryIds(modal) : [];
      if (!ids.length) {
        showToast(this, "Select at least one history item.", "warning");
        return;
      }
      var editorForDelete = this;
      historyRequest(this, { action: "delete", ids: ids }).then(function () {
        refreshHistory(editorForDelete);
      });
      return;
    }
    if (target.closest && target.closest(".rbe-ai-minimize")) {
      event.preventDefault();
      event.stopPropagation();
      setDrawerView(this, ensureState(this).view === "minimized" ? "normal" : "minimized");
      return;
    }
    if (target.closest && target.closest(".rbe-ai-maximize")) {
      event.preventDefault();
      event.stopPropagation();
      setDrawerView(this, ensureState(this).view === "maximized" ? "normal" : "maximized");
      return;
    }
    if (target.closest && target.closest(".rbe-ai-head") && ensureState(this).view === "minimized") {
      event.preventDefault();
      event.stopPropagation();
      setDrawerView(this, "normal");
      return;
    }
    var action = target.closest && target.closest(".rbe-ai-action");
    if (action) {
      event.preventDefault();
      event.stopPropagation();
      runTextAction(this, action.dataset.aiAction);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-generate")) {
      event.preventDefault();
      event.stopPropagation();
      generateBlocks(this);
      return;
    }
    if (target.closest && target.closest(".rbe-ai-apply")) {
      event.preventDefault();
      event.stopPropagation();
      var state = ensureState(this);
      if (state.result && replaceSelection(this, state.result, state.lastRange)) {
        setProgress(this, true, "Applying BlockWriteAI result...");
        updateDrawerSelection(this);
        setProgress(this, false, "", 600);
      } else {
        showToast(this, "There is no AI result ready to apply.", "warning");
      }
      return;
    }
    return originalHandleRootClick.call(this, event);
  };

  var originalHandleDocumentMouseDown = BlockWriteAI.prototype.handleDocumentMouseDown;
  BlockWriteAI.prototype.handleDocumentMouseDown = function (event) {
    if (event.target.closest && event.target.closest(".rbe-ai-drawer, .rbe-ai-history-modal, .rbe-ai-inline-btn, .rbe-ai-toolbar-btn")) return;
    if (isDrawerOpen(this)) closeDrawer(this);
    return originalHandleDocumentMouseDown.call(this, event);
  };

  BlockWriteAI.ai = BlockWriteAI.ai || {};
  BlockWriteAI.enableAI = function (options) {
    BlockWriteAI.ai = Object.assign(BlockWriteAI.ai || {}, options || {});
    BlockWriteAI.configure({ ai: Object.assign({}, BlockWriteAI.ai) });
    return BlockWriteAI;
  };

  hydrateExistingEditors();

  return BlockWriteAI;
});
