/* Dark theme (default) — an original deep blue-slate ramp tuned for long sessions:
   canvas sits darkest, chrome one step up, hover/selection one more, so depth reads
   from luminance alone. Accent is reserved for interaction, never decoration. */
:root {
    color-scheme: dark;
    --bg-color: #0e1420;
    --panel-bg: #151c2a;
    --border-color: #2b3446;
    --accent-color: #6ea8ff;
    --accent-hover: #91bdff;
    --text-color: #e9eef6;
    --text-secondary: #9fabbf;
    --tool-hover: #1c2535;
    /* Motion tokens — one home for the app's easing + durations so panels, the action HUD and
       buttons share a consistent, tunable feel (the mobile bottom-sheet's slide, ported to the
       desktop + tablet chrome). Theme-independent, so defined once here. */
    --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);         /* the signature Material curve */
    --ease-emphasized: cubic-bezier(0.18, 0.7, 0.28, 1);   /* a livelier spring (the radial curve) */
    --dur-fast: 0.12s;
    --dur-base: 0.2s;
    --dur-slow: 0.3s;
    --selected-tool: #1c2f50;
    --selected-border: #6ea8ff;
    --canvas-bg: #0a101a;
    --grid-color: #222e3f;
    --brand-butter: #ffd34e;
    --brand-butter-muted: #3c300f;
    --brand-butter-border: #9d7a18;
    --focus-ring: rgba(110, 168, 255, 0.32);
    --canvas-grid-line: rgba(231, 235, 240, 0.07);
    --toast-bg: #e2e8f0;
    --toast-text: #0f172a;
    --support-cta-bg: #223454;
    --support-cta-hover: #2d4168;
    --support-cta-text: #f8fafc;
    --support-cta-sub: #cbd5e1;
    --input-bg: #141c2a;
    --input-text: #edf2f7;
    --input-border: #303948;
    --btn-primary-bg: #2e4e86;
    --btn-primary-hover: #3a5f9e;
    --btn-primary-text: #dce7fa;
    --notice-ok-bg: #15251f;
    --notice-ok-border: #2c5546;
    --notice-ok-text: #a7d0bf;
    --notice-info-bg: #16243f;
    --notice-info-border: #2d4a7a;
    --notice-info-text: #aecbff;
    --notice-warn-bg: #2e2410;
    --notice-warn-border: #6b5318;
    --notice-warn-text: #f0cd8a;
    --notice-danger-bg: #2a1618;
    --notice-danger-border: #5e2c2f;
    --notice-danger-text: #f3a5a5;
    --bottom-bar-height: 60px;
    --toolbar-handle-height: 48px;
    /* Heights reserved for each row of the mobile bottom message stack (contextual
       action bar + docked toast / read-only banner). Kept a hair generous so stacked
       rows clear each other without overlap. */
    --action-bar-height: 46px;
    --msg-strip-height: 46px;
    /* Single horizontal inset shared by every row of the Menu/Options/Properties
       blade rail — head, body rows, section labels, notes and the footer — so the
       whole panel aligns to one vertical gutter on both edges instead of the old
       mix of 12px (head/foot) vs 14px (rows). 16px is the comfortable desktop
       gutter for a ~272px blade; see CLAUDE.md "blade menu" padding notes. */
    --blade-gutter: 16px;
}

:root[data-theme="light"] {
    color-scheme: light;
    --bg-color: #f5f7fb;
    --panel-bg: #ffffff;
    --border-color: #d8dee8;
    --accent-color: #2f6feb;
    --accent-hover: #1f5cc0;
    --text-color: #1f2937;
    --text-secondary: #5b6472;
    --tool-hover: #eef2f7;
    --selected-tool: #eaf2ff;
    --selected-border: #2f6feb;
    --canvas-bg: #fdfefe;
    --grid-color: #e7ebf0;
    --brand-butter: #7a4d05;
    --brand-butter-muted: #fff4cf;
    --brand-butter-border: #e8b941;
    --focus-ring: rgba(47, 111, 235, 0.28);
    --canvas-grid-line: rgba(31, 41, 55, 0.06);
    --toast-bg: #1f2937;
    --toast-text: #ffffff;
    --support-cta-bg: #eaf2ff;
    --support-cta-hover: #d7e0ff;
    --support-cta-text: #1f2937;
    --support-cta-sub: #5b6472;
    --input-bg: #ffffff;
    --input-text: #1f2937;
    --input-border: #d8dee8;
    --btn-primary-bg: #2f6feb;
    --btn-primary-hover: #1f5cc0;
    --btn-primary-text: #ffffff;
    --notice-ok-bg: #ecfdf5;
    --notice-ok-border: #a7f3d0;
    --notice-ok-text: #065f46;
    --notice-info-bg: #eef2ff;
    --notice-info-border: #c7d2fe;
    --notice-info-text: #3730a3;
    --notice-warn-bg: #fef3c7;
    --notice-warn-border: #fcd34d;
    --notice-warn-text: #92400e;
    --notice-danger-bg: #fee2e2;
    --notice-danger-border: #fca5a5;
    --notice-danger-text: #991b1b;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background-color: var(--bg-color);
    color: var(--text-color);
    overflow: hidden;
    height: 100vh;
    height: 100svh;
    width: 100vw;
}

/* App Container */
.app {
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100svh;
}

/* Top Bar */
.top-bar {
    height: 48px;
    background-color: var(--panel-bg);
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 16px;
    z-index: 100;
    flex-shrink: 0;
}

.logo {
    font-weight: 700;
    font-size: 18px;
    color: var(--accent-color);
    display: flex;
    align-items: center;
    gap: 8px;
}
.logo-mark {
    flex: none;
}
.logo-text {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
}
.logo-name {
    font-weight: 700;
    font-size: 18px;
}
.logo-tld {
    color: var(--text-secondary);
    font-weight: 600;
}
.logo-tagline {
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.2px;
    color: var(--text-secondary);
    text-transform: none;
}
.logo-beta {
    flex: none;
    align-self: flex-start;
    margin-top: 2px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--brand-butter-muted);
    color: var(--brand-butter);
    border: 1px solid var(--brand-butter-border);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    line-height: 1.4;
}

.file-ops {
    display: flex;
    gap: 8px;
}

/* Document-link "← Back" button — a distinct accent so it reads as navigation, not a tool.
   Toggled (display) by DocLinks._renderCrumb; data-mobile-keep keeps it through the compact
   layout, and flex:0 0 auto stops it being squeezed when the bar wraps on small screens. */
.doclink-back-btn {
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    border-color: var(--btn-primary-bg);
    font-weight: 600;
    white-space: nowrap;
    flex: 0 0 auto;
}
.doclink-back-btn:hover {
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    filter: brightness(1.06);
}

/* ── Omni-search ─────────────────────────────────────────────
   One box to find tools / features / diagrams / help. Grows to fill the centre of the
   top bar; the results panel is an absolutely-positioned dropdown. */
.omni-search {
    position: relative;
    flex: 1 1 200px;
    max-width: 460px;
    min-width: 120px;
    display: flex;
    align-items: center;
    margin: 0 8px;
}
.omni-search-icon {
    position: absolute;
    left: 10px;
    font-size: 12px;
    opacity: 0.6;
    pointer-events: none;
}
.omni-search-input {
    width: 100%;
    box-sizing: border-box;
    padding: 6px 10px 6px 30px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    color: var(--text-color);
    font-size: 13px;
}
.omni-search-input:focus {
    outline: none;
    border-color: var(--accent-color);
    box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
}
.omni-search-results {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    max-height: min(60vh, 420px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.28);
    z-index: 400;
    padding: 4px;
    /* Reliability over a live <canvas>: the canvas behind this dropdown is paused while the panel
       is open (see Renderer pause on `omni:open`/`omni:close`), so it never repaints underneath
       and can't "bleed through" — no GPU/compositor hints (translateZ / backface-visibility /
       isolation) are used here. Those hints promote the overlay to its own layer, which on some
       mobile GPUs fails to re-rasterize the layer's children, leaving the panel an empty rounded
       rectangle and the input text invisible while typing. Plain DOM painting is the dependable
       path on phones and tablets. */
}
.omni-group {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-secondary);
    padding: 8px 10px 4px;
}
.omni-row {
    padding: 7px 10px;
    border-radius: 6px;
    font-size: 13px;
    color: var(--text-color);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.omni-row--active, .omni-row:hover {
    background: var(--accent-color);
    color: #fff;
}
.omni-empty {
    padding: 12px 10px;
    font-size: 13px;
    color: var(--text-secondary);
}
/* ── Ask AI row ──────────────────────────────────────────────
   A visually distinct, accent-tinted section pinned above the search results so an AI
   instruction never reads like a plain search match. */
.omni-group--ai { color: var(--accent-color); }
.omni-row--ai {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: normal;
    margin: 2px 0;
    background: rgba(37, 99, 235, 0.10);
    border: 1px solid rgba(37, 99, 235, 0.35);
}
.omni-row--ai.omni-row--active, .omni-row--ai:hover {
    background: var(--accent-color);
    color: #fff;
}
.omni-row--ai-disabled { opacity: 0.75; }
.omni-ai-spark { font-size: 14px; flex: none; }
.omni-ai-text { display: flex; flex-direction: column; min-width: 0; }
.omni-ai-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.omni-ai-sub { font-size: 11px; opacity: 0.75; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.omni-ai-spinner {
    width: 14px; height: 14px; flex: none;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: omni-ai-spin 0.7s linear infinite;
}
@keyframes omni-ai-spin { to { transform: rotate(360deg); } }
/* ── Canvas command row ──────────────────────────────────────
   A deterministic, instant alternative to Ask AI: typed plain-language edits
   that resolve against the canvas with no network. Green-tinted so it reads as
   distinct from both plain search matches and the blue Ask-AI row. */
.omni-group--cmd { color: #16a34a; }
.omni-row--cmd {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: normal;
    margin: 2px 0;
    background: rgba(22, 163, 74, 0.10);
    border: 1px solid rgba(22, 163, 74, 0.35);
}
.omni-row--cmd.omni-row--active, .omni-row--cmd:hover { background: #16a34a; color: #fff; }
.omni-row--cmd-disabled { opacity: 0.75; }
.omni-row--cmd-disabled.omni-row--active, .omni-row--cmd-disabled:hover { background: rgba(22, 163, 74, 0.10); color: inherit; cursor: default; }
.omni-cmd-icon { font-size: 14px; flex: none; }
/* ── Ask help row + answer card ──────────────────────────────
   The help assistant answers "how do I …" questions from the in-app help. Violet-tinted so it
   reads as distinct from the blue Ask-AI row and the green Canvas-command row. */
.omni-group--help { color: #7c3aed; }
.omni-row--help {
    display: flex;
    align-items: center;
    gap: 8px;
    white-space: normal;
    margin: 2px 0;
    background: rgba(124, 58, 237, 0.10);
    border: 1px solid rgba(124, 58, 237, 0.35);
}
.omni-row--help.omni-row--active, .omni-row--help:hover { background: #7c3aed; color: #fff; }
.omni-row--help-disabled { opacity: 0.75; }
.omni-row--help-disabled.omni-row--active, .omni-row--help-disabled:hover { background: rgba(124, 58, 237, 0.10); color: inherit; cursor: default; }
.omni-help-icon { font-size: 14px; flex: none; }
.omni-answer {
    margin: 2px 2px 6px;
    padding: 10px 12px;
    border-radius: 8px;
    background: rgba(124, 58, 237, 0.08);
    border: 1px solid rgba(124, 58, 237, 0.30);
}
.omni-answer-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.omni-answer-icon { font-size: 14px; flex: none; }
.omni-answer-q {
    flex: 1 1 auto; min-width: 0;
    font-weight: 600; font-size: 13px; color: var(--text-color);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.omni-answer-quota { flex: none; font-size: 11px; opacity: 0.7; }
.omni-answer-body {
    font-size: 13px; line-height: 1.5; color: var(--text-color);
    white-space: normal; word-break: break-word;
    max-height: 46vh; overflow-y: auto; overscroll-behavior: contain;
    -webkit-user-select: text; user-select: text;
}
.omni-answer-foot { margin-top: 8px; font-size: 11px; opacity: 0.7; }
/* On phones the top bar is tight — let the search take a full-width row under the logo. */
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .omni-search {
        order: 99;
        flex-basis: 100%;
        max-width: none;
        margin: 6px 0 0;
    }
    .omni-search-results { max-height: 56vh; }
    /* Top-bar wrap lives in the LATE coarse block (after the max-width:768 rules) so it wins
       the height/no-wrap override on ≤600px phones too — see further down this file. */
}

.btn {
    padding: 6px 12px;
    border: 1px solid var(--border-color);
    background-color: var(--panel-bg);
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-color);
    transition: all 0.15s ease;
    display: flex;
    align-items: center;
    gap: 4px;
}

.btn:hover {
    background-color: var(--bg-color);
    border-color: var(--text-secondary);
}

.theme-toggle-btn {
    width: 32px;
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
    font-size: 14px;
}

.btn:focus-visible,
.tool-btn:focus-visible,
.zoom-btn:focus-visible,
.toolbar-handle:focus-visible,
.mobile-menu-item:focus-visible,
.toolbar-dropdown-item:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--focus-ring);
}

.btn-primary {
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    border-color: var(--btn-primary-bg);
}

.btn-primary:hover {
    background-color: var(--btn-primary-hover);
    border-color: var(--btn-primary-hover);
}

/* Global disabled affordance — an inert control must LOOK inert. There was no shared rule, so a
   natively-disabled .btn painted identical to an enabled one (the "gated-but-looks-enabled" trap).
   Covers native [disabled], the :disabled pseudo, and the ARIA form (aria-disabled) used where a
   control stays focusable/tooltipped. The bespoke per-class :disabled rules on OTHER selectors later
   in the file are equal-specificity + later source order, so they still win for their elements — this
   only newly styles .btn/.btn-primary that had no dedicated disabled rule. */
.btn:disabled, .btn[disabled], .btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    box-shadow: none;
}
/* Neutralize hover so a disabled control never signals interactivity. Specificity (0,3,0) beats
   .btn-primary:hover (0,2,0), so the coloured CTA also stops lifting. */
.btn:disabled:hover, .btn[disabled]:hover, .btn[aria-disabled="true"]:hover {
    background-color: var(--panel-bg);
    border-color: var(--border-color);
}
.btn-primary:disabled:hover, .btn-primary[disabled]:hover, .btn-primary[aria-disabled="true"]:hover {
    background-color: var(--btn-primary-bg);
    border-color: var(--btn-primary-bg);
}

/* Destructive action (e.g. delete a multi-selection / group from the Selection panel). */
.btn-danger {
    background-color: #ef4444;
    color: #ffffff;
    border-color: #ef4444;
}
.btn-danger:hover {
    background-color: #dc2626;
    border-color: #dc2626;
}
/* Destructive actions inside the properties/blade footer are demoted to a quiet
   red ghost button — the primary intent there is *edit*, so Delete should not be
   the loudest control in the panel (UX audit: inverted-hierarchy finding). It
   still reads clearly as destructive (red text/border) and fills red on hover. */
.blade-foot .btn-danger {
    background-color: transparent;
    color: #f87171;
    border-color: rgba(248, 113, 113, 0.5);
}
.blade-foot .btn-danger:hover {
    background-color: #ef4444;
    color: #ffffff;
    border-color: #ef4444;
}

/* Themed defaults for every text input. Low specificity on purpose: any
   component class can still override, but nothing falls back to the UA's
   white-on-white in dark mode (the old var(--input-bg, #fff) trap). */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
textarea,
select {
    background-color: var(--input-bg);
    color: var(--input-text);
    border: 1px solid var(--input-border);
    border-radius: 4px;
}

input::placeholder,
textarea::placeholder {
    color: var(--text-secondary);
    opacity: 0.8;
}

/* Arrange popover */
.arrange-btn-wrapper {
    position: relative;
}

.arrange-popover {
    display: none;
    flex-direction: column;
    gap: 10px;
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 230px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 12px;
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.13);
    z-index: 300;
}

.arrange-popover.visible {
    display: flex;
}

/* Right-click / long-press contextual action menu (js/context-menu.js). Positioned at the pointer
   (fixed, clamped on-screen by JS), grouped by the 6-verb taxonomy. Mirrors the panel/popover tokens. */
.ctx-menu {
    position: fixed;
    z-index: 1400;
    min-width: 196px;
    max-width: 260px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 5px;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
    font-size: 13px;
    color: var(--text-color);
    user-select: none;
    /* A tall menu opened near the bottom edge (e.g. from the radial centre "≡" over a low shape)
       must scroll rather than run off-screen. JS pins an exact max-height to window.innerHeight in
       _position(); this dvh cap is the fallback, and overflow-y enables the scroll. */
    max-height: calc(100dvh - 16px);
    overflow-y: auto;
    overscroll-behavior: contain;
}
.ctx-menu .ctx-group-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--text-secondary);
    padding: 7px 9px 3px;
}
.ctx-menu .ctx-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 7px 9px;
    background: none;
    border: none;
    border-radius: 6px;
    color: var(--text-color);
    font-size: 13px;
    cursor: pointer;
}
.ctx-menu .ctx-item:hover,
.ctx-menu .ctx-item:focus {
    background: var(--tool-hover);
    outline: none;
}
.ctx-menu .ctx-item:focus-visible {
    box-shadow: inset 0 0 0 2px var(--focus-ring);
}
.ctx-menu .ctx-item .ctx-ic {
    width: 18px;
    text-align: center;
    flex: 0 0 auto;
    opacity: 0.85;
}
.ctx-menu .ctx-item--danger { color: var(--notice-danger-text); }
.ctx-menu .ctx-item--danger:hover,
.ctx-menu .ctx-item--danger:focus { background: var(--notice-danger-bg); }
.ctx-menu .ctx-sep {
    height: 1px;
    background: var(--border-color);
    margin: 4px 6px;
}

.arrange-popover-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Section headers inside the merged Layout popover ("Align & distribute" / "Auto layout") */
.arrange-section-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-secondary);
    padding-bottom: 2px;
    border-bottom: 1px solid var(--border-color);
}

.arrange-section-label:not(:first-child) {
    margin-top: 4px;
}

.arrange-popover-section {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.arrange-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    width: 68px;
    flex-shrink: 0;
}

.arrange-toggle {
    display: flex;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    overflow: hidden;
    flex: 1;
}

.arrange-opt {
    flex: 1;
    padding: 4px 6px;
    font-size: 12px;
    font-weight: 500;
    background: none;
    border: none;
    border-right: 1px solid var(--border-color);
    cursor: pointer;
    color: var(--text-secondary);
    transition: background 0.1s, color 0.1s;
    white-space: nowrap;
}

.arrange-opt:last-child {
    border-right: none;
}

.arrange-opt:hover {
    background: var(--bg-color);
    color: var(--text-color);
}

.arrange-opt.active {
    background: var(--accent-color);
    color: #fff;
}

.arrange-row-disabled {
    opacity: 0.4;
    pointer-events: none;
}

.arrange-apply-btn {
    width: 100%;
    justify-content: center;
    margin-top: 2px;
}

/* Main Workspace */
.workspace {
    display: flex;
    flex: 1;
    overflow: hidden;
    min-height: 0;
}

/* Tool Sidebar */
.sidebar {
    width: 72px;
    background-color: var(--panel-bg);
    border-right: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 8px 0;
    z-index: 50;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    flex-shrink: 0;
}

.sidebar::-webkit-scrollbar {
    display: none;
}

.tool-btn {
    width: 40px;
    height: 40px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 4px;
    color: var(--text-secondary);
    transition: all 0.15s ease;
    position: relative;
    flex-shrink: 0;
}

.tool-btn:hover {
    background-color: var(--tool-hover);
    color: var(--text-color);
}

.tool-btn.active {
    background-color: var(--selected-tool);
    color: var(--accent-color);
    border-color: var(--selected-border);
}

.tool-btn svg {
    width: 20px;
    height: 20px;
}

.tool-separator {
    width: 24px;
    height: 1px;
    background-color: var(--border-color);
    margin: 8px 0;
}

.tool-section-label {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-secondary);
    text-align: center;
    padding: 5px 2px 3px;
    width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-top: 1px solid var(--border-color);
    margin-top: 2px;
}

/* Palette sections: label + body pairs. Collapse state lives on .collapsed
   (persisted per section in localStorage, see App._initPaletteSections). */
.tool-section {
    width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
}

.tool-section:first-of-type .tool-section-label {
    border-top: none;
    margin-top: 0;
}

.section-chevron {
    display: inline-block;
    transition: transform 0.15s ease;
}

.section-toggle.collapsed .section-chevron {
    transform: rotate(-90deg);
}

.section-content {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    column-gap: 4px;
    width: 100%;
}

.section-content.collapsed {
    display: none;
}

/* Drag handle between the sidebar and the canvas — a 5px hit area overlaying the
   sidebar's right edge (negative margin keeps the flex layout width-neutral).
   Resizing logic lives in js/sidebar-resize.js; hidden on the mobile layout. */
.sidebar-resizer {
    width: 5px;
    margin-left: -5px;
    flex-shrink: 0;
    cursor: ew-resize;
    z-index: 60;
    touch-action: none;
}

.sidebar-resizer:hover,
.sidebar-resizer.dragging {
    background: var(--accent-color);
    opacity: 0.5;
}

/* Canvas Area */
.canvas-container {
    flex: 1;
    position: relative;
    overflow: hidden;
    background-color: var(--canvas-bg);
    cursor: crosshair;
    touch-action: none;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
    contain: layout style paint;
}

#mainCanvas {
    position: absolute;
    top: 0;
    left: 0;
    touch-action: none;
}

/* The celebratory comet overlay (js/comet.js): a transparent canvas above #mainCanvas that a
   glowing spark flies across when you connect two shapes or convert ink to a shape. Never
   interactive (pointer-events: none) and created/removed on demand, so it costs nothing at rest. */
.comet-fx {
    position: absolute;
    top: 0;
    left: 0;
    pointer-events: none;
    z-index: 2;
}
@media (prefers-reduced-motion: reduce) {
    /* Belt-and-braces: comet.js already skips the effect under reduced-motion, but hide the overlay
       if it ever renders. */
    .comet-fx { display: none; }
}

/* Visually hidden, accessible text (e.g. the Layout button's old "Arrange" label) */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---- Image insert chooser (image tool click) — js/image-insert.js ---- */
.image-chooser {
    display: none;
    position: fixed;
    min-width: 200px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 8px;
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.13);
    z-index: 400;
}

.image-chooser-opt {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 10px;
    font-size: 13px;
    background: none;
    border: none;
    border-radius: 6px;
    color: var(--text-color);
    cursor: pointer;
}

.image-chooser-opt:hover {
    background: var(--tool-hover);
}

