    /* App chrome palette. The document uses its own --pd-* tokens, the editor its --e-* tokens. */
    :root {
      --ui-bg: #f3f4f6;
      --ui-surface: #ffffff;
      --ui-sunken: #f7f8fa;
      --ui-hover: #eef2f7;
      --ui-line: #e3e7ed;
      --ui-line-strong: #c9d1db;
      --ui-accent: #1e6b4e;
      --ui-accent-solid: #1e6b4e;
      --ui-accent-solid-hover: #175a41;
      --ui-accent-soft: #2e8763;
      --ui-accent-on: #ffffff;
      --ui-accent-rgb: 30, 107, 78;
      --ui-accent-tint: #e8f3ee;
      --ui-text: #1d2433;
      --ui-text-2: #344054;
      --ui-text-3: #475467;
      --ui-dim: #98a2b3;
      --ui-dim-2: #7a8699;
      --ui-dim-3: #5d6b7e;
      --ui-muted: #c3cad4;
      --ui-ok: #1f8a5f;
      --ui-ok-line: #a7d7c1;
      --ui-ok-bg: #e9f6f0;
      --ui-warn: #a86a12;
      --ui-warn-line: #ecd5a6;
      --ui-warn-bg: #fdf5e6;
      --ui-danger: #c2413f;
      --ui-danger-line: #f0bdbb;
      --ui-danger-bg: #fdeeee;
      --ui-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.05);
      --ui-shadow-md: 0 1px 3px rgba(16, 24, 40, 0.06), 0 4px 12px rgba(16, 24, 40, 0.06);
      --ui-shadow-lg: 0 2px 6px rgba(16, 24, 40, 0.08), 0 12px 32px rgba(16, 24, 40, 0.12);
      --ui-scrim: rgba(15, 23, 42, 0.32);
      --ui-focus: 0 0 0 3px rgba(30, 107, 78, 0.18);
      /* Dropdown caret for app chrome; editor dropdowns use the theme-coloured --caret-e (applyEditTokens). */
      --caret-ui: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 7'%3E%3Cpath fill='%237a8699' d='M1.3 .5h7.4a.8.8 0 0 1 .62 1.3L5.62 6.2a.8.8 0 0 1-1.24 0L.68 1.8A.8.8 0 0 1 1.3.5z'/%3E%3C/svg%3E");
    }
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    /* Every dropdown shares one filled caret. !important beats per-control background shorthands. */
    select:not([multiple]) {
      -webkit-appearance: none; appearance: none;
      background-image: var(--caret, var(--caret-ui)) !important;
      background-repeat: no-repeat !important;
      background-position: right 7px center !important;
      background-size: 10px 7px !important;
      padding-right: 22px !important;
    }
    .fb-dest-select, .fld-opt-select, .tb-cell-select, .tb-col-menu-select { --caret: var(--caret-e, var(--caret-ui)); }

    /* One thin, track-less scrollbar for every scrollable surface in the shell. */
    * {
      scrollbar-width: thin;
      scrollbar-color: #cfd5dd transparent;
    }
    ::-webkit-scrollbar { width: 10px; height: 10px; }
    ::-webkit-scrollbar-track { background: transparent; }
    ::-webkit-scrollbar-thumb {
      background: #cfd5dd;
      border-radius: 6px;
      border: 2px solid transparent;
      background-clip: content-box;
    }
    ::-webkit-scrollbar-thumb:hover { background: #aab3bf; background-clip: content-box; }
    ::-webkit-scrollbar-corner { background: transparent; }

    /* ── In-app file viewer ── */
    .fv-backdrop {
      position: fixed; inset: 0; z-index: 1400;
      display: none; align-items: center; justify-content: center;
      background: var(--ui-scrim);
      backdrop-filter: blur(3px);
      padding: 28px;
    }
    .fv-backdrop.open { display: flex; }
    .fv-panel {
      display: flex; flex-direction: column;
      width: min(1100px, 100%); height: 100%;
      background: var(--ui-surface);
      border: 1px solid var(--ui-line);
      border-radius: 10px;
      overflow: hidden;
      box-shadow: var(--ui-shadow-lg);
    }
    .fv-bar {
      display: flex; align-items: center; gap: 10px;
      padding: 10px 12px;
      border-bottom: 1px solid var(--ui-line);
      background: var(--ui-surface);
      flex-shrink: 0;
    }
    .fv-name {
      font-size: 14px; font-weight: 600; color: var(--ui-text);
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .fv-meta { font-size: 12px; color: var(--ui-dim-2); margin-right: auto; flex-shrink: 0; }
    .fv-x { padding: 4px 10px; }
    .fv-body {
      flex: 1; min-height: 0;
      display: flex; align-items: center; justify-content: center;
      background: var(--ui-bg);
      overflow: auto;
    }
    .fv-body iframe, .fv-body object { width: 100%; height: 100%; border: 0; }
    .fv-body img { max-width: 100%; max-height: 100%; object-fit: contain; }
    .fv-text {
      /* Fill the body: align-self only stretches the cross axis, which in this
         row container is vertical, leaving short files as a narrow centered
         column. Documents read from the left edge. */
      flex: 1 1 auto;
      width: 100%;
      align-self: stretch;
      margin: 0; padding: 20px 24px;
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: 13px; line-height: 1.55;
      color: var(--ui-text-2);
      white-space: pre-wrap; word-break: break-word;
      overflow: auto;
    }
    .fv-media { max-width: 100%; max-height: 100%; }
    audio.fv-media { width: min(560px, 90%); }
    .fv-fallback { color: var(--ui-dim-3); font-size: 14px; padding: 40px; text-align: center; }
    /* HTML preview: rendered vs source toggle */
    .fv-html-wrap { flex: 1 1 auto; width: 100%; align-self: stretch; display: flex; flex-direction: column; min-height: 0; }
    .fv-html-toolbar {
      display: flex; gap: 4px; padding: 6px 8px;
      background: var(--ui-sunken); border-bottom: 1px solid var(--ui-line);
      flex-shrink: 0;
    }
    .fv-html-tab {
      font: inherit; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
      background: transparent; color: var(--ui-dim-2); border: 1px solid transparent;
      padding: 4px 10px; border-radius: 4px; cursor: pointer;
    }
    .fv-html-tab:hover { color: var(--ui-text-2); }
    .fv-html-tab.is-active { background: var(--ui-surface); color: var(--ui-text-2); border-color: var(--ui-line); }
    .fv-html-stage { flex: 1 1 auto; min-height: 0; display: flex; background: #fff; }
    .fv-html-stage > iframe { flex: 1 1 auto; width: 100%; border: 0; background: #fff; }
    .fv-html-stage > .fv-text { display: none; background: var(--ui-sunken); }
    .fv-html-stage.is-source { background: var(--ui-sunken); }
    .fv-html-stage.is-source > iframe { display: none; }
    .fv-html-stage.is-source > .fv-text { display: block; }

    /* Inside themed document surfaces, follow the theme's own line colour. */
    #view-panel *, #edit-panel * { scrollbar-color: var(--e-line, #cfd5dd) transparent; }
    #view-panel ::-webkit-scrollbar-thumb, #edit-panel ::-webkit-scrollbar-thumb {
      background: var(--e-line, #cfd5dd); background-clip: content-box;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      background: var(--ui-bg);
      color: var(--ui-text-2);
      min-height: 100vh;
    }

    /* ── Layout ── */
    #app {
      display: flex;
      align-items: flex-start;
      min-height: 100vh;
    }
    .ctx-menu {
      position: fixed; z-index: 2000; min-width: 172px;
      background: var(--ui-surface); border: 1px solid var(--ui-line); border-radius: 8px;
      padding: 5px; display: flex; flex-direction: column; gap: 1px;
      box-shadow: var(--ui-shadow-lg);
    }
    .ctx-item {
      text-align: left; padding: 8px 12px;
      font-size: 13px; font-family: inherit; color: var(--ui-text-2);
      background: transparent; border: none; border-radius: 5px; cursor: pointer;
    }
    .ctx-item:hover { background: var(--ui-accent-tint); color: var(--ui-accent); }
    .ctx-item.danger { color: var(--ui-danger); }
    .ctx-item.danger:hover { background: var(--ui-danger-bg); color: var(--ui-danger); }
    .ctx-sep { height: 1px; background: var(--ui-line); margin: 4px 6px; }
    /* flex:1 lets the filename claim the free width instead of shrink-wrapping
       to its content box and ellipsising early. */
    .shell-title { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
    #shell {
      flex: 1;
      min-width: 0;
      padding: 0 28px 60px;
    }
    .shell-inner {
      width: 100%;
      max-width: 900px;
      margin: 0 auto;
    }
    .name-input {
      width: 100%;
      padding: 10px 12px;
      font-size: 14px;
      font-family: inherit;
      color: var(--ui-text);
      background: var(--ui-sunken);
      border: 1px solid var(--ui-line);
      border-radius: 6px;
      margin: 8px 0 10px;
      outline: none;
    }
    .name-input:focus { border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .name-hint { font-size: 12px; color: var(--ui-dim-3); }
    .confirm-msg { font-size: 14px; line-height: 1.55; color: var(--ui-text-2); margin: 6px 0 4px; }
    .shell-top {
      display: flex;
      align-items: flex-end;
      justify-content: space-between;
      gap: 16px;
      border-bottom: 2px solid var(--ui-line);
      margin-bottom: 4px;
    }
    .shell-top .filename { padding-bottom: 8px; line-height: 1; }
    .shell-top .tabs { border-bottom: none; }

    /* Sticky document header: title + tabs + action bar stay pinned while the
       document scrolls, so Save / Print / Copy are always reachable. The
       horizontal padding matches the content card's inner padding so the title,
       tabs, and buttons line up with the document body instead of hugging the
       edges. */
    .shell-head {
      position: sticky;
      top: 0;
      z-index: 50;
      background: var(--ui-bg);
      padding: 5px 14px 0;
      box-shadow: 0 10px 12px -12px rgba(16, 24, 40, 0.18);
    }

    @media (max-width: 720px) {
      #shell { padding: 0 18px 48px; width: 100%; }
      .shell-head { padding-top: 16px; }
      .shell-top { align-items: center; gap: 8px; }
      .shell-top .filename { font-size: 21px; padding-bottom: 6px; }
      .shell-top .tabs { margin-left: auto; }
      .shell-top .tabs { gap: 2px; }
      .shell-top .tab { gap: 5px; padding-right: 9px; padding-left: 9px; font-size: 11px; }
      .shell-top .tab-settings { padding-right: 9px; padding-left: 9px; }
    }

    /* ── Tabs ── */
    /* ── Header ── */
    .header {
      padding: 10px 0 0;
      margin-bottom: 0;
    }

    .header-top {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      padding-bottom: 14px;
    }

    .filename {
      font-size: 26px;
      font-weight: 600;
      color: var(--ui-dim);
      letter-spacing: 0.03em;
      border-radius: 6px;
      padding: 0 6px;
      margin-left: -6px;
      outline: none;
      border-bottom: 2px solid transparent;
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      transition: background 0.12s, color 0.12s, border-color 0.12s;
    }
    .filename[contenteditable] { cursor: text; }
    /* Hint sits beside the name while renaming, so the Enter/Escape contract is
       visible without hunting for a tooltip. */
    /* Collapsed to zero width while hidden: as a nowrap, non-shrinking flex item
       it otherwise reserved a chunk of the title row, ellipsising the filename
       long before it ran out of real space. */
    .rename-hint {
      flex: 0 0 auto;
      max-width: 0;
      overflow: hidden;
      align-self: flex-end;
      padding-bottom: 6px;
      font-size: 10px;
      font-weight: 600;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--ui-accent);
      white-space: nowrap;
      opacity: 0;
      transition: opacity .12s;
      pointer-events: none;
    }
    .rename-hint.show { opacity: .9; max-width: 24em; }
    .filename[contenteditable="false"] { cursor: default; }
    .filename[contenteditable]:not([contenteditable="false"]):hover {
      background: var(--ui-hover);
      color: var(--ui-dim-3);
    }
    .filename:focus {
      background: var(--ui-bg);
      color: var(--ui-text);
      border-bottom-color: var(--ui-accent);
      /* Long names scroll horizontally while editing rather than being
         clipped behind an ellipsis, so the caret is always visible. */
      overflow-x: auto;
      text-overflow: clip;
      scrollbar-width: none;
    }
    .filename:focus::-webkit-scrollbar { display: none; }

    .tabs {
      display: flex;
      align-items: center;
      gap: 4px;
      margin-bottom: 0px;
      border-bottom: 2px solid var(--ui-line);
      padding-bottom: 0;
    }

    .app-name {
      font-size: 22px;
      font-weight: 800;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--ui-accent);
      user-select: none;
      line-height: 1;
    }

    .branding {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      gap: 4px;
    }

    .branding-line {
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .attribution {
      font-size: 13px;
      font-style: italic;
      color: var(--ui-dim);
      letter-spacing: 0.02em;
    }

    .version {
      font-size: 11px;
      font-weight: 600;
      color: var(--ui-muted);
      letter-spacing: 0.05em;
      font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
    }

    .set-label {
      display: block;
      font-size: 11.5px; font-weight: 700; letter-spacing: 0.06em;
      text-transform: uppercase; color: var(--ui-dim-3);
      margin: 0 0 6px;
    }
    /* ── Audit log panel ── */
    .audit-head {
      display: flex; align-items: flex-end; justify-content: space-between;
      gap: 16px; margin: 4px 0 16px;
    }
    .audit-title { font-size: 17px; font-weight: 700; color: var(--ui-text); }
    .audit-sub { font-size: 12.5px; color: var(--ui-dim-3); margin-top: 3px; }
    .audit-table { width: 100%; border-collapse: collapse; font-size: 13px; }
    .audit-table th {
      text-align: left; padding: 0 14px 8px 0;
      font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
      color: var(--ui-dim-2); border-bottom: 1px solid var(--ui-line); white-space: nowrap;
    }
    .audit-table td {
      padding: 9px 14px 9px 0; border-bottom: 1px solid var(--ui-line);
      color: var(--ui-text-3); vertical-align: top;
    }
    .audit-when { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; white-space: nowrap; color: var(--ui-text); }
    .audit-zone { display: block; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; color: var(--ui-dim-2); margin-top: 2px; }
    .audit-who { white-space: nowrap; }
    .audit-act { font-weight: 600; color: var(--ui-text); white-space: nowrap; }
    .audit-detail { color: var(--ui-dim-3); }
    .audit-empty { font-size: 13px; color: var(--ui-dim-2); padding: 10px 0; }

    /* Saved-signature store (Settings) */
    /* The store grows with each saved signature, so this one dialog has to be
       able to scroll — the fixed-height dialogs are unaffected. */
    #settings-dialog .dialog { max-height: calc(100vh - 40px); overflow-y: auto; }
    #ws-settings-dialog .dialog { max-height: calc(100vh - 40px); overflow-y: auto; }

    /* Workspace settings split by where they're stored: this browser vs the folder. */
    .ws-scope {
      margin-top: 18px; padding: 14px 16px 16px;
      border: 1px solid var(--ui-line); border-radius: 10px;
      background: var(--ui-sunken);
    }
    .ws-scope .name-input { background: var(--ui-surface); }
    .ws-scope-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
    .ws-scope-title { font-size: 14px; font-weight: 700; color: var(--ui-text); }
    .ws-scope-tag {
      font-size: 10.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
      padding: 2px 8px; border-radius: 999px; white-space: nowrap;
      color: var(--ui-dim-3); background: var(--ui-surface); border: 1px solid var(--ui-line);
    }
    .ws-scope.is-shared .ws-scope-tag { color: var(--ui-accent); background: var(--ui-accent-tint); border-color: rgba(var(--ui-accent-rgb), 0.22); }

    /* Ask AI — a docked panel over the right edge of the document view. */
    .ai-panel {
      position: fixed; top: 0; right: 0; bottom: 0; width: 380px; max-width: 92vw;
      background: var(--ui-surface); border-left: 1px solid var(--ui-line);
      display: none; flex-direction: column; z-index: 60;
      box-shadow: -12px 0 32px rgba(16, 24, 40, 0.12);
    }
    .ai-panel.show { display: flex; }
    .ai-head { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--ui-line); }
    .ai-title { font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ui-dim-3); white-space: nowrap; flex: 0 0 auto; }
    .ai-head .button { padding: 5px 9px; font-size: 11.5px; flex: 0 0 auto; }
    .ai-head #btn-ai-close { margin-right: 4px; }
    .ai-head #btn-ai-prompt { margin-left: auto; }
    .ai-head .ai-icon-btn { padding: 4px 6px; display: inline-flex; align-items: center; justify-content: center; }
    .ai-head .ai-icon-btn svg { width: 14px; height: 14px; display: block; }
    .ai-prompt-view {
      display: none; flex-direction: column; gap: 10px;
      padding: 14px 16px; border-bottom: 1px solid var(--ui-line);
      background: var(--ui-sunken); max-height: 55%; overflow: hidden;
    }
    .ai-prompt-view.show { display: flex; }
    .ai-prompt-note { font-size: 12px; line-height: 1.5; color: var(--ui-dim-3); }
    .ai-prompt-pre {
      flex: 1; min-height: 0; overflow: auto; margin: 0;
      font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
      font-size: 11px; line-height: 1.55; color: var(--ui-text-3);
      white-space: pre-wrap; word-break: break-word;
      background: var(--ui-surface); border: 1px solid var(--ui-line); border-radius: 8px; padding: 10px 12px;
    }
    .ai-prompt-row { display: flex; gap: 8px; align-items: center; }
    .ai-prompt-row .ai-prompt-size { font-size: 11px; color: var(--ui-dim-2); margin-left: auto; }
    .ai-prefs-view {
      display: none; flex-direction: column; gap: 10px;
      padding: 14px 16px; border-bottom: 1px solid var(--ui-line);
      background: var(--ui-sunken);
    }
    .ai-prefs-view.show { display: flex; }
    .ai-prefs-note { font-size: 12px; line-height: 1.5; color: var(--ui-dim-3); }
    .ai-prefs-input {
      resize: vertical; min-height: 130px; max-height: 40vh;
      font-family: inherit; font-size: 12.5px; line-height: 1.55;
      background: var(--ui-surface); color: var(--ui-text);
      border: 1px solid var(--ui-line); border-radius: 8px; padding: 10px 12px;
      outline: none;
    }
    .ai-prefs-input:focus { border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .ai-prefs-row { display: flex; gap: 8px; align-items: center; }
    .ai-prefs-row .ai-prefs-count { font-size: 11px; color: var(--ui-dim-2); margin-left: auto; }
    .ai-prefs-row .ai-prefs-count.over { color: var(--ui-danger); }
    .settings-ai-prefs { display: block; width: 100%; box-sizing: border-box; margin-top: 8px; }
    .ai-model-select {
      flex: 0 0 auto; background: var(--ui-surface); color: var(--ui-text);
      border: 1px solid var(--ui-line); border-radius: 7px;
      padding: 4px 8px; font: inherit; font-size: 11.5px; font-weight: 600;
      cursor: pointer; outline: none;
    }
    .ai-model-select:focus { border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .ai-model-row { display: flex; align-items: center; gap: 8px; }
    .ai-model-row .ai-model-label { font-size: 11px; color: var(--ui-dim-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; }
    .ai-log { flex: 1; overflow-y: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 12px; }
    .ai-msg { font-size: 13.5px; line-height: 1.55; border-radius: 10px; padding: 9px 12px; max-width: 92%; white-space: pre-wrap; }
    .ai-msg.me { align-self: flex-end; background: var(--ui-accent-solid); color: var(--ui-accent-on); }
    .ai-msg.ai { align-self: flex-start; background: var(--ui-sunken); border: 1px solid var(--ui-line); color: var(--ui-text-2); }
    .ai-msg.err { align-self: stretch; background: var(--ui-danger-bg); border: 1px solid var(--ui-danger-line); color: var(--ui-danger); max-width: none; }
    .ai-msg.note { align-self: stretch; max-width: none; background: none; padding: 0; font-size: 12px; color: var(--ui-dim-3); }
    .ai-empty { font-size: 13px; line-height: 1.6; color: var(--ui-dim-3); }
    .ai-empty ul { margin: 8px 0 0; padding-left: 18px; }
    .ai-empty li { margin-bottom: 4px; }
    .ai-foot { padding: 12px 16px; border-top: 1px solid var(--ui-line); display: flex; flex-direction: column; gap: 8px; }
    .ai-input { resize: none; min-height: 62px; font-family: inherit; }
    .ai-send-row { display: flex; align-items: center; gap: 8px; }
    .ai-send-row .ai-hint { font-size: 11.5px; color: var(--ui-dim-2); }
    .ai-send-row #btn-ai-send { margin-left: auto; }
    .ai-atts { display: flex; flex-wrap: wrap; gap: 6px; }
    .ai-att {
      display: flex; align-items: center; gap: 6px; max-width: 100%;
      background: var(--ui-sunken); border: 1px solid var(--ui-line); border-radius: 8px;
      padding: 4px 6px 4px 4px; font-size: 11.5px; color: var(--ui-text-2);
    }
    .ai-att img { width: 30px; height: 30px; object-fit: cover; border-radius: 5px; display: block; }
    .ai-att-doc {
      width: 30px; height: 30px; border-radius: 5px; background: var(--ui-accent-tint);
      display: flex; align-items: center; justify-content: center;
      font-size: 13px; color: var(--ui-accent);
    }
    .ai-att-meta { min-width: 0; display: flex; flex-direction: column; }
    .ai-att-name { max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .ai-att-size { font-size: 10.5px; color: var(--ui-dim-2); }
    .ai-att-del {
      background: none; border: 0; color: var(--ui-dim-3); cursor: pointer;
      font-size: 15px; line-height: 1; padding: 0 2px;
    }
    .ai-att-del:hover { color: var(--ui-danger); }
    .ai-msg-atts { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
    .ai-msg-atts img { width: 54px; height: 54px; object-fit: cover; border-radius: 5px; display: block; }
    .ai-msg-atts .ai-msg-file { font-size: 11px; color: inherit; background: rgba(255, 255, 255, 0.18); border-radius: 5px; padding: 3px 6px; }
    .ai-panel.is-drop { outline: 2px dashed var(--ui-accent); outline-offset: -6px; }
    .sig-store-thumb {
      width: 96px; height: 34px; flex-shrink: 0;
      display: flex; align-items: center; justify-content: center;
      background: #fff; border: 1px solid var(--ui-line); border-radius: 2px; padding: 2px;
    }
    .sig-store-thumb img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
    .sig-store-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; }
    .sig-store-label { display: block; font-size: 13px; font-weight: 700; color: var(--ui-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sig-store-label:empty { display: none; }
    .sig-store-name { display: block; font-size: 12.5px; color: var(--ui-accent-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sig-store-name:empty { display: none; }
    .sig-store-title { display: block; font-size: 11.5px; color: var(--ui-dim-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .sig-store-title:empty { display: none; }
    .sig-store-fname { font-size: 12px; color: var(--ui-dim-3); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* ── Settings list + elegant add button ──
       Shared pattern for API keys and saved signatures: a scroll list of
       clickable rows, with a dashed "+ Add …" tile below. Rows open an edit
       sub-dialog; the add tile opens the same dialog in add mode. */
    .settings-list { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 8px; max-height: 220px; overflow-y: auto; }
    .settings-list-empty { font-size: 12.5px; color: var(--ui-dim-2); font-style: italic; padding: 6px 2px; }
    .settings-list-row {
      display: flex; align-items: center; gap: 12px; width: 100%;
      padding: 8px 10px; border: 1px solid var(--ui-line); border-radius: 3px;
      background: var(--ui-surface); cursor: pointer; text-align: left;
      color: inherit; font: inherit;
      transition: border-color 0.12s, background 0.12s;
    }
    .settings-list-row:hover { border-color: var(--ui-accent); background: var(--ui-hover); }
    .settings-list-row:focus-visible { outline: none; border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .settings-row-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
    .settings-row-title { font-size: 13px; font-weight: 700; color: var(--ui-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .settings-row-sub { font-size: 11.5px; color: var(--ui-dim-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .settings-row-sub:empty { display: none; }
    .settings-row-badge {
      font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
      color: var(--ui-accent); background: var(--ui-accent-tint);
      border: 1px solid rgba(var(--ui-accent-rgb), 0.22); border-radius: 3px;
      padding: 2px 6px; flex-shrink: 0;
    }
    .settings-row-badge.dim { color: var(--ui-dim-3); background: transparent; border-color: var(--ui-line); }
    .settings-list-row .sig-store-thumb { width: 84px; height: 30px; }
    .settings-list-row.is-static { cursor: default; }
    .settings-list-row.is-static:hover { border-color: var(--ui-line); background: var(--ui-surface); }
    .settings-row-remove {
      width: 26px; height: 26px; padding: 0; flex-shrink: 0;
      display: inline-flex; align-items: center; justify-content: center;
      border: 1px solid transparent; border-radius: 3px;
      background: transparent; color: var(--ui-dim-2); cursor: pointer;
      transition: color 0.12s, background 0.12s, border-color 0.12s;
    }
    .settings-row-remove svg { display: block; }
    .settings-row-remove:hover { color: var(--ui-danger); border-color: var(--ui-line); background: var(--ui-hover); }
    .settings-row-remove:focus-visible { outline: none; box-shadow: var(--ui-focus); }
    /* Elegant "+ Add …" tile: dashed border, quiet blue, brightens on hover. */
    .settings-add {
      display: flex; align-items: center; justify-content: center; gap: 8px;
      width: 100%; padding: 9px 10px; margin: 0 0 4px;
      border: 1px dashed var(--ui-line-strong); border-radius: 3px;
      background: transparent; color: var(--ui-accent-soft);
      font-family: inherit; font-size: 12px; font-weight: 700;
      letter-spacing: 0.06em; text-transform: uppercase;
      cursor: pointer;
      transition: border-color 0.12s, background 0.12s, color 0.12s;
    }
    .settings-add svg { width: 13px; height: 13px; display: block; flex-shrink: 0; }
    .settings-add:hover { border-color: var(--ui-accent); background: var(--ui-accent-tint); color: var(--ui-accent); }
    .settings-add:focus-visible { outline: none; border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .settings-add:disabled { opacity: 0.5; cursor: not-allowed; }
    .settings-add:disabled:hover { border-color: var(--ui-line-strong); background: transparent; color: var(--ui-accent-soft); }

    /* Sub-dialogs opened from Settings sit above it. */
    .dialog-backdrop.settings-child { z-index: 1010; }
    /* Signature edit dialog: thumb + file picker on one row. */
    .sig-dlg-image { display: flex; align-items: center; gap: 12px; margin: 6px 0 4px; }
    .sig-dlg-image .sig-store-thumb { width: 120px; height: 46px; }
    .sig-dlg-image .sig-store-thumb.is-empty { background: var(--ui-sunken); border: 1px dashed var(--ui-line-strong); }
    .sig-dlg-file { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
    /* Edit dialogs need a three-slot footer: [Delete] · [Cancel] [Save]. */
    .dialog-footer .settings-footer-spacer { flex: 1; }
    #apikey-dialog .dialog-footer,
    #signature-dialog .dialog-footer { gap: 8px; }

    /* Model row with an inline Refresh link (fetches the provider's current
       model catalogue when the key is set). Sits on one line above the model
       select; the status line below reports cache freshness. */
    .apikey-model-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-top: 4px; }
    .apikey-model-head .set-label { margin: 0; }
    .apikey-refresh {
      background: none; border: 0; padding: 0; margin: 0;
      font-family: inherit; font-size: 10.5px; font-weight: 700;
      letter-spacing: 0.06em; text-transform: uppercase;
      color: var(--ui-accent-soft); cursor: pointer;
      display: inline-flex; align-items: center; gap: 5px;
      transition: color 0.12s;
    }
    .apikey-refresh svg { display: block; transition: transform 0.4s linear; }
    .apikey-refresh:hover { color: var(--ui-accent); }
    .apikey-refresh:focus-visible { outline: none; box-shadow: var(--ui-focus); border-radius: 3px; }
    .apikey-refresh:disabled { color: var(--ui-dim); cursor: not-allowed; }
    .apikey-refresh.is-busy { color: var(--ui-dim-2); pointer-events: none; }
    .apikey-refresh.is-busy svg { animation: apikey-spin 0.9s linear infinite; }
    @keyframes apikey-spin { to { transform: rotate(360deg); } }
    .apikey-model-note { font-size: 11px; color: var(--ui-dim-3); margin-top: 4px; }
    .apikey-model-note.is-shipped { color: var(--ui-dim-3); }
    .apikey-model-note.is-error { color: var(--ui-danger); }
    .sig-pick-list { display: flex; flex-direction: column; gap: 6px; }
    .sig-pick-row {
      display: flex; align-items: center; gap: 12px; width: 100%;
      padding: 8px 10px; border: 1px solid var(--ui-line); border-radius: 3px;
      background: var(--ui-surface); cursor: pointer; text-align: left;
      transition: border-color 0.12s, background 0.12s;
    }
    .sig-pick-row:hover { border-color: var(--ui-accent); background: var(--ui-hover); }
    .about-btn {
      width: 18px;
      height: 18px;
      border-radius: 50%;
      border: 1px solid var(--ui-muted);
      background: transparent;
      color: var(--ui-dim);
      font-size: 11px;
      font-weight: 700;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      line-height: 1;
      transition: color 0.15s, border-color 0.15s, background 0.15s;
    }
    .about-btn:hover {
      color: var(--ui-accent);
      border-color: var(--ui-accent);
      background: var(--ui-accent-tint);
    }
    .about-btn.gear-btn { width: 20px; height: 20px; }
    .about-btn.gear-btn svg { width: 13px; height: 13px; display: block; }

    /* ── About Dialog ── */
    .dialog-backdrop {
      display: none;
      position: fixed;
      inset: 0;
      background: var(--ui-scrim);
      align-items: center;
      justify-content: center;
      z-index: 1000;
      backdrop-filter: blur(3px);
    }
    .dialog-backdrop.open { display: flex; }

    .dialog {
      background: var(--ui-surface);
      border: 1px solid var(--ui-line);
      border-radius: 12px;
      max-width: 420px;
      width: calc(100% - 32px);
      padding: 28px 30px 24px;
      color: var(--ui-text-2);
      box-shadow: var(--ui-shadow-lg);
      position: relative;
    }

    /* About content scrolls as one region; the title and Close button stay visible. */
    #about-dialog .dialog {
      display: flex;
      flex-direction: column;
      max-height: 86vh;
      max-height: min(86vh, calc(100dvh - 32px));
      box-sizing: border-box;
    }
    #about-dialog .about-body {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      overflow-wrap: anywhere;
    }
    #about-dialog h2, #about-dialog .dialog-version, #about-dialog .dialog-footer { flex-shrink: 0; }
    #about-dialog .dialog-footer { margin-top: 14px; }

    .dialog h2 {
      font-size: 20px;
      font-weight: 800;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      color: var(--ui-accent);
      margin-bottom: 4px;
    }

    .dialog .dialog-version {
      font-size: 11px;
      color: var(--ui-muted);
      font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
      margin-bottom: 18px;
      letter-spacing: 0.05em;
    }

    .dialog p {
      font-size: 13px;
      line-height: 1.65;
      color: var(--ui-text-3);
      margin-bottom: 12px;
    }

    .dialog p em {
      color: var(--ui-accent);
      font-style: normal;
      font-weight: 600;
    }

    /* Buttons must never wrap: a wrapped label doubles one button's height and
       leaves the row ragged. Wrap the ROW instead when it runs out of width. */
    .dialog-footer > button { white-space: nowrap; }
    .dialog-footer {
      margin-top: 18px;
      padding-top: 14px;
      border-top: 1px solid var(--ui-line);
      font-size: 12px;
      color: var(--ui-dim);
      font-style: italic;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    /* In a dialog footer, buttons sit a size down; only .quiet goes darker, so
       the committing action keeps its weight next to Cancel. */
    .dialog-footer .button { padding: 6px 14px; font-size: 11px; }
    .dialog-footer .button.quiet { background: var(--ui-sunken); }

    /* ── Toast ── */
    .about-license {
      margin-top: 14px;
      border-top: 1px solid var(--ui-line);
      padding-top: 12px;
    }
    .about-license > summary {
      cursor: pointer;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--ui-dim);
      list-style: none;
      user-select: none;
    }
    .about-license > summary::-webkit-details-marker { display: none; }
    .about-license > summary::before { content: "\25B8  "; color: var(--ui-dim); }
    .about-license[open] > summary::before { content: "\25BE  "; }
    .about-license > summary:hover { color: var(--ui-accent); }
    .about-license p {
      font-size: 11px;
      line-height: 1.55;
      color: var(--ui-dim-3);
    }
    .about-changes {
      margin: 14px 0 4px;
      border-top: 1px solid var(--ui-line);      padding-top: 12px;
    }
    .about-changes-title {
      font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
      color: var(--ui-accent); margin-bottom: 7px;
    }
    .about-changes ul { margin: 0; padding-left: 16px; display: flex; flex-direction: column; gap: 4px; }
    .about-changes li { font-size: 11px; line-height: 1.55; color: var(--ui-dim-3); }
    #toast {
      position: fixed;
      left: 50%;
      bottom: 32px;
      transform: translateX(-50%) translateY(20px);
      min-width: 220px;
      max-width: 90vw;
      padding: 12px 22px;
      border-radius: 8px;
      font-size: 13px;
      font-weight: 600;
      letter-spacing: 0.02em;
      text-align: center;
      box-shadow: var(--ui-shadow-lg);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.25s ease, transform 0.25s ease;
      z-index: 2000;
      border: 1px solid transparent;
    }
    #toast.show {
      opacity: 1;
      transform: translateX(-50%) translateY(0);
    }
    #toast.success {
      background: var(--ui-ok-bg);
      border-color: var(--ui-ok-line);
      color: var(--ui-ok);
    }
    #toast.error {
      background: var(--ui-danger-bg);
      border-color: var(--ui-danger-line);
      color: var(--ui-danger);
    }
    #toast.info {
      background: var(--ui-surface);
      border-color: var(--ui-line);
      color: var(--ui-text-2);
    }

    .tab {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 7px;
      padding: 8px 18px;
      font-size: 13px;
      font-weight: 600;
      color: var(--ui-dim-2);
      cursor: pointer;
      border: none;
      background: none;
      border-bottom: 2px solid transparent;
      margin-bottom: -2px;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      transition: color 0.15s, border-color 0.15s;
    }

    .tab svg { width: 14px; height: 14px; flex: 0 0 auto; }
    .tab.is-dirty svg { color: var(--ui-warn); }
    .tab-settings { padding-right: 11px; padding-left: 11px; }

    .tab:hover { color: var(--ui-accent-soft); }

    .tab.active {
      color: var(--ui-accent);
      border-bottom-color: var(--ui-accent);
    }

    .settings-subnav {
      display: flex;
      align-items: center;
      gap: 4px;
      margin-bottom: 10px;
      border-bottom: 1px solid var(--ui-line);
    }
    .settings-tab {
      padding: 8px 12px;
      margin-bottom: -1px;
      border: 0;
      border-bottom: 2px solid transparent;
      background: transparent;
      color: var(--ui-dim-2);
      font: inherit;
      font-size: 12px;
      font-weight: 600;
      text-transform: uppercase;
      cursor: pointer;
    }
    .settings-tab:hover { color: var(--ui-accent-soft); }
    .settings-tab.active { color: var(--ui-accent); border-bottom-color: var(--ui-accent); }
    .settings-view { display: none; }
    .settings-view.active { display: block; }
    .doc-ws-acts { display: flex; flex-wrap: wrap; gap: 8px; }
    .doc-ws-note { margin: 10px 0 0; }
    .doc-ws-note:empty { display: none; }

    /* ── Action Bar ── */
    .action-bar {
      display: flex;
      justify-content: flex-end;
      align-items: center;
      gap: 8px;
      padding: 6px 0 10px;
    }

    /* ── Buttons ─────────────────────────────────────────────────
       ONE button. Containers adjust it (.dialog-footer .button, .fv-acts
       .button, …); variants set intent (.primary, .green, .danger). Shell
       only — the document renders its own inline-styled controls, and no
       shell rule may reach inside #view-doc. */
    .button {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      padding: 7px 14px;
      font-family: inherit;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      white-space: nowrap;
      border: 1px solid var(--ui-line);
      border-radius: 6px;
      background: var(--ui-surface);
      color: var(--ui-accent);
      cursor: pointer;
      box-shadow: var(--ui-shadow-sm);
      transition: background 0.1s, border-color 0.1s, color 0.1s, box-shadow 0.1s;
    }
    .button:hover { background: var(--ui-hover); border-color: var(--ui-line-strong); color: var(--ui-accent); }
    .button:focus-visible { outline: none; border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .button:disabled { opacity: 0.45; cursor: default; }
    .button:disabled:hover { background: var(--ui-surface); border-color: var(--ui-line); color: var(--ui-accent); }
    .button svg { flex-shrink: 0; }
    .button.icon-only {
      justify-content: center;
      flex: 0 0 36px;
      width: 36px;
      height: 34px;
      padding: 0;
      gap: 0;
    }
    .button.icon-only svg { width: 16px; height: 16px; }
    .button.primary { background: var(--ui-accent-solid); border-color: var(--ui-accent-solid); color: var(--ui-accent-on); }
    .button.primary:hover { background: var(--ui-accent-solid-hover); border-color: var(--ui-accent-solid-hover); color: var(--ui-accent-on); }
    .button.green { background: var(--ui-ok-bg); border-color: var(--ui-ok-line); color: var(--ui-ok); }
    .button.green:hover { background: var(--ui-ok); border-color: var(--ui-ok); color: #fff; }
    .button.danger-quiet { color: var(--ui-danger); border-color: var(--ui-danger-line); }
    /* A button that reads as a checkbox: the box is drawn, the label stays a
       button label. Used for "Workspace template" in document Settings. */
    .button.tickbox { gap: 8px; }
    .button.tickbox .tick {
      width: 13px; height: 13px; flex: 0 0 auto;
      border: 1px solid var(--ui-line-strong); border-radius: 3px; background: var(--ui-surface);
      position: relative; transition: background 0.12s, border-color 0.12s;
    }
    .button.tickbox[aria-pressed="true"] { border-color: var(--ui-ok-line); color: var(--ui-ok); }
    .button.tickbox[aria-pressed="true"] .tick { background: var(--ui-ok); border-color: var(--ui-ok); }
    .button.tickbox[aria-pressed="true"] .tick::after {
      content: ''; position: absolute; left: 3px; top: 0px;
      width: 4px; height: 7px; border: solid #fff; border-width: 0 2px 2px 0;
      transform: rotate(40deg);
    }
    .button.danger { background: var(--ui-danger-bg); border-color: var(--ui-danger-line); color: var(--ui-danger); }
    .button.danger:hover { background: var(--ui-danger); border-color: var(--ui-danger); color: #fff; }
    .button.quiet { background: var(--ui-sunken); box-shadow: none; }
    .button.copied { background: var(--ui-ok-bg); border-color: var(--ui-ok-line); color: var(--ui-ok); }
    /* HTML dropdown (Export / Copy) */
    .action-menu-wrap { position: relative; display: inline-flex; }
    .action-caret { opacity: 0.8; margin-left: 1px; }
    .action-menu {
      position: absolute;
      top: calc(100% + 6px);
      right: 0;
      z-index: 50;
      min-width: 200px;
      display: flex;
      flex-direction: column;
      padding: 5px;
      background: var(--ui-surface);
      border: 1px solid var(--ui-line);
      border-radius: 8px;
      box-shadow: var(--ui-shadow-lg);
    }
    .action-menu[hidden] { display: none; }
    .action-menu-item {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 2px;
      padding: 8px 10px;
      border: none;
      border-radius: 6px;
      background: transparent;
      color: var(--ui-text-2);
      font-family: inherit;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      text-align: left;
      cursor: pointer;
      transition: background 0.1s, color 0.1s;
    }
    .action-menu-item:hover { background: var(--ui-accent-tint); color: var(--ui-accent); }
    .action-menu-item.copied { background: var(--ui-ok-bg); color: var(--ui-ok); }
    .action-menu-sub {
      font-size: 10px;
      font-weight: 500;
      letter-spacing: 0.01em;
      text-transform: none;
      color: var(--ui-dim-2);
    }
    .action-menu-item:hover .action-menu-sub { color: var(--ui-dim-3); }
    .action-menu-warn {
      margin: 2px 4px 6px;
      padding: 7px 10px;
      border-radius: 6px;
      background: var(--ui-warn-bg);
      border: 1px solid var(--ui-warn-line);
      color: var(--ui-warn);
      font-size: 10.5px;
      font-weight: 500;
      line-height: 1.35;
      letter-spacing: 0.01em;
    }
    .action-menu-warn[hidden] { display: none; }

    /* Close the open document — back to the folder view. */
    .doc-close {
      display: inline-flex; align-items: center; justify-content: center;
      width: 30px; height: 30px; flex-shrink: 0;
      margin: 0 2px 6px 0;
      color: var(--ui-dim-2);
      background: transparent;
      border: 1px solid transparent;
      border-radius: 8px;
      cursor: pointer;
      transition: background 0.12s, color 0.12s, border-color 0.12s;
    }
    .doc-close:hover { background: var(--ui-surface); border-color: var(--ui-line); color: var(--ui-text); }
    .doc-close:focus-visible { outline: none; border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    #app.no-doc .doc-close { display: none; }
    @media print { .doc-close { display: none !important; } }
    /* The exported HTML file carries its own print CSS (see exportHtml), so
       #export-doc rules live there, not here. */

    /* ── Publish / lock ── */
    .pub-tag {
      display: inline-flex; align-items: center; gap: 6px;
      font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
      color: var(--ui-warn); margin-right: 4px;
    }
    .pub-tag .pub-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ui-warn); }
    .publish-lock { display: none; }
    #app.is-published #edit-panel .publish-lock {
      display: flex; align-items: center; gap: 16px; justify-content: space-between;
      margin: 0 0 22px; padding: 16px 18px;
      background: var(--ui-warn-bg);
      border: 1px solid var(--ui-warn-line); border-left: 3px solid var(--ui-warn); border-radius: 8px;
    }
    .publish-lock .pl-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
    .publish-lock .pl-title { font-size: 14px; font-weight: 700; color: #7a4d0d; letter-spacing: 0.02em; }
    .publish-lock .pl-title span { color: var(--ui-warn); }
    .publish-lock .pl-sub { font-size: 12px; line-height: 1.5; color: #8a6a3a; }
    .publish-lock .pl-meta { font-size: 11px; font-weight: 600; letter-spacing: 0.02em; color: #a08655; margin-top: 2px; }
    .publish-lock .pl-meta:empty { display: none; }
    .publish-lock .button { flex-shrink: 0; border-color: var(--ui-warn-line); color: var(--ui-warn); }
    .publish-lock .button:hover { background: var(--ui-warn); border-color: var(--ui-warn); color: #fff; }
    /* Lock the editing surface while published (inert also blocks keyboard) */
    #app.is-published #block-list { opacity: 0.5; pointer-events: none; user-select: none; filter: grayscale(0.2); }
    #app.is-published .add-bar { display: none !important; }

    #save-status {
      font-size: 11px;
      font-style: italic;
      color: var(--ui-ok);
      margin-right: 8px;
    }

    .modified-at {
      font-size: 11px;
      font-style: italic;
      color: var(--ui-dim);
      letter-spacing: 0.02em;
      margin-right: 4px;
    }
    .modified-at .label {
      color: var(--ui-muted);
      font-style: normal;
      text-transform: uppercase;
      font-weight: 700;
      letter-spacing: 0.05em;
      margin-right: 4px;
      font-size: 10px;
    }

    /* ── Add Block bar (bottom of editor) ── */
    /* ── Add Block bar (now sits outside the editor card) ── */
    .add-bar {
      display: flex;
      flex-direction: column;
      gap: 8px;
      margin: 20px 0 40px;
      padding: 0;
      border: none;
    }
    .add-bar-row {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
    }
    .add-advanced {
      padding-top: 0;
      border-top: none;
    }
    .add-sep {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-top: 2px;
    }
    .add-sep-label {
      font-size: 10px;
      font-weight: 700;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--ui-dim);
    }
    .add-sep-line { flex: 1; height: 1px; background: var(--ui-line); }
    .add-toggle-line {
      flex: 1;
      min-width: 24px;
      height: 1px;
      background: var(--ui-line);
      align-self: center;
    }
    .add-toggle {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      background: transparent;
      border-style: dashed;
      color: var(--ui-dim-2);
    }
    .add-toggle:hover {
      background: var(--ui-hover);
      border-style: solid;
      color: var(--ui-accent);
    }
    .add-toggle[aria-expanded="true"] {
      color: var(--ui-accent);
      border-style: solid;
      border-color: var(--ui-line);
    }
    .add-toggle-caret {
      font-size: 9px;
      transition: transform 0.15s ease;
      display: inline-block;
    }
    .add-toggle[aria-expanded="true"] .add-toggle-caret {
      transform: rotate(180deg);
    }

    /* The add bar's buttons are a compact row of block types. */
    #add-bar .button { flex: 0 0 auto; padding: 6px 14px; line-height: 1.4; }

    .panel { display: none; }
    .panel.active { display: block; margin-top: 14px; }

    /* ── View Panel (the "card" ─ full width container) ── */
    #view-panel {
      width: 100%;
      padding: 8px 0 40px;
      color: var(--ui-text);
      background: var(--backdrop-bg, var(--ui-bg));
    }

    #view-panel .empty-state {
      color: var(--ui-dim);
      font-size: 14px;
      padding: 24px 0;
    }

    /* ── No-document state ───────────────────────────────────────
       Home and the folder browser share the document view's shell: same
       #shell padding, same .shell-inner width, and the browser's own band
       occupies exactly the box .shell-head does. Only the document chrome
       (filename, tabs, action bars) is hidden. */
    #app.no-doc .shell-title,
    #app.no-doc .tabs,
    #app.no-doc #action-bar-view,
    #app.no-doc #action-bar-edit,
    #app.no-doc #add-bar { display: none !important; }
    #app.no-doc .shell-head { display: none; }
    /* The band is the header now, so nothing may sit above it. */
    #app.no-doc .panel.active { margin-top: 0; }
    #app.no-doc #view-panel { padding-top: 0; }
    /* With no document there is nothing to theme, so the themed backdrop must
       not paint over the shell's home scene. */
    #app.no-doc #view-panel { background: transparent; color: inherit; }
    /* Same for the edit panel: it paints the theme's editing surface, which on a
       light theme is near-white. With no document open the folder browser lives
       inside it, so the themed surface (and its card border/padding) has to go —
       otherwise closing a document from the Edit tab drops the browser onto a
       white slab. The published dimming is cleared here too: no document, so
       nothing may stay greyed. */
    #app.no-doc #edit-panel {
      background: transparent !important;
      color: inherit;
      border-color: transparent;
      box-shadow: none;
      padding: 0;
    }
    #app.no-doc #block-list {
      opacity: 1 !important;
      filter: none !important;
      pointer-events: auto !important;
      user-select: auto !important;
    }
    #app.no-doc #shell {
      min-height: 100vh;
      background-color: var(--ui-bg);
      background-image:
        radial-gradient(ellipse 82% 78% at 50% 42%, rgba(243, 244, 246, 0) 36%, var(--ui-bg) 82%),
        radial-gradient(ellipse 58% 52% at 50% 38%, rgba(var(--ui-accent-rgb), 0.06), rgba(var(--ui-accent-rgb), 0) 70%),
        radial-gradient(circle at center, rgba(var(--ui-accent-rgb), 0.10) 1px, transparent 1.5px);
      background-size: cover, cover, 22px 22px;
      background-position: center, center, center;
      background-repeat: no-repeat, no-repeat, repeat;
    }

    /* ── Folder view (shown when no document is open) ────────────── */
    /* Sits inside .shell-inner exactly as the document does: the band mirrors
       .shell-head's box, the content is inset by the same 14px. */
    .fv {
      display: flex;
      flex-direction: column;
      min-height: calc(100vh - 170px);
      padding: 0 14px 12px;
      gap: 10px;
      border-radius: 10px;
      transition: box-shadow 0.15s, background 0.15s;
    }
    .fv.is-drag {
      background: rgba(31, 138, 95, 0.06);
      box-shadow: inset 0 0 0 2px rgba(31, 138, 95, 0.35);
    }
    .fv-band {
      position: sticky;
      top: 0;
      z-index: 40;
      background: var(--ui-bg);
      margin: 0 -14px 10px;
      padding: 5px 14px 0;
      box-shadow: 0 10px 12px -12px rgba(16, 24, 40, 0.18);
    }
    .fv-top {
      display: flex;
      align-items: flex-end;
      justify-content: space-between;
      gap: 16px;
      border-bottom: 2px solid var(--ui-line);
      margin-bottom: 4px;
      min-height: 40px;
    }
    .fv-crumbs { display: flex; align-items: center; gap: 4px; min-width: 0; flex: 1 1 auto; padding-bottom: 8px; }
    /* The left menu is retired — Home and the folder browser carry its
       functions. The markup stays so its render calls remain harmless. */
    #sidebar, #sidebar-backdrop { display: none !important; }
    .fv-brand {
      background: none; border: none; padding: 0 2px;
      margin: 0 12px 8px 0;
      font-family: inherit; font-size: 18px; font-weight: 800;
      letter-spacing: 0.14em; text-transform: uppercase;
      color: var(--ui-accent); cursor: pointer; flex-shrink: 0;
      transition: color 0.12s;
    }
    .fv-brand:hover { color: var(--ui-accent-soft); }
    .fv-ident {
      display: flex; align-items: center; gap: 10px;
      flex-shrink: 0; padding-bottom: 0;
    }
    .fv-ident .attribution,
    .fv-ident .version { line-height: 1; }
    .fv-ident .fv-brand-static { margin-right: 2px; }
    .fv-ident-text {
      display: flex; flex-direction: column; align-items: flex-end; gap: 1px;
      line-height: 1.25;
    }
    .fv-ident .attribution { font-size: 12px; }
    .fv-search {
      display: flex; align-items: center; gap: 7px;
      min-width: 0; width: 280px; max-width: 40%;
      padding: 7px 10px;
      background: var(--ui-surface); border: 1px solid var(--ui-line); border-radius: 8px;
      box-shadow: var(--ui-shadow-sm);
      transition: border-color 0.1s, box-shadow 0.1s;
    }
    .fv-search:focus-within { border-color: var(--ui-accent); box-shadow: var(--ui-focus); }
    .fv-search-icon { color: var(--ui-dim-2); flex-shrink: 0; }
    .fv-search-input {
      flex: 1; min-width: 0;
      background: none; border: none; outline: none;
      font-family: inherit; font-size: 13px; color: var(--ui-text);
    }
    .fv-search-input::placeholder { color: var(--ui-dim); }
    .fv-search-x {
      display: inline-flex; align-items: center;
      background: none; border: none; padding: 0 2px;
      color: var(--ui-dim-2); cursor: pointer;
    }
    .fv-search-x:hover { color: var(--ui-text); }
    .fv-actbtns { display: flex; gap: 8px; flex-shrink: 0; }
    .fv-row .fv-name .fv-path { color: var(--ui-dim-2); font-weight: 500; flex-shrink: 0; }
    .fv-row .fv-name .fv-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* One style for every icon control in a row: grip, caret, "…". */
    .fv-row .fv-caret,
    .fv-row .fv-grip,
    .fv-row .fv-more {
      display: inline-flex; align-items: center; justify-content: center;
      width: 24px; height: 24px; flex-shrink: 0;
      color: var(--ui-dim-2); border-radius: 5px; cursor: pointer;
      transition: transform 0.12s, color 0.1s, background 0.1s, opacity 0.1s;
    }
    .fv-row .fv-caret:hover,
    .fv-row .fv-grip:hover,
    .fv-row .fv-more:hover { background: var(--ui-line); color: var(--ui-text); opacity: 1; }
    .fv-row .fv-caret { margin: 0 -2px 0 -2px; }
    .fv-row .fv-caret.is-blank { visibility: hidden; }
    /* The grip sits in the row's left gutter rather than in the flow: it used to
       reserve its own width on every row — including folders, which can't be
       dragged — pushing the whole tree in by ~26px. */
    .fv-row .fv-grip {
      position: absolute; left: var(--fv-grip-left, 1px); top: 50%; transform: translateY(-50%);
      margin: 0; opacity: 0; cursor: grab;
    }
    .fv-row .fv-grip.is-blank { display: none; }
    .fv-row:hover .fv-grip { opacity: 1; }
    .fv-row .fv-grip:active { cursor: grabbing; }
    .fv-row.excluded .fv-grip { display: none; }
    .fv-row.expanded .fv-caret { transform: rotate(90deg); }
    .fv-sub-note {
      padding: 7px 12px 7px 46px;
      font-size: 12px; color: var(--ui-dim);
    }
    /* Search marks rows in place instead of collapsing the tree. */
    .fv-hitnote {
      padding: 6px 12px 10px;
      font-size: 12px; color: var(--ui-dim-2);
    }
    .fv-row.is-hit { background: rgba(var(--ui-accent-rgb), 0.08); }
    .fv-row.is-hit .fv-label { color: var(--ui-accent); font-weight: 700; }
    .fv-row.is-hit:hover { background: rgba(var(--ui-accent-rgb), 0.13); }
    .fv-row.is-miss .fv-label,
    .fv-row.is-miss .fv-meta { opacity: 0.45; }
    /* Excluded folders stay visible so you can put them back, but they read as
       inert: dimmed, no caret, no drill-in. */
    .fv-row.excluded { opacity: 0.42; cursor: default; }
    .fv-row.excluded:hover { background: none; }
    .fv-row.excluded .fv-icon.folder { color: var(--ui-dim); }
    .fv-home-h3 {
      margin: 30px 0 12px;
      font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em;
      text-transform: uppercase; color: var(--ui-dim-2);
    }
    .fv-recents {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
      gap: 10px;
    }
    .fv-recent {
      display: grid; grid-template-columns: auto minmax(0, 1fr);
      grid-template-rows: auto auto;
      align-items: center; gap: 2px 11px;
      padding: 12px 14px;
      background: var(--ui-surface); border: 1px solid var(--ui-line); border-radius: 10px;
      font: inherit; font-size: 13.5px; color: var(--ui-text);
      text-align: left; cursor: pointer;
      box-shadow: var(--ui-shadow-sm);
      transition: background 0.1s, border-color 0.1s, box-shadow 0.1s;
    }
    .fv-recent svg { grid-row: span 2; }
    .fv-recent:hover { border-color: var(--ui-line-strong); box-shadow: var(--ui-shadow-md); }
    .fv-recent-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
    .fv-recent-where { font-size: 11.5px; color: var(--ui-dim-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .fv-recent-where:empty { display: none; }
    .fv-crumb {
      background: none; border: none; padding: 2px 4px;
      font: inherit; font-size: 20px; font-weight: 500; color: var(--ui-dim-2);
      border-radius: 6px; cursor: pointer;
      max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .fv-crumb:hover { background: var(--ui-hover); color: var(--ui-text-2); }
    .fv-crumb.current { color: var(--ui-text); font-weight: 700; cursor: default; }
    .fv-crumb.current:hover { background: none; }
    .fv-sep { color: var(--ui-dim); font-size: 15px; flex-shrink: 0; }
    .fv-acts {
      display: flex; gap: 12px;
      justify-content: space-between;
      align-items: center;
      min-height: 44px;
    }
    /* The browser reads as a file manager, not a toolbar: sentence case. */
    .fv .button {
      padding: 6px 12px; font-size: 12px; font-weight: 600;
      letter-spacing: 0; text-transform: none;
      color: var(--ui-text-2); background: var(--ui-surface);
      border-color: var(--ui-line); border-radius: 7px;
    }
    .fv .button:hover { background: var(--ui-hover); border-color: var(--ui-line-strong); color: var(--ui-text); }
    .fv .button.primary { background: var(--ui-accent-solid); border-color: var(--ui-accent-solid); color: var(--ui-accent-on); }
    .fv .button.primary:hover { background: var(--ui-accent-solid-hover); border-color: var(--ui-accent-solid-hover); }

    .fv { position: relative; }
    /* Visibility is driven by the .is-busy class, not the hidden attribute — a
       display declaration here would outrank the UA [hidden] rule. */
    .fv-busy { display: none; }
    .fv.is-busy .fv-busy {
      position: absolute; inset: 0; z-index: 60;
      display: flex; align-items: flex-start; justify-content: center;
      padding-top: 120px;
      background: rgba(243, 244, 246, 0.7);
      backdrop-filter: blur(1px);
      border-radius: 10px;
      cursor: progress;
    }
    .fv-busy-msg {
      padding: 10px 18px;
      font-size: 13px; font-weight: 600; letter-spacing: 0.02em; color: var(--ui-text-2);
      background: var(--ui-surface); border: 1px solid var(--ui-line); border-radius: 8px;
      box-shadow: var(--ui-shadow-lg);
    }
    .fv.is-busy .fv-list, .fv.is-busy .fv-band { pointer-events: none; }
    .fv.is-busy .fv-row { opacity: 0.55; }

    /* Header and rows are separate grids, so the columns must be fixed widths
       to line up. The "…" button sits outside the grid, in reserved padding. */
    .fv-cols, .fv-row {
      display: grid;
      grid-template-columns: minmax(0, 1fr) 78px 116px;
      align-items: center;
      gap: 18px;
      padding-right: 40px;
    }
    .fv-row { position: relative; }
    .fv-row .fv-more {
      position: absolute; top: 50%; right: 8px; transform: translateY(-50%);
      font-size: 15px; line-height: 1; opacity: 0;
    }
    .fv-row:hover .fv-more { opacity: 1; }
    .fv-row.dragging { opacity: 0.45; }
    .fv-row.drop-target { background: var(--ui-accent-tint); outline: 1px dashed var(--ui-accent); outline-offset: -1px; }
    .fv-cols {
      padding: 0 12px 8px;
      padding-right: 40px;
      border-bottom: 1px solid var(--ui-line);
    }
    .fv-col {
      background: none; border: none; padding: 0;
      font: inherit; font-size: 11.5px; font-weight: 700;
      letter-spacing: 0.06em; text-transform: uppercase;
      color: var(--ui-dim-2); text-align: left; cursor: pointer;
      white-space: nowrap;
      display: inline-flex; align-items: center; gap: 5px;
    }
    .fv-col:not(:first-child) { justify-content: flex-end; }
    .fv-col:hover { color: var(--ui-text-3); }
    .fv-col.active { color: var(--ui-text); }
    .fv-col-arrow { font-size: 9px; opacity: 0.9; }
    .fv-list { flex: 1; min-height: 0; overflow: auto; padding-top: 4px; }
    .fv-row {
      width: 100%;
      /* Right padding reserves the "…" slot; keep it in the shorthand so the
         shared grid rule above isn't overridden. */
      padding: 9px 40px 9px 12px;
      background: none;
      border: none;
      border-radius: 8px;
      font: inherit;
      text-align: left;
      color: var(--ui-text-2);
    }
    .fv-open {
      display: flex; align-items: center; gap: 10px;
      min-width: 0; max-width: 100%;
      margin: -4px -8px; padding: 4px 8px;
      background: none; border: none; border-radius: 6px;
      font: inherit; text-align: left; color: inherit; cursor: pointer;
      transition: background 0.1s;
    }
    .fv-open:hover { background: var(--ui-line); }
    .fv-open:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: -2px; }
    .fv-row.excluded .fv-open { cursor: default; }
    .fv-row.excluded .fv-open:hover { background: none; }
    .fv-row:hover { background: var(--ui-surface); box-shadow: 0 0 0 1px var(--ui-line); }
    .fv-row:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: -2px; }
    .fv-row.current { background: var(--ui-accent-tint); }
    .fv-row > .fv-name {
      display: flex; align-items: center; gap: 10px;
      min-width: 0; justify-self: stretch;
      font-size: inherit; font-weight: inherit;
    }
    .fv-row .fv-name .fv-label,
    .fv-row .fv-open .fv-label {
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      font-size: 13.5px; font-weight: 550; color: var(--ui-text);
    }
    .fv-row .fv-icon { flex-shrink: 0; }
    .fv-icon.folder { color: #c8962e; }
    .fv-row .fv-icon.pulp { color: var(--ui-accent); }
    .fv-row .fv-icon.other { color: #d0742a; }
    /* The in-app file viewer uses the same .fv-* names, so scope these to rows
       and reset what leaks in. */
    .fv-row > .fv-meta {
      justify-self: stretch;
      margin: 0;
      font-size: 12px;
      color: var(--ui-dim-2);
      white-space: nowrap;
      text-align: right;
    }
    .fv-empty {
      padding: 28px 12px;
      font-size: 13px;
      color: var(--ui-dim);
      text-align: center;
    }
    .fv-card {
      max-width: 420px;
      margin: 40px auto;
      padding: 26px 24px;
      text-align: center;
      background: var(--ui-surface);
      border: 1px solid var(--ui-line);
      border-radius: 12px;
      box-shadow: var(--ui-shadow-md);
    }
    .fv-card h3 { margin: 0 0 6px; font-size: 17px; font-weight: 700; color: var(--ui-text); }
    .fv-card p { margin: 0 0 16px; font-size: 13px; line-height: 1.55; color: var(--ui-dim-3); }
    .fv-card .fv-acts { justify-content: center; min-height: 0; }
    .fv-ws-picks { display: flex; flex-direction: column; gap: 8px; margin: 0 0 22px; text-align: left; max-width: none; }
    .fv-ws-pick {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center; gap: 12px;
      width: 100%; padding: 13px 16px;
      font: inherit; font-size: 14.5px; font-weight: 600; color: var(--ui-text);
      background: var(--ui-surface); border: 1px solid var(--ui-line);
      border-radius: 10px; cursor: pointer; text-align: left;
      transition: background 0.1s, border-color 0.1s;
    }
    .fv-ws-pick:hover { background: var(--ui-hover); border-color: var(--ui-line-strong); }
    .fv-ws-pick.active { border-color: var(--ui-accent); background: var(--ui-accent-tint); }
    .fv-ws-pick .fv-ws-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .fv-ws-pick .fv-ws-sub { font-size: 12px; font-weight: 500; color: var(--ui-dim-2); }
    .fv-ws-pick .fv-ws-sub:empty { display: none; }
    .fv-ws-item { position: relative; }
    .fv-ws-item .fv-ws-pick { padding-right: 54px; }
    .fv-ws-gear {
      position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
      width: 32px; height: 32px; padding: 0;
      display: inline-flex; align-items: center; justify-content: center;
      border: 1px solid transparent; border-radius: 8px;
      background: transparent; color: var(--ui-dim-2); cursor: pointer;
      transition: color 0.12s, background 0.12s, border-color 0.12s;
    }
    .fv-ws-gear svg { width: 15px; height: 15px; display: block; }
    .fv-ws-gear:hover { color: var(--ui-accent); background: var(--ui-accent-tint); border-color: rgba(var(--ui-accent-rgb), 0.22); }
    .fv-ws-gear:focus-visible { outline: none; box-shadow: var(--ui-focus); }
    .fv-crumb-home {
      display: inline-flex; align-items: center; justify-content: center;
      padding: 4px 6px; color: var(--ui-dim-2);
    }
    .fv-crumb-home.current { color: var(--ui-text); cursor: pointer; }
    .fv-crumb-home:hover { background: var(--ui-hover); color: var(--ui-text-2); }
    .fv-home-top {
      display: flex; align-items: center; justify-content: space-between;
      gap: 16px; flex-wrap: nowrap;
      margin: 0 0 30px;
    }
    .fv-home-icon { display: inline-flex; align-items: center; color: var(--ui-accent); }
    .fv-home-mark { display: flex; align-items: center; gap: 12px; }
    .fv-brand-static { line-height: 1; }
    .fv-brand-static {
      font-size: 20px; font-weight: 800;
      letter-spacing: 0.16em; text-transform: uppercase;
      color: var(--ui-accent);
    }
    .fv-home { max-width: none; padding: 26px 0 10px; }
    .fv-home-hi { margin: 0 0 4px; font-size: 26px; font-weight: 700; color: var(--ui-text); }
    .fv-home-sub { margin: 0 0 22px; font-size: 14px; color: var(--ui-dim-3); }
    .fv-home-acts { justify-content: flex-end; min-height: 0; gap: 8px; }

    /* ── Install as an app ── */
    .about-btn[hidden], .fv-install[hidden] { display: none; }
    .fv-install {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto auto;
      align-items: center; gap: 14px;
      margin: 22px 0 0; padding: 14px 12px 14px 16px;
      background: var(--ui-accent-tint);
      border: 1px solid rgba(var(--ui-accent-rgb), 0.22);
      border-radius: 12px;
    }
    .fv-install-icon { width: 40px; height: 40px; display: block; border-radius: 9px; box-shadow: var(--ui-shadow-sm); }
    .fv-install-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    .fv-install-text strong { font-size: 14px; color: var(--ui-text); }
    .fv-install-text span { font-size: 12.5px; color: var(--ui-text-3); }
    .fv .fv-install .button { display: inline-flex; align-items: center; gap: 6px; }
    .fv-install .button svg { width: 13px; height: 13px; }
    .fv-install-x {
      width: 28px; height: 28px; padding: 0;
      display: inline-flex; align-items: center; justify-content: center;
      border: none; border-radius: 7px; background: transparent;
      color: var(--ui-dim-2); cursor: pointer;
    }
    .fv-install-x:hover { background: rgba(var(--ui-accent-rgb), 0.12); color: var(--ui-text-2); }
    .fv-install-x:focus-visible { outline: none; box-shadow: var(--ui-focus); }
    @media (max-width: 560px) {
      .fv-install { grid-template-columns: auto minmax(0, 1fr) auto; }
      .fv-install .button { grid-column: 1 / -1; justify-content: center; }
    }

    .install-dialog { max-width: 460px; }
    .install-head { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
    .install-head img { border-radius: 10px; box-shadow: var(--ui-shadow-md); }
    .install-head h2 { margin: 0; }
    .install-points { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 10px; }
    .install-points li {
      position: relative; padding-left: 26px;
      font-size: 13px; line-height: 1.55; color: var(--ui-text-3);
    }
    .install-points li::before {
      content: "\2713"; position: absolute; left: 0; top: 1px;
      width: 18px; height: 18px; border-radius: 50%;
      display: inline-flex; align-items: center; justify-content: center;
      font-size: 11px; font-weight: 800;
      background: var(--ui-accent-tint); color: var(--ui-accent);
    }
    .install-points strong { color: var(--ui-text); }
    .dialog p.install-note { font-size: 12px; color: var(--ui-dim-2); margin-bottom: 0; }
    .install-dialog .dialog-footer { justify-content: flex-end; gap: 8px; }