/* "Convert to shape" manual picker — pops near the selection when ink/crop can't be auto-recognized. */
.shape-pick-popover {
    position: fixed;
    z-index: 4000;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 6px;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.25);
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px;
    max-width: 260px;
}
.shape-pick-opt {
    font-size: 13px;
    padding: 8px 10px;
    text-align: left;
    white-space: nowrap;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    color: var(--text-color);
    cursor: pointer;
}
.shape-pick-opt:hover {
    background: var(--accent-color);
    color: #fff;
}

.image-chooser-hint {
    padding: 6px 10px 2px;
    font-size: 11px;
    color: var(--text-secondary);
}

/* Sketch-to-shape quick menu (js/sketch-menu.js): a small floating row of icon choices shown after
   a recognised freehand stroke — best guess, alternatives, and a "keep freeform" squiggle. Theme
   aware; touch-friendly hit targets; labels hidden until hover (desktop) or long-press (touch). */
.sketch-menu {
    position: fixed;
    z-index: 4000;
    display: flex;
    gap: 4px;
    padding: 5px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.28);
}
.sketch-menu-opt {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    min-width: 44px;
    min-height: 44px;
    padding: 5px 7px;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 9px;
    color: var(--text-color);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: none;   /* let the long-press handler own the gesture (no scroll/zoom hijack) */
}
.sketch-menu-opt:hover,
.sketch-menu-opt:focus-visible {
    background: var(--accent-color);
    color: #fff;
    border-color: var(--accent-color);
    outline: none;
}
.sketch-menu-freeform { border-style: dashed; }
.sketch-menu-ic { font-size: 20px; line-height: 1; }
/* Label hidden by default; revealed on hover (desktop) or when the menu has .labels-shown
   (long-press on touch). Kept in the layout flow so the row doesn't reflow when it appears. */
.sketch-menu-label {
    font-size: 10px;
    line-height: 1;
    max-width: 64px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-secondary);
    height: 0;
    opacity: 0;
    transition: opacity .1s ease;
}
.sketch-menu-opt:hover .sketch-menu-label,
.sketch-menu.labels-shown .sketch-menu-label {
    height: auto;
    opacity: 1;
}
.sketch-menu-opt:hover .sketch-menu-label { color: #fff; }

.image-chooser-input {
    width: 100%;
    margin-bottom: 8px;
}

.image-chooser-actions {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
}

/* Properties Panel */
.properties-panel {
    width: 240px;
    background-color: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    padding: 16px;
    overflow-y: auto;
    z-index: 50;
    display: none;
    flex-shrink: 0;
}

.properties-panel.visible {
    display: block;
    /* Flair port: the desktop + tablet docked panel now slides + fades in like the mobile bottom
       sheet, instead of snapping on. A keyframe (not a transition) so it plays on show even where
       the tablet panel pins `transition: none`. Reduced-motion disables it below. */
    animation: panel-slide-in var(--dur-base) var(--ease-standard);
}

@keyframes panel-slide-in {
    /* Rise + fade (like the mobile sheet), NOT a horizontal slide: the docked panel's LEFT edge is
       load-bearing (the canvas re-fits to the strip beside it, and tests measure pp.left), so a
       transient translateX would shift it mid-animation. translateY never touches the x position. */
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* --- Mobile-flair ports to desktop/tablet: motion + tactile feedback -------------------------- */
/* The floating action HUD pops in (fade + slight rise) when it appears above a selection, instead
   of blinking on. _position sets left/top (not transform/opacity), so the entrance never fights it. */
.action-hud {
    animation: hud-pop-in var(--dur-fast) var(--ease-emphasized);
}
@keyframes hud-pop-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Tactile press feedback (the satisfying "give" mobile buttons have, brought to pointer devices).
   Both already transition `all 0.15s`, so the transform eases in/out. */
.tool-btn:active { transform: scale(0.9); }
.btn:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
    .properties-panel.visible,
    .action-hud { animation: none; }
    .tool-btn:active,
    .btn:active { transform: none; }
}

/* Blade-menu compatibility: the Menu blade (#optionsPanel) is a fixed, right-anchored slide-out that
   occupies the SAME right-edge space as the properties rail. When it's open, yield every properties
   panel so the two never overlap on the exact same pixels (the prior bug: opening the Menu while a
   multi-select panel was up — e.g. after an AI edit — stacked them confusingly). The selection is
   untouched, so the panel returns the moment the Menu closes. Applies on all devices: desktop/tablet
   (right rail) and mobile (the Menu covers the sheet's area too). */
body.has-menu-blade-open .properties-panel.visible,
body.has-menu-blade-open .properties-panel.blade-rail.visible:not(.minimized) { display: none !important; }

/* Auto-minimized panel (desktop): when several property panels are open at once,
   the non-active ones collapse to a slim vertical tab — click to re-expand
   (js/ui.js _syncPanelStack). The class is never applied on the mobile layout. */
.properties-panel.visible.minimized {
    width: 28px;
    min-width: 28px;
    padding: 0;
    position: relative;
    overflow: hidden;
}

.properties-panel.visible.minimized > * {
    display: none;
}

.prop-panel-tab {
    display: none;
}

.properties-panel.visible.minimized > .prop-panel-tab {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    writing-mode: vertical-rl;
    background: none;
    border: none;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-secondary);
    cursor: pointer;
}

.properties-panel.visible.minimized > .prop-panel-tab:hover {
    background: var(--tool-hover);
    color: var(--text-color);
}

.prop-group {
    margin-bottom: 16px;
}

/* Header at the top of each properties slide-out: the selected shape's type name
   (or "N elements"), plus the convert-type dropdown on the generic panel. */
.prop-panel-header {
    margin-bottom: 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-color);
}

.prop-panel-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-color);
}

.prop-convert-select {
    margin: 8px 0 0;
}

/* Segmented control — a radio group styled as adjoining buttons (used for the
   connector's Routing and Corners choices). The radios stay real inputs
   (focusable, checkable) stretched invisibly over their segment. */
.seg-control {
    display: flex;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    overflow: hidden;
    margin-bottom: 8px;
}

.seg-option {
    flex: 1;
    position: relative;
    text-align: center;
    font-size: 12px;
    cursor: pointer;
    color: var(--text-secondary);
    background-color: var(--panel-bg);
    user-select: none;
}

.seg-option + .seg-option {
    border-left: 1px solid var(--border-color);
}

.seg-option input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.seg-option span {
    display: block;
    padding: 6px 4px;
}

.seg-option:hover {
    color: var(--text-color);
}

.seg-option input:checked + span {
    background-color: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    font-weight: 600;
}

.seg-option input:focus-visible + span {
    outline: 2px solid var(--accent-color);
    outline-offset: -2px;
}

/* Disabled state — e.g. the Pin control on a connector with no shape-bound end (nothing to pin).
   Dim the label, show a not-allowed cursor, and suppress the hover highlight so the control reads as
   inert instead of looking clickable while silently swallowing the click. */
.seg-option input:disabled {
    cursor: not-allowed;
}
.seg-option input:disabled + span {
    opacity: 0.4;
}
.seg-option:has(input:disabled) {
    cursor: not-allowed;
}
.seg-option:has(input:disabled):hover {
    color: var(--text-secondary);
}

.prop-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    margin-bottom: 6px;
    letter-spacing: 0.5px;
}

/* Small explanatory note under a property field (e.g. the legend items syntax hint). */
.prop-hint {
    margin-top: 6px;
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-secondary);
}
.prop-hint code {
    font-family: monospace;
    background: var(--tool-hover);
    padding: 1px 4px;
    border-radius: 3px;
}

/* Roadmap goal links: the card shows ONLY its linked goals as filled chips (each with an × to
   unlink); the rest live behind "+ Link goal" (a picker). Tinted by each goal's colour. */
.rm-goal-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 6px;
}
.rm-goal-chip {
    --rm-goal-color: #7c3aed;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 6px 3px 10px;
    border: 1.5px solid var(--rm-goal-color);
    border-radius: 999px;
    background: var(--rm-goal-color);
    color: #fff;
    font-size: 12px;
    max-width: 100%;
}
.rm-goal-chip::before {
    content: "";
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #fff;
}
.rm-goal-chip-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.rm-goal-chip-x {
    flex: 0 0 auto;
    border: none;
    background: rgba(255, 255, 255, 0.25);
    color: #fff;
    border-radius: 50%;
    width: 16px;
    height: 16px;
    line-height: 14px;
    font-size: 13px;
    cursor: pointer;
    padding: 0;
}
.rm-goal-chip-x:hover { background: rgba(255, 255, 255, 0.45); }

.rm-goal-actions { display: flex; gap: 6px; }
.rm-goal-actions .prop-input { flex: 1; cursor: pointer; }
.rm-goal-actions .prop-input:disabled { opacity: 0.5; cursor: default; }

/* "+ Link goal" picker — a closed-by-default menu of the goals not yet linked. */
.rm-goal-picker {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 6px;
    max-height: 180px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 4px;
}
.rm-goal-picker[hidden] { display: none; }
.rm-goal-pick {
    --rm-goal-color: #7c3aed;
    display: flex;
    align-items: center;
    gap: 8px;
    text-align: left;
    border: none;
    background: transparent;
    color: var(--text-color);
    border-radius: 6px;
    padding: 6px 8px;
    font-size: 13px;
    cursor: pointer;
}
.rm-goal-pick::before {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--rm-goal-color);
}
.rm-goal-pick:hover { background: var(--tool-hover, #f1f5f9); }

/* AI executive report modal — a read-only overlay showing the generated narrative. */
.rm-report-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
    padding: 20px;
}
.rm-report-card {
    background: var(--panel-bg, #fff);
    color: var(--text-color);
    border-radius: 12px;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
    width: min(680px, 100%);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.rm-report-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color);
}
.rm-report-title { font-weight: 600; font-size: 15px; flex: 1; }
.rm-report-copy,
.rm-report-x {
    border: 1px solid var(--border-color);
    background: transparent;
    color: inherit;
    border-radius: 6px;
    padding: 4px 10px;
    font-size: 13px;
    cursor: pointer;
}
.rm-report-x { padding: 4px 9px; }
.rm-report-body {
    padding: 16px;
    overflow-y: auto;
    white-space: pre-wrap;
    line-height: 1.5;
    font-size: 14px;
}

/* Board-settings extras: per-board columns editor rows + hide-filter rows. */
.board-col-row { display: flex; align-items: center; gap: 6px; margin: 4px 0; }
.board-col-row .prop-input { flex: 1 1 auto; min-width: 0; }
.board-col-btn { flex: 0 0 auto; padding: 4px 8px; }
.board-filter-row { display: flex; align-items: center; gap: 8px; font-size: 13px; margin: 4px 0; cursor: pointer; }

/* Items paste-import dialog ("Paste cards from a table…") — textarea + live dry-run preview. */
.items-import-card { width: min(560px, 100%); }
.items-import-body { white-space: normal; display: flex; flex-direction: column; gap: 10px; }
.items-import-hint { margin: 0; font-size: 13px; line-height: 1.45; color: var(--text-secondary, #64748b); }
.items-import-text {
    width: 100%;
    resize: vertical;
    padding: 8px 10px;
    border: 1px solid var(--input-border);
    border-radius: 6px;
    background: var(--input-bg);
    color: var(--input-text);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
    line-height: 1.4;
}
.items-import-merge { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.items-import-status { margin: 0; font-size: 13px; color: var(--text-secondary, #64748b); }
.items-import-status--error { color: #dc2626; }
.items-import-foot {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding: 14px 16px;
    border-top: 1px solid var(--border-color);
}

/* Sort builder (Menu ▸ Insert ▸ "Sort cards…") — a compact multi-level sort form. */
.rm-sort-card { width: min(520px, 100%); }
.rm-sort-body { white-space: normal; }
.rm-sort-hint { margin: 0 0 14px; font-size: 13px; line-height: 1.45; color: var(--text-secondary, #64748b); }
.rm-sort-rows { display: flex; flex-direction: column; gap: 8px; }
.rm-sort-row { display: flex; align-items: center; gap: 8px; }
.rm-sort-lead { flex: 0 0 52px; text-align: right; font-size: 13px; color: var(--text-secondary, #64748b); }
.rm-sort-attr, .rm-sort-dir {
    padding: 6px 8px;
    border: 1px solid var(--input-border);
    border-radius: 6px;
    background: var(--input-bg);
    color: var(--input-text);
    font-size: 13px;
}
.rm-sort-attr { flex: 0 0 130px; }
.rm-sort-dir { flex: 1 1 auto; }
.rm-sort-del {
    flex: 0 0 auto;
    border: none;
    background: transparent;
    color: var(--text-secondary, #64748b);
    cursor: pointer;
    font-size: 13px;
    padding: 4px 6px;
    border-radius: 6px;
}
.rm-sort-del:hover { color: #dc2626; background: rgba(220, 38, 38, 0.08); }
.rm-sort-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 16px;
    border-top: 1px solid var(--border-color);
}
.rm-sort-spacer { flex: 1; }
.rm-sort-add, .rm-sort-cancel, .rm-sort-go {
    border: 1px solid var(--border-color);
    background: transparent;
    color: inherit;
    border-radius: 6px;
    padding: 6px 12px;
    font-size: 13px;
    cursor: pointer;
}
.rm-sort-go {
    border-color: var(--accent-color, #2563eb);
    background: var(--accent-color, #2563eb);
    color: #fff;
    font-weight: 600;
}
.rm-sort-go:hover { filter: brightness(1.05); }
.rm-sort-add:hover, .rm-sort-cancel:hover { background: var(--tool-hover); }

.prop-input {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 13px;
    margin-bottom: 8px;
    background-color: var(--panel-bg);
    color: var(--text-color);
}

.prop-input:focus {
    outline: none;
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

textarea.prop-input {
    resize: vertical;
    min-height: 60px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 12px;
    line-height: 1.5;
}

.prop-row {
    display: flex;
    gap: 8px;
}

.prop-row .prop-input {
    flex: 1;
}

.color-control {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
}

/* Small caption that names each swatch (Fill / Stroke) — bare swatches aren't
   self-evident (UX audit: unlabelled fill/stroke finding). */
.color-control-caption {
    font-size: 11px;
    color: var(--text-secondary);
    flex-shrink: 0;
}

.color-control-wide {
    width: 100%;
}

.color-control-wide .color-picker {
    flex: 1;
}

.color-picker {
    width: 32px;
    height: 32px;
    padding: 2px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    cursor: pointer;
    background: var(--panel-bg);
}

.prop-reset-btn {
    width: 32px;
    height: 32px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    color: var(--text-secondary);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    line-height: 1;
    flex: 0 0 32px;
    transition: all 0.15s ease;
}

.prop-reset-btn:hover:not(:disabled) {
    background: var(--tool-hover);
    color: var(--text-color);
    border-color: var(--text-secondary);
}

.prop-reset-btn:disabled {
    opacity: 0.38;
    cursor: default;
}

.prop-reset-btn:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--focus-ring);
}

/* Zoom Controls */
.zoom-controls {
    position: absolute;
    bottom: 16px;
    right: calc(16px + var(--right-panel-width, 0px));
    transition: right 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    display: flex;
    align-items: center;
    gap: 4px;
    background-color: var(--panel-bg);
    padding: 4px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    z-index: 10;
}

/* Snap/grid/zoom portion of the cluster — laid out inline next to undo/redo on desktop, hidden
   on mobile (those controls move to Menu → View; only undo/redo stay on the canvas). */
.zoom-view-group {
    display: flex;
    align-items: center;
    gap: 4px;
}

.zoom-btn {
    width: 28px;
    height: 28px;
    border: none;
    background: none;
    cursor: pointer;
    border-radius: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    font-size: 18px;
    line-height: 1;
}

.zoom-btn:hover {
    background-color: var(--tool-hover);
    color: var(--text-color);
}

/* Disabled undo/redo at the ends of the history stack — dimmed and inert. */
.zoom-btn:disabled {
    opacity: 0.35;
    cursor: default;
    pointer-events: none;
}

.snap-toggle-btn,
.smart-guides-toggle-btn {
    color: var(--text-secondary);
}

.snap-toggle-btn.active,
.smart-guides-toggle-btn.active,
.grid-toggle-btn.active,
.shape-recog-btn.active,
.hide-notes-btn.active {
    background-color: var(--accent-color, #3b82f6);
    color: #fff;
}

.snap-toggle-btn.active:hover,
.smart-guides-toggle-btn.active:hover,
.grid-toggle-btn.active:hover,
.shape-recog-btn.active:hover,
.hide-notes-btn.active:hover {
    background-color: var(--accent-hover, #2563eb);
    color: #fff;
}

/* Notes toggle: `.active` means notes are HIDDEN (the "hide" action is engaged) — the opposite
   polarity of the grid toggle beside it (accent = grid SHOWN). The accent alone is therefore
   ambiguous on this icon-only button, so also STRIKE the speech-bubble when notes are hidden: the
   glyph itself then reads "notes off", matching recognition-over-recall. */
.hide-notes-btn { position: relative; }
.hide-notes-btn.active::after {
    content: '';
    position: absolute;
    left: 5px;
    right: 5px;
    top: 50%;
    height: 2px;
    background: currentColor;      /* white, per the .active rule above — reads on the accent fill */
    border-radius: 2px;
    transform: rotate(-45deg);
    pointer-events: none;
}

.zoom-controls-divider {
    width: 1px;
    height: 18px;
    background-color: var(--border-color);
    margin: 0 2px;
}

.zoom-level {
    font-size: 12px;
    font-weight: 600;
    min-width: 48px;
    text-align: center;
    color: var(--text-color);
}

/* Toolbar Dropdown Menus */
.toolbar-dropdown-wrapper {
    position: relative;
    display: inline-block;
}

.toolbar-dropdown-menu {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.12);
    z-index: 150;
    min-width: 180px;
    padding: 4px;
    white-space: nowrap;
}

.toolbar-dropdown-menu.open {
    display: block;
}

.toolbar-dropdown-item {
    display: block;
    width: 100%;
    padding: 7px 12px;
    border: none;
    background: none;
    cursor: pointer;
    font-size: 13px;
    color: var(--text-color);
    text-align: left;
    border-radius: 5px;
}

.toolbar-dropdown-item:hover {
    background: var(--tool-hover);
}

.toolbar-dropdown-divider {
    height: 1px;
    background: var(--border-color);
    margin: 4px 0;
}

/* File dropdown: ensure it stays within viewport on narrow screens */
#fileDropdownMenu {
    min-width: 200px;
}

/* Hidden file input */
#fileInput {
    display: none;
}

/* Toast notification */
.toast {
    position: fixed;
    /* Lifted above the bottom-right zoom controls (bottom:16px, ~40px tall): a centred
       toast shares the bottom band with the zoom cluster and — once the right panel opens
       or the window narrows and the zoom row slides toward centre — the z-1000 toast was
       painting straight over the zoom %/buttons. Anchoring above that band keeps the two
       on separate rows at every width. (Overlap audit, 2026-06.) */
    bottom: 60px;
    left: 50%;
    transform: translateX(-50%) translateY(100px);
    background-color: var(--toast-bg);
    color: var(--toast-text);
    padding: 10px 20px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    opacity: 0;
    transition: all 0.3s ease;
    z-index: 1000;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    white-space: normal; /* long messages wrap instead of clipping */
    max-width: min(560px, 90vw);
    text-align: center;
    pointer-events: none;
}

.toast.show {
    transform: translateX(-50%) translateY(0);
    opacity: 1;
}

/* Error toast: red accent + dismiss button */
.toast.toast-error {
    background-color: #b91c1c;
    border-left: 4px solid #fca5a5;
    color: #ffffff;
}
/* Interactivity is gated on .show, not on the error class: an idle/hidden error toast keeps
   .toast-error until the next toast displays, so an unconditional pointer-events:auto here (it
   out-specifies the base/mobile `.toast { pointer-events:none }`) left an invisible hit box over
   the bottom band that could swallow taps. Only the visible error toast is interactive. */
.toast.toast-error.show { pointer-events: auto; }

.toast .toast-dismiss {
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    font-size: 13px;
    line-height: 1;
    margin-left: 10px;
    padding: 2px;
    opacity: 0.8;
    vertical-align: middle;
}

.toast .toast-dismiss:hover {
    opacity: 1;
}

/* The ✕ is always built into the toast now (it's the close control for the docked mobile
   strip). On desktop keep the minimal look: show it only for error toasts; an informational
   toast there auto-dismisses and needs no button. Mobile re-enables it for all (see @media). */
.toast:not(.toast-error) .toast-dismiss { display: none; }

/* Optional action button inside a toast (e.g. "Remove them"). The toast is pointer-events:none
   except for error toasts, so the button re-enables events on itself to stay clickable on an
   informational toast too. currentColor keeps it legible whether the toast bg is light or dark. */
.toast .toast-action {
    pointer-events: auto;
    cursor: pointer;
    margin-left: 12px;
    padding: 3px 12px;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    color: inherit;
    background: rgba(128, 128, 128, 0.18);            /* fallback for no color-mix() */
    background: color-mix(in srgb, currentColor 12%, transparent);
    border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
    border-radius: 999px;
    vertical-align: middle;
    white-space: nowrap;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.toast .toast-action:hover { background: color-mix(in srgb, currentColor 22%, transparent); }
.toast .toast-action:active { background: color-mix(in srgb, currentColor 30%, transparent); }
.toast .toast-action:focus-visible { outline: 2px solid currentColor; outline-offset: 1px; }

/* Toolbar shape tooltip — name + "good for…" card, shown on hover (desktop) or
   long-press (touch). Built/positioned by js/tool-tooltip.js. Kept compact so it
   never floods a small screen; only one is ever visible. */
.tool-tooltip {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1300;            /* above panels/toasts so it's never occluded */
    max-width: 240px;
    padding: 8px 11px;
    background-color: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
    pointer-events: none;     /* purely informational — never eats taps/clicks */
    opacity: 0;
    transform: translateY(2px);
    transition: opacity 0.12s ease, transform 0.12s ease;
    visibility: hidden;
}

.tool-tooltip.visible {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
}

/* Caret pointing at the pressed button (touch "above"/"below" placement only).
   --tt-arrow-x is the button centre, measured from the card's left edge. */
.tool-tooltip[data-side="above"]::after,
.tool-tooltip[data-side="below"]::after {
    content: "";
    position: absolute;
    left: var(--tt-arrow-x, 50%);
    transform: translateX(-50%);
    border: 6px solid transparent;
}
.tool-tooltip[data-side="above"]::after {
    top: 100%;
    border-top-color: var(--panel-bg);
}
.tool-tooltip[data-side="below"]::after {
    bottom: 100%;
    border-bottom-color: var(--panel-bg);
}

.tool-tooltip .tt-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

.tool-tooltip .tt-label {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-color);
    line-height: 1.2;
}

.tool-tooltip .tt-key {
    font-family: inherit;
    font-size: 10px;
    font-weight: 600;
    color: var(--text-secondary);
    background: var(--tool-hover);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 1px 5px;
    margin-left: auto;
    white-space: nowrap;
}

.tool-tooltip .tt-use {
    margin-top: 3px;
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--text-secondary);
}

/* Bottom spacer — provides layout space for the mobile fixed bottom toolbar */
.bottom-spacer {
    display: none;
    flex-shrink: 0;
}

/* Toolbar handle — only rendered on mobile */
.toolbar-handle {
    display: none;
}

/* Swipe-up capture zone — mobile only, hidden by default and when toolbox is open */
.swipe-zone {
    display: none;
}

/* Mobile label editor panel — slides in from top, only active on mobile */
.mobile-label-panel {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1100;
    transform: translateY(-100%);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    background: var(--panel-bg);
    border-bottom: 1px solid var(--border-color);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    padding: max(env(safe-area-inset-top, 0px), 8px) max(8px, env(safe-area-inset-right, 0px)) 8px max(8px, env(safe-area-inset-left, 0px));
}

.mobile-label-panel.visible {
    transform: translateY(0);
}

.mobile-label-inner {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 44px;
}

.mobile-label-input {
    flex: 1;
    /* Without this, the input's default min-content width keeps the row from shrinking, so the
       chain-add (+Child/+Sib) buttons push the ✓ confirm off the right edge on narrow phones
       (≤390px). min-width:0 lets the input give up space so every control stays on-screen. */
    min-width: 0;
    /* A <textarea> (multi-line labels): starts one row tall like the old input, grows to a few rows
       for a wrapped/multi-line label then scrolls, and never lets the user drag-resize it. */
    height: 40px;
    min-height: 40px;
    max-height: 120px;
    resize: none;
    overflow-y: auto;
    line-height: 1.35;
    border: 1.5px solid var(--accent-color);
    border-radius: 6px;
    padding: 9px 10px;
    font-size: 16px;
    font-family: inherit;
    outline: none;
    background: var(--bg-color);
    color: var(--text-color);
}

.mobile-label-cancel,
.mobile-label-confirm {
    width: 40px;
    height: 40px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    cursor: pointer;
    font-size: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}

.mobile-label-confirm {
    background: var(--accent-color);
    color: white;
    border-color: var(--accent-color);
}

/* Mind-map chain-add: save the current label and create a child/sibling without dropping the
   keyboard, so a whole branch can be typed in one go. Shown only while editing a mind node. */
.mobile-label-mind {
    height: 40px;
    padding: 0 10px;
    border: 1px solid var(--accent-color);
    border-radius: 6px;
    background: var(--panel-bg);
    color: var(--accent-color);
    font-size: 13px;
    font-weight: 600;
    flex-shrink: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.mobile-label-mind[hidden] { display: none; }

/* Desktop mind-map rapid-populate bar — sits under the inline label editor with one-click
   add-child / add-sibling (keyboard Tab / Enter do the same), so a map fills with no panel trips. */
.mind-inline-add {
    display: flex;
    gap: 6px;
}
.mind-inline-add button {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 9px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    background: var(--accent-color);
    border: none;
    border-radius: 999px;
    cursor: pointer;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
    white-space: nowrap;
}
.mind-inline-add button:hover { filter: brightness(1.05); }
.mind-inline-add button .k {
    font-size: 10px;
    font-weight: 600;
    opacity: 0.85;
    background: rgba(255, 255, 255, 0.22);
    border-radius: 4px;
    padding: 0 4px;
}

/* Inline field-toggle strip under the info-card title editor (js/ui.js LabelEditor): one elegant,
   horizontally-scrollable row of chips so the card's optional fields are tweakable in place. */
.label-editor-toggles {
    display: flex;
    gap: 6px;
    max-width: min(440px, 80vw);
    overflow-x: auto;
    white-space: nowrap;
    padding: 6px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16);
    scrollbar-width: thin;
}

/* Rich text-box editor (contenteditable) + its floating format toolbar (js/format-toolbar.js). */
.rich-label-editor { cursor: text; overflow-wrap: anywhere; }

/* Mobile rich editor: the docked contenteditable shares the textarea's look; the format bar row
   docks the toolbar (position static, larger touch targets) inside the label panel. */
.mobile-label-rich {
    min-height: 38px;
    max-height: 30vh;
    overflow-y: auto;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    cursor: text;
}
/* The mobile rich-format style bar: fixed to the bottom of the screen and lifted above the
   soft keyboard by --kb-inset (js/keyboard-inset.js — the properties-sheet precedent), the
   Docs/Notion "formatting above the keyboard" convention. It lives OUTSIDE the (transformed)
   top label panel so position:fixed anchors to the viewport, and clears the OS selection
   bubble, which hugs the selected text at the top. display gated on [hidden] so it only
   ever shows while the mobile rich editor has populated it. */
.mobile-label-format {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(env(safe-area-inset-bottom, 0px) + var(--kb-inset, 0px));
    z-index: 1100;   /* the label panel's own band — an active edit surface, above toasts */
    justify-content: center;
    background: var(--panel-bg);
    border-top: 1px solid var(--border-color);
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.12);
    padding: 6px 8px;
}
.mobile-label-format:not([hidden]) { display: flex; }
.mobile-label-format .format-toolbar {
    position: static;
    box-shadow: none;
    border: none;
    background: none;
    gap: 6px;
}
.mobile-label-format .format-toolbar-btn { min-width: 40px; height: 36px; font-size: 17px; }
.mobile-label-format .format-toolbar-color { height: 36px; }
.mobile-label-format .format-toolbar-size { height: 34px; font-size: 14px; }
.format-toolbar {
    position: absolute;
    z-index: 1002;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
    font-family: system-ui, sans-serif;
}
.format-toolbar-btn {
    min-width: 28px;
    height: 28px;
    border: none;
    background: none;
    cursor: pointer;
    border-radius: 6px;
    color: var(--text-color);
    font-size: 15px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}
.format-toolbar-btn:hover { background: var(--hover-bg, rgba(127, 127, 127, 0.18)); }
.format-toolbar-color {
    display: flex;
    align-items: center;
    gap: 3px;
    cursor: pointer;
    height: 28px;
    border-radius: 6px;
    color: var(--text-color);
    font-weight: 700;
    padding: 0 4px;
}
.format-toolbar-color:hover { background: var(--hover-bg, rgba(127, 127, 127, 0.18)); }
.format-toolbar-color input[type="color"] {
    width: 18px;
    height: 18px;
    border: none;
    padding: 0;
    background: none;
    cursor: pointer;
}
.format-toolbar-size {
    height: 26px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--input-bg);
    color: var(--text-color);
    font-size: 12px;
    cursor: pointer;
}
.label-editor-toggle {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--text-color);
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--tool-hover, rgba(127, 127, 127, 0.10));
    cursor: pointer;
    user-select: none;
}
.label-editor-toggle:hover { background: var(--accent-soft, rgba(59, 130, 246, 0.14)); }
.label-editor-toggle input { margin: 0; cursor: pointer; }

/* The same chip row docked INSIDE the mobile label panel (under the input), not floating: drop the
   panel-on-panel chrome and let it span the full width, scrolling horizontally if it overflows. */
.mobile-label-toggles {
    max-width: none;
    margin: 8px 0 0;
    padding: 2px 0;
    background: transparent;
    border: 0;
    box-shadow: none;
}
.mobile-label-toggles[hidden] { display: none; }
.mobile-label-toggles .label-editor-toggle { padding: 6px 11px; }   /* roomier tap targets on touch */

/* Mobile overflow menu — hidden on desktop */
.mobile-menu-btn {
    display: none;
}

.mobile-menu {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 500;
}

.mobile-menu.open {
    display: block;
}

.mobile-menu-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.25);
}

.mobile-menu-panel {
    position: absolute;
    top: 50px;
    right: 8px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.18);
    min-width: 200px;
    overflow: hidden;
}

.mobile-menu-item {
    display: flex;
    width: 100%;
    align-items: center;
    padding: 14px 18px;
    border: none;
    background: none;
    font-size: 15px;
    font-weight: 500;
    color: var(--text-color);
    cursor: pointer;
    text-align: left;
    border-bottom: 1px solid var(--border-color);
    transition: background 0.12s;
    -webkit-tap-highlight-color: transparent;
}

.mobile-menu-item:last-child {
    border-bottom: none;
}

.mobile-menu-item:active {
    background: var(--tool-hover);
}

/* Tablet responsive (768px) */
@media (max-width: 768px) {
    .sidebar {
        width: 60px;
    }
    .tool-btn {
        width: 36px;
        height: 36px;
    }
    .top-bar {
        height: 44px;
        padding: 0 8px;
    }
    .logo {
        font-size: 14px;
    }
    .logo-name {
        font-size: 14px;
    }
    .logo-tagline {
        display: none;
    }
    .logo-beta {
        font-size: 9px;
        padding: 0 5px;
        margin-top: 0;
        align-self: center;
    }
    .btn {
        padding: 4px 8px;
        font-size: 12px;
    }
    .properties-panel.visible {
        width: 200px;
    }
    .history-panel {
        top: 0;
    }
    .shortcuts-panel {
        top: 0;
    }
    .settings-panel {
        top: 44px;
    }
    .nlp-panel {
        top: 44px;
    }
}

/* History Panel */
.history-panel {
    position: absolute;
    top: 0;
    left: -280px;
    width: 260px;
    bottom: 0;
    background: var(--panel-bg);
    border-right: 1px solid var(--border-color);
    z-index: 200;
    display: flex;
    flex-direction: column;
    transition: left 0.25s ease;
    box-shadow: 2px 0 8px rgba(0,0,0,0.1);
}

.history-panel.visible {
    left: 0;
}

.history-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600;
    font-size: 14px;
}

.history-close {
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
    color: var(--text-secondary);
    padding: 0 4px;
    line-height: 1;
}

.history-close:hover {
    color: var(--text-color);
}

.history-list {
    flex: 1;
    overflow-y: auto;
    padding: 8px;
}

.history-item {
    padding: 6px 10px;
    border-radius: 4px;
    font-size: 12px;
    cursor: pointer;
    margin-bottom: 2px;
    transition: background 0.15s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.history-item:hover {
    background: var(--tool-hover);
}

.history-done {
    color: var(--text-color);
}

.history-undone {
    color: var(--text-secondary);
    text-decoration: line-through;
    opacity: 0.6;
}

.history-active {
    background: var(--selected-tool) !important;
    font-weight: 600;
}

.history-empty {
    padding: 16px;
    text-align: center;
    color: var(--text-secondary);
    font-size: 12px;
}

.history-actions {
    display: flex;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
}

.history-btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px 12px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    color: var(--text-color);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s;
}

.history-btn:hover {
    background: var(--tool-hover);
    border-color: var(--accent-color);
}

.history-btn:active {
    transform: scale(0.96);
}

.history-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
    border-color: var(--border-color);
}

/* Shortcuts Panel */
.shortcuts-panel {
    position: absolute;
    top: 0;
    right: -340px;
    width: 320px;
    bottom: 0;
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    z-index: 200;
    display: flex;
    flex-direction: column;
    transition: right 0.25s ease;
    box-shadow: -2px 0 8px rgba(0,0,0,0.1);
}

.shortcuts-panel.visible {
    right: 0;
}

.shortcuts-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600;
    font-size: 14px;
}

.shortcuts-close {
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
    color: var(--text-secondary);
    padding: 0 4px;
    line-height: 1;
}

.shortcuts-close:hover {
    color: var(--text-color);
}

.shortcuts-content {
    flex: 1;
    overflow-y: auto;
    padding: 12px 16px;
}

.licenses-link {
    color: var(--accent-color, #2563eb);
    font-size: 12px;
    text-decoration: none;
    cursor: pointer;
}

.licenses-link:hover {
    text-decoration: underline;
}

.licenses-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1200;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.licenses-backdrop.visible {
    display: flex;
}

.licenses-modal {
    background: var(--panel-bg, #fff);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    width: min(720px, 100%);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
}

.licenses-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600;
    font-size: 15px;
}

.licenses-close {
    background: none;
    border: none;
    font-size: 22px;
    cursor: pointer;
    color: var(--text-secondary);
    padding: 0 4px;
    line-height: 1;
}

.licenses-close:hover {
    color: var(--text-color);
}

.licenses-body {
    flex: 1;
    overflow-y: auto;
    padding: 16px 18px;
}

.licenses-intro {
    margin: 0 0 16px;
    font-size: 13px;
    color: var(--text-secondary);
    line-height: 1.5;
}

.licenses-entry {
    margin-bottom: 20px;
}

.licenses-entry-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.licenses-entry-name {
    font-weight: 600;
    font-size: 14px;
}

.licenses-entry-license {
    font-size: 11px;
    color: var(--text-secondary);
}

.licenses-entry-desc {
    font-size: 12px;
    color: var(--text-secondary);
    margin: 2px 0 8px;
    line-height: 1.5;
}

.licenses-text {
    margin: 0;
    padding: 10px 12px;
    background: var(--canvas-bg, #f6f8fa);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11px;
    line-height: 1.45;
    white-space: pre-wrap;
    word-break: break-word;
    color: var(--text-color);
}

.shortcuts-section {
    margin-bottom: 16px;
}

.shortcuts-section-title {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-secondary);
    margin-bottom: 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border-color);
}

.shortcuts-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 0;
    font-size: 13px;
}

.shortcuts-key {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 60px;
    padding: 3px 8px;
    background: var(--canvas-bg);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    font-size: 11px;
    font-weight: 600;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    color: var(--text-color);
    white-space: nowrap;
}

/* Mobile-only panel nav buttons — hidden by default on desktop */
.prop-mobile-back-btn,
.prop-mobile-nav-btn {
    display: none;
}

/* ============================================================
   Mobile layout — phones and small/medium touch tablets.
   Touch-aware breakpoint: ≤600px OR any coarse-pointer device ≤1024px,
   so a phone in "Request Desktop Site" mode (which reports a ~980px
   viewport) keeps the full-width bottom toolbar instead of the desktop
   sidebar. Query is kept in sync with MOBILE_MEDIA_QUERY in js/responsive.js.
   Sidebar converts to a horizontal bottom toolbar.
   Properties panel becomes a slide-up bottom sheet.
   ============================================================ */
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {

    /* Wherever the omni-search switches to a full-width row (same query), let the top bar
       wrap so the search lands on its own row instead of being squeezed. Placed in this LATE
       coarse block so it overrides the max-width:768 `.top-bar { height: 44px }` on phones,
       and also covers coarse tablets / desktop-site widths in the 769–1024px range. */
    .top-bar {
        height: auto;
        min-height: 44px;
        flex-wrap: wrap;
        row-gap: 6px;
    }

    /* Use dynamic/small viewport height to avoid address-bar layout shifts */
    body {
        height: 100svh;
    }

    .app {
        height: 100svh;
    }

    /* Top bar: respect horizontal safe areas (landscape notch) */
    .top-bar {
        padding-left: max(12px, env(safe-area-inset-left));
        padding-right: max(12px, env(safe-area-inset-right));
    }

    /* Show mobile menu button, hide secondary file-op buttons */
    .mobile-menu-btn {
        display: flex !important;
        font-size: 20px;
        padding: 4px 10px;
        letter-spacing: 2px;
    }

    .file-ops .btn:not([data-mobile-keep]):not(.btn-primary):not(.mobile-menu-btn) {
        display: none;
    }

    /* Tablet portrait has room for command labels even while keeping the
       touch-friendly bottom toolbox. Phones keep the compact overflow. */
    @media (min-width: 760px) {
        #arrangeBtnWrapper > .btn,
        #optionsBtn,
        .file-ops > .btn[title="Keyboard shortcuts & gestures"],
        #premiumBtn {
            display: flex !important;
        }

        /* Premium-gated: ID specificity beats the compact-layout hide rule,
           but no !important so the inline display:none premium gate still
           wins until activation clears it. (Advisor has no toolbar button
           anymore — it's a tab inside this panel.) */
        #aiChatBtn {
            display: flex;
        }

        .mobile-menu-btn {
            display: none !important;
        }
    }

    /* Reserve space at the bottom for the collapsed toolbar handle */
    .bottom-spacer {
        display: block;
        height: calc(var(--toolbar-handle-height) + env(safe-area-inset-bottom));
        flex-shrink: 0;
    }

    /* ── Bottom toolbar drawer ───────────────────────────── */
    .sidebar {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        /* Collapsed: only the handle strip is visible */
        height: calc(var(--toolbar-handle-height) + env(safe-area-inset-bottom));
        padding: 0;
        flex-direction: column;
        align-items: center;
        overflow: hidden;
        border-right: none;
        border-top: 1px solid var(--border-color);
        z-index: 200;
        box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.08);
        transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        scrollbar-width: none;
        -ms-overflow-style: none;
    }

    .sidebar::-webkit-scrollbar {
        display: none;
    }

    /* Expanded: a half-height sheet of labelled, scrollable tool groups */
    .sidebar.open {
        height: calc(46vh + env(safe-area-inset-bottom));
        overflow-y: auto;
        flex-direction: column;
        flex-wrap: nowrap;
        align-items: stretch;
        justify-content: flex-start;
        padding: 0 max(12px, env(safe-area-inset-right)) calc(env(safe-area-inset-bottom) + 12px) max(12px, env(safe-area-inset-left));
        border-radius: 16px 16px 0 0;
        box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.16);
        -webkit-overflow-scrolling: touch;
    }

    /* Quick-shapes: a single edge-to-edge horizontally-scrollable strip at the top of the open
       drawer (no wrap), so it stays one row and the rest of the drawer is the full tool palette.
       Clipped away with the toolbar when the drawer is collapsed (sidebar overflow:hidden). It
       scrolls WITH the drawer content (not sticky) so it never overlaps a tool button below it.
       Scoped to `.sidebar` (specificity 0,2,0) so it beats the base `.frequent-shapes` desktop
       hide (0,1,0) regardless of source order — the base rule appears later in the stylesheet. */
    .sidebar .frequent-shapes {
        display: flex;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
        -ms-overflow-style: none;
        -webkit-overflow-scrolling: touch;
        padding: 8px 4px;
        margin-bottom: 4px;
        border-bottom: 1px solid var(--border-color);
    }
    .sidebar .frequent-shapes::-webkit-scrollbar { display: none; }

    /* Handle strip — grip pill that the user taps to expand/collapse */
    .toolbar-handle {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        width: 100%;
        height: var(--toolbar-handle-height);
        flex-shrink: 0;
        background: transparent;
        border: none;
        padding: 0;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
        /* When expanded the handle must stay at the top */
        order: -1;
    }

    .toolbar-handle-grip {
        display: block;
        width: 56px;
        height: 5px;
        background: var(--border-color);
        border-radius: 3px;
        transition: background 0.15s;
    }

    .toolbar-handle:active .toolbar-handle-grip {
        background: var(--text-secondary);
    }

    /* "Tools" label — only while collapsed, to make it obvious the strip is a
       tappable button that brings up the tools (the bare grip pill alone reads as
       decoration, and a bottom-edge swipe collides with Android's home gesture).
       Rendered as a filled pill so it reads as a button even on the dark canvas. */
    .toolbar-handle-label {
        display: none;
        align-items: center;
        gap: 6px;
        padding: 6px 18px;
        font-size: 14px;
        font-weight: 600;
        color: var(--text-color);
        letter-spacing: 0.2px;
        background: var(--tool-hover);
        border: 1px solid var(--border-color);
        border-radius: 999px;
    }
    .toolbar-handle-chevron {
        font-size: 12px;
        line-height: 1;
    }

    /* Collapsed: hide the drag grip, show the labeled "Tools ▴" affordance. */
    .sidebar:not(.open) .toolbar-handle-grip {
        display: none;
    }
    .sidebar:not(.open) .toolbar-handle-label {
        display: inline-flex;
    }
    .sidebar:not(.open) .toolbar-handle:active .toolbar-handle-label {
        background: var(--selected-tool);
        border-color: var(--accent-color);
    }

    /* Swipe-up capture zone — sits above the collapsed handle, hidden when toolbox is open */
    .swipe-zone {
        display: block;
        position: fixed;
        bottom: calc(var(--toolbar-handle-height) + env(safe-area-inset-bottom));
        left: 0;
        right: 0;
        height: 20px;
        z-index: 210;
        touch-action: none;
        background: transparent;
    }
    .swipe-zone.hidden {
        display: none;
    }

    /* The sidebar is a bottom drawer here — no edge to drag */
    .sidebar-resizer {
        display: none;
    }

    /* Sheet layout: every group shows a left-aligned header with its tools
       wrapped in rows beneath it. Collapsing is a desktop affordance — on the
       sheet everything is visible and scrollable, so .collapsed is ignored
       and the labels are inert headers (no toggle, no chevron). */
    .tool-section {
        display: block;
        width: 100%;
    }

    .tool-section-label {
        display: flex;
        width: 100%;
        justify-content: flex-start;
        text-align: left;
        font-size: 11px;
        letter-spacing: 0.6px;
        padding: 12px 4px 6px;
        border-top: none;
        margin-top: 0;
        background: none;
        pointer-events: none;
    }

    .section-chevron {
        display: none;
    }

    .sidebar .section-content,
    .sidebar .section-content.collapsed {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: 6px;
        width: 100%;
    }

    /* Bigger touch targets (44px Apple HIG minimum) */
    .tool-btn {
        width: 44px;
        height: 44px;
        margin-bottom: 0;
        margin-right: 0;
        flex-shrink: 0;
    }

    .tool-btn svg {
        width: 22px;
        height: 22px;
    }

    /* Mobile label editor panel — shown when editing labels */
    .mobile-label-panel {
        display: block;
    }

    /* ── Properties bottom sheet ─────────────────────────── */
    .properties-panel {
        position: fixed !important;
        left: 0 !important;
        right: 0 !important;
        /* --kb-inset lifts the sheet above the soft keyboard (see js/keyboard-inset.js) so
           the field being edited isn't occluded; 0 when no keyboard is up. */
        bottom: calc(var(--toolbar-handle-height) + env(safe-area-inset-bottom) + var(--kb-inset, 0px)) !important;
        top: auto !important;
        width: 100% !important;
        /* Peek height by default — most of the canvas stays visible. The drag
           handle (or a swipe up) expands the sheet via .sheet-expanded. */
        max-height: 46vh !important;
        max-height: min(46dvh, calc(100svh - var(--toolbar-handle-height) - 56px - env(safe-area-inset-bottom) - var(--kb-inset, 0px))) !important;
        border-left: none !important;
        border-top: 1px solid var(--border-color) !important;
        border-radius: 14px 14px 0 0 !important;
        display: block !important;
        transform: translateY(calc(100% + var(--toolbar-handle-height) + env(safe-area-inset-bottom) + 8px)) !important;
        transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1) !important;
        overflow-y: auto !important;
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
        box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.12) !important;
        z-index: 300 !important;
        padding: 0 16px calc(20px + env(safe-area-inset-bottom)) !important;
        pointer-events: none;
    }

    /* Drag handle pill */
    .properties-panel::before {
        content: '';
        display: block;
        width: 36px;
        height: 4px;
        background: var(--border-color);
        border-radius: 2px;
        margin: 10px auto 12px;
        flex-shrink: 0;
    }

    .properties-panel.visible {
        transform: translateY(0) !important;
        pointer-events: auto;
    }

    .properties-panel.sheet-expanded {
        max-height: 86vh !important;
        max-height: min(86dvh, calc(100svh - var(--toolbar-handle-height) - 8px - env(safe-area-inset-bottom))) !important;
    }

    /* Dragged below the minimum: the sheet becomes a slim tappable tab (drag pill +
       title peek) instead of disappearing, so the canvas is never fully covered and a
       tap restores it to the default peek height. */
    .properties-panel.sheet-collapsed {
        max-height: 54px !important;
        height: 54px !important;
        overflow: hidden !important;
        cursor: pointer;
    }
    /* While actively dragging, suppress the slide transition so the sheet tracks the
       finger 1:1. */
    .properties-panel.sheet-dragging {
        transition: none !important;
    }

    /* ── Bottom message stack ──────────────────────────────
       The mobile bottom band stacks, from the toolbar handle upward:
         handle → contextual action bar → read-only banner → toast → undo/redo cluster.
       Each occupant flips a body class that contributes its height to these running
       totals, so every element above simply sums what's below it — no JS measurement,
       and any combination clears without overlap. */
    body { --stack-action: 0px; --stack-banner: 0px; --stack-toast: 0px; }
    body.has-action-bar  { --stack-action: var(--action-bar-height); }
    body.has-viewer-banner { --stack-banner: var(--msg-strip-height); }
    body.has-toast       { --stack-toast: var(--msg-strip-height); }

    /* The docked bottom strips (toast, viewer / live-edit band, undo-redo cluster) normally
       sit just above the collapsed tools handle. When the drawer is expanded (tap "Tools")
       it grows to 46vh and would paint over them — so they ride up to clear its full height
       instead. :has() is a progressive enhancement: where unsupported the strips simply stay
       at the handle (the prior behaviour), they just don't follow the drawer up. */
    body { --toolbar-dock-height: var(--toolbar-handle-height); }
    body:has(.sidebar.open) { --toolbar-dock-height: 46vh; }

    /* ── Zoom controls: fixed above the collapsed handle ────
       position:fixed keeps them viewport-relative so they can't overlap the toolbar even if
       canvas-container height differs. Lifts above the whole message stack so undo/redo stays
       visible and tappable whatever is docked below. */
    .zoom-controls {
        position: fixed;
        bottom: calc(var(--toolbar-dock-height) + env(safe-area-inset-bottom) +
                     var(--stack-action) + var(--stack-banner) + var(--stack-toast) + 12px);
        right: 12px;
        z-index: 90;
        transition: bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }

    /* Snap/grid/zoom live in Menu → View on mobile; only undo/redo stay on the canvas. */
    .zoom-view-group {
        display: none;
    }

    body.has-open-prop-panel .zoom-controls {
        opacity: 0;
        pointer-events: none;
    }

    .zoom-btn {
        width: 36px;
        height: 36px;
    }

    /* ── Toast: docked as a single-line strip above the tools / action bar ──
       Mirrors the contextual action bar (edge-to-edge, one line, horizontally scrollable) so
       messages never paint over the controls they point at. Sits directly above the tools
       handle, above the action bar when a selection is up, and above the read-only banner when
       one is present — the message scrolls, the ✕ stays pinned right to close it early. */
    .toast {
        left: 0;
        right: 0;
        bottom: calc(var(--toolbar-dock-height) + env(safe-area-inset-bottom) +
                     var(--stack-action) + var(--stack-banner));
        transform: translateY(120%);
        max-width: none;
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px 12px;
        border-radius: 0;
        border-top: 1px solid var(--border-color);
        box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.16);
        background-color: var(--panel-bg);
        color: var(--text-color);
        text-align: left;
        z-index: 600;
        pointer-events: none;   /* only the VISIBLE strip is interactive (see .toast.show) — an */
    }                           /* idle, translated-away toast must not swallow taps near the band */
    /* While the rich-format style bar is docked at the bottom (body.has-style-bar, set by the
       mobile rich editor), toasts lift above it and ride the SAME --kb-inset — so a toast fired
       mid-edit stays visible right above the bar instead of buried behind the OS keyboard, and
       the very first toast a user sees here (the hint that TEACHES the bar) is never clipped
       by it. 56px = bar height + clearance. */
    body.has-style-bar .toast {
        bottom: calc(56px + env(safe-area-inset-bottom, 0px) + var(--kb-inset, 0px));
    }
    /* And hide the selection ACTION BAR for the session (Codex #611 P2): it occupies the very
       band the lifted toast lands in, the style bar already clipped its bottom edge, and its
       verbs (Delete, most dangerously) acting on the shape MID-EDIT are a slip hazard right
       where the user is typing — Docs/Notion hide selection chrome behind the format bar too.
       body.has-action-bar (and so --stack-action) is left alone: JS state stays consistent
       and the bar reappears the instant the edit session ends. */
    body.has-style-bar .mobile-action-bar { display: none; }
    .toast.show {
        transform: translateY(0);
        pointer-events: auto;
    }
    .toast .toast-msg {
        flex: 1 1 auto;
        min-width: 0;
        overflow-x: auto;
        white-space: nowrap;
        text-align: center;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .toast .toast-msg::-webkit-scrollbar { display: none; }
    /* The ✕ is the strip's close control on mobile — show it for every toast, pinned right. */
    .toast:not(.toast-error) .toast-dismiss { display: inline-flex; }
    .toast .toast-dismiss {
        flex: 0 0 auto;
        margin-left: 0;
        align-self: center;
        font-size: 15px;
        padding: 4px 6px;
    }

    /* ── Read-only viewer / document-library banner: same docked strip ──
       Moves from the top of the canvas down to the message stack (above the tools / action bar),
       single line + horizontally scrollable, its Leave/✕ pinned to the right. The `body` prefix
       lifts specificity above the base .viewer-info-banner rule, which is defined LATER in the
       file (media queries add no specificity, so source order would otherwise win). */
    body .viewer-info-banner {
        top: auto;
        left: 0;
        right: 0;
        bottom: calc(var(--toolbar-dock-height) + env(safe-area-inset-bottom) + var(--stack-action));
        transform: none;
        max-width: none;
        border-radius: 0;
        border-left: none;
        border-right: none;
        border-bottom: none;
        border-top: 1px solid var(--border-color);
        z-index: 600;
        gap: 8px;
        padding: 8px 12px;
        transition: bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }
    .viewer-info-banner > span {
        flex: 1 1 auto;
        min-width: 0;
        overflow-x: auto;
        white-space: nowrap;
        text-align: center;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .viewer-info-banner > span::-webkit-scrollbar { display: none; }
    .viewer-info-banner .btn,
    .viewer-info-banner .viewer-info-dismiss { flex: 0 0 auto; }

    /* ── History panel: full-width on mobile ─────────────── */
    .history-panel {
        width: 100%;
        left: -100vw;
        top: 0;
        bottom: calc(var(--toolbar-handle-height) + env(safe-area-inset-bottom));
    }

    .history-panel.visible {
        left: 0;
    }

    /* ── Shortcuts panel: full-width on mobile ───────────── */
    .shortcuts-panel {
        width: 100%;
        right: -100vw;
        top: 0;
        bottom: calc(var(--toolbar-handle-height) + env(safe-area-inset-bottom));
    }

    .shortcuts-panel.visible {
        right: 0;
    }

    /* ── Settings panel: full-screen slide-in on mobile ──── */
    .settings-panel {
        top: 0;
        width: 100%;
    }

    /* ── NLP panel: full-screen slide-in from right on mobile ── */
    .nlp-panel {
        top: 0;
        width: 100%;
        border-left: none;
        z-index: 500;
        /* --kb-inset lifts the sheet above the soft keyboard (see js/keyboard-inset.js) so the
           footer (Build) and the lower textarea stay reachable instead of being covered — the
           panel is position:fixed and would otherwise anchor its bottom to the layout viewport,
           which the keyboard overlaps. */
        bottom: var(--kb-inset, 0px);
    }

    .nlp-footer {
        flex-wrap: wrap;
    }

    .nlp-replace-label {
        font-size: 11px;
    }

    /* ── Textareas: compact on mobile so they fit the sheet ── */
    #entityFields,
    #swimlaneLanes,
    #classboxAttributes,
    #classboxMethods {
        height: 72px;
        min-height: 72px;
        resize: none;
    }

    #classboxPanel .prop-group:nth-of-type(2) {
        position: sticky;
        top: 0;
        z-index: 2;
        margin: -2px 0 12px;
        padding: 8px 0;
        background: var(--panel-bg);
        border-bottom: 1px solid var(--border-color);
    }

    #connectorPanel {
        display: flex !important;
        flex-direction: column;
    }

    #connectorBackBtn {
        order: -2;
    }

    #connectorPanel .prop-group:nth-of-type(4) {
        order: -1;
        position: sticky;
        top: 0;
        z-index: 2;
        margin: -2px 0 12px;
        padding: 8px 0 12px;
        background: var(--panel-bg);
        border-bottom: 1px solid var(--border-color);
    }

    /* ── Mobile panel navigation buttons ─────────────────── */
    .prop-mobile-back-btn {
        display: flex;
        align-items: center;
        gap: 4px;
        width: 100%;
        padding: 10px 0 14px;
        margin-bottom: 4px;
        border: none;
        border-bottom: 1px solid var(--border-color);
        background: transparent;
        color: var(--accent-color);
        font-size: 14px;
        font-weight: 500;
        cursor: pointer;
        text-align: left;
        -webkit-tap-highlight-color: transparent;
    }

    .prop-mobile-nav-btn {
        display: block;
        width: 100%;
        padding: 11px;
        border: 1px solid var(--border-color);
        border-radius: 8px;
        background: transparent;
        color: var(--text-color);
        font-size: 14px;
        font-weight: 500;
        cursor: pointer;
        text-align: center;
        -webkit-tap-highlight-color: transparent;
    }
}

/* ---- Cloud Save Status Dot ---- */
.cloud-save-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border-color);
    flex-shrink: 0;
    transition: background 0.3s;
    align-self: center;
}
.cloud-save-dot.saving { background: #f59e0b; }
.cloud-save-dot.saved  { background: #22c55e; }
.cloud-save-dot.error  { background: #ef4444; }
.cloud-save-dot.idle   { background: var(--border-color); }

/* "Saved in browser memory" pill — the non-cloud (anonymous / Free) counterpart of the cloud-save dot.
   Small, unobtrusive, theme-aware; sits in the same .file-ops slot. Only one of cloud-dot /
   local-badge / collab-indicator is ever visible at a time. */
.local-save-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    line-height: 1;
    color: var(--text-secondary);
    padding: 0 6px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    align-self: center;
    transition: color 0.3s;
}
.local-save-badge.saving { color: #f59e0b; }
.local-save-badge.saved  { color: var(--text-secondary); }
.local-save-badge.warn   { color: #ef4444; }

/* ---- Premium Button Active State ---- */
.btn.premium-active {
    background-color: var(--notice-ok-bg);
    border-color: var(--notice-ok-border);
    color: var(--notice-ok-text);
}
.btn.premium-active:hover {
    background-color: var(--notice-ok-bg);
    border-color: var(--notice-ok-text);
}

/* Success/info notes (e.g. the encryption notice) — theme-aware, low contrast */
.settings-note.note-ok {
    border-color: var(--notice-ok-border);
    background: var(--notice-ok-bg);
    color: var(--notice-ok-text);
}

/* Sign-in reason callout — the highlighted box above the sign-in wall that explains WHY a
   signed-out user was sent here (they tried Ask AI / Ask help). Uses the theme-aware info
   notice tokens so it reads on both the dark and light canvas. Hidden until a reason is set. */
.signin-reason {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--notice-info-text);
    background: var(--notice-info-bg);
    border: 1px solid var(--notice-info-border);
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 14px;
}
/* .signin-reason sets display:flex, which would otherwise win over the [hidden] UA rule. */
.signin-reason[hidden] { display: none; }
.signin-reason-icon { flex: 0 0 auto; font-size: 15px; line-height: 1.3; }

/* ---- Cloud Diagram Dialog ---- */
.cloud-dialog-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 1000;
    align-items: center;
    justify-content: center;
}
.cloud-dialog {
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 24px;
    max-width: 400px;
    width: calc(100% - 32px);
    box-shadow: 0 8px 32px rgba(0,0,0,0.18);
}
.cloud-dialog-title {
    font-size: 16px;
    font-weight: 600;
    margin-bottom: 10px;
    color: var(--text-color);
}
.cloud-dialog-body {
    font-size: 13px;
    color: var(--text-secondary);
    margin-bottom: 16px;
    line-height: 1.5;
}
.cloud-dialog-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 14px;
}
.cloud-dialog-actions .btn {
    justify-content: center;
    width: 100%;
}
.cloud-dialog-note {
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.5;
}

/* ---- Diagram list (inside Premium panel) ---- */
.diagram-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 8px;
    /* Grow the list proportionally to the viewport so it fills the blade instead
       of stranding empty space below a fixed 300px box. The floor keeps it at
       least as tall as the old fixed cap (so small screens never regress); the
       calc() subtracts the chrome above it (top bar + blade head + search/sort,
       action row and folder tree) on taller screens. 100svh tracks the mobile
       dynamic viewport. */
    max-height: max(300px, calc(100svh - 320px));
    overflow-y: auto;
}
.diagram-list-empty {
    font-size: 12px;
    color: var(--text-secondary);
    padding: 10px 0;
    text-align: center;
}
.diagram-list-item {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--bg-color);
    gap: 8px;
}
.diagram-list-item--active {
    border-color: #22c55e;
    background: rgba(34, 197, 94, 0.1);
}
.diagram-list-item { cursor: grab; }
.diagram-list-item--dragging { opacity: 0.5; cursor: grabbing; }
.diagram-list-item-info {
    flex: 1;
    min-width: 0;
}
.diagram-list-item-title {
    font-size: 13px;
    font-weight: 500;
    color: var(--text-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.diagram-list-item-meta {
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 2px;
}
.diagram-list-item-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 4px;
}
.diagram-list-item-badge {
    font-size: 10px;
    color: var(--notice-ok-text);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 2px 6px;
    border: 1px solid var(--notice-ok-border);
    border-radius: 3px;
    background: var(--notice-ok-bg);
}
.diagram-open-btn,
.diagram-delete-btn {
    font-size: 11px;
    padding: 3px 8px;
}
.diagram-delete-btn {
    color: #dc2626;
}
.diagram-history-btn,
.diagram-tags-btn {
    font-size: 12px;
    padding: 3px 6px;
}
.diagram-list-item-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
}
.doc-folder-select {
    font-size: 11px;
    padding: 2px 4px;
    max-width: 96px;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    background: var(--input-bg);
    color: var(--input-text);
}

/* ---- Library: search / sort controls ---- */
.library-controls {
    display: flex;
    gap: 6px;
    margin: 8px 0 6px;
}
.library-search { flex: 1; min-width: 0; font-size: 12px; }
.library-sort   { flex-shrink: 0; width: 120px; font-size: 12px; }

/* ---- Tag chips + filter bar ---- */
.tag-chip {
    display: inline-flex;
    align-items: center;
    font-size: 10px;
    line-height: 1;
    padding: 3px 6px;
    border-radius: 10px;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    cursor: pointer;
    user-select: none;
}
.tag-chip:hover { border-color: var(--accent-color); color: var(--accent-color); }
.tag-chip--active {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: #fff;
}
.tag-filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    margin-bottom: 8px;
}
.tag-clear-btn { font-size: 11px; padding: 2px 8px; }

/* ---- Folder tree ---- */
.folder-tree {
    display: flex;
    flex-direction: column;
    margin-bottom: 8px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    overflow: hidden;
    max-height: 220px;
    overflow-y: auto;
}
.folder-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 5px 8px;
    font-size: 12px;
    cursor: pointer;
    border-bottom: 1px solid var(--bg-color);
}
.folder-row:last-child { border-bottom: none; }
.folder-row:hover { background: var(--bg-color); }
.folder-row--active { background: var(--selected-tool); color: var(--accent-color); font-weight: 600; }
.folder-row--drop {
    background: var(--selected-tool);
    box-shadow: inset 0 0 0 2px var(--accent-color);
}
.folder-row-name { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.folder-row-count {
    font-size: 10px;
    color: var(--text-secondary);
    background: var(--bg-color);
    border-radius: 8px;
    padding: 1px 6px;
    flex-shrink: 0;
}
.folder-toggle {
    width: 12px;
    flex-shrink: 0;
    text-align: center;
    color: var(--text-secondary);
    font-size: 10px;
}
.folder-toggle--leaf { visibility: hidden; }
.folder-row-actions {
    display: none;
    gap: 2px;
    flex-shrink: 0;
}
.folder-row:hover .folder-row-actions { display: flex; }
.folder-act {
    border: none;
    background: none;
    cursor: pointer;
    font-size: 11px;
    padding: 1px 3px;
    color: var(--text-secondary);
    border-radius: 3px;
}
.folder-act:hover { background: var(--border-color); color: var(--text-color); }

/* ---- Version history modal ---- */
.version-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.version-modal {
    background: var(--panel-bg, #fff);
    border-radius: 10px;
    width: min(520px, 100%);
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
    overflow: hidden;
}
.version-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600;
    font-size: 14px;
}
.version-modal-close {
    border: none;
    background: none;
    font-size: 16px;
    cursor: pointer;
    color: var(--text-secondary);
}
.version-modal-list {
    overflow-y: auto;
    padding: 8px;
}
.version-empty {
    padding: 24px 16px;
    text-align: center;
    color: var(--text-secondary);
    font-size: 13px;
}
.version-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 10px;
    border-radius: 6px;
}
.version-row:hover { background: var(--bg-color); }
.version-row-info { flex: 1; min-width: 0; }
.version-row-name { font-size: 13px; font-weight: 500; }
.version-row-meta { font-size: 11px; color: var(--text-secondary); margin-top: 2px; }
.version-row-actions { display: flex; gap: 4px; flex-shrink: 0; }
.version-row-actions .btn { font-size: 11px; padding: 3px 7px; }
.version-restore { color: var(--accent-color); }
.version-del { color: #dc2626; }

/* ---- AI Settings Panel (repurposed as Premium Panel) ---- */
.settings-panel {
    position: fixed;
    top: 48px;
    right: 0;
    bottom: 0;
    width: 300px;
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    z-index: 300;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: -4px 0 20px rgba(0,0,0,0.1);
    overflow: hidden;
}

.settings-panel.open {
    transform: translateX(0);
}

.settings-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600;
    font-size: 14px;
    flex-shrink: 0;
}

.settings-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--border-color);
    margin-left: auto;
    flex-shrink: 0;
    transition: background 0.2s;
}

.settings-status-dot.configured {
    background: #22c55e;
}

.settings-close {
    background: none;
    border: none;
    font-size: 16px;
    cursor: pointer;
    color: var(--text-secondary);
    padding: 2px 4px;
    border-radius: 4px;
    line-height: 1;
    flex-shrink: 0;
}

.settings-close:hover {
    color: var(--text-color);
    background: var(--tool-hover);
}

.settings-body {
    padding: 16px;
    overflow-y: auto;
    flex: 1;
}

.settings-note {
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.5;
    margin-bottom: 16px;
    padding: 8px 10px;
    background: var(--bg-color);
    border-radius: 6px;
    border: 1px solid var(--border-color);
}

/* ---- NLP Chat Panel ---- */
.nlp-panel {
    position: fixed;
    top: 48px;
    right: 0;
    bottom: 0;
    width: 360px;
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    box-shadow: -4px 0 20px rgba(0,0,0,0.1);
    z-index: 200;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform: translateX(100%);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

.nlp-panel.open {
    transform: translateX(0);
}

.nlp-header {
    display: flex;
    align-items: center;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-color);
    font-weight: 600;
    font-size: 13px;
    background: var(--bg-color);
    cursor: default;
    gap: 6px;
}

.assistant-header-left {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}

.assistant-title {
    font-weight: 600;
    font-size: 13px;
    white-space: nowrap;
}

.assistant-tabs {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    flex-shrink: 0;
}

.assistant-tab {
    background: transparent !important;
    border: none !important;
    border-radius: 4px !important;
    color: var(--text-secondary) !important;
    cursor: pointer;
    font-size: 12px !important;
    font-weight: 500;
    line-height: 1;
    padding: 5px 8px !important;
}

.assistant-tab:hover {
    background: var(--tool-hover) !important;
    color: var(--text-color) !important;
}

.assistant-tab.active {
    background: var(--selected-tool) !important;
    color: var(--accent-color) !important;
    font-weight: 600;
}

.nlp-header button {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 11px;
    color: var(--text-secondary);
    padding: 2px 4px;
    border-radius: 4px;
}

.nlp-header button:last-child {
    margin-left: auto;
}

.nlp-reset-btn {
    font-size: 14px !important;
}

.nlp-header button:hover {
    background: var(--tool-hover);
    color: var(--text-color);
}

.nlp-body {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* Chat message thread */
.nlp-chat {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 2px 0;
}

.nlp-msg {
    font-size: 13px;
    line-height: 1.5;
    padding: 8px 10px;
    border-radius: 8px;
    max-width: 88%;
    word-wrap: break-word;
}

.nlp-msg,
.nlp-summary-content,
.advisor-msg,
.advisor-suggestion-title,
.advisor-suggestion-desc,
.advisor-buildprompt-name,
.advisor-buildprompt-hint,
.advisor-buildprompt-body,
.omni-answer-q,
.omni-answer-body,
.amend-bar-title,
.amend-bar-summary,
.amend-bar-hint {
    -webkit-user-select: text;
    user-select: text;
}

/* Outline "→ merge" authoring aids: target autocomplete + live unresolved-reference notice. */
.outline-ac {
    position: absolute;
    left: 0; right: 0; top: 100%;
    margin-top: 2px;
    z-index: 50;
    max-height: 168px;
    overflow-y: auto;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.32);
}
.outline-ac-item {
    padding: 7px 10px;
    font-size: 13px;
    color: var(--text-color);
    cursor: pointer;
}
.outline-ac-item.active { background: rgba(127, 127, 127, 0.18); }
.outline-warn {
    font-size: 12px;
    line-height: 1.5;
    color: #d8a23a;
    padding: 6px 2px 2px;
}
.outline-warn .ow-fix { color: #6ea8fe; cursor: pointer; text-decoration: underline; }

/* Contextual "Flowchart actions" disclosure in the selection panels. */
.flow-actions > summary {
    cursor: pointer;
    list-style: none;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    padding: 4px 0 8px;
    user-select: none;
}
.flow-actions > summary::-webkit-details-marker { display: none; }
.flow-actions > summary:hover { color: var(--text-color); }
.flow-tag-row { display: flex; gap: 6px; margin-bottom: 6px; }
.flow-tag-input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 6px 8px;
    font-size: 13px;
    color: var(--text-color);
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
}
.flow-tag-row .btn { flex: 0 0 auto; }

/* Flowchart review panel — findings list (theme-driven, light/dark safe). */
.review-summary {
    font-size: 13px;
    color: var(--text-secondary);
    padding: 4px 2px 8px;
}
.review-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.review-item {
    display: flex;
    align-items: stretch;
    gap: 6px;
    width: 100%;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    overflow: hidden;
}
.review-item:hover { border-color: var(--text-secondary); }
.review-main {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    flex: 1 1 auto;
    text-align: left;
    padding: 8px 10px;
    font-size: 13px;
    line-height: 1.45;
    color: var(--text-color);
    background: var(--panel-bg);
    border: none;
    cursor: pointer;
}
.review-main:disabled { cursor: default; opacity: 0.8; }
.review-fix {
    flex: 0 0 auto;
    align-self: stretch;
    padding: 0 12px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    background: #2563eb;
    border: none;
    cursor: pointer;
}
.review-fix:hover { background: #1d4ed8; }
.review-dot {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    margin-top: 5px;
    border-radius: 50%;
    background: var(--text-secondary);
}
.review-warn .review-dot { background: #e0533d; }
.review-info .review-dot { background: #d8a23a; }
.review-msg { flex: 1 1 auto; }

.nlp-msg.user {
    align-self: flex-end;
    background: var(--accent-color);
    color: #fff;
}

.nlp-msg.assistant {
    align-self: flex-start;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    color: var(--text-color);
}

/* Running summary */
.nlp-summary {
    border: 1px solid var(--border-color);
    border-radius: 6px;
    overflow: hidden;
}

.nlp-summary-header {
    padding: 5px 10px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary);
    background: var(--bg-color);
    border-bottom: 1px solid var(--border-color);
}

.nlp-summary-content {
    padding: 8px 10px;
    max-height: 130px;
    overflow-y: auto;
    font-size: 12px;
    line-height: 1.7;
    color: var(--text-color);
    white-space: pre-wrap;
    font-family: inherit;
}

/* Input row: textarea + mic side by side */
.nlp-input-row {
    display: flex;
    gap: 6px;
    align-items: flex-end;
}

.nlp-input-row .nlp-textarea {
    flex: 1;
}

.nlp-textarea {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    line-height: 1.5;
    resize: none;
    background: var(--bg-color);
    color: var(--text-color);
}

.nlp-textarea:focus {
    outline: none;
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px rgba(37,99,235,0.1);
}

.nlp-footer {
    display: flex;
    align-items: center;
    gap: 8px;
}

.nlp-replace-label {
    font-size: 12px;
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
    flex: 1;
}

.nlp-mode-select {
    font-size: 12px;
    padding: 5px 8px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    color: var(--text-color);
    cursor: pointer;
}

.nlp-mic-btn {
    padding: 6px 10px;
    flex-shrink: 0;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.nlp-mic-btn.recording {
    background: #dc2626;
    border-color: #dc2626;
    color: white;
    animation: nlp-mic-pulse 1.4s ease infinite;
}

.nlp-mic-btn.transcribing {
    opacity: 0.5;
    cursor: not-allowed;
}

@keyframes nlp-mic-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.45); }
    50%       { box-shadow: 0 0 0 6px rgba(220, 38, 38, 0); }
}

/* ---- Mermaid Import/Export Modals ---- */
.mermaid-modal-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.45);
    z-index: 2000;
    align-items: center;
    justify-content: center;
}
.mermaid-modal {
    background: var(--bg-color, #fff);
    border-radius: 10px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.22);
    width: min(660px, 96vw);
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.mermaid-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 18px;
    font-weight: 600;
    font-size: 15px;
    border-bottom: 1px solid var(--border-color, #e5e7eb);
}
.mermaid-modal-close {
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
    color: var(--text-secondary, #6b7280);
    line-height: 1;
    padding: 2px 6px;
    border-radius: 4px;
}
.mermaid-modal-close:hover { background: var(--tool-hover); }

/* ---- Start-a-new-diagram dialog (#startDialog) — theme-aware via the shared CSS vars ---- */
.start-dialog-backdrop.visible { display: flex; }
.start-dialog { width: min(640px, 96vw); }
.start-dialog-body { gap: 14px; }
.start-actions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
}
.start-action,
.start-type {
    display: flex;
    align-items: center;
    gap: 10px;
    text-align: left;
    padding: 12px 14px;
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 10px;
    background: var(--panel-bg, #fff);
    color: var(--text-color, #111);
    cursor: pointer;
    transition: border-color .12s ease, background .12s ease, transform .06s ease;
}
.start-action:hover,
.start-type:hover {
    border-color: var(--accent-color, #2f6feb);
    background: var(--tool-hover);
}
/* The primary returning-user action ("Continue last diagram") gets an accent border + tint so the
   most likely choice stands out without stealing the whole grid's emphasis. */
.start-action--primary {
    border-color: var(--accent-color, #2f6feb);
    box-shadow: inset 0 0 0 1px var(--accent-color, #2f6feb);
}
.start-action:active,
.start-type:active { transform: translateY(1px); }
.start-action:focus-visible,
.start-type:focus-visible,
.start-browse:focus-visible {
    outline: 2px solid var(--accent-color, #2f6feb);
    outline-offset: 2px;
}
.start-action-ico { font-size: 22px; line-height: 1; flex: 0 0 auto; }
.start-type-ico { font-size: 18px; line-height: 1; flex: 0 0 auto; }
.start-action-tx,
.start-type-tx { display: flex; flex-direction: column; min-width: 0; }
.start-action-tx b { font-size: 14px; font-weight: 600; }
.start-type-tx b { font-size: 13px; font-weight: 600; }
.start-action-tx small,
.start-type-tx small {
    font-size: 12px;
    color: var(--text-secondary, #6b7280);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.start-section-label {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    color: var(--text-secondary, #6b7280);
    margin-top: 2px;
}
.start-types {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 8px;
}
.start-browse {
    align-self: flex-start;
    background: none;
    border: none;
    padding: 4px 2px;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent-color, #2f6feb);
    cursor: pointer;
}
.start-browse:hover { text-decoration: underline; }
@media (max-width: 480px) {
    .start-actions { grid-template-columns: 1fr; }
    .start-types { grid-template-columns: 1fr 1fr; }
}

/* ---- New-diagram name dialog (#newDiagramDialog) — theme-aware via the shared CSS vars ---- */
.new-diagram-backdrop.visible { display: flex; }
.new-diagram-modal { width: min(460px, 96vw); }
.new-diagram-body { gap: 14px; }
.nd-premium { display: flex; flex-direction: column; gap: 14px; }
.nd-field { display: flex; flex-direction: column; gap: 5px; }
.nd-label {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--text-secondary, #6b7280);
}
.nd-input {
    width: 100%;
    box-sizing: border-box;
    font-size: 14px;
    padding: 9px 11px;
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 8px;
    background: var(--input-bg, #fff);
    color: var(--text-color, #111);
}
.nd-input:focus-visible {
    outline: none;
    border-color: var(--accent-color, #2f6feb);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-color, #2f6feb) 28%, transparent);
}
.nd-input:disabled {
    opacity: .55;
    cursor: not-allowed;
    background: var(--tool-hover);
}
.nd-upsell {
    margin: -4px 0 0;
    font-size: 12px;
    color: var(--text-secondary, #6b7280);
}
.nd-secondary {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    border-top: 1px solid var(--border-color, #e5e7eb);
    padding-top: 12px;
}
.nd-link {
    background: none;
    border: none;
    padding: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent-color, #2f6feb);
    cursor: pointer;
}
.nd-link:hover { text-decoration: underline; }
.nd-link:focus-visible {
    outline: 2px solid var(--accent-color, #2f6feb);
    outline-offset: 2px;
    border-radius: 3px;
}
.nd-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 2px;
}

.mermaid-modal-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px 18px;
    overflow-y: auto;
}
.mermaid-hint { margin: 0; font-size: 13px; color: var(--text-secondary, #6b7280); }
.mermaid-export-warning {
    font-size: 13px;
    color: var(--notice-warn-text);
    background: var(--notice-warn-bg);
    border: 1px solid var(--notice-warn-border);
    border-radius: 6px;
    padding: 8px 12px;
}
.mermaid-hint code { font-family: monospace; background: var(--tool-hover); padding: 1px 5px; border-radius: 3px; }
.mermaid-textarea {
    width: 100%;
    min-height: 220px;
    font-family: 'Courier New', monospace;
    font-size: 13px;
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 6px;
    padding: 10px;
    resize: vertical;
    box-sizing: border-box;
    background: var(--input-bg, #fff);
    color: var(--text-color, #111);
    line-height: 1.5;
}
.mermaid-modal-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.mermaid-mode-radio {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 13px;
    cursor: pointer;
}
/* Template & examples gallery (MermaidUI.showTemplates) — reuses .mermaid-modal. */
.tpl-group { display: flex; flex-direction: column; gap: 8px; }
.tpl-group + .tpl-group { margin-top: 6px; }
.tpl-group-label {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-secondary, #6b7280);
}
.tpl-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 10px;
}
.tpl-card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    text-align: left;
    padding: 12px 14px;
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 8px;
    background: var(--input-bg, #fff);
    color: var(--text-color, #111);
    cursor: pointer;
    font: inherit;
}
.tpl-card:hover { border-color: var(--accent-color); background: var(--tool-hover); }
.tpl-card:focus-visible { outline: 2px solid var(--accent-color); outline-offset: 1px; }
.tpl-card-label { font-size: 14px; font-weight: 600; }
.tpl-card-desc { font-size: 12px; color: var(--text-secondary, #6b7280); line-height: 1.4; }

/* ---- Mermaid Mode Badge ---- */
.mermaid-mode-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    font-size: 12px;
    font-weight: 600;
    padding: 4px 10px 4px 12px;
    border-radius: 20px;
    white-space: nowrap;
}
.mermaid-mode-exit {
    background: rgba(255,255,255,0.25);
    border: none;
    color: #fff;
    cursor: pointer;
    font-size: 14px;
    border-radius: 50%;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 1;
}
.mermaid-mode-exit:hover { background: rgba(255,255,255,0.4); }

/* ---- AI Advisor Panel ---- */
.advisor-panel {
    position: fixed;
    top: 48px;
    right: 0;
    bottom: 0;
    width: 360px;
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    box-shadow: -4px 0 20px rgba(0,0,0,0.1);
    z-index: 200;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform: translateX(100%);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.advisor-panel.open {
    transform: translateX(0);
}
.advisor-header {
    display: flex;
    align-items: center;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-color);
    gap: 6px;
    flex-shrink: 0;
}
.advisor-header-left {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}
.advisor-title {
    font-weight: 600;
    font-size: 13px;
    white-space: nowrap;
}
.advisor-architect-badge {
    font-size: 11px;
    font-weight: 500;
    color: var(--notice-info-text);
    background: var(--notice-info-bg);
    border: 1px solid var(--notice-info-border);
    padding: 2px 8px;
    border-radius: 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.advisor-icon-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 13px;
    color: var(--text-secondary);
    padding: 3px 5px;
    border-radius: 4px;
    line-height: 1;
    flex-shrink: 0;
}
.advisor-icon-btn:hover {
    color: var(--text-color);
    background: var(--tool-hover);
}
.advisor-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    padding: 10px 12px;
    gap: 8px;
}
.advisor-chat {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 2px 0;
}
.advisor-msg {
    font-size: 13px;
    line-height: 1.55;
    padding: 9px 11px;
    border-radius: 8px;
    max-width: 90%;
    word-wrap: break-word;
    white-space: pre-wrap;
}
.advisor-msg.assistant {
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    align-self: flex-start;
}
.advisor-msg.user {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-text);
    align-self: flex-end;
}
.advisor-suggestion {
    background: var(--notice-ok-bg);
    border: 1px solid var(--notice-ok-border);
    border-radius: 8px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 5px;
    align-self: flex-start;
    max-width: 94%;
}
.advisor-suggestion-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--notice-ok-text);
}
.advisor-suggestion-desc {
    font-size: 12px;
    color: var(--notice-ok-text);
    line-height: 1.45;
}
.advisor-suggestion-btn {
    margin-top: 4px;
    font-size: 12px;
    padding: 4px 10px;
    background: #16a34a;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    align-self: flex-start;
}
.advisor-suggestion-btn:hover {
    background: #15803d;
}
.advisor-suggestion-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 4px;
}
.advisor-suggestion-actions .advisor-suggestion-btn {
    margin-top: 0;
}
.advisor-suggestion-btn-secondary {
    background: transparent;
    color: var(--notice-ok-text);
    border: 1px solid var(--notice-ok-border);
}
.advisor-suggestion-btn-secondary:hover {
    background: var(--notice-ok-bg);
}

/* ---- Build-prompt card (starting prompt for an AI coding agent) ---- */
.advisor-buildprompt-btn {
    font-size: 12px;
    padding: 5px 10px;
}
.advisor-buildprompt-card {
    background: var(--notice-info-bg);
    border: 1px solid var(--notice-info-border);
    border-radius: 8px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 7px;
    align-self: stretch;
    max-width: 100%;
}
.advisor-buildprompt-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}
.advisor-buildprompt-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--notice-info-text);
}
.advisor-buildprompt-name {
    font-size: 11px;
    color: var(--notice-info-text);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.advisor-buildprompt-hint {
    font-size: 11px;
    color: var(--notice-info-text);
    line-height: 1.45;
}
.advisor-buildprompt-body {
    margin: 0;
    max-height: 300px;
    overflow-y: auto;
    background: var(--bg-color, #fff);
    border: 1px solid var(--notice-info-border);
    border-radius: 6px;
    padding: 9px 10px;
    font-family: 'Courier New', monospace;
    font-size: 11.5px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-wrap: break-word;
    color: var(--text-color, #1e1b4b);
}
.advisor-buildprompt-actions {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}
.advisor-buildprompt-actions .advisor-suggestion-btn {
    margin-top: 0;
    background: var(--btn-primary-bg);
}
.advisor-buildprompt-actions .advisor-suggestion-btn:hover {
    background: var(--btn-primary-hover);
}
.advisor-buildprompt-actions .advisor-suggestion-btn-secondary {
    background: transparent;
    color: var(--notice-info-text);
    border: 1px solid var(--notice-info-border);
}
.advisor-buildprompt-actions .advisor-suggestion-btn-secondary:hover {
    background: var(--notice-info-bg);
}

/* ---- Amend review bar ---- */
.amend-bar {
    position: absolute;
    top: 14px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 60;
    display: flex;
    align-items: center;
    gap: 18px;
    max-width: calc(100% - 32px);
    padding: 10px 14px;
    background: var(--panel-bg, #ffffff);
    border: 1px solid var(--border-color, #d1d5db);
    border-radius: 10px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
    font-size: 13px;
}
.amend-bar-title {
    font-weight: 600;
    font-size: 13px;
}
.amend-bar-summary {
    color: var(--text-secondary, #475569);
    font-size: 12px;
    margin-top: 1px;
}
.amend-bar-legend {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 5px;
    flex-wrap: wrap;
}
.amend-key {
    font-size: 11px;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid transparent;
}
.amend-key-add    { color: var(--notice-ok-text); background: var(--notice-ok-bg); border-color: var(--notice-ok-border); }
.amend-key-rename { color: var(--notice-warn-text); background: var(--notice-warn-bg); border-color: var(--notice-warn-border); }
.amend-key-remove { color: var(--notice-danger-text); background: var(--notice-danger-bg); border-color: var(--notice-danger-border); }
.amend-bar-hint {
    font-size: 11px;
    color: var(--text-secondary, #64748b);
}
.amend-bar-actions {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .amend-bar {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        top: 8px;
    }
    .amend-bar-actions { justify-content: flex-end; }
}
.advisor-input-row {
    flex-shrink: 0;
}
.advisor-textarea {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 8px 10px;
    font-size: 13px;
    font-family: inherit;
    resize: none;
    background: var(--input-bg, #fff);
    color: var(--text-color);
    line-height: 1.45;
}
.advisor-textarea:focus {
    outline: none;
    border-color: var(--accent-color);
}
.advisor-footer {
    display: flex;
    justify-content: flex-end;
    flex-shrink: 0;
}

@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .nlp-panel,
    .advisor-panel {
        top: 0;
        width: 100%;
        z-index: 500;
        border-left: none;
    }
}

/* Advanced / collapsible section toggles */
.advanced-toggle,
.section-toggle {
    cursor: pointer;
    user-select: none;
    background-color: var(--sidebar-bg);
    border-radius: 3px;
    color: var(--accent-color);
}

.advanced-toggle:hover,
.section-toggle:hover {
    color: var(--text-color);
    background-color: var(--tool-hover);
}

#advancedShapes,
.section-content {
    width: 100%;
}

/* ---- Resizable right panel (Account) ---- */
.panel-resize-handle {
    position: absolute;
    left: -3px;
    top: 0;
    bottom: 0;
    width: 7px;
    cursor: ew-resize;
    z-index: 10;
}
.panel-resize-handle:hover,
.panel-resize-handle.dragging {
    background: var(--focus-ring);
}

/* ---- Mobile selection action bar ---- */
/* One edge-to-edge row that rides directly on top of the toolbar handle (matching its width),
   so the contextual actions take a single bar and leave the rest of the screen for diagramming.
   Too many actions to fit? The row scrolls horizontally rather than wrapping or growing thicker.
   It stays up whenever a selection exists (it hides only when the tools drawer / a property sheet
   opens, which provide their own controls). */
.mobile-action-bar {
    position: fixed;
    top: auto;
    bottom: calc(var(--toolbar-handle-height, 0px) + env(safe-area-inset-bottom));
    left: 0;
    right: 0;
    display: none;
    align-items: center;
    gap: 4px;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    background: var(--panel-bg);
    border-top: 1px solid var(--border-color);
    padding: 4px 8px;
    z-index: 220;
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.16);
}
.mobile-action-bar::-webkit-scrollbar { display: none; }
.mobile-action-bar.visible { display: flex; }
.mobile-action-bar .mab-style { color: var(--accent-color); font-weight: 600; }
.mobile-action-bar .mab-count {
    font-size: 11px;
    color: var(--text-secondary);
    padding: 0 4px;
    white-space: nowrap;
    flex: 0 0 auto;
}
.mobile-action-bar .mab-btn {
    flex: 0 0 auto;
    background: transparent;
    border: none;
    color: var(--text-color);
    font-size: 13px;
    padding: 7px 10px;
    border-radius: 999px;
    cursor: pointer;
    white-space: nowrap;
}
.mobile-action-bar .mab-btn:active { background: var(--tool-hover); }
.mobile-action-bar .mab-delete { color: #ef4444; font-weight: 600; }
/* Mind-map fast-add: accent-filled pills so adding a node reads as the primary action. */
.mobile-action-bar .mab-mind {
    background: var(--accent-color);
    color: #fff;
    font-weight: 600;
}
.mobile-action-bar .mab-mind:active { background: var(--accent-color); filter: brightness(0.9); }
/* "Ask AI" — accent-filled pill so the intrinsic AI entry reads as a primary action and leads the
   bar (theme-aware via --accent-color, so it adapts to light/dark like the rest of the chrome). */
.mobile-action-bar .mab-ai {
    background: var(--accent-color);
    color: #fff;
    font-weight: 600;
}
.mobile-action-bar .mab-ai:active { background: var(--accent-color); filter: brightness(0.9); }

/* ---- Notification system ---- */
.notif-btn-wrapper {
    position: relative;
}
.notif-btn {
    position: relative;
}
.notif-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    background: #dc2626;
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    min-width: 14px;
    height: 14px;
    border-radius: 7px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 3px;
    line-height: 1;
    pointer-events: none;
}
.notif-panel {
    position: fixed;
    top: 48px;
    right: 0;
    width: 320px;
    height: calc(100vh - 48px);
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    z-index: 500;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 0.22s ease;
    box-shadow: -4px 0 20px rgba(0,0,0,0.18);
}
.notif-panel.open {
    transform: translateX(0);
}
/* Mobile: full-width sheet above the bottom toolbar and property sheets,
   sized with dvh so the browser chrome can't push it off-screen. */
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .notif-panel {
        width: 100%;
        top: 48px;
        bottom: 0;
        height: auto;
        max-height: calc(100dvh - 48px);
        border-left: none;
        z-index: 1200;
    }
}
.notif-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}
.notif-panel-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-color);
}
.notif-panel-actions {
    display: flex;
    gap: 6px;
    align-items: center;
}
.notif-clear-btn {
    font-size: 11px;
    padding: 3px 8px;
    border: 1px solid var(--border-color);
    background: none;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text-secondary);
}
.notif-clear-btn:hover { color: var(--text-color); background: var(--tool-hover); }
.notif-close-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-secondary);
    font-size: 16px;
    padding: 2px 4px;
}
.notif-close-btn:hover { color: var(--text-color); }
.notif-list {
    flex: 1;
    overflow-y: auto;
    padding: 8px 0;
}
.notif-empty {
    text-align: center;
    color: var(--text-secondary);
    font-size: 12px;
    padding: 32px 16px;
}
.notif-item {
    padding: 9px 14px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.notif-item:last-child { border-bottom: none; }
.notif-item--error .notif-item-msg { color: #f87171; }
.notif-item-msg {
    font-size: 12px;
    color: var(--text-color);
    line-height: 1.4;
}
.notif-item-time {
    font-size: 10px;
    color: var(--text-secondary);
}

/* ---- Ellipsis slide-out panel (Options) ---- */
.options-panel {
    position: fixed;
    top: 48px;
    right: 0;
    width: 260px;
    height: calc(100vh - 48px);
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    z-index: 499;
    display: flex;
    flex-direction: column;
    transform: translateX(100%);
    transition: transform 0.22s ease;
    box-shadow: -4px 0 20px rgba(0,0,0,0.18);
    overflow-y: auto;
}
.options-panel.open {
    transform: translateX(0);
}
/* Drag handle on the Menu blade's left (canvas-facing) edge — desktop only (js/blade-resize.js
   toggles `hidden`). An absolute child of the panel so it AUTO-tracks the left edge as the width
   changes (drag or a wider blade like Share) and never floats over the canvas/content. Sits over the
   panel's left padding only; invisible until hovered/dragged. */
.blade-resizer {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    width: 10px;
    cursor: ew-resize;
    z-index: 5;
    touch-action: none;
    background: transparent;
    transition: background 0.15s ease;
    display: flex;
    align-items: center;
    justify-content: center;
}
.blade-resizer:hover,
.blade-resizer.dragging { background: var(--accent-soft, rgba(59,130,246,0.25)); }
.blade-resizer[hidden] { display: none; }
/* Visible grip so the drag affordance is discoverable at rest (not just on hover): a short
   vertical bar of dots centred on the handle. Strengthens on hover/drag. */
.blade-resizer-grip {
    width: 4px;
    height: 28px;
    border-radius: 3px;
    background:
        radial-gradient(circle, var(--text-secondary, #888) 1.2px, transparent 1.4px) center / 4px 6px repeat-y;
    opacity: 0.45;
    transition: opacity 0.15s ease;
    pointer-events: none;
}
.blade-resizer:hover .blade-resizer-grip,
.blade-resizer.dragging .blade-resizer-grip { opacity: 0.9; }
.options-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px var(--blade-gutter);
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}
.options-panel-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-color);
}
.options-close-btn {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-secondary);
    font-size: 16px;
    padding: 2px 4px;
}
.options-close-btn:hover { color: var(--text-color); }
.options-section-label {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-secondary);
    padding: 14px var(--blade-gutter) 4px;
    margin-top: 6px;
    border-top: 1px solid var(--border);
}
/* The first section header in a panel needs no divider above it. */
.blade-body > .options-section-label:first-child,
.options-section-label + .options-section-label {
    border-top: none;
    margin-top: 0;
}
/* Muted helper line inside a blade (e.g. pointing to where a relocated action now lives). */
.options-hint {
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-secondary);
    padding: 4px var(--blade-gutter) 10px;
}
.options-item {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px var(--blade-gutter);
    background: none;
    border: none;
    cursor: pointer;
    font-size: 13px;
    color: var(--text-color);
    border-bottom: 1px solid transparent;
}
.options-item:hover { background: var(--tool-hover); }
/* A menu item whose context isn't ready yet (e.g. "Sort cards…" with no roadmap): greyed and inert,
   but still visible + tooltipped so the feature stays discoverable. aria-disabled (set by
   App._refreshMenuAvailability) keeps the hover title working; the dispatchers bail on it. */
.menu-item-disabled { opacity: 0.4; cursor: not-allowed; }
.menu-item-disabled:hover { background: none; }
/* Roadmap "View" switcher: a STATEFUL segmented control (Phase columns | Goal lanes) that replaces
   the old ambiguous "Group cards by goal" toggle. The lit segment shows the active view, so the
   choice reads as a view selection, not a one-way action. Lives in the Insert blade alongside the
   .options-item rows; deliberately NOT an .options-item so clicking a segment doesn't auto-close the
   blade (the user sees the highlight move to confirm the switch). */
.options-seg {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px var(--blade-gutter);
}
.options-seg-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-secondary);
    flex: 0 0 auto;
}
.options-seg-track {
    display: flex;
    flex: 1 1 auto;
    gap: 3px;
    padding: 3px;
    background: var(--input-bg);
    border: 1px solid var(--border-color);
    border-radius: 9px;
}
.options-seg-btn {
    flex: 1 1 0;
    text-align: center;
    padding: 6px 8px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
    background: none;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
}
.options-seg-btn:hover { background: var(--tool-hover); color: var(--text-color); }
.options-seg-btn--on,
.options-seg-btn[aria-pressed="true"] {
    background: var(--accent-color);
    color: var(--btn-primary-text);
}
.options-seg-btn--on:hover,
.options-seg-btn[aria-pressed="true"]:hover {
    background: var(--accent-color);
    color: var(--btn-primary-text);
}
/* A segment greyed because no roadmap exists yet: dim the whole control + make the segments inert. */
.options-seg-btn.menu-item-disabled { opacity: 0.4; cursor: not-allowed; }
.options-seg-btn.menu-item-disabled:hover { background: none; color: var(--text-secondary); }
/* Toggle row in a blade: label text left, checkbox right. Overrides the
   block-button layout of .options-item it sits alongside. */
.options-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.options-toggle input[type="checkbox"] { margin: 0; cursor: pointer; flex: none; }

/* Diagram info card → "Show in card" field checkboxes. A nested, indented sub-list under the
   "Diagram info card" toggle; deliberately NOT .options-item so toggling several boxes in a row
   doesn't close the menu between clicks (see js/actions.js). */
.info-field-group {
    padding: 2px var(--blade-gutter) 8px calc(var(--blade-gutter) + 8px);
    border-bottom: 1px solid transparent;
}
.info-field-head {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.6;
    margin: 4px 0 4px;
    color: var(--text-color);
}
.info-field-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 5px 0;
    font-size: 13px;
    color: var(--text-color);
    cursor: pointer;
}
.info-field-toggle input[type="checkbox"] { margin: 0; cursor: pointer; flex: none; }
.info-field-toggle input[type="checkbox"]:disabled { cursor: not-allowed; opacity: 0.5; }

/* Menu → View: zoom stepper row (− / % / +). */
.view-zoom-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 14px;
}
.view-zoom-btn {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    color: var(--text-color);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
}
.view-zoom-btn:hover { background: var(--tool-hover); }
.view-zoom-level {
    flex: 1 1 auto;
    text-align: center;
    font-size: 15px;
    font-weight: 600;
    color: var(--text-color);
}

.options-divider {
    height: 1px;
    background: var(--border-color);
    margin: 4px 14px;
}

/* ---- Azure-portal-style blade rail (Options panel) ----------------------- */
/* The rail anchors to the right; blades sit in a row, the active one expanded
   on the right with parent blades collapsed to slim clickable strips on its
   left (the breadcrumb). Width is content-driven so deeper stacks grow left. */
.options-panel.blade-rail {
    width: auto;
    max-width: 96vw;
    flex-direction: row;
    justify-content: flex-end;
    align-items: stretch;
    overflow: visible;
    padding: 0;
}
.blade {
    /* --blade-w lets the drag handle (js/blade-resize.js) widen the active blade; defaults to 272px.
       Slim parent strips (.blade--strip) and the wide Share blade override this below/elsewhere. */
    width: var(--blade-w, 272px);
    flex: 0 0 var(--blade-w, 272px);
    height: 100%;
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.blade[hidden] { display: none; }
.blade .blade-strip { display: none; }
/* The "Generate index map" library action is gated behind the diagrams-room/share
   feature flag; .btn sets display:flex, so an id-specificity [hidden] rule is needed
   to let the hidden attribute actually hide it (UA [hidden] loses to .btn). */
#generateIndexMapBtn[hidden] { display: none; }

/* Collapsed parent: a slim vertical strip with a rotated title. */
.blade--strip {
    width: 40px;
    flex: 0 0 40px;
    overflow: hidden;
    background: var(--tool-hover, rgba(127,127,127,0.06));
    cursor: pointer;
    padding: 0;
}
.blade--strip .blade-head,
.blade--strip .blade-body { display: none; }
.blade--strip .blade-strip {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: none;
    border: none;
    cursor: pointer;
}
.blade--strip:hover { background: var(--accent-soft, rgba(59,130,246,0.10)); }
.blade-strip-label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    color: var(--text-secondary);
    white-space: nowrap;
}

.blade-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px var(--blade-gutter);
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}
.blade-title { font-size: 13px; font-weight: 600; color: var(--text-color); flex: 1; }
.blade-back {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-secondary);
    font-size: 18px;
    line-height: 1;
    padding: 2px 6px;
    border-radius: 6px;
}
.blade-back:hover { color: var(--text-color); background: var(--tool-hover); }
/* Per-blade close (×): injected into every blade head by blades.js so the Menu
   can be dismissed from any depth — the title takes the slack so it sits hard
   right, mirroring the root blade's close button. */
.blade-head .blade-close { margin-left: auto; flex-shrink: 0; border-radius: 6px; line-height: 1; }
.blade-head .blade-close:hover { background: var(--tool-hover); }
.blade-body { flex: 1 1 auto; overflow-y: auto; padding: 6px 0 14px; }
/* Inside a blade rail every row owns its own horizontal gutter (so hover-fill
   rows like .blade-nav can stay edge-to-edge). .prop-group holds the inputs /
   swatches / sliders and has no hover fill, so give it the gutter directly —
   otherwise its inputs sit flush to the panel edge while the section labels and
   nav rows beside them are inset, which reads as broken. Scoped to .blade-body
   so the older direct-child property panels (which inset via .properties-panel
   padding) are unaffected. */
.blade-body > .prop-group,
#qgQuickBody > .prop-group {
    padding-left: var(--blade-gutter);
    padding-right: var(--blade-gutter);
}

/* Smart Inspector — the "Quick" group of pinned + most-used property controls at the
   top of the inspector. Groups are MOVED here from their home sections (not cloned), so
   they keep their own ids/listeners; the pin button travels with each group. */
.qg-quick {
    background: var(--bg-subtle, rgba(127, 127, 127, 0.06));
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 8px;
    margin-bottom: 4px;
}
.qg-quick .options-section-label {
    border-top: none;
    margin-top: 0;
}
/* The pin affordance lives in the top-right corner of every promotable group. */
.qg-promotable {
    position: relative;
}
.qg-pin {
    position: absolute;
    top: -2px;
    right: var(--blade-gutter);
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    font-size: 12px;
    line-height: 22px;
    text-align: center;
    opacity: 0.3;
    filter: grayscale(1);
    border-radius: 4px;
    z-index: 1;
}
.qg-pin:hover {
    opacity: 0.7;
    background: var(--hover-bg, rgba(127, 127, 127, 0.12));
}
.qg-pin--on {
    opacity: 1;
    filter: none;
}
.qg-pin:focus-visible {
    outline: 2px solid var(--accent-color, #4c8bf5);
    outline-offset: 1px;
    opacity: 0.9;
}
.blade-foot {
    flex-shrink: 0;
    padding: 10px var(--blade-gutter);
    border-top: 1px solid var(--border-color);
}

/* Category navigation row: icon · two-line label · chevron. */
.blade-nav {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 10px var(--blade-gutter);
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-color);
}
.blade-nav:hover { background: var(--tool-hover); }
.blade-nav-ic { font-size: 16px; width: 20px; text-align: center; flex-shrink: 0; }
.blade-nav-tx { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.blade-nav-tx b { font-size: 13px; font-weight: 600; }
.blade-nav-tx small,
.options-item--2line small {
    font-size: 11px;
    color: var(--text-secondary);
    margin-top: 1px;
}
.blade-chev { color: var(--text-secondary); font-size: 16px; flex-shrink: 0; }
.options-item--2line { display: flex; flex-direction: column; gap: 0; line-height: 1.3; }
/* A direct-action .options-item that borrows the blade-nav row layout (icon · two-line text)
   so it can carry an icon alongside the .blade-nav category rows it sits with — but stays an
   .options-item (no chevron, closes the menu on click). */
.options-item--nav { display: flex; align-items: center; gap: 10px; }
.blade-note {
    font-size: 11px;
    color: var(--text-secondary);
    padding: 8px var(--blade-gutter) 4px;
    line-height: 1.4;
}

/* The shape Properties inspector is the same blade rail, but it lives in the
   workspace flow (not a fixed overlay). When not minimized by the desktop panel
   stack, lay it out as a row of blades anchored right; the outer .minimized rule
   (28px slim tab) still wins because this rule excludes that state. */
.properties-panel.blade-rail.visible:not(.minimized) {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    align-items: stretch;
    width: auto;
    padding: 0;
    overflow: visible;
}

/* Mobile / touch: a fixed-width blade rail would overflow a phone, so degrade
   to one blade at a time at full panel width — parents stay in the stack but
   are hidden, and you navigate back with each child's "‹" button. */
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .options-panel.blade-rail { width: min(320px, 88vw); max-width: 88vw; }
    .blade { width: 100%; flex: 0 0 100%; }
    .blade--strip { display: none; }
    /* Properties stays the bottom-sheet (block flow); the single active blade
       sizes to its content rather than forcing full sheet height. */
    .properties-panel.blade-rail.visible:not(.minimized) { display: block; width: auto; padding: 0; }
    .properties-panel.blade-rail .blade { height: auto; overflow: visible; }
    .properties-panel.blade-rail .blade-body { overflow: visible; }
}

/* Touch layouts: the panel is reached via the mobile menu's "File & export…"
   item (the #optionsBtn toolbar trigger is hidden on phones), so size it for
   fingers and the shorter svh viewport. */
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .options-panel {
        width: min(320px, 88vw);
        height: calc(100svh - 48px);
    }
    .options-item {
        padding: 12px 16px;
        font-size: 14px;
    }
    .options-close-btn {
        font-size: 18px;
        padding: 8px 12px;
    }
}

/* Matches the 44px top bar below 768px (base rule assumes the 48px bar) */
@media (max-width: 768px) {
    .options-panel {
        top: 44px;
        height: calc(100svh - 44px);
    }
}

/* sidebar Terms link */
.sidebar-terms {
    margin-top: auto;
    width: 100%;
    padding: 6px 0 4px;
    border-top: 1px solid var(--border-color);
    text-align: center;
    flex-shrink: 0;
}
.sidebar-terms-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 9px;
    color: var(--text-secondary);
    text-decoration: underline;
    padding: 2px 4px;
}
.sidebar-terms-btn:hover { color: var(--text-color); }

/* ---- Collaboration: sync indicator + join modal ---- */
.collab-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--text-secondary, #555);
    padding: 0 6px;
    white-space: nowrap;
    /* Fixed footprint: the label text changes constantly ("Syncing…",
       "Synced · 12s ago · 2 here") — reserve the widest size so the rest of
       the top bar never reflows; only colors/text inside the slot change. */
    min-width: 190px;
    max-width: 190px;
    overflow: hidden;
    text-overflow: ellipsis;
    font-variant-numeric: tabular-nums;
}
.collab-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #9ca3af;
    flex-shrink: 0;
}
.collab-dot.synced  { background: #22c55e; }
.collab-dot.syncing { background: #3b82f6; animation: collab-pulse 1s ease-in-out infinite; }
.collab-dot.offline { background: #ef4444; }
@keyframes collab-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }

/* Lag warning: shown when this client falls far enough behind to hold up compaction (§9). */
.collab-lag-warning {
    position: fixed;
    top: 56px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10001;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 90vw;
    padding: 8px 12px;
    font-size: 13px;
    color: var(--notice-warn-text);
    background: var(--notice-warn-bg);
    border: 1px solid var(--notice-warn-border);
    border-radius: 8px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);
}
.collab-lag-resync {
    flex-shrink: 0;
    padding: 4px 10px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    background: #f59e0b;
    border: none;
    border-radius: 6px;
    cursor: pointer;
}
.collab-lag-resync:hover { background: #d97706; }

/* "New version available" banner (js/update-check.js) — same notice styling as the
   collab lag warning, with a primary refresh action and a quiet dismiss. */
.update-banner {
    position: fixed;
    top: 56px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 10001;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 90vw;
    padding: 8px 12px;
    font-size: 13px;
    color: var(--notice-warn-text);
    background: var(--notice-warn-bg);
    border: 1px solid var(--notice-warn-border);
    border-radius: 8px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);
}
.update-banner-reload {
    flex-shrink: 0;
    padding: 4px 10px;
    font-size: 12px;
    font-weight: 600;
    color: #fff;
    background: #2563eb;
    border: none;
    border-radius: 6px;
    cursor: pointer;
}
.update-banner-reload:hover { background: #1d4ed8; }
.update-banner-reload:disabled { opacity: 0.6; cursor: default; }
.update-banner-later {
    flex-shrink: 0;
    padding: 4px 10px;
    font-size: 12px;
    color: inherit;
    background: transparent;
    border: 1px solid var(--notice-warn-border);
    border-radius: 6px;
    cursor: pointer;
}

.join-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10000;
}
.join-card {
    background: var(--panel-bg, #fff);
    border-radius: 10px;
    padding: 22px;
    width: 320px;
    max-width: calc(100vw - 32px);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}
.join-title {
    font-size: 17px;
    font-weight: 700;
    margin-bottom: 14px;
    color: var(--text-color, #111);
}
.join-label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary, #555);
    margin: 10px 0 4px;
}
.join-error {
    color: #dc2626;
    font-size: 12px;
    min-height: 16px;
    margin-top: 8px;
}
.join-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 14px;
}

/* ---- Terms of Service gate ---- */
.tos-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 11000;
    padding: 16px;
}
/* While the gate is up, lock the page behind it from scrolling. */
body.tos-locked {
    overflow: hidden;
}
.tos-card {
    background: var(--panel-bg, #fff);
    border-radius: 12px;
    width: 560px;
    max-width: 100%;
    /* `100vh` counts the area behind the mobile URL bar, so calc(100vh - 32px) can be
       taller than the *visible* viewport and push the footer (the action buttons) off
       screen on phones/tablets. `100dvh` (dynamic viewport height) tracks the visible
       area; the vh line is the fallback for browsers without dvh. */
    max-height: calc(100vh - 32px);
    max-height: min(calc(100dvh - 24px), 760px);
    display: flex;
    flex-direction: column;
    box-shadow: 0 18px 60px rgba(0, 0, 0, 0.35);
    overflow: hidden;
}
.tos-card-header {
    padding: 22px 24px 14px;
    border-bottom: 1px solid var(--border-color, #e5e7eb);
}
.tos-badge {
    display: inline-block;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #fff;
    background: var(--accent-color, #2563eb);
    border-radius: 999px;
    padding: 3px 10px;
    margin-bottom: 10px;
}
.tos-title {
    font-size: 22px;
    font-weight: 700;
    margin: 0;
    color: var(--text-color, #111);
}
.tos-subtitle {
    font-size: 13px;
    color: var(--text-secondary, #555);
    margin: 6px 0 0;
}
.tos-version {
    font-size: 11px;
    color: var(--text-secondary, #6b7280);
    margin: 4px 0 0;
    font-variant-numeric: tabular-nums;
}
.tos-body {
    padding: 18px 24px;
    /* The body is the one region that scrolls; flex:1 + min-height:0 lets it shrink so
       the footer stays pinned inside the card instead of being pushed below the fold. */
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-color, #1f2937);
}
.tos-body h2 {
    font-size: 14px;
    font-weight: 700;
    margin: 18px 0 4px;
    color: var(--text-color, #111);
}
.tos-body p {
    margin: 0 0 8px;
}
.tos-body ul {
    margin: 0 0 8px;
    padding-left: 20px;
}
.tos-body li {
    margin: 0 0 4px;
}
.tos-divider {
    border: none;
    border-top: 1px solid var(--border-color, #e5e7eb);
    margin: 22px 0 16px;
}
.tos-section-heading {
    font-size: 18px !important;
    font-weight: 700;
    margin: 0 0 8px !important;
}
.tos-callout {
    background: var(--notice-warn-bg);
    border: 1px solid var(--notice-warn-border);
    border-radius: 8px;
    padding: 12px 14px;
    margin-bottom: 6px;
    color: var(--notice-warn-text);
    font-size: 13px;
    line-height: 1.55;
}
.tos-footer {
    /* Never shrink the footer, and keep the buttons clear of the home indicator /
       gesture bar on notched devices. */
    flex-shrink: 0;
    padding: 14px 24px calc(18px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border-color, #e5e7eb);
    background: var(--bg-color, #f9fafb);
}
.tos-agree-row {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    font-size: 13px;
    color: var(--text-color, #111);
    cursor: pointer;
    margin-bottom: 12px;
}
.tos-agree-row input {
    margin-top: 2px;
    flex-shrink: 0;
}
.tos-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
.tos-reopen-link {
    position: fixed;
    left: 10px;
    bottom: 8px;
    z-index: 9000;
    background: transparent;
    border: none;
    padding: 4px 6px;
    font-size: 11px;
    color: var(--text-secondary, #6b7280);
    text-decoration: underline;
    cursor: pointer;
    opacity: 0.7;
}
.tos-reopen-link:hover {
    opacity: 1;
}

/* ---- Align & distribute popover ---- */
.align-grid {
    display: flex;
    gap: 4px;
    flex: 1;
    flex-wrap: wrap;
}
.align-opt {
    flex: 1 0 auto;
    min-width: 34px;
    padding: 5px 8px;
    font-size: 15px;
    line-height: 1;
    background: none;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    cursor: pointer;
    color: var(--text-secondary);
    transition: background 0.1s, color 0.1s;
}
.align-opt:hover {
    background: var(--accent-color);
    color: #fff;
}

/* ---- AI Import panel ---- */
.ai-import-textarea {
    width: 100%;
    min-height: 200px;
    resize: vertical;
    font-family: 'Courier New', monospace;
    font-size: 12px;
    margin-bottom: 8px;
}
.ai-import-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}
.ai-import-bytes {
    font-size: 12px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}
.ai-import-bytes.over-limit {
    color: #dc2626;
    font-weight: 600;
}
.ai-import-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 4px 0 8px;
}
.ai-import-chip {
    padding: 5px 12px;
    font-size: 12px;
    font-weight: 500;
    background: var(--bg-color);
    border: 1px solid var(--accent-color);
    border-radius: 14px;
    color: var(--accent-color);
    cursor: pointer;
    transition: background 0.1s, color 0.1s;
}
.ai-import-chip:hover {
    background: var(--accent-color);
    color: #fff;
}

/* ---- Photo → shapes (whiteboard import), inside the AI Import paste stage ---- */
.ai-import-photo {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}
/* The file input is hidden but kept IN the layout (not display:none) so its label reliably
   opens the picker on every browser, including mobile Safari. */
.wb-file-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* The label-as-buttons need to look/sit like the adjacent <button class="btn">. */
.ai-import-photo-actions label.btn {
    display: inline-flex;
    align-items: center;
    cursor: pointer;
}
/* "Take a photo" (camera) is only meaningful on devices with a camera/touch — hide it on
   pointer-precise (desktop) where capture is ignored anyway; "Upload a photo" covers desktop. */
.ai-import-photo-actions label.wb-camera-only {
    display: none;
}
@media (pointer: coarse) {
    .ai-import-photo-actions label.wb-camera-only {
        display: inline-flex;
    }
}
.ai-import-or {
    text-align: center;
    font-size: 12px;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin: -20px auto 8px;
    width: 2.4em;
    background: var(--panel-bg, var(--bg-color));
}
.ai-import-photo-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 8px 0;
}
.ai-import-photo-preview {
    margin: 8px 0;
}
.ai-import-photo-preview img {
    max-width: 100%;
    max-height: 180px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    display: block;
}
.ai-import-photo-status {
    font-size: 12px;
    color: var(--text-secondary);
    min-height: 16px;
}
.ai-import-photo-status.error {
    color: #dc2626;
}

/* ---- Mobile: align/distribute popover becomes a centred sheet ---- */
@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .align-popover {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        min-width: 280px;
        max-width: calc(100vw - 32px);
        z-index: 4000;
        box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3);
    }
    .align-popover.align-popover { /* keep specificity over desktop top/left */
        top: 50%;
        left: 50%;
    }
    .align-grid { gap: 8px; }
    .align-opt {
        min-width: 48px;
        min-height: 44px;
        font-size: 20px;
    }
}

/* ── Help-panel "Ask a question" box (routes to the omni-search Ask-help flow) ── */
.shortcuts-ask { padding-bottom: 6px; }
.shortcuts-ask-row { display: flex; gap: 6px; }
.shortcuts-ask-input {
    flex: 1;
    min-width: 0;
    padding: 8px 10px;
    font: inherit;
    font-size: 13px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--canvas-bg);
    color: var(--text-color);
}
.shortcuts-ask-input:focus { outline: none; border-color: var(--accent-color); }
.shortcuts-ask-btn {
    flex: 0 0 auto;
    padding: 8px 14px;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    border: 1px solid var(--accent-color);
    border-radius: 6px;
    background: var(--accent-color);
    color: #fff;
    cursor: pointer;
    transition: filter .12s;
}
.shortcuts-ask-btn:hover { filter: brightness(1.06); }
.shortcuts-ask-hint { font-size: 12px; line-height: 1.45; color: var(--text-secondary); margin-top: 6px; }

/* ── Help-panel collapsible sections (reference/limits/about/credits) ───────── */
.shortcuts-details { margin-bottom: 8px; border-bottom: 1px solid var(--border-color); }
.shortcuts-details > summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 9px 0;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-secondary);
}
.shortcuts-details > summary::-webkit-details-marker { display: none; }
.shortcuts-details > summary::after {
    content: '▸';
    font-size: 12px;
    transition: transform .15s ease;
}
.shortcuts-details[open] > summary::after { transform: rotate(90deg); }
.shortcuts-details > summary:hover { color: var(--text-color); }
.shortcuts-details[open] > summary { color: var(--text-color); }
/* Inner sections already carry their own titles/margins; trim the last so the
   collapsible doesn't add a double gap above its border. */
.shortcuts-details .shortcuts-section:last-child { margin-bottom: 6px; }

/* ===================== Support / Report an issue ===================== */
/* Entry point button at the top of the Help (?) panel */
.shortcuts-support { padding-bottom: 4px; }
.shortcuts-support-btn {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    text-align: left;
    padding: 12px 14px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--support-cta-bg);
    color: var(--support-cta-text);
    cursor: pointer;
    font: inherit;
    transition: background .12s, border-color .12s;
}
.shortcuts-support-btn:hover { background: var(--support-cta-hover); border-color: var(--accent-color); }
.shortcuts-support-icon { font-size: 22px; line-height: 1; }
.shortcuts-support-text { display: flex; flex-direction: column; }
.shortcuts-support-title { font-weight: 600; font-size: 14px; }
.shortcuts-support-sub { font-size: 12px; color: var(--support-cta-sub); }
.shortcuts-terms-link {
    display: block;
    width: 100%;
    margin-top: 8px;
    padding: 0;
    border: none;
    background: none;
    text-align: center;
    color: var(--text-secondary);
    font: inherit;
    font-size: 12px;
    text-decoration: underline;
    cursor: pointer;
}
.shortcuts-terms-link:hover { color: var(--accent-color); }

/* ── Help-panel "Tutorials" section ───────────────────────────────────────── */
.shortcuts-about { padding-bottom: 6px; }
.shortcuts-about-lead { margin: 2px 0 12px; font-size: 13px; line-height: 1.5; color: var(--text-color); }
.shortcuts-about-journey { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.shortcuts-about-journey li {
    position: relative;
    padding: 9px 11px 9px 13px;
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-color);
    border-radius: 8px;
    background: var(--panel-bg);
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--text-secondary);
}
.shortcuts-about-step { display: block; font-weight: 600; font-size: 13px; color: var(--text-color); margin-bottom: 2px; }
.shortcuts-about-pillar { margin: 0 0 8px; font-size: 12.5px; line-height: 1.5; color: var(--text-secondary); }
.shortcuts-about-pillar strong { color: var(--text-color); }
.shortcuts-tutorials { padding-bottom: 6px; }
.shortcuts-tut-sub { font-size: 12px; color: var(--text-secondary); margin: 2px 0 8px; }
.shortcuts-tut-list { display: flex; flex-direction: column; gap: 6px; }
.shortcuts-tut-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 9px 11px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    color: var(--text-color);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    transition: background .12s, border-color .12s;
}
.shortcuts-tut-btn:hover { border-color: var(--accent-color); background: var(--bg-color); }
.shortcuts-tut-emoji { font-size: 17px; line-height: 1; }
.shortcuts-tut-all {
    display: block;
    width: 100%;
    margin-top: 8px;
    padding: 0;
    border: none;
    background: none;
    text-align: center;
    color: var(--accent-color);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
}
.shortcuts-tut-all:hover { text-decoration: underline; }

/* ── Tutorials modal ──────────────────────────────────────────────────────── */
.tut-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 1300;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.tut-backdrop.visible { display: flex; }
.tut-modal {
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    width: min(820px, 100%);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}
.tut-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border-color);
}
.tut-title { flex: 1; font-weight: 600; font-size: 16px; }
.tut-back {
    background: none;
    border: none;
    color: var(--accent-color);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 6px;
}
.tut-back:hover { background: var(--bg-color); }
.tut-close {
    background: none;
    border: none;
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
    color: var(--text-secondary);
    padding: 0 4px;
}
.tut-close:hover { color: var(--text-color); }
.tut-body { flex: 1; overflow-y: auto; padding: 18px 22px 24px; }

.tut-lede { margin: 0 0 16px; font-size: 14px; color: var(--text-secondary); line-height: 1.5; }
.tut-cat { margin-bottom: 20px; }
.tut-cat-title {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--text-secondary);
    margin: 0 0 8px;
}
.tut-grid { display: flex; flex-direction: column; gap: 10px; }
.tut-card {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    text-align: left;
    padding: 14px 16px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-color);
    color: var(--text-color);
    cursor: pointer;
    font: inherit;
    transition: border-color .12s, transform .06s;
}
.tut-card:hover { border-color: var(--accent-color); transform: translateY(-1px); }
.tut-card-emoji { font-size: 28px; line-height: 1; }
.tut-card-tx { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.tut-card-title { font-weight: 600; font-size: 15px; }
.tut-card-tag { font-size: 12.5px; color: var(--text-secondary); line-height: 1.4; }
.tut-card-meta { font-size: 11.5px; color: var(--text-secondary); opacity: .8; margin-top: 2px; }
.tut-card-chev { font-size: 22px; color: var(--text-secondary); }

.tut-intro { font-size: 14px; line-height: 1.6; margin: 14px 0 18px; }
.tut-intro code, .tut-step-body code {
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 1px 5px;
    font-size: 12.5px;
}
.tut-figure {
    margin: 0 0 18px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    overflow: hidden;
    background: var(--bg-color);
}
.tut-figure img { display: block; width: 100%; height: auto; }

/* Tablet + phone showcase — every tutorial shows the feature on smaller screens. */
.tut-responsive { margin: 4px 0 22px; }
.tut-responsive h3 { margin: 0 0 4px; font-size: 15px; font-weight: 600; }
.tut-responsive-lede { margin: 0 0 14px; font-size: 13.5px; line-height: 1.6; color: var(--text-secondary); }
.tut-responsive-grid {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: center;
    gap: 22px;
}
.tut-device { margin: 0; text-align: center; }
.tut-device figcaption {
    margin-top: 8px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-secondary);
}
.tut-device-shot {
    border: 1px solid var(--border-color);
    border-radius: 14px;
    overflow: hidden;
    background: var(--bg-color);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.22);
}
.tut-device-shot img { display: block; width: 100%; height: auto; }
.tut-device-tablet { flex: 0 1 300px; max-width: 320px; }
.tut-device-mobile { flex: 0 1 170px; max-width: 190px; }
@media (max-width: 560px) {
    .tut-responsive-grid { gap: 16px; }
    .tut-device-tablet { flex-basis: 220px; }
    .tut-device-mobile { flex-basis: 130px; }
}

.tut-steps { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.tut-step { margin: 0 0 22px; }
.tut-step-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.tut-step-n {
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--accent-color);
    color: #0e1420;
    font-weight: 700;
    font-size: 13px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.tut-step-head h3 { margin: 0; font-size: 15px; font-weight: 600; }
.tut-step-body { font-size: 14px; line-height: 1.6; color: var(--text-color); }
.tut-step-body ul { margin: 8px 0; padding-left: 20px; }
.tut-step-body li { margin: 3px 0; }
.tut-step-body .tut-figure { margin-top: 12px; }
.tut-step .tut-figure { margin-top: 12px; margin-bottom: 0; }

.tut-kbd {
    display: inline-block;
    min-width: 18px;
    padding: 1px 6px;
    border: 1px solid var(--border-color);
    border-bottom-width: 2px;
    border-radius: 5px;
    background: var(--bg-color);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 12px;
    text-align: center;
    line-height: 1.5;
}

.tut-checklist {
    margin-top: 8px;
    padding: 14px 16px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-color);
}
.tut-checklist h3 { margin: 0 0 8px; font-size: 14px; }
.tut-checklist ul { margin: 0; padding-left: 20px; }
.tut-checklist li { font-size: 13.5px; line-height: 1.6; color: var(--text-secondary); }
.tut-detail-foot { margin-top: 20px; }
.tut-back-btn {
    background: none;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    color: var(--accent-color);
    font: inherit;
    font-size: 13px;
    padding: 8px 14px;
    cursor: pointer;
}
.tut-back-btn:hover { border-color: var(--accent-color); background: var(--panel-bg); }

@media (max-width: 600px) {
    .tut-backdrop { padding: 0; }
    .tut-modal { max-height: 100vh; height: 100%; width: 100%; border-radius: 0; }
    .tut-body { padding: 14px 16px 20px; }
}

/* Modal reuses .mermaid-modal-backdrop / .mermaid-modal structure */
.support-backdrop.visible { display: flex; }
.support-modal { width: min(560px, 96vw); }
.support-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-color);
    margin-top: 6px;
}
.support-req { color: #dc2626; }
.support-opt { font-weight: 400; color: var(--text-secondary); font-size: 12px; }
.support-input,
.support-textarea {
    width: 100%;
    border: 1px solid var(--border-color, #e5e7eb);
    border-radius: 6px;
    padding: 9px 11px;
    font: inherit;
    font-size: 14px;
    background: var(--input-bg, #fff);
    color: var(--text-color, #111);
    box-sizing: border-box;
}
.support-textarea { min-height: 120px; resize: vertical; line-height: 1.5; }
.support-input:focus,
.support-textarea:focus { outline: none; border-color: var(--accent-color); box-shadow: 0 0 0 2px rgba(37,99,235,.15); }

.support-drop { border: 1px dashed var(--border-color); border-radius: 8px; padding: 10px 12px; }
.support-filelist { display: flex; flex-direction: column; gap: 5px; margin-top: 8px; }
.support-file {
    display: flex; align-items: center; gap: 8px;
    background: var(--tool-hover); border-radius: 6px; padding: 5px 8px; font-size: 13px;
}
.support-file-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.support-file-size { color: var(--text-secondary); font-size: 12px; }
.support-file-x {
    border: 0; background: none; color: var(--text-secondary); cursor: pointer;
    font-size: 16px; line-height: 1; padding: 0 4px; border-radius: 4px;
}
.support-file-x:hover { background: var(--notice-danger-bg); color: var(--notice-danger-text); }
.support-file-total { font-size: 12px; color: var(--text-secondary); text-align: right; }

.support-captcha {
    display: flex; flex-direction: column; gap: 8px;
    font-size: 13px; color: var(--text-secondary);
    background: var(--tool-hover); border-radius: 6px; padding: 10px;
}
.support-captcha-row { display: flex; align-items: center; gap: 10px; }
.support-captcha-img {
    width: 200px; height: 70px; flex: none;
    border-radius: 6px; overflow: hidden; background: #0b0d12;
    display: flex; align-items: center; justify-content: center;
}
.support-captcha-img svg { display: block; width: 200px; height: 70px; }
.support-captcha-loading { color: #8b93a7; font-size: 12px; }
.support-captcha-refresh {
    border: 1px solid var(--border-color); background: var(--panel-bg); color: var(--text-secondary);
    cursor: pointer; font-size: 18px; line-height: 1; width: 36px; height: 36px;
    border-radius: 6px; flex: none;
}
.support-captcha-refresh:hover { background: var(--tool-hover); color: var(--text-color); }
.support-captcha-input { letter-spacing: .18em; text-transform: uppercase; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.support-captcha-state { display: flex; align-items: center; gap: 8px; }
.support-captcha-dot {
    width: 9px; height: 9px; border-radius: 50%; background: #9ca3af; flex: none;
}
.support-captcha-dot.pending { background: #f59e0b; animation: support-pulse 1s ease-in-out infinite; }
.support-captcha-dot.ok { background: #16a34a; }
.support-captcha-dot.err { background: #dc2626; }
@keyframes support-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

.support-status { font-size: 13px; min-height: 18px; }
.support-status.err { color: #dc2626; }
.support-status.warn { color: var(--notice-warn-text); }
.support-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }
.support-submit { background: var(--btn-primary-bg); color: var(--btn-primary-text); border-color: var(--btn-primary-bg); }
.support-submit:hover { background: var(--btn-primary-hover); }
.support-submit:disabled { opacity: .6; cursor: default; }

.support-success { text-align: center; padding: 8px 4px; }
.support-success-icon {
    width: 46px; height: 46px; border-radius: 50%; margin: 0 auto 10px;
    background: var(--notice-ok-bg); color: var(--notice-ok-text); font-size: 26px; line-height: 46px;
}
.support-success h3 { margin: 0 0 6px; }
.support-ref { color: var(--accent-color); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.support-save-warn {
    font-size: 13px; color: var(--notice-warn-text); background: var(--notice-warn-bg);
    border: 1px solid var(--notice-warn-border); border-radius: 6px; padding: 9px 12px; margin: 12px 0 8px;
}
.support-linkrow { display: flex; gap: 8px; }
.support-linkrow .support-input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* ---- Shape info slide-out: descriptions + comment threads ---- */
.shape-info-panel {
    position: fixed;
    top: 48px;
    right: 0;
    bottom: 0;
    width: 340px;
    background: var(--panel-bg);
    border-left: 1px solid var(--border-color);
    box-shadow: -4px 0 20px rgba(0,0,0,0.12);
    z-index: 350;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transform: translateX(100%);
    transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.shape-info-panel.open { transform: translateX(0); }

.shape-info-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-color);
    flex-shrink: 0;
}
.shape-info-title { font-weight: 600; font-size: 14px; color: var(--text-color); }
.shape-info-close {
    border: none; background: transparent; cursor: pointer;
    font-size: 15px; line-height: 1; color: var(--text-color);
    padding: 4px 6px; border-radius: 6px;
}
.shape-info-close:hover { background: var(--tool-hover); }

.shape-info-body {
    flex: 1;
    overflow-y: auto;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Editor + composer shared bits */
.si-textarea {
    width: 100%;
    box-sizing: border-box;
    min-height: 96px;
    resize: vertical;
    font: inherit;
    font-size: 13px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-color);
    color: var(--text-color);
}
.si-hint { font-size: 11px; color: var(--text-secondary); }
.si-preview-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.04em; }
.si-preview { background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 8px; padding: 8px 10px; min-height: 24px; }
.si-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.si-actions .btn { flex: 1; }
.si-primary { background: var(--accent-color); color: #fff; border-color: var(--accent-color); }
.si-primary:hover { filter: brightness(1.05); }
.si-danger { color: #dc2626; }
.si-resolve { color: var(--notice-ok-text); }
.si-empty { font-size: 13px; color: var(--text-secondary); padding: 8px 0; }

/* Comment thread */
.si-thread { display: flex; flex-direction: column; gap: 10px; max-height: 55vh; overflow-y: auto; }
.si-msg { border: 1px solid var(--border-color); border-radius: 8px; padding: 8px 10px; background: var(--panel-bg); }
.si-msg-topic { border-left: 3px solid var(--accent-color); }
.si-msg-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.si-msg-author { font-weight: 600; font-size: 12px; color: var(--text-color); }
.si-msg-time { font-size: 11px; color: var(--text-secondary); }
.si-msg-del { margin-left: auto; border: none; background: transparent; cursor: pointer; color: var(--text-secondary); font-size: 12px; padding: 2px 4px; border-radius: 4px; }
.si-msg-del:hover { background: var(--tool-hover); color: #dc2626; }
.si-composer { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--border-color); padding-top: 10px; }

/* Sanitized markdown rendering */
.md-body { font-size: 13px; line-height: 1.5; color: var(--text-color); word-break: break-word; }
.md-body > *:first-child { margin-top: 0; }
.md-body > *:last-child { margin-bottom: 0; }
.md-body h1, .md-body h2, .md-body h3, .md-body h4, .md-body h5, .md-body h6 { margin: 10px 0 6px; line-height: 1.25; }
.md-body h1 { font-size: 18px; } .md-body h2 { font-size: 16px; } .md-body h3 { font-size: 14px; }
.md-body h4, .md-body h5, .md-body h6 { font-size: 13px; }
.md-body p { margin: 6px 0; }
.md-body ul, .md-body ol { margin: 6px 0; padding-left: 22px; }
.md-body li { margin: 2px 0; }
.md-body a { color: var(--accent-color); text-decoration: underline; }
.md-body code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; background: var(--bg-color); padding: 1px 4px; border-radius: 4px; }
.md-body pre { background: var(--bg-color); border: 1px solid var(--border-color); border-radius: 8px; padding: 8px 10px; overflow-x: auto; }
.md-body pre code { background: none; padding: 0; }
.md-body blockquote { margin: 6px 0; padding: 2px 12px; border-left: 3px solid var(--border-color); color: var(--text-secondary); }
.md-body hr { border: none; border-top: 1px solid var(--border-color); margin: 10px 0; }

@media (max-width: 600px), (pointer: coarse) and (max-width: 1366px) {
    .shape-info-panel { top: 0; width: 100%; z-index: 600; border-left: none; }
    .si-thread { max-height: 48vh; }
}

/* ---- Quick-create glyphs (js/quick-create.js) ----
   A "+" button floats on each side of the single selected shape; tapping one
   opens a picker of the five most recently used shapes and creates the chosen
   shape connected in that direction. */
#quickCreateLayer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 60;
}

.qc-glyph {
    position: absolute;
    width: 22px;
    height: 22px;
    margin: -11px 0 0 -11px;
    border-radius: 50%;
    border: none;
    padding: 0;
    background: var(--accent-color);
    color: #fff;
    font-size: 15px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    opacity: 0.85;
    transition: transform 0.12s ease, opacity 0.12s ease;
}

.qc-glyph:hover {
    transform: scale(1.18);
    opacity: 1;
}

/* Contextual Action HUD (js/action-hud.js): a floating toolbar of primary actions above the selection
   (desktop). Overlay layer is click-through; only the bar + its buttons take pointer input. */
#actionHudLayer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 70;   /* above the quick-create "+" glyphs (60) */
}
.action-hud {
    position: absolute;
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.4);
    pointer-events: auto;
}
.action-hud-btn {
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: 7px;
    background: none;
    color: var(--text-color);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}
.action-hud-btn:hover { background: var(--tool-hover); }
.action-hud-btn:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--focus-ring); }
.action-hud-more { color: var(--accent-color); font-weight: 700; }
.action-hud-btn--danger { color: var(--notice-danger-text); }
.action-hud-btn--danger:hover { background: var(--notice-danger-bg); }
.action-hud-sep {
    width: 1px;
    height: 20px;
    background: var(--border-color);
    margin: 0 3px;
}

/* Radial marking menu (js/radial-menu.js): wedges fan around the cursor on right-click / long-press.
   Full-viewport click-through layer; only the wedges + centre take input (positioned at their CENTRES,
   so translate(-50%,-50%) anchors them). */
.radial-layer {
    position: fixed;
    inset: 0;
    z-index: 1450;
    pointer-events: none;
}
.radial-menu { position: absolute; inset: 0; }
.radial-centre,
.radial-wedge {
    position: absolute;
    transform: translate(-50%, -50%);
    pointer-events: auto;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    color: var(--text-color);
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.45);
    cursor: pointer;
}
.radial-centre {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border-color: var(--accent-color);
    color: var(--accent-color);
    font-size: 18px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}
.radial-wedge {
    width: 70px;
    height: 70px;
    border-radius: 14px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 4px;
}
.radial-wedge .radial-ic { font-size: 18px; line-height: 1; }
.radial-wedge .radial-label {
    font-size: 10px;
    line-height: 1.1;
    text-align: center;
    color: var(--text-secondary);
    max-width: 62px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.radial-wedge:hover,
.radial-wedge:focus-visible,
.radial-wedge--hot {
    background: var(--accent-color);
    border-color: var(--accent-color);
    color: var(--btn-primary-text);
    outline: none;
}
.radial-wedge:hover .radial-label,
.radial-wedge:focus-visible .radial-label,
.radial-wedge--hot .radial-label { color: var(--btn-primary-text); }
.radial-wedge--danger { color: var(--notice-danger-text); }
.radial-wedge--danger.radial-wedge--hot,
.radial-wedge--danger:hover { background: var(--notice-danger-bg); border-color: var(--notice-danger-border); }

/* Spin-out flourish (js/radial-menu.js): wedges fan out around the ring on open, the sweep starting
   slow, accelerating, then easing out as the circle is completed — landing in 1.5s. Each wedge pops
   with a centre-preserving scale+rotate (transform-origin is the wedge centre, kept fixed by the
   leading translate(-50%,-50%)), so the *final* geometry equals the static layout; only arrival time
   animates. JS sets each wedge's animation-delay along an ease-in-out-inverse so the reveal sweeps
   the ring. `backwards` fill holds the hidden start state through the delay (no pre-animation flash). */
@keyframes radial-wedge-spin-in {
    from { opacity: 0; transform: translate(-50%, -50%) scale(0.25) rotate(-150deg); }
    55%  { opacity: 1; }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
}
@keyframes radial-centre-pop-in {
    from { opacity: 0; transform: translate(-50%, -50%) scale(0.2); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
.radial-menu--anim .radial-wedge {
    animation: radial-wedge-spin-in 360ms cubic-bezier(0.18, 0.7, 0.28, 1) backwards;
}
.radial-menu--anim .radial-centre {
    animation: radial-centre-pop-in 260ms cubic-bezier(0.18, 0.7, 0.28, 1) backwards;
}
@media (prefers-reduced-motion: reduce) {
    .radial-menu--anim .radial-wedge,
    .radial-menu--anim .radial-centre { animation: none; }
}

.qc-picker {
    position: absolute;
    display: flex;
    gap: 4px;
    padding: 6px;
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
    pointer-events: auto;
}

.qc-picker .tool-btn {
    margin: 0;
}

/* Roadmap glyph overlay — same overlay contract as quick-create (buttons are the only hit areas). */
#roadmapGlyphLayer,
#orgFamilyGlyphLayer {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 60;
}

/* The "+ Phase" pill: anchored to the right of the last column, vertically centred on its point. */
.rm-phase-glyph {
    position: absolute;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 11px;
    border: none;
    border-radius: 999px;
    background: var(--accent-color);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    pointer-events: auto;
    cursor: pointer;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
    opacity: 0.9;
    transition: transform 0.12s ease, opacity 0.12s ease;
}
.rm-phase-glyph:hover {
    transform: translateY(-50%) scale(1.06);
    opacity: 1;
}

/* Bigger touch targets on touch devices */
@media (pointer: coarse) {
    .qc-glyph {
        width: 30px;
        height: 30px;
        margin: -15px 0 0 -15px;
        font-size: 19px;
    }
    .rm-phase-glyph {
        padding: 8px 14px;
        font-size: 13px;
    }
}

/* ---- Frequent-shapes row (one-tap placement) ---- */
/* A MOBILE/tablet affordance: when the tool palette is a bottom drawer, this row of recents sits
   just under the handle so a shape is one tap away, and hides with the toolbar. Hidden on desktop
   (the full palette is always docked there, so recents would only add clutter and push the
   Navigate tools down). The mobile single-row-scroll styling lives in the mobile media block. */
.frequent-shapes {
    display: none;
    flex-wrap: nowrap;
    gap: 4px;
    width: 100%;
    flex-shrink: 0;
}
.frequent-shape-btn {
    flex: 0 0 auto;
    margin: 0;
    width: 40px;
    height: 40px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    transition: background 0.15s ease;
}
.frequent-shape-btn:hover { background: var(--tool-hover); color: var(--text-color); }
.frequent-shape-btn svg { width: 22px; height: 22px; }

/* ---- Expiring view-only links (share panel) + viewer banner + provenance ---- */
.view-link-block {
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
}
.view-link-contact {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-secondary);
    cursor: pointer;
}
.view-link-contact input { margin-top: 1px; }
.view-link-list { margin-top: 6px; display: flex; flex-direction: column; gap: 4px; }
.view-link-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 5px 8px;
    border: 1px solid var(--border-color);
    border-radius: 5px;
    background: var(--bg-color);
    font-size: 11px;
    color: var(--text-color);
}
.view-link-row-info { min-width: 0; }
.view-link-row-access { color: var(--text-secondary); margin-top: 1px; }
.view-link-state--off {
    color: var(--text-secondary);
    font-style: italic;
}
.view-link-revoke { font-size: 11px; padding: 2px 8px; color: #dc2626; flex-shrink: 0; }

/* Persistent (dismissible) "Shared by … / Link expires …" chip for view-link visitors,
   anchored near the top of the canvas next to the collab indicator. */
.viewer-info-banner {
    position: fixed;
    top: 52px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 900;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--panel-bg);
    color: var(--text-secondary);
    font-size: 12px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}
.viewer-info-banner a { color: var(--accent-color); text-decoration: none; }
.viewer-info-banner a:hover { text-decoration: underline; }
.viewer-info-dismiss {
    background: none;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 12px;
    padding: 0 2px;
    line-height: 1;
}
.viewer-info-dismiss:hover { color: var(--text-color); }

/* Diagrams-Room "🟢 Live editing" band (js/workspace-live.js #wsLiveBanner) — a
   collapse toggle shrinks the full message + Leave button down to a single live-dot
   pill pinned to the right, which the user taps to expand the message and reach Leave
   again. Keeps the long status band from dominating the (already cramped) mobile canvas. */
.live-banner-toggle {
    flex: 0 0 auto;
    background: none;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 4px 6px;
    border-radius: 6px;
}
.live-banner-toggle:hover { color: var(--text-color); background: var(--tool-hover); }
.live-banner-toggle:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* Collapsed: the band becomes a compact right-anchored pill showing only the toggle.
   ID + class specificity (1,1,0) beats the mobile `body .viewer-info-banner` docked
   rule, so this wins on both desktop (top-anchored) and the mobile docked strip. The
   collapsed band KEEPS reserving its docked-strip row (has-viewer-banner stays set), so
   the undo/redo cluster and toast stack above the pill rather than dropping onto it. */
#wsLiveBanner.live-collapsed {
    left: auto;
    right: max(8px, env(safe-area-inset-right));
    width: auto;
    max-width: none;
    transform: none;
    gap: 0;
    padding: 2px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
}
#wsLiveBanner.live-collapsed .live-banner-msg,
#wsLiveBanner.live-collapsed #wsLiveLeave { display: none; }
#wsLiveBanner.live-collapsed .live-banner-toggle { font-size: 16px; padding: 6px 8px; }

/* Per-diagram provenance details (the ⓘ toggle in the Account panel's document list). */
.diagram-info-btn--active { border-color: var(--accent-color); color: var(--accent-color); }
.diagram-list-item-details {
    border-top: 1px solid var(--border-color);
    padding-top: 6px;
    font-size: 11px;
    color: var(--text-secondary);
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.diagram-detail-row { display: flex; justify-content: space-between; gap: 8px; }
.diagram-detail-label { color: var(--text-secondary); opacity: 0.8; flex-shrink: 0; }

/* Monthly AI-chat quota note in the AI assistant panel */
.ai-quota-note {
    font-size: 11px;
    color: var(--text-secondary);
    padding: 4px 10px;
    margin: 0 0 4px;
    border-bottom: 1px solid var(--border-color);
}
.ai-quota-note.ai-quota-low { color: #f59e0b; font-weight: 600; }

/* ---- New-shape default colours (Options panel) ---------------------------- */
.options-defaults {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    padding: 6px 14px 4px;
}
.options-default-swatch {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--text-secondary);
    cursor: pointer;
}
.options-default-swatch .color-picker {
    width: 38px;
    height: 30px;
    padding: 2px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    cursor: pointer;
}
.options-defaults .btn {
    margin-left: auto;
    padding: 6px 12px;
}
.options-default-hint {
    padding: 0 14px 8px;
    font-size: 11px;
    color: var(--text-secondary);
    line-height: 1.4;
}

/* ---- Mind map colours blade: one swatch row per level --------------------- */
.mind-colors-rows {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 6px 14px;
}
.mind-color-row {
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
}
.mind-color-row .color-picker {
    width: 44px;
    height: 30px;
    padding: 2px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--panel-bg);
    cursor: pointer;
    flex: none;
}
.mind-color-name {
    font-size: 13px;
    color: var(--text-primary);
}
#mindColorsReset { margin: 4px 14px 8px; }

/* ---- Handwriting → label suggestion chip ---------------------------------- */
.hw-chip {
    position: fixed;
    z-index: 1200;
    width: 264px;
    max-width: calc(100vw - 24px);
    background: var(--panel-bg);
    border: 1px solid var(--accent-color);
    border-radius: 12px;
    padding: 12px 14px;
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.4);
    font-size: 13px;
    color: var(--text-color);
    animation: hw-chip-in 0.14s ease-out;
}
@keyframes hw-chip-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.hw-chip-eyebrow {
    font-size: 11px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    font-weight: 700;
    color: var(--accent-color);
}
.hw-chip-read {
    margin: 8px 0 12px;
    line-height: 1.4;
}
.hw-chip-read b { font-weight: 600; }
.hw-chip-row {
    display: flex;
    gap: 8px;
}
.hw-chip-row .btn {
    flex: 1;
    justify-content: center;
}
.hw-chip-alt {
    margin-top: 10px;
    font-size: 11px;
    color: var(--text-secondary);
}

/* ---- Managed PNG embed links (js/embed-share.js) ---------------------------- */
.embed-links-panel { font-size: 12px; }
.embed-warning {
    margin: 0 0 8px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-left: 3px solid #d97706;            /* amber: "read this" */
    border-radius: 6px;
    background: var(--accent-soft, rgba(217, 119, 6, 0.08));
    line-height: 1.45;
}
.embed-list { display: flex; flex-direction: column; gap: 8px; }
.embed-row {
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 8px 10px;
    background: var(--panel-bg);
}
.embed-row-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.embed-row-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 2px; }
.embed-row-meta { font-size: 11px; color: var(--text-secondary); }
.embed-badge {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px;
    border: 1px solid currentColor; border-radius: 999px; padding: 1px 8px;
}
.embed-act { font-size: 11px; padding: 3px 8px; }
.embed-act:disabled { opacity: 0.5; cursor: default; }
.embed-url { background: var(--tool-hover); }

/* ---- Share & collaborate blade sections (js/blades.js Share blade) ---------- */
.share-section { padding: 4px 0 14px; border-bottom: 1px solid var(--border-color); margin-bottom: 14px; }
.share-section:last-child { border-bottom: none; margin-bottom: 0; }
.share-section-h { font-size: 13px; font-weight: 700; color: var(--text-color); margin: 2px 0 8px; }
/* Accordion: each section is a native <details>; the header is its <summary>. Collapsed by
   default on every device (closed in markup) so the blade opens as a tidy list of section
   headers instead of one long scroll — the user expands the section they want. */
details.share-section > summary.share-section-h {
    cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between;
    user-select: none; padding: 2px 0;
}
details.share-section > summary.share-section-h::-webkit-details-marker { display: none; }
details.share-section > summary.share-section-h::after {
    content: '\2304'; font-weight: 400; color: var(--text-secondary); transition: transform 0.15s ease;
}
details.share-section[open] > summary.share-section-h::after { transform: rotate(180deg); }
/* Comfortable touch targets for the per-link action buttons. */
.embed-act { min-height: 34px; }
@media (max-width: 700px) { .embed-act, .embed-links-panel .btn { min-height: 40px; } }

/* Managing share links is a deliberate, text-heavy task — on tablet/desktop give the Share blade
   real room instead of the phone-width rail (URLs were truncated and Renew/Rotate/Revoke crammed
   onto one line). Only the ACTIVE Share blade widens; the slim parent breadcrumb strip is unaffected,
   and we never exceed the rail's viewport cap. Mobile keeps the full-width rail (no change). */
@media (min-width: 768px) {
    .options-panel.blade-rail .blade[data-blade="share"].blade--active {
        width: min(560px, calc(96vw - 80px));
        flex: 0 0 min(560px, calc(96vw - 80px));
    }
}

/* Bulk PNG export progress bar (Menu ▸ File ▸ My Diagrams ▸ ⬇ PNG) */
.bulk-progress {
    height: 6px;
    background: var(--border-color);
    border-radius: 3px;
    overflow: hidden;
    margin: 6px 0;
}
.bulk-progress-fill {
    height: 100%;
    width: 0%;
    background: var(--accent-color);
    border-radius: 3px;
    transition: width 0.15s ease;
}

/* ---- Plans & pricing blade (Options panel) ---------------------------------- */
.plans-banner {
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--text-color);
    background: var(--bg-color);
    border: 1px solid var(--accent-color);
    border-radius: 8px;
    padding: 10px 12px;
    margin-bottom: 12px;
}
.plan-card {
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 12px;
    margin-bottom: 10px;
    background: var(--panel-bg);
}
.plan-card--team { border-color: var(--accent-color); }
.plan-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 2px;
}
.plan-name  { font-size: 16px; font-weight: 700; color: var(--text-color); }
.plan-price { font-size: 11.5px; font-weight: 600; color: var(--accent-color); text-align: right; }
.plan-tag   { margin: 0 0 8px; font-size: 12px; color: var(--text-secondary); }
.plan-feats { list-style: none; margin: 0 0 10px; padding: 0; }
.plan-feats li {
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-color);
    padding-left: 18px;
    position: relative;
}
.plan-feats li::before { content: "✓"; position: absolute; left: 0; color: var(--accent-color); font-weight: 700; }
.plan-feats li.plan-feat--off { color: var(--text-secondary); }
.plan-feats li.plan-feat--off::before { content: "—"; color: var(--text-secondary); font-weight: 400; }
.plan-cta { width: 100%; }
.plan-refer-note {
    font-size: 12px;
    line-height: 1.45;
    color: var(--text-secondary);
    margin: 14px 0 10px;
    padding: 10px 12px;
    border: 1px dashed var(--border-color);
    border-radius: 8px;
}

/* ---- Premium-code request mode (support modal) ------------------------------ */
.support-plan-pick { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.support-plan-pick label {
    font-size: 12.5px;
    color: var(--text-color);
    display: flex;
    gap: 8px;
    align-items: flex-start;
    line-height: 1.4;
    cursor: pointer;
}
.support-plan-pick input { margin-top: 2px; }

/* ---- Referral invites block (Account panel) --------------------------------- */
.referral-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.referral-row {
    display: flex;
    align-items: center;
    gap: 8px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 6px 8px;
}
.referral-code {
    font-family: monospace;
    font-size: 12px;
    color: var(--text-color);
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.referral-meta { flex: 0 0 auto; }
.referral-act  { flex: 0 0 auto; }
.referral-status { font-size: 11px; color: var(--text-secondary); white-space: nowrap; }
.referral-status--done { color: var(--accent-color); }
.referral-status--exp  { color: var(--text-secondary); text-decoration: line-through; }
.referral-copy { font-size: 11px; padding: 4px 8px; }

/* Phone: the Account / settings drawer must be a full-width sheet. The base
   `.settings-panel` width (300px) is declared late in this file and overrode the
   earlier mobile blocks, leaving a dead canvas strip on narrow screens (UX audit
   L3). This end-of-file rule wins by source order; tablets keep their own width. */
@media (max-width: 600px) {
    .settings-panel { width: 100%; }
}

/* Read-only access-code viewer (#/cv/…, js/code-share.js): hide editing chrome so the page
   reads as a viewer, not an editor. The read-only edit gates already block mutation; this just
   removes the affordances that imply drawing. Cleared when the viewer leaves (full reload). */
body.qd-cv-viewing .sidebar,
body.qd-cv-viewing .zoom-controls,
body.qd-cv-viewing #emptyCanvasHint { display: none !important; }

/* ── Tablet: dock the shape Properties panel as a right-side rail (UX audit H3) ──
   Phones keep the bottom-sheet (scarce canvas); tablets have room, so revert the
   panel from the fixed bottom-sheet to a docked flex column. As a flex sibling of
   the canvas it reflows the canvas exactly like the desktop panel does — the canvas
   overflows-clipped behind it, no resize wiring needed (desktop works the same way).
   The inner single-blade-block layout from the mobile rules is kept; only the outer
   positioning changes. Placed last so it wins over the mobile sheet's !important.
   The query (incl. the min-aspect-ratio tablet guard that excludes "Request Desktop
   Site" phones) is shared verbatim with TABLET_MEDIA_QUERY in js/responsive.js. */
@media (pointer: coarse) and (min-width: 760px) and (max-width: 1366px) and (min-aspect-ratio: 3 / 5) {
    .properties-panel {
        position: static !important;
        inset: auto !important;
        transform: none !important;
        width: 320px !important;
        max-width: 340px !important;
        min-width: 0 !important;
        max-height: none !important;
        height: auto !important;
        flex-shrink: 0 !important;
        display: none !important;            /* hidden until .visible frees its flex space */
        border-left: 1px solid var(--border-color) !important;
        border-top: none !important;
        border-radius: 0 !important;
        box-shadow: none !important;
        z-index: 50 !important;
        padding: 0 !important;
        overflow-y: auto !important;
        pointer-events: auto !important;
        transition: none !important;
    }
    .properties-panel.visible { display: block !important; }
    /* #connectorPanel carries an ID-level `display:flex !important` (its internal
       column layout) that beats the class rule above, so when NOT selected it would
       keep taking flex space. Hide it at ID specificity until it's the active panel. */
    #connectorPanel:not(.visible) { display: none !important; }
    .properties-panel.blade-rail.visible:not(.minimized) {
        display: block !important;           /* one blade at a time, but docked not sheeted */
        width: 320px !important;
        padding: 0 !important;
    }
    /* No bottom-sheet drag handle or gesture states on the docked rail. */
    .properties-panel::before { display: none !important; }
    .properties-panel.sheet-collapsed,
    .properties-panel.sheet-expanded,
    .properties-panel.sheet-dragging {
        max-height: none !important;
        height: auto !important;
    }
    /* The fixed zoom cluster (bottom-right) must clear the docked rail AND stay
       visible: the phone rule hides it (opacity:0 / pointer-events:none) because the
       bottom-sheet covers it, but the rail is on the right so the cluster — incl. the
       undo/redo buttons — stays usable. Shift it left of the rail and un-hide it. */
    body.has-open-prop-panel .zoom-controls {
        right: calc(332px + env(safe-area-inset-right, 0px)) !important;
        opacity: 1 !important;
        pointer-events: auto !important;
    }
    /* The open tools drawer is a half-height sheet that scrolls (the palette is taller than it),
       but the phone rule hides the scrollbar — on the bigger tablet screen that left users unsure
       it scrolled at all. Show a thin scrollbar on the open drawer so the affordance is visible. */
    .sidebar.open { scrollbar-width: thin; }
    .sidebar.open::-webkit-scrollbar { display: block; width: 8px; }
    .sidebar.open::-webkit-scrollbar-thumb { background: var(--border-color); border-radius: 4px; }

    /* #2 — tablet row-rail: restore the desktop multi-column Menu rail on a tablet so navigating into
       a child collapses each parent to a slim 40px breadcrumb strip (the shared phone rule makes the
       rail a single full-width blade and hides the strips). The rail sizes to its row, capped at the
       viewport (96vw); the active blade keeps the 272px width — or the wider Share override above —
       and Esc / tap-outside / the per-blade × still close it. Menu rail only (not the docked
       Properties rail, handled above). */
    .options-panel.blade-rail { width: auto; max-width: 96vw; }
    .options-panel.blade-rail .blade { width: var(--blade-w, 272px); flex: 0 0 var(--blade-w, 272px); }
    .options-panel.blade-rail .blade--strip { display: flex; width: 40px; flex: 0 0 40px; }
}

/* --- Omni-search floating dock (the petal→pill morph target) ---------------------------------
   The radial's Search wedge reparents the REAL #omniSearch into this fixed wrap at the wheel's
   centre — same element, same dropdown; restored to the header on Escape / outside press / resize
   / after a command runs (js/omni-search.js _dockAt/_undock). */
.omni-float {
    position: fixed;
    z-index: 1500;                      /* above the radial layer (1450) it morphs out of */
    animation: omni-float-pop 150ms ease-out;
}
.omni-float .omni-search {
    max-width: none;
    min-width: 0;
    margin: 0;
    width: 100%;
}
.omni-float .omni-search-input {
    padding: 10px 12px 10px 34px;
    font-size: 14px;
    border-radius: 12px;
    border-color: var(--accent-color);
    box-shadow: 0 14px 44px rgba(0, 0, 0, 0.45), 0 0 0 4px rgba(110, 168, 255, 0.14);
}
@keyframes omni-float-pop {
    from { opacity: 0; transform: scale(0.88); }
}

/* Petal collapse — the wheel doesn't vanish when Search fires, it transforms: wedges shrink and
   fade toward the centre for 150ms while the pill pops in (RadialMenu.close({soft:true})). The
   layer is inert during the out-animation. */
.radial-layer--out * { pointer-events: none !important; }
.radial-layer--out .radial-wedge,
.radial-layer--out .radial-centre {
    /* !important delay: wedges carry an inline spin-out animation-delay (JS-staggered); the
       collapse must start NOW for every wedge, not replay that stagger. */
    animation: radial-wedge-collapse 150ms ease-in forwards !important;
    animation-delay: 0ms !important;
}
@keyframes radial-wedge-collapse {
    to { opacity: 0; transform: translate(-50%, -50%) scale(0.12); }
}
@media (prefers-reduced-motion: reduce) {
    .omni-float { animation: none; }
    .radial-layer--out .radial-wedge,
    .radial-layer--out .radial-centre { animation: none; display: none; }
}

/* --- Radial delight layer --------------------------------------------------------------------- */
/* Radar sweep: one scanner beam circles the ring in step with the 1.5s spin-out reveal, then
   fades. Sits UNDER the wedges (first child) and never intercepts input. */
.radial-sweep {
    position: absolute;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    pointer-events: none;
    background: conic-gradient(from 0deg,
        rgba(110, 168, 255, 0.14) 0deg,
        rgba(110, 168, 255, 0.05) 26deg,
        transparent 48deg);
    animation: radial-sweep-turn 1.5s ease-in-out forwards;
    opacity: 0;
}
@keyframes radial-sweep-turn {
    0%   { opacity: 0.9; transform: translate(-50%, -50%) rotate(0deg); }
    85%  { opacity: 0.5; }
    100% { opacity: 0;   transform: translate(-50%, -50%) rotate(360deg); }
}

/* Wedge whisper: the shortcut chip under the centre — the wheel teaching the faster path. */
.radial-whisper {
    position: absolute;
    transform: translate(-50%, 0);
    background: var(--panel-bg);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 3px 10px;
    font-size: 11px;
    color: var(--text-secondary);
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.45);
    opacity: 0;
    transition: opacity 120ms ease-out;
    pointer-events: none;
    white-space: nowrap;
}
.radial-whisper--on { opacity: 1; }

/* First-flick cheer: one chip, once ever (localStorage qd_radial_flick_seen). */
.radial-flick-cheer {
    position: fixed;
    transform: translate(-50%, 0);
    z-index: 1600;
    background: var(--panel-bg);
    border: 1px solid var(--accent-color);
    border-radius: 999px;
    padding: 6px 14px;
    font-size: 13px;
    color: var(--text-color);
    box-shadow: 0 14px 44px rgba(0, 0, 0, 0.45), 0 0 0 4px rgba(110, 168, 255, 0.16);
    animation: radial-cheer 1.9s ease-out forwards;
    pointer-events: none;
    white-space: nowrap;
}
@keyframes radial-cheer {
    0%   { opacity: 0; transform: translate(-50%, 10px) scale(0.85); }
    12%  { opacity: 1; transform: translate(-50%, 0) scale(1.04); }
    20%  { transform: translate(-50%, 0) scale(1); }
    80%  { opacity: 1; }
    100% { opacity: 0; transform: translate(-50%, -8px); }
}
/* Comet flick-trail: a full-viewport canvas that sits just UNDER the radial layer (1450), so the
   violet trail reads behind the wedges it chases toward. Painted by radial-menu.js only while a
   touch flick is in flight, then removed. */
.radial-comet {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 1445;
    pointer-events: none;
}
/* The "catch": a violet ring that pops at the wedge the flick lands on (~120ms expand, ~300ms fade).
   Standalone so it outlives the wheel's close() on that same tick. */
.radial-comet-catch {
    position: fixed;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    border-radius: 50%;
    z-index: 1448;
    pointer-events: none;
    border: 2px solid rgba(167, 139, 250, 0.9);
    box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.25);
    animation: radial-comet-catch 300ms ease-out forwards;
}
@keyframes radial-comet-catch {
    0%   { opacity: 0.9; transform: scale(0.4); }
    40%  { opacity: 1;   transform: scale(1.5); }   /* ~120ms in: the pulse peak */
    100% { opacity: 0;   transform: scale(2.4); }
}
@media (prefers-reduced-motion: reduce) {
    .radial-sweep { display: none; }
    .radial-flick-cheer { animation: none; }
    /* Belt-and-braces: radial-menu.js already skips the comet entirely under reduced-motion, but
       hide the overlay + kill the pulse if either ever renders. */
    .radial-comet { display: none; }
    .radial-comet-catch { animation: none; display: none; }
}
