:root {
    /* Tell the UA which scheme is active so NATIVE controls (checkboxes, radios, selects,
       scrollbars, <dialog> canvas) render to match the theme — author CSS can't restyle their
       internals. The dark block flips this to `dark`. Accent unifies the checked/active color
       of those controls with the app accent in both themes. */
    color-scheme: light;
    accent-color: var(--primary-color);

    --bg-app: #ffffff;
    --bg-sidebar: #f4f6fa;
    --bg-list-pane: #f9fbff;
    --bg-editor-pane: #ffffff;
    --bg-pane: #ffffff;
    --border-color: #dfe5ee;
    --pane-divider: #d9e1eb;
    /* Ring marking which pane plain note-list clicks open into (e.g. the focused split screen). */
    --pane-focus-ring: var(--primary-color);
    --primary-color: #007aff; /* Apple-like blue */
    --primary-hover: #0062cc;
    --text-main: #333333;
    --text-muted: #888888;
    --danger-color: #ff3b30;
    --success-color: #15803d;
    --warning-color: #b45309;
    --selection-color: #e5f1ff;
    --item-hover: #eceef1;

    /* Segmented "pill" tab control (the standard for tabbed dialogs — see .app-tabs). Track is a soft
       inset; the active tab is a raised surface pill. Distinct from bg-app/bg-pane (equal in light mode). */
    --tab-track-bg: #eceef1;
    --tab-active-bg: #ffffff;

    /* System design language tokens */
    --radius-sm: 6px;
    --radius-md: 10px;
    --radius-lg: 14px;

    --shadow-sm: 0 3px 10px rgba(15, 25, 40, 0.07);
    --shadow-md: 0 8px 20px rgba(15, 25, 40, 0.12);
    --shadow-lg: 0 18px 50px rgba(15, 25, 40, 0.18);

    /* Text and icons sitting ON an accent / gradient fill. Stays white in both themes on purpose:
       the fill is the same saturated blue in both. */
    --on-accent: #ffffff;
    /* color-mix() endpoints for "darken a bit" / "lighten a bit" recipes, so a slice never needs a
       raw #000 / #fff to shade a token. */
    --mix-dark: #000000;
    --mix-light: #ffffff;

    /* Accent gradient (glass confirm buttons, progress sweeps, active rails). One source for what
       used to be a dozen copies of linear-gradient(135deg, #2f7cff, #00b3ff). */
    --accent-gradient-start: #2f7cff;
    --accent-gradient-end: #00b3ff;
    --accent-gradient: linear-gradient(135deg, var(--accent-gradient-start), var(--accent-gradient-end));
    --accent-gradient-h: linear-gradient(90deg, var(--accent-gradient-start), var(--accent-gradient-end));

    /* Primary tints: theme-safe alpha recipes over the accent (they follow the user's accent preset,
       which a hard-coded rgba(0, 122, 255, x) never did). */
    --primary-alpha-06: color-mix(in srgb, var(--primary-color) 6%, transparent);
    --primary-alpha-10: color-mix(in srgb, var(--primary-color) 10%, transparent);
    --primary-alpha-14: color-mix(in srgb, var(--primary-color) 14%, transparent);
    --primary-alpha-18: color-mix(in srgb, var(--primary-color) 18%, transparent);
    --primary-alpha-25: color-mix(in srgb, var(--primary-color) 25%, transparent);
    --primary-alpha-38: color-mix(in srgb, var(--primary-color) 38%, transparent);

    /* Dark overlay chrome (lightbox, code-block and SVG viewers, tooltips): dark in BOTH themes by
       design — a viewer floating over content does not flip with the page behind it. */
    --overlay-chrome-bg: rgba(35, 40, 48, 0.92);
    --overlay-chrome-bg-strong: rgba(16, 20, 28, 0.98);
    --overlay-chrome-fg: #e2e8f0;
    --overlay-scrim: rgba(8, 12, 18, 0.72);
    --overlay-danger-bg: rgba(134, 33, 33, 0.95);
    --overlay-danger-border: rgba(255, 151, 151, 0.45);
    --tooltip-bg: rgba(20, 28, 42, 0.94);
    --tooltip-fg: #f0f4ff;

    /* Glass dialog family (the .glass-overlay / .glass-dialog system in 180-dialogs-overlays.css).
       The scrim and rim are deliberately dark-on-dark in both themes; the surfaces themselves mix
       --bg-pane toward transparent, so they follow the theme without a dark block here. */
    --glass-overlay-bg: rgba(6, 10, 18, 0.58);
    --glass-surface-blur: 12px;
    --glass-border: rgba(255, 255, 255, 0.22);
    --glass-radius: 20px;
    --glass-shadow: 0 18px 50px rgba(0, 0, 0, 0.40);
    --glass-confirm-blue-start: var(--accent-gradient-start);
    --glass-confirm-blue-end: var(--accent-gradient-end);
    --glass-confirm-orange-start: #ff7a18;
    --glass-confirm-orange-end: #ff3d6e;
    --glass-confirm-red-start: #e8403a;
    --glass-confirm-red-end: #b41818;

    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;

    --anim-fast: 140ms;
    --anim-base: 180ms;
    --anim-ease: cubic-bezier(.2,.8,.2,1);

    --btn-height: 38px;
    --btn-height-compact: 30px;
    --btn-pad-x: 14px;
    --btn-font-size: 0.92rem;

    --icon-size: 17px;
    --icon-stroke: 1.9;
    --fmt-toolbar-icon-size: 18px;
    --fmt-heading-icon-size: 26px;
    --fmt-heading-icon-scale: 1.12;

    /* Editor/content readability tokens */
    --text-editor: #2b3442;
    --text-editor-muted: #6f7f94;
    --text-placeholder: #8d99ab;
    --blockquote-border: #d4dbe7;

    /* Code readability tokens */
    --code-bg: #f5f7fb;
    --code-fg: #1f2937;
    --code-border: #d7dfeb;
    --inline-code-bg: rgba(15, 23, 42, 0.06);
    --inline-code-fg: #1f2937;

    /* Shell and note-list state tokens */
    --note-card-hover-border: #cfd8e5;
    --note-card-hover-shadow: 0 6px 14px rgba(17, 28, 45, 0.08);
    --note-card-active-border: #c7dcfb;
    --note-card-active-shadow: 0 8px 18px rgba(0, 122, 255, 0.14);
    --note-card-selected-shadow: 0 6px 14px rgba(0, 122, 255, 0.11);
    --note-card-time-color: #8d98a8;
    --note-card-meta-icon-color: #9aa6b5;

    --status-pinned-accent: #d2a400;
    --status-pinned-title-accent: #8a6a00;
    --status-pinned-fg: #7a5a00;
    --status-pinned-bg: #fff6da;
    --status-pinned-border: #f7df94;

    --status-live-fg: #0b5d42;
    --status-live-bg: #e8f7ef;
    --status-live-border: #b9e5c8;

    --status-draft-fg: #4f3f8c;
    --status-draft-bg: #f1ebff;
    --status-draft-border: #d7c8ff;

    --status-pending-fg: #7a4a05;
    --status-pending-bg: #fff2dc;
    --status-pending-border: #f1d29b;

    --status-error-fg: #8b1e2d;
    --status-error-bg: #fdecef;
    --status-error-border: #f7c2cb;
    
    --sidebar-width: 260px;
    --list-width: 300px;
    --reference-width: 50%;   /* split screen opens at half the editor pane; a dragged width is stored in px */
    --nav-rail-width: 48px;

    /* UI font stack (body) and the note body's base text, which the global default text Style Set
       may override per note. */
    --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --note-base-size: 14px;
    --note-base-font: var(--font-ui);
}

.tree-selection-status {
    margin: 2px 8px 8px 8px;
    padding: 3px 8px;
    font-size: 0.76rem;
    color: var(--text-muted);
    background: color-mix(in srgb, var(--primary-color) 8%, transparent);
    border: 1px solid var(--primary-alpha-18);
    border-radius: 999px;
    width: fit-content;
    max-width: calc(100% - 16px);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --bg-app: #0f141d;
    --bg-sidebar: #151b25;
    --bg-list-pane: #141b24;
    --bg-editor-pane: #101722;
    --bg-pane: #161f2b;
    --border-color: #2a3547;
    --pane-divider: #273243;
    --text-main: #e7edf7;
    --text-muted: #95a4ba;
    /* Dark counterpart of the light #e5f1ff selection tint (primary blue sunk into the dark
       pane) — without it every selected row/card kept the pale light-mode blue behind light
       text. Fallback only: applyThemeSettings() inlines the accent's selection/selectionDark
       pair on the root, so keep this in sync with ACCENT_PRESETS.blue.selectionDark. */
    --selection-color: #113660;
    --item-hover: #1c2738;

    /* Segmented tab control (dark): recessed track, raised lighter active pill. */
    --tab-track-bg: #0f141d;
    --tab-active-bg: #26313f;

    /* Editor/content readability tokens (dark) */
    --text-editor: #e8eef8;
    --text-editor-muted: #b6c2d4;
    --text-placeholder: #8d9bb0;
    --blockquote-border: #3a4b63;

    /* Code readability tokens (dark) */
    --code-bg: #111a26;
    --code-fg: #e8eef8;
    --code-border: #2e3c52;
    --inline-code-bg: rgba(148, 163, 184, 0.2);
    --inline-code-fg: #eff6ff;

    /* Shell and note-list state tokens (dark) */
    --note-card-hover-border: #3a475d;
    --note-card-hover-shadow: 0 8px 18px rgba(0, 0, 0, 0.22);
    --note-card-active-border: #4d6ea7;
    --note-card-active-shadow: 0 8px 18px rgba(0, 0, 0, 0.34);
    --note-card-selected-shadow: 0 8px 18px rgba(0, 0, 0, 0.3);
    --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.5);
    --note-card-time-color: #8fa0b8;
    --note-card-meta-icon-color: #93a6bf;

    --status-pinned-accent: #f0c24b;
    --status-pinned-title-accent: #f0c24b;
    --status-pinned-fg: #f3d782;
    --status-pinned-bg: #3d3110;
    --status-pinned-border: #7a6221;

    --status-live-fg: #8dd9b3;
    --status-live-bg: #123126;
    --status-live-border: #2f6a52;

    --status-draft-fg: #c6b0ff;
    --status-draft-bg: #2d2147;
    --status-draft-border: #5d4496;

    --status-pending-fg: #f0c48c;
    --status-pending-bg: #3b2710;
    --status-pending-border: #7c5724;

    --status-error-fg: #f1a5b1;
    --status-error-bg: #3b1720;
    --status-error-border: #7c3343;

    --success-color: #46c98b;
    --warning-color: #f0b860;
    /* Dark-tuned danger so state glows (e.g. Cache Board overdue tinge) aren't the harsh
       light-mode red. Light --danger-color is defined in :root; this pairs the dark side. */
    --danger-color: #f1a5b1;
    /* Brighter than the shared accent so the focused-pane ring reads on dark surfaces. */
    --pane-focus-ring: color-mix(in srgb, var(--primary-color) 70%, var(--text-main));
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: var(--font-ui);
    background-color: var(--bg-app);
    color: var(--text-main);
    height: 100vh;
    overflow: hidden;
    transition: background-color var(--anim-base) var(--anim-ease), color var(--anim-base) var(--anim-ease);
}

::highlight(qnt-multi-select) {
    background-color: color-mix(in srgb, var(--selection-color) 88%, transparent);
}

::highlight(qnt-ai-agent-selection-hold) {
    background-color: color-mix(in srgb, var(--selection-color) 82%, transparent);
}

/* --- LAYOUT --- */
.app-container {
    display: flex;
    height: 100vh;
    width: 100vw;
}

/* Mobile Header (Hidden by default on Desktop) */
.mobile-header {
    display: none;
    height: 50px;
    align-items: center;
    padding: 0 16px;
    background: var(--bg-pane);
    border-bottom: 1px solid var(--border-color);
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;
}

.mobile-header h1 {
    font-size: 1.1rem;
    font-weight: 600;
    flex-grow: 1;
    text-align: center;
}

.mobile-actions {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    min-width: 38px;
}

.install-banner {
    position: fixed;
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    z-index: 1200;
}

.install-banner-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    box-shadow: var(--shadow-md);
}

.install-banner-text {
    font-size: 0.9rem;
    color: var(--text-main);
    margin: 0;
}

.install-banner-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.install-banner-actions .glass-btn {
    min-height: 34px;
    padding: 6px 10px;
}

@media (max-width: 640px) {
    .install-banner-content {
        flex-direction: column;
        align-items: stretch;
    }

    .install-banner-actions {
        justify-content: flex-end;
    }
}

/* --- SIDEBAR (Pane 1) --- */
.sidebar {
    width: var(--sidebar-width);
    background-color: var(--bg-sidebar);
    border-right: 1px solid var(--pane-divider);
    display: flex;
    flex-direction: column;
    height: 100%;
    transition: transform 0.3s ease;
    z-index: 30;
    flex-shrink: 0;
    position: relative; /* For resizer positioning */
}

/* --- RESIZERS --- */
.resizer {
    position: absolute;
    top: 0;
    right: 0;
    width: 5px;
    height: 100%;
    background-color: var(--border-color);
    cursor: col-resize;
    z-index: 40;
    touch-action: none;
    transition: background-color 0.15s;
}

/* Wider invisible hit area for easier grabbing */
.resizer::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: -4px;
    width: 13px;
    cursor: col-resize;
    z-index: 41;
}

.resizer:hover, .resizer.active {
    background-color: var(--primary-color);
}

body.resizing {
    cursor: col-resize !important;
    user-select: none;
}
body.resizing * {
    cursor: col-resize !important;
}
body.resizing iframe {
    pointer-events: none;
}


.sidebar-header {
    padding: 18px 16px 14px;
    border-bottom: 1px solid var(--border-color);
}

.workspace-selector {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
        "settings db"
        "workspace workspace";
    column-gap: 8px;
    row-gap: 8px;
    margin-bottom: 12px;
    align-items: center;
}

.workspace-note-history-nav {
    grid-column: 1 / -1;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.workspace-note-history-nav .icon-btn-small:disabled {
    opacity: 0.45;
    cursor: default;
}

#workspace-select {
    grid-area: workspace;
    width: 100%;
    min-width: 0;
    padding: 6px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.9rem;
}

.active-db-badge {
    grid-area: db;
    display: inline-flex;
    align-items: center;
    width: 100%;
    min-width: 0;
    gap: 5px;
    max-width: min(70%, 240px);
    padding: 4px 8px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 25%, var(--border-color));
    background: color-mix(in srgb, var(--selection-color) 75%, var(--bg-pane));
    color: var(--text-main);
    font-size: 0.78rem;
    line-height: 1;
    white-space: nowrap;
}

.active-db-badge svg {
    width: 13px;
    height: 13px;
    flex: 0 0 auto;
}

#active-db-badge-label {
    overflow: hidden;
    text-overflow: ellipsis;
}

.workspace-selector #btn-settings {
    grid-area: settings;
}

.sidebar-content {
    flex-grow: 1;
    overflow: hidden;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 10px;
}

.tree-list {
    list-style: none;
    padding-left: 0;
    font-size: 13.5px;
    line-height: 1.4;
}

.tree-scroll-area {
    flex-grow: 1;
    overflow-y: auto;
    min-height: 0;
    margin-bottom: 8px;
}

/* Tree Items */
.tree-item {
    margin-bottom: 4px;
}

.tree-content {
    display: flex;
    align-items: center;
    padding: 7px 10px;
    border-radius: 6px;
    cursor: pointer;
    color: var(--text-main);
    user-select: none;
}

.tree-content:hover {
    background-color: var(--item-hover);
}

.tree-item.active > .tree-content {
    background-color: var(--selection-color);
    color: var(--primary-color);
    font-weight: 500;
}

.tree-content i {
    width: 16px;
    height: 16px;
    margin-right: 8px;
    color: var(--text-muted);
}

.tree-item.active > .tree-content i {
    color: var(--primary-color);
}

.tree-content .label {
    flex-grow: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Badge marking a folder as manually ("static") ordered. */
.tree-static-badge {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    margin: 0 4px;
    color: var(--text-muted);
    opacity: 0.7;
}
.tree-static-badge svg,
.tree-static-badge i {
    width: 13px;
    height: 13px;
    margin: 0;
}
.tree-item.active > .tree-content .tree-static-badge {
    color: var(--primary-color);
    opacity: 0.85;
}

/* Nested lists */
.nested-list {
    padding-left: 20px;
    display: none; /* Collapsed by default */
}
.nested-list.expanded {
    display: block;
}

/* --- NOTE LIST (Pane 2) --- */
.note-list-pane {
    width: var(--list-width);
    background-color: var(--bg-list-pane);
    border-right: 1px solid var(--pane-divider);
    display: flex;
    flex-direction: column;
    height: 100%;
    flex-shrink: 0;
    position: relative; /* For resizer positioning */
}

.pane-header {
    padding: 18px 18px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid var(--border-color);
}

.pane-header h2 {
    font-size: 1.34rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    line-height: 1.2;
}

.search-bar-container {
    padding: 12px 18px 14px 18px;
    border-bottom: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 86%, transparent);
}

.search-input-wrap {
    position: relative;
}

/* Reserve just enough left gutter for the pill (it sits over the field, left:10px, and the
   widest label "Global" is ~54px wide) so the typed text starts right after it. Fixed (not
   per-label) so the text doesn't jump when toggling Local↔Global. Was 124px — sized for the
   pill's 104px max-width — which cramped the usable input width on the PC. */
.search-input-wrap.scope-pill-visible #search-input {
    padding-left: 72px;
}

.search-scope-pill {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    max-width: 104px;
    height: 22px;
    padding: 0 8px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 34%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    color: color-mix(in srgb, var(--primary-color) 82%, var(--text-main));
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: auto;
    cursor: pointer;
}

.search-scope-pill:hover {
    background: color-mix(in srgb, var(--primary-color) 18%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 50%, var(--border-color));
}

.search-scope-pill[data-scope="global"] {
    background: color-mix(in srgb, var(--primary-color) 22%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 60%, var(--border-color));
    color: color-mix(in srgb, var(--primary-color) 92%, var(--text-main));
}

#search-input {
    width: 100%;
    padding: 8px 34px 8px 12px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-sidebar);
}

.inline-clear-btn {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    border: none;
    border-radius: 999px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease);
}

.inline-clear-btn svg {
    width: 13px;
    height: 13px;
}

.inline-clear-btn:hover {
    background: color-mix(in srgb, var(--primary-color) 14%, transparent);
    color: var(--primary-color);
}

.inline-clear-btn:disabled {
    opacity: 0.45;
    cursor: default;
}

.note-list-scroll {
    flex-grow: 1;
    overflow-y: auto;
    padding: 8px 10px 14px;
    margin-right: 8px;
}

/* Fill the scroll viewport so the empty space below the notes is still part of the
   note-list element (which owns the contextmenu handler). Otherwise a right-click below
   the last note lands on the scroll wrapper and the browser's native menu shows instead. */
#note-list-container {
    min-height: 100%;
}

.note-list-scroll:focus,
.note-list-scroll:focus-visible {
    outline: none;
}

#note-list-container:focus,
#note-list-container:focus-visible,
.note-list-component:focus,
.note-list-component:focus-visible {
    outline: none;
    box-shadow: none;
}

.note-card {
    position: relative;
    padding: 14px 14px;
    border: 1px solid var(--border-color);
    border-left: 3px solid transparent;
    border-radius: 10px;
    margin-bottom: 8px;
    cursor: pointer;
    background: var(--bg-pane);
    transition: background-color 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease;
}

.note-card:hover {
    background-color: var(--bg-pane);
    border-color: var(--note-card-hover-border);
    box-shadow: var(--note-card-hover-shadow);
    transform: translateY(-1px);
}

.note-card.active-note {
    background-color: var(--selection-color);
    border-left: 3px solid var(--primary-color);
    border-color: var(--note-card-active-border);
    box-shadow: var(--note-card-active-shadow);
}

.note-card.note-card-selected {
    background-color: color-mix(in srgb, var(--selection-color) 72%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
    box-shadow: var(--note-card-selected-shadow);
}

:root[data-theme="dark"] .note-card.active-note {
    background-color: color-mix(in srgb, var(--primary-color) 30%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 44%, var(--border-color));
    box-shadow: var(--note-card-active-shadow);
}

:root[data-theme="dark"] .note-card.note-card-selected {
    background-color: color-mix(in srgb, var(--primary-color) 20%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border-color));
    box-shadow: var(--note-card-selected-shadow);
}

:root[data-theme="dark"] .note-card.active-note .note-card-title {
    color: var(--text-main);
}

:root[data-theme="dark"] .note-card.active-note .note-card-preview {
    color: color-mix(in srgb, var(--text-main) 74%, var(--text-muted));
}

.note-card-title {
    font-weight: 600;
    margin-bottom: 6px;
    font-size: 1rem;
    line-height: 1.35;
    display: block;
    min-width: 0;
    max-width: 100%;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.note-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
}

.note-card-actions {
    display: none;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.note-card-menu-btn {
    width: 28px;
    height: 28px;
    border: 1px solid color-mix(in srgb, var(--border-color) 88%, transparent);
    border-radius: 7px;
    background: color-mix(in srgb, var(--bg-pane) 86%, transparent);
    color: var(--text-muted);
    font-size: 16px;
    line-height: 1;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.note-card-menu-btn:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

.note-card-pinned .note-card-title {
    color: color-mix(in srgb, var(--status-pinned-title-accent) 70%, var(--text-main));
}

.note-card.note-card-pinned {
    border-left-color: var(--status-pinned-accent);
    background: color-mix(in srgb, var(--status-pinned-bg) 42%, var(--bg-pane));
}

.note-card-preview {
    font-size: 0.88rem;
    color: var(--text-muted);
    line-height: 1.4;
    white-space: normal;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 5;
    max-height: 7em;
}

.note-card-search-path {
    margin-top: 6px;
    font-size: 0.76rem;
    line-height: 1.35;
    color: color-mix(in srgb, var(--text-muted) 92%, var(--primary-color));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.note-card-preview :where(p,div,h1,h2,h3,h4,h5,h6,li,ul,ol,blockquote,pre) {
    display: inline;
    margin: 0;
    padding: 0;
}

.note-card-preview :where(br) {
    display: none;
}

.note-card-preview :where(img,video,audio,iframe,object,embed,canvas,svg,math) {
    display: none !important;
}

.note-card-time {
    font-size: 0.78rem;
    color: var(--note-card-time-color);
    margin-top: 0;
    display: inline-block;
}

.note-card-meta {
    margin-top: 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.note-card-meta-right {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    min-width: 0;
}

.note-card-select-toggle {
    display: none;
    width: 24px;
    height: 24px;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: 8px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 32%, var(--border-color));
    background: color-mix(in srgb, var(--bg-pane) 90%, var(--selection-color) 10%);
}

.note-card-select-checkbox {
    width: 16px;
    height: 16px;
    margin: 0;
    cursor: pointer;
    accent-color: var(--primary-color);
}

.meta-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
}

.meta-icon {
    display: inline-flex;
    width: 13px;
    height: 13px;
    color: var(--note-card-meta-icon-color);
    flex-shrink: 0;
}

.meta-icon svg {
    width: 13px;
    height: 13px;
}

.note-card-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.72rem;
    line-height: 1;
    padding: 4px 8px;
    border-radius: 999px;
    border: 1px solid transparent;
    white-space: nowrap;
}

.note-card-chip-pinned {
    color: var(--status-pinned-fg);
    background: var(--status-pinned-bg);
    border-color: var(--status-pinned-border);
}

.note-card-chip-blogger-live {
    color: var(--status-live-fg);
    background: var(--status-live-bg);
    border-color: var(--status-live-border);
}

.note-card-chip-blogger-draft {
    color: var(--status-draft-fg);
    background: var(--status-draft-bg);
    border-color: var(--status-draft-border);
}

.note-card-chip-blogger-pending {
    color: var(--status-pending-fg);
    background: var(--status-pending-bg);
    border-color: var(--status-pending-border);
}

.note-card-chip-blogger-error {
    color: var(--status-error-fg);
    background: var(--status-error-bg);
    border-color: var(--status-error-border);
}

.note-card-chip-pinned.pin-pop {
    animation: pinPop 260ms ease;
}

@media (max-width: 768px), (hover: none) and (pointer: coarse), (any-pointer: coarse) {
    .note-card-actions {
        display: inline-flex;
    }

    .note-card-menu-btn {
        display: inline-flex;
    }
}

@media (max-width: 768px) {
    .note-card-select-toggle {
        display: inline-flex;
    }
}

body.touch-device-ui .note-card-actions {
    display: inline-flex;
}

body.touch-device-ui .note-card-menu-btn {
    display: inline-flex;
}

@keyframes pinPop {
    0% { transform: scale(0.85) rotate(-8deg); }
    60% { transform: scale(1.12) rotate(4deg); }
    100% { transform: scale(1) rotate(0deg); }
}

/* --- NAVIGATOR RAIL & COLLAPSIBLE TREE (desktop-only) --- */
/*
 * Owner slice for the collapsible tree (Phase 1) and the activity rail + navigator
 * panels (Phase 2). Loads right after 010-shell-layout.css, which it extends.
 *
 * Rules (per Docs/000-navigator-panels-and-collapsible-tree-design.md):
 *   - Feature-scoped selectors: .nav-rail* / .nav-panel, plus state on .app-container.
 *   - Semantic tokens only (surface/text/border/hover/accent); no hardcoded colors.
 *   - Collapsed/inactive states use explicit `display:none` (author display beats [hidden]).
 *   - Desktop-only: rail/collapse rules live behind min-width:769px so they never collide
 *     with the mobile sidebar overlay (max-width:768px). A stale `.nav-collapsed` class is
 *     therefore inert on mobile.
 */

/* Phase 1 — collapse the sidebar (Pane 1) on desktop. The reclaimed width flows to the
   editor pane (the flex-grow child); the note-list keeps its fixed width. The sidebar's
   own resizer lives inside #sidebar, so it hides with it. */
@media (min-width: 769px) {
    .app-container.nav-collapsed #sidebar {
        display: none;
    }
}

/* The permanent rail hamburger (#btn-nav-rail-config) owns the config menu on desktop, so the
   in-sidebar #btn-settings hamburger is a duplicate there. Hide it only while the rail feature is
   on (flag off → no rail → the sidebar button returns as the sole trigger). Mobile is unaffected
   (the rail is hidden below 769px, and the mobile header keeps its own settings toggle). */
@media (min-width: 769px) {
    .app-container.nav-enabled #btn-settings {
        display: none;
    }
}

/* Pane-2 header tree-toggle button. Visibility is CSS-driven (not the [hidden] attribute)
   so it is present only on desktop AND only when the feature flag is on. Hidden by default
   → no flash on mobile or when the feature is off. */
#btn-toggle-tree {
    display: none;
}

@media (min-width: 769px) {
    .app-container.nav-enabled #btn-toggle-tree {
        display: inline-flex;
    }
}

/* Reflect collapsed state on the toggle button (subtle active affordance). */
#btn-toggle-tree[aria-pressed="true"] {
    color: var(--primary-color);
}

/* --- NAVIGATOR PANELS (Phase 2) --- */
/* The panel host is layout-invisible: display:contents means the wrapper generates no
   box, so its children participate in .sidebar-content's flex column exactly as if the
   wrapper weren't there. This is what makes wrapping the tree provably safe. An inactive
   panel is display:none (explicit — beats the [hidden] attribute reliably). */
.nav-panel {
    display: contents;
}

.nav-panel[hidden] {
    display: none;
}

/* --- ACTIVITY RAIL (Phase 2) --- */
/* Desktop-only, feature-on only. Hidden by default so there is no flash on mobile or
   when the flag is off. Sits at the far left as the first flex child of .app-container. */
.nav-rail {
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
    width: var(--nav-rail-width);
    height: 100%;
    padding: 10px 0;
    background: var(--bg-sidebar);
    border-right: 1px solid var(--pane-divider);
    z-index: 31; /* just above the sidebar so its border reads cleanly */
}

@media (min-width: 769px) {
    .app-container.nav-enabled .nav-rail {
        display: flex;
    }
}

/* Config (hamburger) sits at the top of the rail, set off from the panel buttons by a hairline
   divider so it reads as shell chrome (menu) rather than a navigator panel. The divider spans the
   rail width via a pseudo-element rather than bordering the (narrower) button itself. */
.nav-rail-config {
    position: relative;
    margin-bottom: 11px;
}

.nav-rail-config::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -6px;
    transform: translateX(-50%);
    width: 28px;
    height: 1px;
    background: var(--pane-divider);
}

.nav-rail-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--anim-fast, 0.15s) ease, color var(--anim-fast, 0.15s) ease, border-color var(--anim-fast, 0.15s) ease;
}

.nav-rail-btn:hover {
    background: var(--item-hover);
    color: var(--text-main);
}

.nav-rail-btn:focus-visible {
    outline: none;
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
}

.nav-rail-btn svg {
    width: 20px;
    height: 20px;
}

/* Active = its panel is the open one (expanded). Uses the accent selection treatment
   that the tree's active row already uses, so the rail reads as part of the shell. */
.nav-rail-btn.is-active {
    background: var(--selection-color);
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 22%, transparent);
}
/* --- EDITOR (Pane 3) --- */
.editor-pane {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    background-color: var(--bg-editor-pane);
    height: 100%;
    overflow: hidden; /* Ensure no body scroll */
}

.editor-toolbar {
    padding: 18px 26px 14px;
    border-bottom: none;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    color: var(--text-muted);
    font-size: 0.86rem;
    line-height: 1.35;
    flex-shrink: 0; /* Prevent shrinking */
}

.editor-meta-row {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0 26px 12px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-muted);
    font-size: 0.82rem;
    line-height: 1.35;
    flex-shrink: 0;
}

.editor-meta-top {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
}

.editor-meta-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.note-breadcrumb {
    flex: 1 1 auto;
    opacity: 0.9;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.timestamp {
    opacity: 0.85;
}

/* Keep the save/edited status on a single, shrinkable line. Its text changes
   length as it saves ("Saving…" → "Saved to Disk (12:34:56)" → "Saved"); on
   mobile the meta row is allowed to wrap, so a longer label would flip the row
   to a taller height and shove the note content up/down (a visible jump on every
   save). Truncating instead keeps the row height constant. */
.editor-meta-bottom .timestamp {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.editor-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.editor-actions-layout {
    display: flex;
    flex-direction: row;
    align-items: flex-end;
    justify-content: flex-end;
    gap: 6px;
    width: 100%;
}

.editor-actions-system {
    opacity: 0.96;
}

/* New Note button sits at the far LEFT of the toolbar row; margin-right:auto pushes the system
   actions to their usual right edge. desktop-only hides it on mobile (handled in shared UI). */
.editor-new-note-btn {
    margin-right: auto;
}

.editor-actions-note {
    flex-shrink: 0;
}

.editor-actions-mobile-row {
    display: none;
}

.editor-actions .icon-btn {
    height: var(--btn-height-compact);
    min-width: var(--btn-height-compact);
    padding: 0;
}

#btn-theme-toggle {
    gap: 5px;
    padding: 0 7px;
}

#btn-music-panel {
    gap: 5px;
    padding: 0 7px;
}

#btn-focus-mode {
    gap: 5px;
    padding: 0 7px;
}

.ai-agent-launch-btn img {
    width: 18px;
    height: 18px;
    border-radius: 4px;
    object-fit: cover;
}

.ai-agent-launch-btn.active {
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 25%, transparent);
}

#btn-music-panel.active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 16%, transparent);
}

.music-panel-shell {
    position: fixed;
    left: 16px;
    top: 72px;
    width: min(94vw, 500px);
    max-width: 92vw;
    min-width: 320px;
    min-height: 0;
    background:
        linear-gradient(180deg, color-mix(in srgb, var(--bg-pane) 98%, var(--mix-light) 2%), color-mix(in srgb, var(--bg-editor-pane) 92%, var(--bg-pane))),
        var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: 18px;
    box-shadow: 0 24px 60px color-mix(in srgb, var(--mix-dark) 28%, transparent);
    z-index: 5150;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    container-type: size;
    --music-panel-grip-hit-size: 26px;
    --music-panel-grip-glyph-size: 16px;
    --music-panel-grip-inset: 6px;
}

.music-panel-shell[data-view="jukebox"] {
    width: min(94vw, 420px);
}

.music-panel-shell[data-view="clock"] {
    width: min(94vw, 540px);
}

/* Tools window (clock + calculator) — an independent sibling of the Music window.
   Defaults to the right so the two don't open stacked; JS then restores/persists
   its own position. Calculator gets a narrower width than the wide clock. */
.music-panel-tools-shell {
    left: auto;
    right: 24px;
    top: 96px;
}
.music-panel-tools-shell[data-view="clock"] {
    width: min(94vw, 360px);
    height: 190px;
}
.music-panel-tools-shell[data-view="calculator"] {
    width: min(94vw, 320px);
    height: 430px;
}

.music-panel-shell.is-dragging {
    user-select: none;
    -webkit-user-select: none;
}

.music-panel-shell.is-resizing {
    user-select: none;
    -webkit-user-select: none;
}

.music-panel-header {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border-bottom: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--mix-dark) 8%);
    cursor: grab;
    /* Claim touch drags for the drag handler instead of letting the page/panel
       scroll and cancel the pointer (mobile: "moves slightly then stops"). */
    touch-action: none;
}

.music-panel-shell.is-dragging .music-panel-header {
    cursor: grabbing;
}

.music-panel-shell.music-panel-compact-mode .music-panel-header {
    justify-content: flex-end;
    gap: 4px;
    padding: 2px 4px 0;
    border-bottom: none;
    background: transparent;
}

.music-panel-shell.music-panel-compact-mode .music-panel-title-wrap,
.music-panel-shell.music-panel-compact-mode .music-panel-tabs {
    display: none;
}

.music-panel-shell.music-panel-compact-mode {
    min-width: 0;
    --music-panel-grip-hit-size: clamp(10px, 18cqmin, 18px);
    --music-panel-grip-glyph-size: clamp(6px, 10cqmin, 10px);
    --music-panel-grip-inset: 3px;
}

.music-panel-title-wrap {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    min-width: 0;
}

.music-panel-title {
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--text-main);
}

.music-panel-tabs {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    min-width: 0;
    /* Absorb the free space to the right so the icon tabs stay left (hugging the
       Toolbox title) and the window controls (minimal/close) sit at the right
       edge. Order-independent — works even while the compact toggle is hidden. */
    margin-right: auto;
}

.music-panel-tab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 30px;
    min-width: 30px;
    padding: 0;
    border: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 96%, var(--bg-pane) 4%);
    color: var(--text-main);
    border-radius: 8px;
    cursor: pointer;
    line-height: 1;
}

.music-panel-tab-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.music-panel-tab svg {
    width: 17px;
    height: 17px;
}

.music-panel-tab:hover {
    border-color: color-mix(in srgb, var(--primary-color) 28%, var(--border-color));
    color: var(--primary-color);
}

.music-panel-tab.active,
.music-panel-tab[aria-selected="true"] {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 12%, var(--bg-pane));
}

.music-panel-close,
.music-panel-compact-toggle {
    flex: 0 0 auto;
    height: 26px;
    min-width: 26px;
    padding: 0 6px;
    border-radius: 8px;
}

.music-panel-close svg,
.music-panel-compact-toggle svg {
    width: 14px;
    height: 14px;
}

.music-panel-shell.music-panel-compact-mode .music-panel-close,
.music-panel-shell.music-panel-compact-mode .music-panel-compact-toggle {
    height: 22px;
    min-width: 22px;
    padding: 0 4px;
    border-radius: 7px;
}

.music-panel-shell.music-panel-compact-mode .music-panel-close svg,
.music-panel-shell.music-panel-compact-mode .music-panel-compact-toggle svg {
    width: 12px;
    height: 12px;
}

.music-panel-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 10px 12px 12px;
    max-height: min(74vh, 620px);
    overflow: auto;
}

.music-panel-shell[data-view="jukebox"] .music-panel-body,
.music-panel-shell[data-view="clock"] .music-panel-body {
    padding: 8px;
    max-height: none;
    overflow: hidden;
}

.music-panel-shell[data-view="jukebox"] .music-panel-body,
.music-panel-shell[data-view="clock"] .music-panel-body {
    flex: 1 1 auto;
    min-height: 0;
}

.music-panel-shell.music-panel-compact-mode .music-panel-body {
    gap: 4px;
    padding: 2px calc(6px + (var(--music-panel-grip-hit-size) * 0.45)) calc(6px + (var(--music-panel-grip-hit-size) * 0.45)) 6px;
}

.music-panel-resize-handle {
    position: absolute;
    right: var(--music-panel-grip-inset);
    bottom: var(--music-panel-grip-inset);
    width: var(--music-panel-grip-hit-size);
    height: var(--music-panel-grip-hit-size);
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    color: transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0;
    line-height: 0;
    cursor: nwse-resize;
    touch-action: none;
    z-index: 3;
    appearance: none;
    -webkit-appearance: none;
}

.music-panel-resize-handle::before {
    content: '';
    display: block;
    width: var(--music-panel-grip-glyph-size);
    height: var(--music-panel-grip-glyph-size);
    background:
        linear-gradient(135deg,
            transparent 0 50%,
            color-mix(in srgb, var(--text-muted) 86%, transparent) 50% 56%,
            transparent 56% 68%,
            color-mix(in srgb, var(--text-muted) 86%, transparent) 68% 74%,
            transparent 74% 86%,
            color-mix(in srgb, var(--text-muted) 86%, transparent) 86% 92%,
            transparent 92% 100%);
    opacity: 0.96;
}

.music-panel-resize-handle:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 46%, transparent);
    outline-offset: 1px;
}

.music-panel-resize-handle:hover::before,
.music-panel-shell.is-resizing .music-panel-resize-handle::before {
    background:
        linear-gradient(135deg,
            transparent 0 50%,
            color-mix(in srgb, var(--primary-color) 82%, transparent) 50% 56%,
            transparent 56% 68%,
            color-mix(in srgb, var(--primary-color) 82%, transparent) 68% 74%,
            transparent 74% 86%,
            color-mix(in srgb, var(--primary-color) 82%, transparent) 86% 92%,
            transparent 92% 100%);
}

.music-panel-pane {
    display: none;
    min-height: 0;
}

.music-panel-pane.active {
    display: block;
}

.music-panel-shell[data-view="clock"] .music-panel-pane.active {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

.music-panel-shell[data-view="jukebox"] .music-panel-pane.active {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

.music-panel-shell[data-view="calculator"] .music-panel-body {
    flex: 1 1 auto;
    min-height: 0;
    padding: 8px;
    max-height: none;
    overflow: hidden;
}

/* Calculator is a fixed size — hide the resize gripper and (with the JS guard)
   block the drag, so its sensitive corner can't be nudged on mobile. The resize
   machinery stays intact for the other tabs. */
.music-panel-shell[data-view="calculator"] .music-panel-resize-handle {
    display: none;
}

.music-panel-shell[data-view="calculator"] .music-panel-pane.active {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

/* Music Player (Settings) must fill the dialog height when the panel is resized
   ("flexed"). Without these the body keeps its default max-height while the
   dialog grows, leaving dead space and a stale-looking pane. Mirror the
   jukebox/clock/calculator fill pattern, but keep the body scrollable and let
   the song list be the scroll region. */
.music-panel-shell[data-view="settings"] .music-panel-body {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    overflow: auto;
}

.music-panel-shell[data-view="settings"] .music-panel-pane.active {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.music-panel-shell[data-view="settings"] .music-panel-settings-card {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

/* Only the songs section (the one holding the track list) absorbs the extra
   height; the playlist/volume/transport rows keep their natural size. */
.music-panel-shell[data-view="settings"] .music-panel-settings-section:has(.music-panel-track-list) {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.music-panel-shell[data-view="settings"] .music-panel-track-list {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
}


.music-panel-calculator-card {
    display: grid;
    grid-template-rows: 1.25fr repeat(5, 1fr);
    gap: 8px;
    flex: 1 1 auto;
    width: 100%;
    min-height: 0;
}

.music-panel-calculator-card .music-panel-calculator-display {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: stretch;
    gap: 4px;
    min-height: 0;
}

.music-panel-calculator-card .music-panel-calculator-display .music-panel-clock-date {
    width: 100%;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.music-panel-calculator-card .music-panel-calculator-display .music-panel-clock-time-row {
    width: 100%;
    justify-content: flex-end;
    align-items: center;
    overflow: hidden;
}

.music-panel-calculator-card .music-panel-calculator-display .music-panel-clock-time-value {
    width: 100%;
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: clip;
}

.music-panel-calculator-card .music-panel-calculator-row {
    margin: 0;
    min-height: 0;
}

.music-panel-calculator-card .music-panel-calculator-row .music-panel-transport-btn {
    aspect-ratio: auto;
    height: 100%;
    font-size: clamp(1rem, 6cqmin, 2.4rem);
    font-weight: 600;
}

/* Calculator copy-to-clipboard affordance — overlaid on the left of the
   display, hidden until the display is hovered (mouse) or tapped (touch).
   Reveal/fade lifecycle is driven from MusicPanelRuntime. */
.music-panel-calculator-display {
    position: relative;
}

.music-panel-calc-copy-btn {
    position: absolute;
    left: max(6px, 2.4cqmin);
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border-radius: 8px;
    border: 1px solid color-mix(in srgb, var(--border-color) 80%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 78%, transparent);
    color: var(--text-main);
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transition: opacity 200ms ease, visibility 200ms ease, color 150ms ease, border-color 150ms ease;
    z-index: 2;
}

.music-panel-calc-copy-btn svg {
    width: 16px;
    height: 16px;
}

.music-panel-calculator-display.copy-visible .music-panel-calc-copy-btn {
    opacity: 1;
    visibility: visible;
}

.music-panel-calc-copy-btn:hover {
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
}

.music-panel-calc-copy-btn.copied {
    color: var(--success-color, var(--success-color));
    border-color: color-mix(in srgb, var(--success-color, var(--success-color)) 55%, var(--border-color));
}

/* The calculator screen is an editable <input> (caret, arrow-key editing,
   horizontal scroll-to-caret). Strip the native input chrome so it reads as the
   big right-aligned number; sizing/font/alignment come from the shared
   .music-panel-clock-time-value rule that this element also carries. */
.music-panel-calc-input {
    appearance: none;
    -webkit-appearance: none;
    border: 0;
    background: transparent;
    padding: 0;
    margin: 0;
    min-width: 0;
    caret-color: var(--primary-color);
    outline: none;
}

.music-panel-calc-input:focus,
.music-panel-calc-input:focus-visible {
    outline: none;
}

.music-panel-calc-input::selection {
    background: color-mix(in srgb, var(--primary-color) 28%, transparent);
}

.music-panel-pane h3 {
    margin: 0 0 8px;
    font-size: 1rem;
}

.music-panel-pane p {
    margin: 0;
    color: var(--text-muted);
    line-height: 1.5;
}

.music-panel-clock-card {
    display: grid;
    gap: 6px;
    gap: max(2px, 1.1cqmin);
    grid-template-rows: auto auto auto;
    justify-items: center;
    align-items: center;
    align-content: center;
    flex: 1 1 auto;
    width: 100%;
    height: 100%;
    min-height: 0;
    padding: 10px 12px 8px;
    padding: max(8px, 2.6cqmin) max(10px, 3.6cqmin) max(6px, 2cqmin);
    border-radius: 16px;
    border-radius: max(16px, 4.8cqmin);
    border: 1px solid color-mix(in srgb, var(--border-color) 88%, transparent);
    background:
        radial-gradient(130% 170% at 100% 0%, color-mix(in srgb, var(--primary-color) 20%, transparent), transparent 65%),
        radial-gradient(120% 150% at 0% 100%, color-mix(in srgb, var(--primary-color) 12%, transparent), transparent 70%),
        color-mix(in srgb, var(--bg-editor-pane) 84%, var(--bg-pane));
    container-type: size;
    overflow: hidden;
}

.music-panel-clock-time-row {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 7px;
    gap: max(4px, 1.2cqmin);
    min-height: 0;
    white-space: nowrap;
    align-self: center;
}

.music-panel-clock-time-value {
    font-family: "JetBrains Mono", "Cascadia Mono", "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: clamp(2.2rem, 8vw, 3.7rem);
    font-size: clamp(2.1rem, 22cqmin, 5.2rem);
    font-weight: 700;
    letter-spacing: 0.02em;
    line-height: 1;
    color: var(--text-main);
    white-space: nowrap;
}

.music-panel-clock-meridiem-btn {
    border: none;
    background: transparent;
    color: color-mix(in srgb, var(--text-main) 88%, transparent);
    border-radius: 0;
    min-height: 0;
    padding: 0;
    font: inherit;
    font-size: 1rem;
    font-size: clamp(1rem, 6.6cqmin, 1.9rem);
    font-weight: 700;
    text-transform: lowercase;
    cursor: pointer;
    margin-bottom: max(1px, 0.45cqmin);
    line-height: 1;
}

.music-panel-clock-meridiem-btn:hover {
    color: var(--primary-color);
}

.music-panel-clock-meridiem-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 46%, transparent);
    outline-offset: 2px;
}

.music-panel-clock-date {
    text-align: center;
    font-size: 0.82rem;
    font-size: clamp(0.82rem, 3.8cqmin, 1.1rem);
    font-weight: 500;
    color: var(--text-muted);
    letter-spacing: 0.01em;
    min-height: 0;
    line-height: 1.05;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    align-self: center;
}

.music-panel-clock-song {
    text-align: center;
    font-size: 0.94rem;
    font-size: clamp(0.88rem, 4.6cqmin, 1.2rem);
    color: var(--text-main);
    font-style: italic;
    padding-top: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0.86;
    align-self: center;
    width: 100%;
}

.music-panel-clock-song.hidden {
    display: none;
}

.music-panel-jukebox-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1 1 auto;
    min-height: 0;
    container-type: size;
    justify-content: center;
}

.music-panel-jukebox-now-playing {
    display: grid;
    gap: 0;
    padding: 0 2px;
    border-radius: 0;
    border: none;
    background: transparent;
    min-height: 0;
}

.music-panel-jukebox-track-title {
    font-size: 0.98rem;
    font-weight: 700;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.15;
}

.music-panel-jukebox-track-title.empty {
    color: var(--text-muted);
}

.music-panel-jukebox-track-meta {
    font-size: 0.82rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.1;
}

.music-panel-transport-row {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 6px;
    margin-top: 0;
}

.music-panel-settings-transport-row {
    width: fit-content;
    justify-self: center;
    grid-template-columns: repeat(7, 40px);
    gap: 8px;
}

.music-panel-transport-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 45px;
    aspect-ratio: 1 / 1;
    border: 1px solid var(--border-color);
    border-radius: 13px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    color: var(--text-main);
    cursor: pointer;
}

.music-panel-settings-transport-row .music-panel-transport-btn {
    width: 40px;
    min-height: 40px;
    border-radius: 11px;
}

.music-panel-transport-btn:hover {
    border-color: color-mix(in srgb, var(--primary-color) 34%, var(--border-color));
}

.music-panel-transport-btn.primary {
    color: var(--on-accent);
    background: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 72%, var(--mix-dark) 28%);
}

/* Shuffle / Repeat-one are toggles: tint them when active so their on/off state reads
   at a glance (aria-pressed carries it for assistive tech). */
.music-panel-transport-btn.music-panel-transport-toggle.active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 16%, var(--bg-pane));
}

.music-panel-transport-btn.music-panel-transport-toggle.active:hover {
    border-color: color-mix(in srgb, var(--primary-color) 68%, var(--border-color));
}

.music-panel-transport-btn:disabled {
    opacity: 0.55;
    cursor: default;
}

.music-panel-transport-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 46%, transparent);
    outline-offset: 2px;
}

.music-panel-transport-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    font-size: 1.2rem;
    line-height: 1;
}

.music-panel-transport-icon svg {
    width: 18px;
    height: 18px;
}

.music-panel-jukebox-status {
    min-height: 18px;
    font-size: 0.86rem;
    color: var(--text-muted);
    padding: 0 2px;
    margin-top: 0;
}

.music-panel-shell.music-panel-compact-mode .music-panel-clock-card,
.music-panel-shell.music-panel-compact-mode .music-panel-jukebox-card {
    gap: max(2px, 0.8cqmin);
}

.music-panel-shell.music-panel-compact-mode .music-panel-clock-card {
    padding: max(6px, 2cqmin) max(8px, 2.8cqmin) max(4px, 1.4cqmin);
}

.music-panel-shell.music-panel-compact-mode .music-panel-transport-row {
    gap: 5px;
}

.music-panel-shell.music-panel-compact-mode .music-panel-transport-btn {
    min-height: 34px;
    border-radius: 10px;
}

.music-panel-shell.music-panel-compact-mode .music-panel-transport-icon svg {
    width: 14px;
    height: 14px;
}

@media (min-width: 769px) {
    .music-panel-shell.music-panel-compact-mode {
        min-width: 0;
        --music-panel-grip-hit-size: clamp(9px, 16cqmin, 16px);
        --music-panel-grip-glyph-size: clamp(5px, 9cqmin, 9px);
        --music-panel-grip-inset: 2px;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-header {
        padding: 1px 3px 0;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-close,
    .music-panel-shell.music-panel-compact-mode .music-panel-compact-toggle {
        height: 18px;
        min-width: 18px;
        padding: 0 3px;
        border-radius: 6px;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-close svg,
    .music-panel-shell.music-panel-compact-mode .music-panel-compact-toggle svg {
        width: 10px;
        height: 10px;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-body {
        gap: 2px;
        padding: 1px calc(4px + (var(--music-panel-grip-hit-size) * 0.4)) calc(4px + (var(--music-panel-grip-hit-size) * 0.4)) 4px;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-clock-card {
        gap: max(1px, 0.45cqmin);
        padding: max(3px, 1.1cqmin) max(6px, 2cqmin) max(2px, 0.8cqmin);
        border-radius: max(10px, 2.8cqmin);
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-clock-time-row {
        gap: max(2px, 0.65cqmin);
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-clock-time-value {
        font-size: clamp(1.15rem, 16cqmin, 2rem);
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-clock-meridiem-btn {
        font-size: clamp(0.7rem, 3.9cqmin, 0.92rem);
        margin-bottom: 0;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-jukebox-card {
    gap: max(2px, 0.8cqmin);
}

    .music-panel-shell.music-panel-compact-mode .music-panel-transport-btn {
        min-height: 24px;
        border-radius: 8px;
    }

    .music-panel-shell.music-panel-compact-mode .music-panel-transport-icon svg {
        width: 11px;
        height: 11px;
    }
}

@container (max-height: 210px) {
    .music-panel-clock-card {
        gap: max(2px, 0.9cqmin);
        padding: max(6px, 1.8cqmin) max(8px, 2.8cqmin) max(4px, 1.4cqmin);
    }

    .music-panel-clock-song {
        display: none;
    }
}

@container (max-height: 160px) {
    .music-panel-clock-card {
        grid-template-rows: 1fr;
        align-items: center;
        justify-items: center;
        gap: 0;
    }

    .music-panel-clock-time-row {
        align-self: center;
    }

    .music-panel-clock-time-value {
        font-size: clamp(1.65rem, 20cqmin, 4rem);
    }

    .music-panel-clock-meridiem-btn {
        font-size: clamp(0.92rem, 5.4cqmin, 1.4rem);
    }

    .music-panel-clock-date,
    .music-panel-clock-song {
        display: none;
    }
}

@container (max-height: 168px) {
    .music-panel-jukebox-now-playing,
    .music-panel-jukebox-status {
        display: none;
    }

    .music-panel-jukebox-card {
        justify-content: center;
        gap: 0;
    }

    .music-panel-transport-btn {
        min-height: 37px;
        border-radius: 10px;
    }

    .music-panel-transport-icon svg {
        width: 14px;
        height: 14px;
    }
}

@container (max-height: 205px) {
    .music-panel-jukebox-track-meta {
    font-size: 0.82rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.1;
}

    .music-panel-transport-btn {
        min-height: 37px;
        border-radius: 11px;
    }
}

@container (max-height: 168px) {
    .music-panel-jukebox-now-playing,
    .music-panel-jukebox-status {
        display: none;
    }

    .music-panel-jukebox-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1 1 auto;
    min-height: 0;
    container-type: size;
    justify-content: center;
}

    .music-panel-transport-btn {
        min-height: 37px;
        border-radius: 10px;
    }

    .music-panel-transport-icon svg {
        width: 14px;
        height: 14px;
    }
}

.music-panel-settings-card {
    display: grid;
    gap: 14px;
    padding: 8px 4px 4px;
}

.music-panel-settings-row {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    color: var(--text-main);
}

.music-panel-settings-row-indented {
    margin-top: -4px;
    padding-left: 22px;
    font-weight: 500;
    color: var(--text-muted);
}

.music-panel-settings-row input[type="checkbox"] {
    width: 16px;
    height: 16px;
}

.music-panel-settings-section {
    display: grid;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 14px;
    border: 1px solid color-mix(in srgb, var(--border-color) 88%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-editor-pane));
}

.music-panel-section-title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.music-panel-section-title {
    font-size: 0.98rem;
    font-weight: 700;
    color: var(--text-main);
}

.music-panel-track-title-row {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.music-panel-track-title-row .icon-btn-small {
    width: 28px;
    min-width: 28px;
    height: 28px;
    padding: 0;
}

.music-panel-track-title-row .icon-btn-small svg {
    width: 15px;
    height: 15px;
}

.music-panel-track-count-label {
    font-size: 0.85rem;
    color: var(--text-muted);
}

.music-panel-playlist-row {
    display: grid;
    /* select + save-temp + rename + cover + new + delete */
    grid-template-columns: minmax(0, 1fr) auto auto auto auto auto;
    gap: 8px;
    align-items: center;
}

/* The selected playlist already carries a picture of its own (playlists.cover_media_id). Tinting the
   button is what tells the user that a click REPLACES rather than adds, and that alt/right-click has
   something to remove. Owner: utils/MusicPanelRuntime.js + utils/PlaylistCoverArt.js. */
.music-panel-playlist-cover[data-has-cover="true"]:not(:disabled) {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
}

.music-panel-save-temp-btn:disabled,
.music-panel-save-temp-btn:disabled:hover,
.music-panel-rename-playlist:disabled,
.music-panel-rename-playlist:disabled:hover,
.music-panel-playlist-cover:disabled,
.music-panel-playlist-cover:disabled:hover,
.music-panel-delete-playlist:disabled,
.music-panel-delete-playlist:disabled:hover {
    cursor: default;
    opacity: 0.55;
    color: var(--text-muted);
    border-color: var(--border-color);
    background: var(--bg-pane);
    box-shadow: none;
    transform: none;
}

.music-panel-playlist-select {
    width: 100%;
    min-height: 38px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--bg-pane) 96%, var(--bg-pane) 4%);
    color: var(--text-main);
    padding: 0 12px;
    font: inherit;
}

.music-panel-playlist-select:focus,
.music-panel-volume-slider:focus-visible,
.music-panel-track-item:focus-visible,
.music-panel-link-note-btn:focus-visible,
.music-panel-transport-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 46%, transparent);
    outline-offset: 2px;
}

.music-panel-link-note-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 96%, var(--bg-pane) 4%);
    color: var(--text-main);
    border-radius: 10px;
    width: 36px;
    min-width: 36px;
    min-height: 36px;
    padding: 0;
    font: inherit;
    cursor: pointer;
}

.music-panel-link-note-btn:hover {
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border-color));
}

.music-panel-link-note-btn {
    font-size: 0.88rem;
    font-weight: 600;
}

.music-panel-link-note-btn svg {
    width: 16px;
    height: 16px;
}

.music-panel-track-list {
    display: grid;
    gap: 8px;
    align-content: start;
    grid-auto-rows: min-content;
    max-height: 220px;
    overflow: auto;
    padding-right: 2px;
}

.music-panel-track-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 8px;
    align-items: stretch;
}

.music-panel-track-row.draggable .music-panel-track-item {
    cursor: grab;
}

.music-panel-track-row.dragging .music-panel-track-item {
    cursor: grabbing;
}

.music-panel-track-item,
.music-panel-track-empty {
    display: grid;
    gap: 4px;
    width: 100%;
    text-align: left;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--border-color) 86%, transparent);
    background: color-mix(in srgb, var(--bg-editor-pane) 84%, var(--bg-pane));
}

.music-panel-track-item {
    cursor: pointer;
    min-width: 0;
}

.music-panel-track-item:hover {
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
}

.music-panel-track-item.active {
    border-color: color-mix(in srgb, var(--primary-color) 50%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 12%, var(--bg-pane));
}

.music-panel-track-item.playback-error {
    border-color: color-mix(in srgb, var(--status-error-border) 78%, var(--border-color));
    background: color-mix(in srgb, var(--status-error-bg) 62%, var(--bg-pane));
}

.music-panel-track-row.playback-error .music-panel-track-title,
.music-panel-track-row.playback-error .music-panel-track-meta {
    color: var(--status-error-fg);
}

.music-panel-track-empty {
    color: var(--text-muted);
}

.music-panel-track-empty--error {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 45%, transparent);
}

.music-panel-track-title {
    font-weight: 700;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.music-panel-track-meta {
    font-size: 0.83rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.music-panel-track-link-btn,
.music-panel-track-remove-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    min-width: 42px;
    padding: 0;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--border-color) 86%, transparent);
    background: color-mix(in srgb, var(--bg-editor-pane) 84%, var(--bg-pane));
    color: var(--text-muted);
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

.music-panel-track-link-btn:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 42%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    transform: translateY(-1px);
}

.music-panel-track-remove-btn:hover {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 42%, var(--border-color));
    background: color-mix(in srgb, var(--danger-color) 10%, var(--bg-pane));
    transform: translateY(-1px);
}

.music-panel-track-link-btn svg,
.music-panel-track-remove-btn svg {
    width: 16px;
    height: 16px;
}

.music-panel-volume-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
}

.music-panel-volume-label,
.music-panel-volume-value {
    font-weight: 600;
    color: var(--text-main);
}

.music-panel-volume-slider {
    width: 100%;
}

.music-panel-status {
    min-height: 20px;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.music-panel-status.ok,
.music-panel-jukebox-status.ok {
    color: var(--success-color, var(--success-color));
}

.music-panel-status.warn,
.music-panel-jukebox-status.warn {
    color: var(--warning-color, var(--warning-color));
}

.music-panel-status.error,
.music-panel-jukebox-status.error {
    color: var(--danger-color);
}

@media (max-width: 768px) {
    .music-panel-shell {
        width: min(96vw, 500px);
        min-width: min(96vw, 320px);
    }

    .music-panel-shell[data-view="jukebox"] {
        width: min(96vw, 400px);
    }

    .music-panel-shell[data-view="clock"] {
        width: min(96vw, 500px);
    }

    .music-panel-header {
        align-items: center;
        flex-wrap: wrap;
    }

    .music-panel-tabs {
        flex-wrap: wrap;
    }

    .music-panel-body {
        max-height: min(70vh, 620px);
    }

    .music-panel-section-title-row {
        align-items: flex-start;
    }

    .music-panel-volume-row {
        grid-template-columns: 1fr;
    }

    .music-panel-transport-row {
        gap: 6px;
    }

    .music-panel-settings-transport-row {
        grid-template-columns: repeat(7, 38px);
        gap: 7px;
    }

    .music-panel-transport-btn {
        min-height: 54px;
        border-radius: 14px;
    }

    .music-panel-settings-transport-row .music-panel-transport-btn {
        width: 38px;
        min-height: 38px;
        border-radius: 10px;
    }

    .music-panel-clock-card {
        min-height: 0;
    }
}


/* ---- Music sleep timer (button on the Loop Playlist line + chips popover) --------------
   Owner: utils/MusicPanelRuntime.js (armMusicSleepTimer / updateSleepTimerUi), timing core
   shared with the EPUB reader via utils/SleepTimer.js. */

.music-panel-loop-line {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.music-sleep-timer-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.music-sleep-timer-btn.is-armed {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 35%, transparent);
    background: color-mix(in srgb, var(--primary-color) 10%, transparent);
}

.music-sleep-timer-remaining {
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.music-timer-popover {
    margin: 6px 0 8px;
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-pane);
}

.music-timer-popover.hidden {
    display: none;
}

.music-timer-chips {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
}

.music-timer-chip {
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
    font-size: 0.82rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.music-timer-chip:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
}

.music-timer-chip.is-active {
    background: color-mix(in srgb, var(--primary-color) 20%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
    font-weight: 600;
}

.music-timer-custom {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
}

.music-timer-custom.hidden {
    display: none;
}

.music-timer-custom-input {
    width: 96px;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: 7px;
    background: var(--bg-app);
    color: var(--text-main);
    font: inherit;
    font-size: 0.85rem;
}

.music-timer-custom-set {
    padding: 6px 12px;
    border: 1px solid var(--border-color);
    border-radius: 7px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
    font-size: 0.85rem;
}

.music-timer-custom-set:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
}
.ai-agent-chatbox {
    position: fixed;
    left: 16px;
    top: 16px;
    width: min(88vw, 420px);
    min-width: 300px;
    min-height: 170px;
    max-width: 92vw;
    max-height: 88vh;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    box-shadow: 0 22px 50px color-mix(in srgb, var(--mix-dark) 28%, transparent);
    z-index: 5200;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    resize: both;
}

.ai-agent-chatbox.ai-agent-chat-running::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent 0%, var(--accent-gradient-start) 45%, var(--accent-gradient-end) 55%, transparent 100%);
    background-size: 220% 100%;
    animation: aiAgentChatRail 1.1s linear infinite;
    z-index: 4;
}

.ai-agent-chatbox.is-dragging,
.ai-agent-chatbox.is-resizing {
    user-select: none;
    -webkit-user-select: none;
}

/* Two-row header: row 1 = title + settings/close; row 2 = model selector + the
   output toggle / history / preset actions. Stacking gives the model selector its own
   line so it can grow to full width instead of being squeezed/cut off by the buttons. */
.ai-agent-chat-header {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 12px 8px;
    cursor: move;
    user-select: none;
    border-bottom: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 84%, var(--mix-dark) 16%);
}

.ai-agent-chat-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-width: 0;
}

.ai-agent-chat-drag-handle {
    display: none;
    border: none;
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--mix-dark) 8%);
    color: var(--text-muted);
    border-radius: 8px;
    height: 24px;
    min-width: 24px;
    padding: 0 6px;
    align-items: center;
    justify-content: center;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    flex: 0 0 auto;
    line-height: 1;
    font-size: 15px;
}

.ai-agent-chatbox.is-dragging .ai-agent-chat-drag-handle {
    cursor: grabbing;
    color: var(--primary-color);
}

.ai-agent-chat-resize-handle {
    display: none;
    position: absolute;
    right: 6px;
    bottom: 6px;
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--mix-dark) 6%);
    color: var(--text-muted);
    align-items: center;
    justify-content: center;
    font-size: 12px;
    line-height: 1;
    cursor: nwse-resize;
    touch-action: none;
    z-index: 2;
}

.ai-agent-chatbox.is-resizing .ai-agent-chat-resize-handle {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 50%, var(--border-color));
}

/* Touch devices wider than the mobile breakpoint (iPad, touch laptops): native
   `resize: both` has no touch affordance (iOS Safari never draws the corner), so
   swap it for the same pointer-driven grip the mobile layout uses. */
@media (any-pointer: coarse) {
    .ai-agent-chatbox {
        resize: none;
    }

    .ai-agent-chat-resize-handle {
        display: inline-flex;
    }
}

.ai-agent-chat-header-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* Keep the button cluster intact; the title / model selector absorb the free space. */
    flex: 0 0 auto;
}

.ai-agent-chatbox.list-lock .ai-agent-chat-header {
    cursor: default;
    box-shadow: inset 0 -2px 0 color-mix(in srgb, var(--primary-color) 36%, transparent);
}

.ai-agent-chatbox.list-lock .ai-agent-chat-header-actions .icon-btn-small:not(.ai-agent-chat-history-btn):not(.ai-agent-chat-preset-btn) {
    opacity: 0.5;
}

.ai-agent-chat-history-btn.active {
    border-color: color-mix(in srgb, var(--primary-color) 60%, var(--border-color));
    color: var(--primary-color);
}

.ai-agent-chat-config-btn.active {
    border-color: color-mix(in srgb, var(--primary-color) 60%, var(--border-color));
    color: var(--primary-color);
}

/* Recover button: only present when a background (codex/-pro) response is pending. Tinted with
   the warning colour so it reads as "something is waiting for you". */
.ai-agent-chat-recover-btn[hidden] {
    display: none;
}

.ai-agent-chat-recover-btn {
    gap: 2px;
    color: var(--warning-color);
    border-color: color-mix(in srgb, var(--warning-color) 45%, var(--border-color));
}

.ai-agent-chat-recover-btn.active,
.ai-agent-chat-recover-btn:hover {
    color: var(--warning-color);
    border-color: color-mix(in srgb, var(--warning-color) 70%, var(--border-color));
    background: color-mix(in srgb, var(--warning-color) 12%, var(--bg-pane));
}

.ai-agent-chat-recover-count {
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1;
}

/* Per-request live web search toggle (🌐). Author display would beat [hidden], so gate on it. */
.ai-agent-chat-web-btn[hidden] {
    display: none;
}

.ai-agent-chat-web-btn {
    opacity: 0.5;
    filter: grayscale(1);
}

.ai-agent-chat-web-btn:hover {
    opacity: 0.8;
}

.ai-agent-chat-web-btn.is-on {
    opacity: 1;
    filter: none;
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 12%, var(--bg-pane));
}

.ai-agent-chat-web-btn.is-disabled {
    opacity: 0.35;
    cursor: not-allowed;
}

.ai-agent-chat-web-glyph {
    font-size: 0.92rem;
    line-height: 1;
}

.ai-agent-chat-recover-menu {
    position: fixed;
    min-width: 240px;
    max-width: min(420px, calc(100vw - 22px));
    max-height: min(52vh, 460px);
    overflow-y: auto;
    margin: 0;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    box-shadow: var(--shadow-sm);
    padding: 6px;
    z-index: 5600;
}

.ai-agent-chat-recover-head {
    padding: 4px 8px 6px;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.ai-agent-chat-recover-empty {
    padding: 10px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.82rem;
}

.ai-agent-chat-recover-row {
    display: flex;
    align-items: center;
    gap: 4px;
}

.ai-agent-chat-recover-item {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    text-align: left;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-main);
    border-radius: 8px;
    padding: 7px 10px;
    font: inherit;
    cursor: pointer;
}

.ai-agent-chat-recover-item:hover {
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

.ai-agent-chat-recover-model {
    font-size: 0.85rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-agent-chat-recover-meta {
    font-size: 0.72rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-agent-chat-recover-dismiss {
    flex: 0 0 auto;
    color: var(--text-muted);
}

.ai-agent-chat-recover-dismiss:hover {
    color: var(--danger-color, var(--warning-color));
    border-color: color-mix(in srgb, var(--danger-color, var(--warning-color)) 45%, var(--border-color));
}

/* Copy-output button: .icon-btn-small sets display:inline-flex, which would beat the [hidden]
   attribute — this higher-specificity rule lets `hidden` actually hide it. */
.ai-agent-chat-copy-btn[hidden] {
    display: none;
}

/* Ticked feedback after a successful copy. */
.ai-agent-chat-copy-btn.copied {
    color: var(--success-color, var(--primary-color));
    border-color: color-mix(in srgb, var(--success-color, var(--primary-color)) 60%, var(--border-color));
}

/* Output-destination toggle button — a compact pill beside the header icon buttons that cycles
   New Note → Insert → Clipboard. Routes the note-context actions' output; dimmed when ignored. */
.ai-agent-chat-output-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 66px;
    padding: 2px 8px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 50%, var(--border-color));
    border-radius: 8px;
    background: var(--bg-pane);
    cursor: pointer;
    user-select: none;
    font: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--primary-color);
    white-space: nowrap;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}

.ai-agent-chat-output-toggle:hover {
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 70%, var(--border-color));
}

/* Dimmed + non-interactive when the current action ignores output routing (Ask / Spelling /
   App-commands) or while a run is in progress. */
.ai-agent-chat-output-toggle.is-disabled {
    opacity: 0.4;
    cursor: not-allowed;
    color: var(--text-muted);
    border-color: var(--border-color);
    background: var(--bg-pane);
}

/* Gear (settings) dropdown — shares the history menu's surface treatment. */
.ai-agent-chat-config-menu {
    position: fixed;
    min-width: 220px;
    max-width: min(320px, calc(100vw - 22px));
    margin: 0;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    box-shadow: var(--shadow-sm);
    padding: 6px;
    z-index: 5600;
}

.ai-agent-chat-config-item {
    width: 100%;
    text-align: left;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-main);
    border-radius: 8px;
    padding: 8px 10px;
    min-height: 38px;
    display: flex;
    align-items: center;
    gap: 10px;
    font: inherit;
    font-size: 0.85rem;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}

.ai-agent-chat-config-item:hover {
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

.ai-agent-chat-config-item:focus-visible {
    outline: none;
    border-color: color-mix(in srgb, var(--primary-color) 54%, var(--border-color));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 20%, transparent);
}

.ai-agent-chat-config-label {
    flex: 1 1 auto;
}

/* Pill showing the stream/batch state on the toggle row. */
.ai-agent-chat-config-state {
    flex: 0 0 auto;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 999px;
    color: var(--text-muted);
    background: color-mix(in srgb, var(--text-muted) 16%, transparent);
}

.ai-agent-chat-config-item.is-toggle.is-on .ai-agent-chat-config-state {
    color: var(--primary-color);
    background: color-mix(in srgb, var(--primary-color) 18%, transparent);
}

.ai-agent-chat-config-sep {
    height: 1px;
    margin: 4px 6px;
    background: var(--border-color);
}

/* Quick Model Switcher dropdown — shares the menu surface treatment. */
.ai-agent-chat-switcher-menu {
    position: fixed;
    min-width: 220px;
    max-width: min(340px, calc(100vw - 22px));
    max-height: min(56vh, 460px);
    overflow-y: auto;
    margin: 0;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    box-shadow: var(--shadow-sm);
    padding: 6px;
    z-index: 5600;
}

/* Provider filter — sticks to the top of the scrolling menu so it stays reachable while the
   model list below scrolls. The negative margins let it bleed over the menu's 6px padding. */
.ai-agent-switcher-provider-row {
    position: sticky;
    top: -6px;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: -6px -6px 6px;
    padding: 8px 10px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    border-bottom: 1px solid var(--border-color);
}

.ai-agent-switcher-provider-label {
    flex: 0 0 auto;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.ai-agent-switcher-provider {
    flex: 1 1 auto;
    min-width: 0;
    font: inherit;
    font-size: 0.82rem;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 5px 8px;
    cursor: pointer;
}

.ai-agent-switcher-provider:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 60%, transparent);
    outline-offset: 1px;
}

/* Left marker column: pin or star, for quick identification. */
.ai-agent-switcher-mark {
    flex: 0 0 auto;
    width: 1.2em;
    text-align: center;
    font-size: 0.82em;
    line-height: 1;
}

.ai-agent-switcher-mark.is-pin {
    color: var(--primary-color);
}

.ai-agent-switcher-mark.is-star {
    color: var(--warning-color);
}

.ai-agent-switcher-empty {
    padding: 10px;
    text-align: center;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.ai-agent-switcher-item,
.ai-agent-switcher-manage {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    text-align: left;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-main);
    border-radius: 8px;
    padding: 7px 10px;
    font: inherit;
    font-size: 0.85rem;
    line-height: 1.3;
    cursor: pointer;
}

.ai-agent-switcher-item:hover,
.ai-agent-switcher-manage:hover,
.ai-agent-switcher-item.is-focused,
.ai-agent-switcher-manage.is-focused {
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

.ai-agent-switcher-check {
    flex: 0 0 auto;
    width: 1em;
    text-align: center;
    color: var(--primary-color);
    font-weight: 700;
}

.ai-agent-switcher-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    flex: 1 1 auto;
}

.ai-agent-switcher-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-agent-switcher-item.is-active .ai-agent-switcher-name {
    color: var(--primary-color);
    font-weight: 600;
}

.ai-agent-switcher-engine {
    font-size: 0.72rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-agent-switcher-manage {
    color: var(--text-muted);
    font-size: 0.8rem;
    justify-content: flex-start;
}

.ai-agent-chat-history-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1em;
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1;
}

.ai-agent-chat-history-menu {
    position: fixed;
    min-width: 240px;
    max-width: min(420px, calc(100vw - 22px));
    margin: 0;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    box-shadow: var(--shadow-sm);
    /* Flex column so the list scrolls while the Clear-history footer stays pinned at the bottom. */
    display: flex;
    flex-direction: column;
    max-height: min(52vh, 460px);
    padding: 6px;
    z-index: 5600;
}

/* The scrolling list of history rows (the footer below it does not scroll). */
.ai-agent-chat-history-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ai-agent-chat-history-list::-webkit-scrollbar,
.ai-preset-list::-webkit-scrollbar {
    width: 10px;
}

.ai-agent-chat-history-list::-webkit-scrollbar-thumb,
.ai-preset-list::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--primary-color) 32%, var(--border-color));
    border: 2px solid transparent;
    border-radius: 999px;
    background-clip: content-box;
}

/* A history row pairs the prompt (load) with a save-as-preset button. */
.ai-agent-chat-history-row {
    display: flex;
    align-items: stretch;
    gap: 4px;
}

.ai-agent-chat-history-save,
.ai-agent-chat-history-delete {
    flex: 0 0 auto;
    align-self: center;
    color: var(--text-muted);
}

.ai-agent-chat-history-save:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.ai-agent-chat-history-delete:hover {
    color: var(--danger-color, var(--warning-color));
    border-color: color-mix(in srgb, var(--danger-color, var(--warning-color)) 45%, var(--border-color));
}

/* Pinned footer action to clear all history. */
.ai-agent-chat-history-clear {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 6px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-pane);
    color: var(--danger-color, var(--warning-color));
    font: inherit;
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
}

.ai-agent-chat-history-clear svg {
    width: 15px;
    height: 15px;
}

.ai-agent-chat-history-clear:hover {
    background: color-mix(in srgb, var(--danger-color, var(--warning-color)) 12%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--danger-color, var(--warning-color)) 45%, var(--border-color));
}

.ai-agent-chat-history-empty {
    color: var(--text-muted);
    font-size: 0.82rem;
    padding: 8px;
}

.ai-agent-chat-history-item {
    flex: 1 1 auto;
    min-width: 0;
    text-align: left;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-main);
    border-radius: 8px;
    padding: 8px 10px;
    min-height: 38px;
    display: flex;
    align-items: center;
    font: inherit;
    font-size: 0.85rem;
    line-height: 1.3;
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

.ai-agent-chat-history-item:hover {
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    transform: translateX(1px);
}

.ai-agent-chat-history-item:focus-visible {
    outline: none;
    border-color: color-mix(in srgb, var(--primary-color) 54%, var(--border-color));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 20%, transparent);
}

.ai-agent-chat-title {
    /* Natural width on the shared title row — the model selector beside it absorbs the free space
       (and truncates), so the short "Agent Chat" label always stays intact. */
    flex: 0 0 auto;
    min-width: 0;
    font-size: 0.98rem;
    font-weight: 700;
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The model label doubles as the Quick Model Switcher trigger (a button styled as text + caret).
   It shares the title row and grows to absorb the free space, pushing settings/close hard right;
   a long model name truncates with an ellipsis instead of being cut off on the crowded second row. */
.ai-agent-chat-model {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex: 1 1 auto;
    min-width: 40px;
    max-width: 100%;
    margin: 0;
    padding: 1px 4px 1px 0;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.8rem;
    color: var(--text-muted);
    line-height: 1.2;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-agent-chat-model::after {
    content: '▾';
    flex: 0 0 auto;
    font-size: 0.7em;
    opacity: 0.7;
}

.ai-agent-chat-model:hover,
.ai-agent-chat-model.active {
    color: var(--primary-color);
}

.ai-agent-chat-body {
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-gutter: stable;
}

.ai-agent-chat-action-row {
    display: grid;
    grid-template-columns: 70px minmax(0, 1fr);
    gap: 8px;
    align-items: center;
    flex: 0 0 auto;
}

.ai-agent-chat-action-label {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-weight: 600;
}

.ai-agent-chat-action-select {
    min-height: 34px;
    border: 1px solid var(--border-color);
    border-radius: 9px;
    padding: 6px 8px;
    font: inherit;
    font-size: 0.86rem;
    background: var(--bg-editor-pane);
    color: var(--text-main);
}

.ai-agent-chat-action-select:focus {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 45%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
}

.ai-agent-chat-command-filter-row {
    display: grid;
    grid-template-columns: 70px minmax(0, 1fr);
    gap: 8px;
    align-items: start;
}

.ai-agent-chat-command-filter-field {
    position: relative;
    min-width: 0;
}

.ai-agent-chat-command-filter-input {
    width: 100%;
    min-height: 32px;
    border: 1px solid var(--border-color);
    border-radius: 9px;
    padding: 6px 30px 6px 8px;
    font: inherit;
    font-size: 0.84rem;
    background: var(--bg-editor-pane);
    color: var(--text-main);
}

.ai-agent-chat-command-filter-clear {
    position: absolute;
    top: 50%;
    right: 5px;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    min-width: 22px;
    min-height: 22px;
    border-radius: 7px;
}

/* No text to clear → hide the X (placeholder is showing). */
.ai-agent-chat-command-filter-input:placeholder-shown + .ai-agent-chat-command-filter-clear {
    opacity: 0;
    pointer-events: none;
}

.ai-agent-chat-command-filter-input:focus {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 45%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
}

.ai-agent-chat-command-filter-list {
    grid-column: 2;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 160px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-pane);
    padding: 4px;
}

.ai-agent-chat-command-item {
    border: 0;
    background: transparent;
    color: var(--text-main);
    border-radius: 7px;
    padding: 7px 9px;
    width: 100%;
    text-align: left;
    font: inherit;
    font-size: 0.8rem;
    cursor: pointer;
}

.ai-agent-chat-command-item:hover {
    background: color-mix(in srgb, var(--primary-color) 14%, transparent);
}

.ai-agent-chat-command-item.active,
.ai-agent-chat-command-item[aria-selected="true"] {
    background: color-mix(in srgb, var(--primary-color) 18%, transparent);
}

.ai-agent-chat-command-item:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 45%, transparent);
    outline-offset: 1px;
}

.ai-agent-chat-command-empty {
    color: var(--text-muted);
    font-size: 0.78rem;
    padding: 6px 8px;
}

.ai-agent-chat-input-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 40px;
    gap: 8px;
    align-items: stretch;
    flex: 1;
    min-height: 0;
}

.ai-agent-chat-input-wrap {
    position: relative;
    min-height: 0;
}

.ai-agent-chat-input {
    width: 100%;
    min-height: 72px;
    height: 100%;
    flex: 1;
    resize: vertical;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 10px 34px 10px 12px;
    background: var(--bg-editor-pane);
    color: var(--text-main);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 0.92rem;
    font-weight: 400;
    line-height: 1.45;
}

.ai-agent-chat-clear-input {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 24px;
    height: 24px;
    min-width: 24px;
    min-height: 24px;
    border-radius: 8px;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

.ai-agent-chat-input-row:hover .ai-agent-chat-clear-input,
.ai-agent-chat-input-row:focus-within .ai-agent-chat-clear-input {
    opacity: 1;
    pointer-events: auto;
}

.ai-agent-chat-clear-input:disabled {
    opacity: 0.35;
    pointer-events: none;
}

.ai-agent-chat-input:focus {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 45%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
}

/* Live streaming preview — fills token-by-token while a response generates, then
   the final text routes to its destination. Hidden (via the [hidden] attribute)
   for batch providers and between runs; no `display` is set here so the attribute
   keeps working. */
.ai-agent-chat-preview {
    flex: 1 1 auto;
    min-height: 0;
    max-height: 45%;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 9px 11px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: var(--bg-editor-pane);
    color: var(--text-main);
    font-size: 0.9rem;
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    scrollbar-gutter: stable;
}

/* Blinking caret while tokens are still arriving. */
.ai-agent-chat-preview.streaming::after {
    content: '▋';
    display: inline-block;
    margin-left: 1px;
    color: var(--primary-color);
    animation: aiAgentChatCaret 1s steps(2, start) infinite;
}

@keyframes aiAgentChatCaret {
    50% { opacity: 0; }
}

/* Transient region inside the NOTE where AI output streams in before it's committed. Its
   children are normal note content (inherit the editor's element styles); this only marks
   the live region with a subtle pulsing accent rule so the user sees where it's writing. It
   is never persisted — replaced by the final editable content on completion. */
.ai-agent-stream-region {
    border-left: 2px solid color-mix(in srgb, var(--primary-color) 55%, transparent);
    padding-left: 8px;
    margin: 2px 0;
    animation: aiAgentStreamPulse 1.4s ease-in-out infinite;
}

@keyframes aiAgentStreamPulse {
    50% { opacity: 0.74; }
}

.ai-agent-chat-status {
    font-size: 0.82rem;
    color: var(--text-muted);
    min-height: 1.2em;
    flex: 0 0 auto;
}

.ai-agent-chat-status.busy::after {
    content: ' ...';
    display: inline-block;
    width: 1.6em;
    overflow: hidden;
    white-space: nowrap;
    vertical-align: bottom;
    animation: aiAgentChatDots 900ms steps(4, end) infinite;
}

.ai-agent-chat-status.ok {
    color: var(--success-color);
}

.ai-agent-chat-status.warn {
    color: var(--warning-color);
}

.ai-agent-chat-status.error {
    color: var(--danger-color);
}

/* Execute button + elapsed-time readout stacked in the grid's action column. */
.ai-agent-chat-submit-wrap {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    min-width: 0;
    min-height: 0;
}

.ai-agent-chat-submit-timer {
    flex: 0 0 auto;
    margin-top: 4px;
    text-align: center;
    font-size: 0.62rem;
    font-weight: 600;
    line-height: 1;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.ai-agent-chat-submit {
    width: 100%;
    height: auto;
    flex: 1 1 auto;
    min-height: 40px;
    border: 1px solid transparent;
    border-radius: 12px;
    cursor: pointer;
    color: var(--on-accent);
    font-size: 1.2rem;
    line-height: 1;
    font-weight: 700;
    background: var(--accent-gradient);
    box-shadow: 0 10px 22px color-mix(in srgb, var(--accent-gradient-start) 34%, transparent);
}

.ai-agent-chat-submit:hover {
    transform: translateY(-1px);
    box-shadow: 0 12px 24px color-mix(in srgb, var(--accent-gradient-start) 38%, transparent);
}

.ai-agent-chat-submit:disabled {
    cursor: not-allowed;
    opacity: 0.55;
    box-shadow: none;
}

/* Pulse the execute button on/off every 250ms while a run is generating (streaming or batch) —
   users love clear "working" feedback. */
.ai-agent-chat-submit.running {
    animation: aiAgentChatExecutePulse 0.5s linear infinite;
}

@keyframes aiAgentChatExecutePulse {
    0%, 50% { opacity: 1; }
    50.01%, 100% { opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
    .ai-agent-chat-submit.running {
        animation: none;
        opacity: 0.85;
    }
}

.ai-agent-chat-submit-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid color-mix(in srgb, var(--mix-light) 35%, transparent);
    border-top-color: var(--bg-pane);
    animation: aiAgentChatSpin 700ms linear infinite;
}

@keyframes aiAgentChatSpin {
    to { transform: rotate(360deg); }
}

@keyframes aiAgentChatDots {
    from { width: 0; }
    to { width: 1.6em; }
}

@keyframes aiAgentChatRail {
    from { background-position: 200% 0; }
    to { background-position: -20% 0; }
}

@keyframes aiButtonPulse {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger-color) 30%, transparent); }
    65% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--danger-color) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger-color) 0%, transparent); }
}

@keyframes aiHeartbeat {
    0% { transform: scale(1); opacity: 0.9; }
    18% { transform: scale(1.15); opacity: 1; }
    36% { transform: scale(0.98); opacity: 0.94; }
    52% { transform: scale(1.12); opacity: 1; }
    72% { transform: scale(1); opacity: 0.92; }
    100% { transform: scale(1); opacity: 0.9; }
}

/* ============================================================================
   AI Background Jobs — toolbar launcher + standalone ledger panel
   Surfaces long codex/-pro Responses runs (running → done/failed/expired) in one
   place, with a link back to the delivered note. Feature-owned; semantic tokens.
   ============================================================================ */

/* --- Toolbar launcher (always-available entry; hidden only when no jobs) ----- */
/* Author `display` would beat the [hidden] attribute, so gate visibility on it. */
.ai-bg-jobs-launch-btn[hidden] {
    display: none;
}

.ai-bg-jobs-launch-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: var(--warning-color);
}

.ai-bg-jobs-launch-btn:hover {
    color: var(--warning-color);
    background: color-mix(in srgb, var(--warning-color) 12%, var(--bg-pane));
}

/* A running job gently pulses the glyph so an in-flight run is noticeable. */
.ai-bg-jobs-launch-btn.has-running .ai-bg-jobs-glyph {
    animation: ai-bg-jobs-pulse 1.8s ease-in-out infinite;
}

@keyframes ai-bg-jobs-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.45; }
}

.ai-bg-jobs-glyph {
    font-size: 0.95rem;
    line-height: 1;
}

.ai-bg-jobs-badge[hidden] {
    display: none;
}

.ai-bg-jobs-badge {
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    border-radius: 7px;
    background: var(--warning-color);
    color: var(--bg-pane);
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
}

/* --- Panel ------------------------------------------------------------------- */
.ai-bg-jobs-dialog {
    width: min(560px, calc(100vw - 28px));
    max-width: min(560px, calc(100vw - 28px));
}

.ai-bg-jobs-body {
    padding-top: 6px;
}

.ai-bg-jobs-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: min(60vh, 540px);
    overflow-y: auto;
}

.ai-bg-jobs-empty {
    padding: 22px 14px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.86rem;
    line-height: 1.5;
}

.ai-bg-jobs-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--mix-dark) 6%);
}

.ai-bg-jobs-row.status-completed {
    border-color: color-mix(in srgb, var(--success-color, var(--primary-color)) 40%, var(--border-color));
}

.ai-bg-jobs-row.status-failed {
    border-color: color-mix(in srgb, var(--danger-color, var(--warning-color)) 45%, var(--border-color));
}

.ai-bg-jobs-row-main {
    min-width: 0;
    flex: 1 1 auto;
}

.ai-bg-jobs-row-head {
    display: flex;
    align-items: center;
    gap: 8px;
}

.ai-bg-jobs-model {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-bg-jobs-meta {
    margin-top: 3px;
    color: var(--text-muted);
    font-size: 0.78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-bg-jobs-msg {
    margin-top: 4px;
    font-size: 0.76rem;
    color: var(--text-muted);
}

.ai-bg-jobs-row-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

.ai-bg-jobs-action {
    white-space: nowrap;
}

/* --- Status pills ------------------------------------------------------------ */
.ai-bg-jobs-pill {
    flex: 0 0 auto;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    border: 1px solid transparent;
}

.ai-bg-jobs-pill.running {
    color: var(--warning-color);
    border-color: color-mix(in srgb, var(--warning-color) 45%, transparent);
    background: color-mix(in srgb, var(--warning-color) 14%, var(--bg-pane));
}

.ai-bg-jobs-pill.completed {
    color: var(--success-color, var(--primary-color));
    border-color: color-mix(in srgb, var(--success-color, var(--primary-color)) 45%, transparent);
    background: color-mix(in srgb, var(--success-color, var(--primary-color)) 14%, var(--bg-pane));
}

.ai-bg-jobs-pill.failed {
    color: var(--danger-color, var(--warning-color));
    border-color: color-mix(in srgb, var(--danger-color, var(--warning-color)) 45%, transparent);
    background: color-mix(in srgb, var(--danger-color, var(--warning-color)) 14%, var(--bg-pane));
}

.ai-bg-jobs-pill.gone {
    color: var(--text-muted);
    border-color: color-mix(in srgb, var(--text-muted) 40%, transparent);
    background: color-mix(in srgb, var(--text-muted) 10%, var(--bg-pane));
}
#btn-toolbar-toggle {
    min-width: 36px;
    padding: 0;
}

#btn-toolbar-toggle.is-on,
#btn-toolbar-toggle[aria-pressed="true"] {
    color: var(--primary-color);
    border-color: var(--note-card-hover-border);
    background: var(--bg-pane);
}

.theme-mode-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 14px;
    height: 14px;
    border-radius: 999px;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1;
    background: color-mix(in srgb, var(--primary-color) 16%, transparent);
    color: color-mix(in srgb, var(--primary-color) 88%, var(--text-main));
    border: 1px solid color-mix(in srgb, var(--primary-color) 36%, var(--border-color));
}

.focus-mode-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 14px;
    height: 14px;
    border-radius: 999px;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1;
    background: color-mix(in srgb, var(--text-muted) 18%, transparent);
    color: var(--text-muted);
    border: 1px solid color-mix(in srgb, var(--text-muted) 34%, var(--border-color));
}

#btn-focus-mode.active .focus-mode-pill {
    background: color-mix(in srgb, var(--primary-color) 18%, transparent);
    color: color-mix(in srgb, var(--primary-color) 88%, var(--text-main));
    border-color: color-mix(in srgb, var(--primary-color) 36%, var(--border-color));
}

#btn-focus-mode.inactive {
    color: var(--text-muted);
    border-color: var(--border-color);
}

#btn-theme-toggle.active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.editor-content-wrapper {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    padding: 10px 42px 44px 42px;
    max-width: 100%; /* Full Width */
    margin: 0;
    width: 100%;
    min-height: 0; /* Critical for flex child scrolling */
}

.note-title-input {
    display: block;
    font-size: 2rem;
    font-weight: 700;
    /* Heading-tight leading so a wrapped title doesn't show the body's loose 1.6 gap between its
       lines (that inter-line gap scales with font size, unlike the margin-based before/after
       spacing). */
    line-height: 1.2;
    border: none;
    outline: none;
    padding: 8px 44px 8px 0;
    margin-bottom: 16px;
    width: 100%;
    max-width: 100%;
    min-width: 0;
    color: var(--text-main);
    background: transparent;
    cursor: text;
    /* Wrap long titles onto multiple lines (breaking long unbroken tokens like filenames)
       instead of truncating with an ellipsis. */
    white-space: normal;
    overflow-wrap: anywhere;
}

.note-title-input:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
    font-style: italic;
    font-weight: 400;
}

.note-title-row {
    position: relative;
    width: 100%;
    min-width: 0;
}

.title-clear-btn {
    right: 0;
    top: 12px;
    transform: none;
}

.note-body-input, .note-editor {
    flex-grow: 1;
    border: none;
    outline: none;
    resize: none;
    /* Base text size/family come from the global default text Style Set, set as CSS vars by
       applyTextStyleBase(); the fallbacks reproduce the legacy default (14px / system sans). */
    font-size: var(--note-base-size);
    /* --note-zoom is a transient reading-zoom multiplier set by NoteZoomController
       (pinch / Ctrl+wheel / Ctrl+/-); it defaults to 1 and resets on every note open.
       CSS zoom (a layout scale, not a transform) re-lays-out content at the new size, so
       text reflows to width and the caret stays correct. Unlike multiplying font-size,
       zoom also reaches text with explicit px sizes — per-note Style Set rules (whose
       #note-body id rules out-specify this class rule) and per-selection
       <span style="font-size:Npx"> runs — so every note zooms identically. */
    zoom: var(--note-zoom, 1);
    line-height: 1.6;
    color: var(--text-editor);
    font-family: var(--note-base-font);
    overflow-y: auto;
    /* Keep 1-finger vertical scrolling with the browser, but hand multi-touch
       (the reading-zoom pinch in NoteZoomController) to our JS instead of letting
       the browser swallow it as a scroll/zoom gesture. */
    touch-action: pan-y;
}

/* Live speech-dictation interim text: unconfirmed words render faint/italic as they stream in, then
   solidify into normal note text when the recognizer confirms them (utils/DictationInterimController.js).
   Semantic --text-muted keeps it legible-but-secondary in both light and dark themes. Transient: never
   persisted (stripped in editor.js getCleanClone). */
.cyb-dictation-interim {
    color: var(--text-muted);
    font-style: italic;
    opacity: 0.85;
}

.note-editor[placeholder]:empty:before {
    content: attr(placeholder);
    color: var(--text-placeholder);
    cursor: text;
    padding-right: 34px;
}

.note-editor.note-editor-empty-state[placeholder]:empty:before {
    display: block;
    width: 100%;
    text-align: center;
    font-size: 1.1rem;
    padding-right: 0;
    margin-top: 30vh;
    cursor: default;
}

.note-backlinks {
    flex-shrink: 0;
    margin-top: 14px;
    border-top: 1px solid var(--border-color);
    padding-top: 10px;
}

.note-backlinks-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.note-backlinks.hidden {
    display: none;
}

.note-backlinks-title {
    margin: 0;
    flex: 1;
    font-size: 0.86rem;
    color: var(--text-muted);
    font-weight: 600;
}

/* Floating prev/next note navigation. Overlays the note text rather than taking
   layout space, and is decoupled from the backlinks section so it still shows
   when a note has no backlinks. Hidden on desktop (no note nav there today);
   shown on mobile, vertically centred on the left/right edges (see media query
   below). The container is click-through; only the buttons capture taps. */
.note-nav-floating {
    display: none;
}

.note-nav-floating-btn {
    position: absolute;
    /* Sit in the lower 25% of the note (centred within the 75%–100% band) rather than the
       vertical middle, so the buttons don't overlap the main reading/editing area. */
    top: 87.5%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 86%, transparent);
    color: var(--text-main);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    opacity: 0.5;
    box-shadow: 0 4px 12px color-mix(in srgb, var(--mix-dark) 16%, transparent);
    pointer-events: auto;
    cursor: pointer;
    transition: opacity var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease);
}

.note-nav-floating-btn:hover,
.note-nav-floating-btn:focus-visible,
.note-nav-floating-btn:active {
    opacity: 1;
    background: var(--bg-pane);
}

.note-nav-floating-btn svg {
    width: 20px;
    height: 20px;
}

.note-nav-floating-prev { left: 6px; }
.note-nav-floating-next { right: 6px; }

.note-backlinks-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 180px;
    overflow-y: auto;
}

.note-backlink-item {
    text-align: left;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-pane);
    color: var(--text-main);
    padding: 8px 10px;
    cursor: pointer;
}

.note-backlink-item:hover,
.note-backlink-item:focus-visible {
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 8%, var(--bg-pane));
}

.note-backlink-title {
    font-size: 0.86rem;
    font-weight: 600;
    margin-bottom: 2px;
}

.note-backlink-snippet {
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.note-backlinks-empty {
    font-size: 0.82rem;
    color: var(--text-muted);
    padding: 6px 0;
}

@media (max-width: 768px) {
    /* The format toolbar is fixed to the bottom of the screen on mobile, so the
       thin divider it normally draws between the title and the content (its
       border-bottom on desktop) is missing, leaving a loose empty gap. Recreate
       that divider on the title row and tighten the spacing so the note text
       starts just beneath the line. */
    .note-title-input {
        margin-bottom: 8px;
    }

    .note-title-row {
        border-bottom: 1px solid var(--border-color);
        margin-bottom: 12px;
    }

    .note-backlinks-title {
        text-align: center;
    }

    /* Show the floating nav, spanning the editor pane so the buttons centre on
       the viewport edges. Click-through container; buttons re-enable pointers. */
    .note-nav-floating {
        display: block;
        position: absolute;
        inset: 0;
        pointer-events: none;
        z-index: 45;
    }
}

/* --- LINKS INSIDE NOTES --- */
.note-editor a {
    color: var(--primary-color);
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--primary-color) 40%, transparent);
    text-underline-offset: 2px;
    cursor: text;
    transition: color 0.15s, text-decoration-color 0.15s;
    position: relative;
    /* Press-and-hold on touch opens our link action card, not the OS callout. */
    -webkit-touch-callout: none;
}
.note-editor a:hover {
    text-decoration-color: var(--primary-color);
}

/* Link tooltip popover */
.link-tooltip {
    position: fixed;
    z-index: 6000;
    background: var(--selection-color);
    border: 1px solid var(--note-card-active-border);
    border-left: 3px solid var(--primary-color);
    border-radius: 10px;
    box-shadow: 0 8px 18px var(--primary-alpha-14);
    padding: 0;
    max-width: 340px;
    min-width: 200px;
    font-size: 0.88rem;
    pointer-events: auto;
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
    overflow: hidden;
}

:root[data-theme="dark"] .link-tooltip {
    background-color: color-mix(in srgb, var(--primary-color) 30%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 44%, var(--border-color));
    box-shadow: 0 8px 18px color-mix(in srgb, var(--mix-dark) 34%, transparent);
}
/* Invisible bridge above tooltip to cover the gap between link and tooltip */
.link-tooltip::before {
    content: '';
    position: absolute;
    top: -14px;
    left: 0;
    right: 0;
    height: 14px;
}
.link-tooltip.visible {
    opacity: 1;
    transform: translateY(0);
}
.link-tooltip-preview {
    display: flex;
    flex-direction: column;
    gap: 0;
}
.link-tooltip-preview .lt-image {
    width: 100%;
    /* 1.91:1 is the ratio every site publishes its og:image at, so honour it rather than imposing a
       box of our own. The previous fixed 120px height made this box 2.83:1, and object-fit: cover
       then threw away a THIRD of every preview image — 103px off the top and bottom of a standard
       1200x630 card, which is exactly where sites put their logo and their tagline. */
    aspect-ratio: 1.91 / 1;
    /* Still cover: an image that is not 1.91:1 fills the box centred rather than letterboxing. */
    object-fit: cover;
    display: block;
    background: color-mix(in srgb, var(--border-color) 30%, var(--bg-pane));
}
.link-tooltip-preview .lt-body {
    padding: 10px 12px 11px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.link-tooltip-preview .lt-title {
    font-weight: 600;
    font-size: 0.94rem;
    color: var(--text-main);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.link-tooltip-preview .lt-desc {
    font-size: 0.83rem;
    color: color-mix(in srgb, var(--text-main) 74%, var(--text-muted));
    line-height: 1.35;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.link-tooltip-preview .lt-domain {
    font-size: 0.78rem;
    color: color-mix(in srgb, var(--text-main) 62%, var(--text-muted));
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 3px;
}
.link-tooltip-preview .lt-domain img {
    width: 14px;
    height: 14px;
    border-radius: 2px;
    flex-shrink: 0;
}
/* Typed cards (PDF / image / other): the resource kind, under the filename that replaces the title. */
.link-tooltip-preview .lt-kind {
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: color-mix(in srgb, var(--text-main) 58%, var(--text-muted));
}
.link-tooltip-actions {
    display: flex;
    gap: 8px;
    border-top: 1px solid var(--border-color);
    padding: 8px 10px;
    background: color-mix(in srgb, var(--bg-pane) 86%, transparent);
}
.link-tooltip-actions button {
    flex: 1;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-pane);
    padding: 7px 10px;
    font-size: 0.82rem;
    cursor: pointer;
    color: var(--primary-color);
    font-weight: 500;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease);
}
.link-tooltip-actions button:hover {
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 42%, var(--border-color));
    box-shadow: var(--shadow-sm);
    transform: translateY(-1px);
}
.link-tooltip-actions button:active {
    transform: translateY(0);
    box-shadow: none;
}
.link-tooltip-fallback {
    padding: 10px 12px;
    word-break: break-all;
    color: color-mix(in srgb, var(--text-main) 72%, var(--text-muted));
    font-size: 0.82rem;
    line-height: 1.4;
}
.link-tooltip-fallback .lt-url {
    color: var(--primary-color);
    text-decoration: none;
}
/* "Local link": an address the bridge will never fetch (intranet, loopback, odd port). A settled
   answer, not a pending one, so it reads as a label rather than a card still loading. */
.link-tooltip-fallback .lt-note {
    display: block;
    margin-bottom: 4px;
    font-size: 0.76rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.link-tooltip-internal-preview {
    padding: 10px 12px 11px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.link-tooltip-internal-preview .lt-title {
    font-weight: 600;
    font-size: 0.94rem;
    color: var(--text-main);
    line-height: 1.3;
}

.link-tooltip-internal-preview .lt-title > * {
    margin: 0;
}

.link-tooltip-internal-preview .lt-breadcrumb {
    font-size: 0.76rem;
    color: color-mix(in srgb, var(--text-main) 58%, var(--text-muted));
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.link-tooltip-internal-preview .lt-desc {
    font-size: 0.83rem;
    color: color-mix(in srgb, var(--text-main) 74%, var(--text-muted));
    line-height: 1.35;
}

.link-tooltip-internal-preview .lt-rich {
    max-height: 150px;
    overflow: hidden;
    font-size: 0.84rem;
    line-height: 1.45;
    color: color-mix(in srgb, var(--text-main) 88%, var(--text-muted));
}

.link-tooltip-internal-preview .lt-rich h1,
.link-tooltip-internal-preview .lt-rich h2,
.link-tooltip-internal-preview .lt-rich h3 {
    margin: 0 0 5px 0;
    font-size: 0.9rem;
    line-height: 1.3;
}

.link-tooltip-internal-preview .lt-rich p,
.link-tooltip-internal-preview .lt-rich div,
.link-tooltip-internal-preview .lt-rich ul,
.link-tooltip-internal-preview .lt-rich ol,
.link-tooltip-internal-preview .lt-rich blockquote,
.link-tooltip-internal-preview .lt-rich pre {
    margin: 0 0 6px 0;
}

.link-tooltip-internal-preview .lt-rich p:last-child,
.link-tooltip-internal-preview .lt-rich div:last-child,
.link-tooltip-internal-preview .lt-rich ul:last-child,
.link-tooltip-internal-preview .lt-rich ol:last-child,
.link-tooltip-internal-preview .lt-rich blockquote:last-child,
.link-tooltip-internal-preview .lt-rich pre:last-child {
    margin-bottom: 0;
}

.link-tooltip-internal-preview .lt-rich pre,
.link-tooltip-internal-preview .lt-rich code {
    white-space: pre-wrap;
    word-break: break-word;
}

.link-tooltip-internal-preview .lt-domain {
    font-size: 0.78rem;
    color: color-mix(in srgb, var(--text-main) 62%, var(--text-muted));
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: 2px;
}

/* --- FORMAT TOOLBAR --- */
.format-toolbar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 8px 0;
    margin-bottom: 12px;
    background: var(--bg-editor-pane);
    position: sticky;
    top: 0;
    z-index: 10;
    border-bottom: 1px solid var(--border-color);
}
.format-toolbar.hidden {
    display: none;
}

.format-toolbar-drag-handle {
    display: none;
    border: none;
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--mix-dark) 8%);
    color: var(--text-muted);
    border-radius: 8px;
    height: 24px;
    min-width: 24px;
    padding: 0 6px;
    align-items: center;
    justify-content: center;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    flex: 0 0 auto;
    line-height: 1;
    font-size: 15px;
}

.format-toolbar.is-dragging .format-toolbar-drag-handle {
    cursor: grabbing;
    color: var(--primary-color);
}
.fmt-btn {
    background: none;
    border: none;
    border-radius: 4px;
    padding: 4px 6px;
    color: var(--text-muted);
    cursor: pointer;
    display: flex;
    align-items: center;
    font-size: 0.9rem;
    font-weight: 600;
}
.fmt-btn:hover {
    background: var(--item-hover);
    color: var(--primary-color);
}
.fmt-btn[aria-pressed="true"],
.fmt-btn[data-state="armed"],
.fmt-btn[data-state="locked"] {
    background: color-mix(in srgb, var(--primary-color) 12%, white);
    color: var(--primary-color);
}
.fmt-btn[data-state="locked"] {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--primary-color) 35%, transparent);
}
.fmt-btn i {
    width: var(--fmt-toolbar-icon-size);
    height: var(--fmt-toolbar-icon-size);
}
.fmt-btn[data-val="H1"],
.fmt-btn[data-val="H2"] {
    padding: 4px 6px;
}
.fmt-btn[data-val="H1"] i,
.fmt-btn[data-val="H2"] i {
    width: var(--fmt-heading-icon-size);
    height: var(--fmt-heading-icon-size);
    transform: scale(var(--fmt-heading-icon-scale));
    transform-origin: center;
}

.fmt-btn .fmt-glyph {
    font-size: 18px;
    line-height: 1;
    font-weight: 700;
}
.fmt-sep {
    width: 1px;
    height: 16px;
    background: var(--item-hover);
    margin: 0 4px;
}
/* Rich Text Content Styling */
.note-editor ul, .note-editor ol {
    padding-left: 24px;
    margin-bottom: 10px;
}
.note-editor h1 { font-size: 1.6em; margin: 0.5em 0; border-bottom: 1px solid var(--blockquote-border);}
.note-editor h2 { font-size: 1.3em; margin: 0.5em 0; }
/* H3-H6 were previously unstyled (only H1/H2 were reachable). Give them a sensible descending
   scale so the new Heading 3-6 levels render distinctly. em-based so they track the base size. */
.note-editor h3 { font-size: 1.15em; font-weight: 600; margin: 0.5em 0; }
.note-editor h4 { font-size: 1.05em; font-weight: 600; margin: 0.5em 0; }
.note-editor h5 { font-size: 1em; font-weight: 600; margin: 0.5em 0; }
.note-editor h6 { font-size: 0.9em; font-weight: 600; margin: 0.5em 0; color: var(--text-editor-muted); }
/* Heading-tight leading: headings otherwise inherit the body's 1.6 line-height, which leaves a large
   gap between the lines of a wrapped heading (the gap scales with font size, unlike the margin-based
   before/after spacing). */
.note-editor h1, .note-editor h2, .note-editor h3,
.note-editor h4, .note-editor h5, .note-editor h6 { line-height: 1.2; }
.note-editor p { margin-bottom: 0.8em; }
.note-editor blockquote { 
    border-left: 3px solid var(--blockquote-border); 
    padding-left: 10px; 
    color: var(--text-editor-muted);
    margin: 10px 0;
}

.note-editor table {
    border-collapse: collapse;
    width: 100%;
    margin: 10px 0;
    font-size: 0.95rem;
}

.note-editor th,
.note-editor td {
    border: 1px solid var(--border-color);
    padding: 6px 8px;
    vertical-align: top;
}

.note-editor th {
    background: color-mix(in srgb, var(--selection-color) 45%, var(--bg-pane));
    font-weight: 600;
}

.note-editor caption {
    text-align: left;
    color: var(--text-muted);
    margin-bottom: 6px;
}

.note-editor .note-table-wrap {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 10px 0;
}

.note-editor .note-table-wrap table {
    margin: 0;
}

@media (max-width: 768px) {
    .note-editor .note-table-wrap table {
        width: max-content;
        min-width: 100%;
    }
}

/* AI Model Manager dialog (Phase G3). A provider-scoped modal for browsing,
   selecting, and organizing AI models. Feature-owned; all selectors are scoped
   under .ai-mm to avoid global collisions. Driven entirely by semantic theme
   tokens so it themes light/dark with the rest of the app.
   See Docs/AI Integration/007-ai-model-manager-dialog-design.md. */

.ai-mm {
    display: flex;
    flex-direction: column;
    width: min(640px, 100vw - 24px);
    max-height: min(86vh, 880px);
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg, 14px);
    box-shadow: var(--shadow-md, 0 12px 40px color-mix(in srgb, var(--mix-dark) 25%, transparent));
    overflow: hidden;
}

/* The [hidden] attribute must win over the explicit `display` rules on buttons and bars
   below (an author `display` overrides the user-agent `[hidden]{display:none}`), so the
   per-mode chrome toggling (render() sets el.hidden) actually hides elements. */
.ai-mm [hidden] { display: none !important; }

.ai-mm__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color);
}

.ai-mm__heading {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex: 1 1 auto;
    min-width: 0;
}

.ai-mm__title {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 650;
    flex: 0 0 auto;
}

/* The active (in-use) model, shown beside the title so it's clear across all
   providers which model is selected. */
.ai-mm__selected {
    min-width: 0;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--success-color);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ai-mm__selected.is-empty { color: var(--text-muted); font-weight: 500; }

.ai-mm__close {
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 1.05rem;
    line-height: 1;
    width: 30px;
    height: 30px;
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
}
.ai-mm__close:hover { background: var(--item-hover); color: var(--text-main); }

.ai-mm__toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px 6px;
}

.ai-mm__provider-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.84rem;
    color: var(--text-muted);
    flex: 1 1 auto;
    min-width: 0;
}

.ai-mm__provider {
    flex: 1 1 auto;
    min-width: 0;
    padding: 7px 10px;
    font-size: 0.9rem;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
}

.ai-mm__icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 10px;
    font-size: 0.9rem;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
    white-space: nowrap;
}
.ai-mm__icon-btn:hover { background: var(--item-hover); }
.ai-mm__icon-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.ai-mm__search-wrap { padding: 6px 16px 8px; }

.ai-mm__search {
    width: 100%;
    padding: 8px 12px;
    font-size: 0.92rem;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
}
.ai-mm__search::placeholder { color: var(--text-muted); }

.ai-mm__grid {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 4px 10px;
    min-height: 120px;
}

.ai-mm__empty {
    padding: 28px 16px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.ai-mm__divider {
    height: 1px;
    background: var(--border-color);
    margin: 6px 8px;
    border: none;
}

.ai-mm__model {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: var(--radius-sm, 8px);
    cursor: pointer;
}
.ai-mm__model:hover { background: var(--item-hover); }

/* Clicked/focused row — a highlight only; it does NOT change the active model
   (the row's ✓ button does that). */
.ai-mm__model.is-highlight {
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    box-shadow: inset 3px 0 0 var(--primary-color);
}

/* The active (in-use) model, marked by the green ✓ in the extreme-left column. */
.ai-mm__model.is-active {
    background: color-mix(in srgb, var(--success-color) 12%, var(--bg-pane));
    font-weight: 600;
}

/* A model the provider has deprecated (no longer in its catalog): muted name + ⚠. */
.ai-mm__model.is-deprecated .ai-mm__name { color: var(--text-muted); }

/* Extreme-left column: green ✓ for the active model; empty (but space-holding)
   otherwise so the type icons line up across rows. */
.ai-mm__check {
    flex: 0 0 auto;
    width: 16px;
    text-align: center;
    color: var(--success-color);
    font-weight: 700;
    font-size: 0.95rem;
    line-height: 1;
}

/* Left margin: exactly one type icon (local or cloud) per row. */
.ai-mm__type {
    flex: 0 0 auto;
    width: 20px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.95rem;
}
.ai-mm__model.is-active .ai-mm__type { color: var(--primary-color); }

/* Left cluster: type icon + compact status indicators (pin/star/web). Only the
   active indicators render, packed tightly next to each other. */
.ai-mm__left {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 3px;
}
.ai-mm__ind {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.78rem;
    color: var(--text-muted);
}
.ai-mm__ind--pin.is-on { color: var(--primary-color); }
.ai-mm__ind--deprecated.is-on { color: var(--warning-color); }
.ai-mm__ind--web.is-on {
    border: 1px solid currentColor;
    border-radius: 4px;
    padding: 0 2px;
    font-size: 0.6rem;
    font-weight: 700;
}
/* Notes/description marker — hover reveals the model's description. */
.ai-mm__ind--desc.is-on {
    color: var(--primary-color);
    cursor: help;
}

/* Main column: name row (+ inline availability badge) over an optional meta line.
   flex-basis 0 (not auto) is deliberate: the meta line's long fact string would
   otherwise size this column by its content and — with min-width:0 — let flexbox
   shrink it toward zero, collapsing the name to "ne…" and overflowing the row on
   narrow screens. Basis 0 sizes it from the available space, so the name stays
   readable and the meta wraps inside the column. */
.ai-mm__main {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ai-mm__namerow {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.ai-mm__name {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Secondary metadata line on an implemented row (facts + feature chips), mirroring the
   Ollama fetch list. Only present for models that carry provider metadata. */
.ai-mm__meta {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: 0.74rem;
    color: var(--text-muted);
}

/* Per-row actions, revealed on hover/active. */
.ai-mm__row-actions {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    opacity: 0;
    transition: opacity 0.12s ease;
}
.ai-mm__model:hover .ai-mm__row-actions,
.ai-mm__model.is-active .ai-mm__row-actions,
.ai-mm__model.is-highlight .ai-mm__row-actions { opacity: 1; }

.ai-mm__row-btn {
    border: none;
    background: transparent;
    color: var(--text-muted);
    width: 26px;
    height: 26px;
    border-radius: var(--radius-sm, 6px);
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1;
}
.ai-mm__row-btn:hover { background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane)); color: var(--primary-color); }
.ai-mm__row-btn.is-on { color: var(--primary-color); }
/* The select (✓) action reads as the active-state green. */
.ai-mm__row-btn[data-mm="row-select"].is-on { color: var(--success-color); }
.ai-mm__row-btn[data-mm="row-select"]:hover { background: color-mix(in srgb, var(--success-color) 16%, var(--bg-pane)); color: var(--success-color); }
.ai-mm__row-btn--danger:hover { background: color-mix(in srgb, var(--danger-color) 16%, var(--bg-pane)); color: var(--danger-color); }

.ai-mm__grid-footer,
.ai-mm__footer {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-top: 1px solid var(--border-color);
}
.ai-mm__footer { justify-content: flex-end; }
.ai-mm__grid-footer { justify-content: flex-start; }

/* Sub-views (add provider / fetched models) reuse the grid area. */
.ai-mm__sub {
    padding: 6px 6px;
}
.ai-mm__sub-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: var(--radius-sm, 8px);
    cursor: pointer;
}
.ai-mm__sub-row:hover { background: var(--item-hover); }
.ai-mm__sub-row input[type="checkbox"] { width: 16px; height: 16px; }

/* Web access not possible for this model/provider (018 WS-6a): greyed + non-interactive. */
.ai-mm__sub-row--disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.ai-mm__sub-row--disabled:hover { background: transparent; }
.ai-mm__sub-row--disabled input[type="checkbox"] { cursor: not-allowed; }

.ai-mm__sub-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 4px 12px 10px;
    color: var(--text-muted);
    font-size: 0.86rem;
}
.ai-mm__note { padding: 8px 12px; color: var(--text-muted); font-size: 0.82rem; }
.ai-mm__note--warn { color: var(--danger-color); }

/* Per-model edit form fields. */
.ai-mm__field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px 12px;
}
.ai-mm__field-label {
    font-size: 0.8rem;
    color: var(--text-muted);
}
.ai-mm__field-input {
    padding: 8px 10px;
    font-size: 0.9rem;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
}
.ai-mm__field-input::placeholder { color: var(--text-muted); }
/* Multi-line model Description: vertically resizable, comfortable for a lot of detail. */
.ai-mm__field-textarea {
    min-height: 64px;
    max-height: 260px;
    resize: vertical;
    font-family: inherit;
    line-height: 1.4;
}
.ai-mm__field-hint {
    padding: 0 12px 4px;
    font-size: 0.76rem;
    line-height: 1.35;
    color: var(--text-muted);
}

/* --- Add-models fetch list (rich rows) ----------------------------------- */
.ai-mm__fetch-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 2px 12px 8px;
}
.ai-mm__fetch-filter {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.84rem;
    color: var(--text-main);
    cursor: pointer;
}
.ai-mm__fetch-filter input[type="checkbox"] { width: 15px; height: 15px; }
.ai-mm__fetch-hint { font-size: 0.78rem; color: var(--text-muted); font-style: italic; }

.ai-mm__fetch-list { display: flex; flex-direction: column; }

.ai-mm__fetch-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 12px;
    border-radius: var(--radius-sm, 8px);
    cursor: pointer;
}
.ai-mm__fetch-row:hover { background: var(--item-hover); }
.ai-mm__fetch-cb { width: 16px; height: 16px; margin-top: 2px; flex: 0 0 auto; }

.ai-mm__fetch-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
.ai-mm__fetch-namerow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ai-mm__fetch-name {
    font-size: 0.92rem;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}
.ai-mm__fetch-badges { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }

.ai-mm__fetch-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: 0.78rem;
    color: var(--text-muted);
    min-height: 1em;
}
.ai-mm__fetch-facts { white-space: nowrap; }
.ai-mm__fetch-facts--wait { opacity: 0.6; }

/* Availability pill. */
.ai-mm__pill {
    display: inline-flex;
    align-items: center;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1.5;
    padding: 0 7px;
    border-radius: 999px;
    border: 1px solid var(--border-color);
    white-space: nowrap;
}
.ai-mm__pill--free { color: var(--success-color); border-color: color-mix(in srgb, var(--success-color) 45%, var(--border-color)); }
.ai-mm__pill--cloud { color: var(--primary-color); border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color)); }

/* Feature chip (vision / tools / thinking / …). */
.ai-mm__chip {
    display: inline-flex;
    align-items: center;
    font-size: 0.68rem;
    font-weight: 600;
    line-height: 1.5;
    padding: 0 6px;
    border-radius: 4px;
    color: var(--text-muted);
    background: var(--item-hover);
}

/* Primary action in the fixed footer bar (e.g. "Add selected" in the fetch view). Accent-tinted
   so it reads as the main action, using theme tokens (no hardcoded colors). */
.ai-mm__grid-footer-primary {
    font-weight: 600;
    color: var(--primary-color);
    background: color-mix(in srgb, var(--primary-color) 16%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
}
.ai-mm__grid-footer-primary:hover { background: color-mix(in srgb, var(--primary-color) 26%, var(--bg-pane)); }

/* --- Narrow screens -------------------------------------------------------- */
/* On phones a model row has little width to spare. The biggest waster was the
   per-row hover-action cluster: it is opacity:0 by default but `display:flex` still
   RESERVES ~138px of the row, squeezing the name down to "ne…". Collapse it until the
   row is tapped (active/highlight), which frees that width for the name. Then let the
   name and the facts line wrap instead of ellipsing/overflowing, so every model name
   is fully readable and the row no longer scrolls sideways. */
@media (max-width: 768px) {
    .ai-mm__row-actions { display: none; }
    .ai-mm__model.is-active .ai-mm__row-actions,
    .ai-mm__model.is-highlight .ai-mm__row-actions { display: inline-flex; opacity: 1; }

    .ai-mm__namerow { align-items: flex-start; }
    .ai-mm__name {
        flex: 1 1 auto;
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        overflow-wrap: anywhere;
    }
    /* The facts line is nowrap by default (tidy single line on desktop); let it wrap
       on phones so the spec/price string never forces a horizontal scrollbar. */
    .ai-mm__fetch-facts { white-space: normal; }
}
/* Paragraph-style dropdown (Title / Normal / Heading 1-6) in the editor format toolbar.
   Phase 1 of the text-styles feature. Scoped under .para-style-control to avoid global collisions.
   The menu is an absolutely-positioned popover (like the existing color picker); the toolbar is left
   without overflow clipping so the popover isn't cut off (horizontal-scroll toolbar arrives later
   with fixed-positioned popovers). */

.para-style-control,
.font-style-control {
    position: relative;
    display: inline-flex;
    flex: 0 0 auto;
}

.para-style-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    width: auto;
    min-width: 62px;
    padding: 0 6px;
    white-space: nowrap;
}

.para-style-current {
    font-size: 0.82rem;
    font-weight: 600;
}

.para-style-caret {
    width: 14px;
    height: 14px;
    opacity: 0.7;
}

.para-style-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 60;
    min-width: 168px;
    max-height: 60vh;
    overflow-y: auto;
    padding: 6px;
    background: var(--bg-editor-pane);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 10px 28px color-mix(in srgb, var(--mix-dark) 18%, transparent);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.para-style-menu.hidden {
    display: none;
}

.para-style-item {
    display: block;
    width: 100%;
    text-align: left;
    border: none;
    background: none;
    color: var(--text-editor);
    padding: 6px 10px;
    border-radius: 6px;
    cursor: pointer;
    line-height: 1.2;
    font-family: inherit;
}

.para-style-item:hover:not([disabled]) {
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-editor-pane));
}

.para-style-item.is-active {
    background: color-mix(in srgb, var(--primary-color) 20%, var(--bg-editor-pane));
}

.para-style-item[disabled] {
    opacity: 0.5;
    cursor: default;
}

/* Separator + "Manage styles…" entry at the foot of the paragraph-style menu. */
.para-style-sep {
    height: 1px;
    margin: 4px 2px;
    background: var(--border-color);
}
.para-style-manage {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--primary-color);
}

/* "Text styles" manage dialog (per-note paragraph styles). Reuses the shared .modal-overlay /
   .modal-box base; only the inner layout is feature-owned here. */
.ts-box {
    width: min(94vw, 460px);
    max-width: 460px;
    text-align: left;
}
.ts-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}
.ts-title { font-weight: 600; color: var(--text-editor); }
.ts-x {
    border: none;
    background: none;
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    color: var(--text-editor-muted);
}
.ts-x:hover { color: var(--text-editor); }
.ts-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.8rem;
    color: var(--text-editor-muted);
}
.ts-field > span { font-weight: 600; }
.ts-field select,
.ts-field input[type="number"] {
    padding: 5px 7px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--bg-editor-pane);
    color: var(--text-editor);
    font-family: inherit;
}
.ts-level-field { margin-bottom: 12px; }
.ts-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px 12px;
}
.ts-color-wrap { display: flex; align-items: center; gap: 8px; }
.ts-color-wrap input[type="color"] {
    width: 36px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: none;
    cursor: pointer;
}
.ts-default { display: flex; align-items: center; gap: 4px; font-weight: 400; }
.ts-preview-wrap {
    margin: 14px 0;
    padding: 14px;
    border: 1px dashed var(--border-color);
    border-radius: 8px;
    background: var(--bg-editor-pane);
}
.ts-preview { color: var(--text-editor); }
.ts-defaults {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    font-size: 0.8rem;
    color: var(--text-editor-muted);
}
.ts-defaults-label { font-weight: 600; }
.ts-presets {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    font-size: 0.8rem;
    color: var(--text-editor-muted);
}
.ts-presets select,
.ts-presets .ts-preset-name {
    padding: 5px 7px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--bg-editor-pane);
    color: var(--text-editor);
    font-family: inherit;
}
.ts-presets .ts-preset-name { flex: 1 1 120px; min-width: 100px; }
.ts-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-end;
}

/* Per-level live previews so each option looks roughly like what it applies. */
.para-style-item[data-level="title"]  { font-size: 1.5rem;  font-weight: 700; }
.para-style-item[data-level="normal"] { font-size: 0.95rem; font-weight: 400; }
.para-style-item[data-level="h1"]     { font-size: 1.5rem;  font-weight: 700; }
.para-style-item[data-level="h2"]     { font-size: 1.3rem;  font-weight: 700; }
.para-style-item[data-level="h3"]     { font-size: 1.15rem; font-weight: 600; }
.para-style-item[data-level="h4"]     { font-size: 1.05rem; font-weight: 600; }
.para-style-item[data-level="h5"]     { font-size: 0.95rem; font-weight: 600; }
.para-style-item[data-level="h6"]     { font-size: 0.88rem; font-weight: 600; }
/* Copy / Apply document format — the two paragraph-style-menu rows and the small "Apply document
   format" confirm dialog. Scoped under feature classes (.para-style-copyfmt/.applyfmt, .fmtcopy-*)
   to avoid global collisions. Reuses the shared .modal-overlay / .modal-box base and semantic
   theme tokens. See Docs/000-copy-document-format-design.md. */

/* Menu rows sit with "Manage styles…" — match its compact size (override the per-level previews). */
.para-style-item.para-style-copyfmt,
.para-style-item.para-style-applyfmt {
    font-size: 0.82rem;
    font-weight: 600;
}

/* Confirm dialog box. */
.fmtcopy-box {
    width: min(94vw, 420px);
    max-width: 420px;
    text-align: left;
}
.fmtcopy-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
}
.fmtcopy-title { font-weight: 600; color: var(--text-editor); }

.fmtcopy-source-line {
    margin: 0 0 12px;
    font-size: 0.85rem;
    color: var(--text-editor-muted);
}
.fmtcopy-source-line strong { color: var(--text-editor); }

.fmtcopy-opt {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 0.88rem;
    color: var(--text-editor);
    cursor: pointer;
}
.fmtcopy-opt input { margin-top: 2px; }
.fmtcopy-opt-fixed {
    color: var(--text-editor-muted);
    cursor: default;
}

.fmtcopy-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin-top: 16px;
}
/* Create Table of Contents — the level-picker dialog and the brief flash on a heading reached via a
   TOC heading link. Scoped under feature classes; reuses the shared .modal-overlay / .modal-box base
   and semantic theme tokens. See utils/TocBuilder.js. */

.toc-box {
    width: min(94vw, 380px);
    max-width: 380px;
    text-align: left;
}
.toc-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.toc-title { font-weight: 600; color: var(--text-editor); }
.toc-sub {
    margin: 0 0 12px;
    font-size: 0.85rem;
    color: var(--text-editor-muted);
}
.toc-levels {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 16px;
}
.toc-opt {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.9rem;
    color: var(--text-editor);
    cursor: pointer;
}
/* Folder-mode row (tree folder context menu): Include Subfolders + depth spinner. Hidden
   for the note-selection path (TocStyleDialog toggles it per open). */
.toc-subfolders {
    display: flex;
    align-items: center;
    gap: 16px;
    margin: -4px 0 16px;
    padding-top: 10px;
    border-top: 1px solid var(--border-color);
}
.toc-subfolders.hidden { display: none; }
.toc-sub-levels-label { color: var(--text-editor-muted); }
.toc-sub-levels {
    width: 58px;
    padding: 4px 6px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--bg-app);
    color: var(--text-editor);
    font: inherit;
    font-size: 0.9rem;
}
.toc-sub-levels:disabled,
.toc-subfolders input[type="checkbox"]:disabled {
    opacity: 0.45;
    cursor: default;
}

.toc-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

/* Brief highlight when a TOC heading link scrolls a heading into view. */
.toc-target-flash {
    animation: toc-target-flash-kf 1.6s ease-out;
    border-radius: 4px;
}
@keyframes toc-target-flash-kf {
    0%   { background-color: color-mix(in srgb, var(--primary-color) 38%, transparent); }
    100% { background-color: transparent; }
}

/* Generated TOC rows render compactly (links sit at the note's body size, indented inline by level). */
#note-body .cyb-toc-row {
    margin-top: 2px;
    margin-bottom: 2px;
    line-height: 1.5;
}
#note-body .cyb-toc-title { margin-top: 8px; }
/* ==========================================================================
   Toolbar profiles & customization (desktop/tablet)
   Owner: editor/ToolbarProfileController.js
   Scoped under .format-toolbar / .tb-* so it can't collide globally.
   ========================================================================== */

/* The bar wraps controls onto new lines as the editor pane narrows, instead of
   collapsing them into an overflow menu. (Mobile keeps its own layout below.) */
.format-toolbar {
    flex-wrap: wrap;
    row-gap: 6px;
}

/* --- Injected chrome: overflow trigger + profile cycler sit at the bar tail --- */
.format-toolbar .tb-overflow-btn {
    position: relative;
}
.format-toolbar .tb-overflow-btn .tb-glyph {
    font-size: 18px;
    line-height: 1;
    font-weight: 700;
    letter-spacing: 1px;
}
.format-toolbar .tb-overflow-btn.tb-has-items {
    color: var(--primary-color);
}

.tb-overflow-popover {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 4px;
    min-width: 240px;
    max-width: 320px;
    background: var(--bg-pane, var(--bg-pane));
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 8px;
    box-shadow: 0 8px 24px color-mix(in srgb, var(--mix-dark) 18%, transparent);
    padding: 6px;
    z-index: 40;
}
.tb-overflow-popover.hidden { display: none; }

.tb-overflow-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 260px;
    overflow-y: auto;
}
.tb-overflow-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 4px 6px;
    border-radius: 6px;
}
.tb-overflow-row:hover { background: color-mix(in srgb, var(--primary-color) 8%, transparent); }
.tb-overflow-label {
    font-size: 0.85rem;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tb-overflow-action {
    flex: 0 0 auto;
    border: 1px solid var(--border-color, var(--border-color));
    background: none;
    color: var(--primary-color);
    font-size: 0.75rem;
    font-weight: 600;
    border-radius: 5px;
    padding: 2px 8px;
    cursor: pointer;
}
.tb-overflow-action:hover { background: color-mix(in srgb, var(--primary-color) 12%, transparent); }
.tb-overflow-empty {
    font-size: 0.8rem;
    color: var(--text-muted, var(--text-muted));
    padding: 8px 6px;
    line-height: 1.35;
}

.tb-overflow-footer {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--border-color, var(--border-color));
}
.tb-overflow-footer-btn {
    text-align: left;
    border: none;
    background: none;
    color: var(--text-main);
    font-size: 0.82rem;
    padding: 6px;
    border-radius: 6px;
    cursor: pointer;
}
.tb-overflow-footer-btn:hover { background: color-mix(in srgb, var(--primary-color) 10%, transparent); color: var(--primary-color); }

/* --- Profile cycler --- */
.tb-profile-cycler {
    display: flex;
    align-items: center;
    gap: 2px;
    position: relative;
    flex: 0 0 auto;
    padding-left: 4px;
    border-left: 1px solid var(--border-color, var(--border-color));
    margin-left: auto; /* push the cycler + overflow trigger to the bar's right edge */
}
.tb-profile-step {
    border: none;
    background: none;
    color: var(--text-muted, var(--text-muted));
    cursor: pointer;
    font-size: 10px;
    line-height: 1;
    padding: 2px 3px;
    border-radius: 4px;
}
.tb-profile-step:hover:not(:disabled) { background: var(--item-hover); color: var(--primary-color); }
.tb-profile-step:disabled { opacity: 0.35; cursor: default; }
.tb-profile-name {
    border: none;
    background: none;
    color: var(--text-main);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 4px;
    max-width: 120px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tb-profile-name:hover { background: var(--item-hover); }

.tb-profile-menu {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 4px;
    min-width: 200px;
    background: var(--bg-pane, var(--bg-pane));
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 8px;
    box-shadow: 0 8px 24px color-mix(in srgb, var(--mix-dark) 18%, transparent);
    padding: 6px;
    z-index: 41;
}
.tb-profile-menu.hidden { display: none; }
.tb-profile-row { display: flex; align-items: center; gap: 2px; }
.tb-profile-pick {
    flex: 1 1 auto;
    text-align: left;
    border: none;
    background: none;
    color: var(--text-main);
    font-size: 0.85rem;
    padding: 6px;
    border-radius: 6px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tb-profile-pick:hover { background: color-mix(in srgb, var(--primary-color) 10%, transparent); }
.tb-profile-pick.is-active { color: var(--primary-color); font-weight: 700; }
.tb-profile-action {
    flex: 0 0 auto;
    border: none;
    background: none;
    color: var(--text-muted, var(--text-muted));
    cursor: pointer;
    font-size: 0.85rem;
    padding: 4px 6px;
    border-radius: 5px;
}
.tb-profile-action:hover { background: var(--item-hover); color: var(--primary-color); }
.tb-profile-add {
    width: 100%;
    margin-top: 4px;
    border: 1px dashed var(--border-color, var(--border-color));
    background: none;
    color: var(--primary-color);
    font-size: 0.8rem;
    font-weight: 600;
    padding: 6px;
    border-radius: 6px;
    cursor: pointer;
}
.tb-profile-add:hover { background: color-mix(in srgb, var(--primary-color) 8%, transparent); }

/* --- Customize mode --- */
.tb-customize-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: color-mix(in srgb, var(--primary-color) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--primary-color) 30%, transparent);
    border-radius: 8px;
    padding: 6px 10px;
    margin-bottom: 8px;
    font-size: 0.82rem;
    color: var(--text-main);
}
.tb-customize-done {
    border: none;
    background: var(--primary-color);
    color: var(--on-accent);
    font-size: 0.8rem;
    font-weight: 600;
    padding: 4px 14px;
    border-radius: 6px;
    cursor: pointer;
}

/* In customize mode every control is shown (no auto-overflow), so let the bar
   wrap instead of clipping the rightmost controls on a narrow editor pane. */
.format-toolbar.tb-customizing {
    flex-wrap: wrap;
    row-gap: 14px;
}

.format-toolbar.tb-customizing .tb-unit,
.format-toolbar.tb-customizing .fmt-sep.tb-generated.tb-draggable {
    position: relative;
    outline: 1px dashed color-mix(in srgb, var(--primary-color) 40%, transparent);
    outline-offset: 1px;
    border-radius: 6px;
    cursor: grab;
}
.format-toolbar.tb-customizing .tb-unit.tb-dragging,
.format-toolbar.tb-customizing .fmt-sep.tb-dragging { opacity: 0.4; }
.format-toolbar.tb-customizing .tb-unit.tb-drop-before,
.format-toolbar.tb-customizing .fmt-sep.tb-drop-before { box-shadow: -3px 0 0 var(--primary-color); }
.format-toolbar.tb-customizing .tb-unit.tb-drop-after,
.format-toolbar.tb-customizing .fmt-sep.tb-drop-after { box-shadow: 3px 0 0 var(--primary-color); }

/* Park badge: a small × overlaid on each control in customize mode. */
.tb-unit-park {
    position: absolute;
    top: -7px;
    right: -7px;
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--danger-color, var(--danger-color));
    color: var(--on-accent);
    border-radius: 50%;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    z-index: 2;
    box-shadow: 0 1px 3px color-mix(in srgb, var(--mix-dark) 30%, transparent);
}
.tb-unit-park:hover { background: color-mix(in srgb, var(--danger-color, var(--danger-color)) 80%, var(--mix-dark)); }

.fmt-sep.tb-generated.tb-draggable .tb-sep-remove {
    position: absolute;
    top: -7px;
    left: -6px;
    width: 14px;
    height: 14px;
    border: none;
    background: var(--danger-color, var(--danger-color));
    color: var(--on-accent);
    border-radius: 50%;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}

/* Customization chrome never shows on mobile (the bar reverts to shipped order). */
@media (max-width: 768px) {
    .format-toolbar .tb-overflow-btn,
    .format-toolbar .tb-profile-cycler,
    .tb-overflow-popover,
    .tb-customize-banner { display: none !important; }
}
/* ==========================================================================
   Note action bar — configurable, wrapping button row
   Owner: editor/NoteActionBarController.js
   Scoped under .editor-actions-note / .nab-* so it can't collide globally.
   ========================================================================== */

/* The bar wraps its buttons onto new lines instead of clipping the rightmost one
   (the delete/bin button was falling off the edge on phones). The overflow "⋯"
   trigger and its menu anchor to the bar's right edge. */
.editor-actions-note {
    position: relative;
    flex-wrap: wrap;
    row-gap: 6px;
}

/* Parked (hidden) buttons stay in the DOM so runtime id/attr toggles keep working,
   but are visually removed. !important beats the mobile `.visible-mobile { display:flex }`
   override for buttons that are both mobile-only and user-hidden. */
.editor-actions-note .nab-parked { display: none !important; }

/* On a phone the meta row stacks the timestamp on its own line, so give the action
   bar the full next line — that constrains its width and lets flex-wrap trigger,
   rather than the row sizing to max-content and clipping off the edge. */
@media (max-width: 768px) {
    .editor-actions-note {
        flex: 1 1 100%;
        min-width: 0;
        justify-content: flex-end;
    }
}

/* --- Overflow trigger (inherits the note bar's .icon-btn sizing) --- */
.nab-overflow-btn .nab-glyph {
    font-size: 18px;
    line-height: 1;
    font-weight: 700;
    letter-spacing: 1px;
}
.nab-overflow-btn.nab-has-hidden { color: var(--primary-color); }

/* --- Quick menu (anchored to the bar's right edge) --- */
.nab-menu {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 6px;
    min-width: 210px;
    max-width: 280px;
    background: var(--bg-pane, var(--bg-pane));
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 10px;
    box-shadow: 0 10px 28px color-mix(in srgb, var(--mix-dark) 22%, transparent);
    padding: 6px;
    z-index: 60;
}
.nab-menu.hidden { display: none; }
.nab-menu-head {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted, var(--text-muted));
    padding: 4px 8px 2px;
}
.nab-menu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    text-align: left;
    border: none;
    background: none;
    color: var(--text-main);
    font-size: 0.86rem;
    padding: 8px;
    border-radius: 7px;
    cursor: pointer;
}
.nab-menu-item:hover { background: color-mix(in srgb, var(--primary-color) 10%, transparent); }
.nab-menu-label { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nab-menu-plus { color: var(--primary-color); font-weight: 700; }
.nab-menu-check { width: 14px; color: transparent; font-weight: 700; }
.nab-menu-profile.is-active .nab-menu-check { color: var(--primary-color); }
.nab-menu-profile.is-active .nab-menu-label { font-weight: 700; color: var(--primary-color); }
.nab-menu-customize { color: var(--primary-color); font-weight: 600; }
.nab-menu-divider {
    height: 1px;
    background: var(--border-color, var(--item-hover));
    margin: 5px 4px;
}

/* --- Customize dialog --- */
.nab-dialog-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: color-mix(in srgb, var(--mix-dark) 42%, transparent);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}
.nab-dialog {
    width: min(480px, 100%);
    max-height: min(80vh, 720px);
    display: flex;
    flex-direction: column;
    background: var(--bg-pane, var(--bg-pane));
    color: var(--text-main);
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 14px;
    box-shadow: 0 20px 60px color-mix(in srgb, var(--mix-dark) 35%, transparent);
    overflow: hidden;
}
.nab-dialog-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-color, var(--border-color));
}
.nab-dialog-title { margin: 0; font-size: 1.02rem; font-weight: 700; }
.nab-dialog-close {
    border: none;
    background: none;
    color: var(--text-muted, var(--text-muted));
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 6px;
}
.nab-dialog-close:hover { background: color-mix(in srgb, var(--text-main) 8%, transparent); color: var(--text-main); }

/* profile controls */
.nab-profile-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color, var(--border-color));
}
.nab-profile-select {
    flex: 1 1 140px;
    min-width: 120px;
    padding: 6px 8px;
    font-size: 0.86rem;
    color: var(--text-main);
    background: var(--bg-pane, var(--bg-pane));
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 7px;
}

.nab-dialog-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 8px 16px 12px;
}
.nab-section-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 12px 0 6px;
}
.nab-section-title { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-main); }
.nab-section-hint { font-size: 0.74rem; color: var(--text-muted); }

.nab-list { display: flex; flex-direction: column; gap: 4px; }
.nab-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 8px;
    background: color-mix(in srgb, var(--text-main) 3%, transparent);
}
.nab-row-off { opacity: 0.72; }
.nab-row-icon {
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-main);
}
.nab-row-icon svg, .nab-row-icon img { width: 18px; height: 18px; }
.nab-row-icon img { border-radius: 4px; }
.nab-row-label { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; }
.nab-row-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.88rem; }
.nab-row-hint {
    flex: 0 0 auto;
    font-size: 0.66rem;
    color: var(--text-muted, var(--text-muted));
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 4px;
    padding: 1px 5px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.nab-row-controls { flex: 0 0 auto; display: flex; align-items: center; gap: 3px; }
.nab-step {
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-color, var(--border-color));
    background: var(--bg-pane, var(--bg-pane));
    color: var(--text-main);
    border-radius: 7px;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
}
.nab-step:hover:not(:disabled) { border-color: var(--primary-color); color: var(--primary-color); }
.nab-step:disabled { opacity: 0.3; cursor: default; }
.nab-row-hide:hover { border-color: var(--danger-color, var(--danger-color)); color: var(--danger-color, var(--danger-color)); }
.nab-row-add { color: var(--primary-color); border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color)); }

.nab-row-empty {
    font-size: 0.82rem;
    color: var(--text-muted, var(--text-muted));
    padding: 8px;
}

.nab-dialog-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--border-color, var(--border-color));
}
.nab-btn {
    border: 1px solid var(--border-color, var(--border-color));
    background: var(--bg-pane, var(--bg-pane));
    color: var(--text-main);
    font-size: 0.86rem;
    font-weight: 600;
    padding: 8px 16px;
    border-radius: 8px;
    cursor: pointer;
}
.nab-btn:hover { border-color: var(--primary-color); color: var(--primary-color); }
.nab-btn-primary { background: var(--primary-color); border-color: var(--primary-color); color: var(--mix-light); }
.nab-btn-primary:hover { filter: brightness(1.05); color: var(--mix-light); }
.nab-btn-ghost { border: none; background: none; color: var(--text-muted); }
.nab-btn-ghost:hover { color: var(--danger-color, var(--danger-color)); }
.nab-btn-mini { padding: 6px 10px; font-size: 0.8rem; }
.nab-btn-mini:disabled { opacity: 0.4; cursor: default; }
/* ============================================================================
   049 — Read Aloud (speaker toolbar button + spoken-sentence highlight)
   Owner: editor/ReadAloudController.js · Docs/000-note-read-aloud-tts-design.md
   ============================================================================ */

/* Button states are driven by data-read-aloud (idle | speaking | paused). */
#btn-read-aloud[data-read-aloud="speaking"],
#btn-read-aloud[data-read-aloud="paused"] {
    color: var(--primary-color);
}

#btn-read-aloud[data-read-aloud="speaking"] svg {
    animation: read-aloud-pulse 1.6s ease-in-out infinite;
}

@keyframes read-aloud-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.45; }
}

/* App-kind notes (board/map/storyboard) have no rich-text surface to read. */
#btn-read-aloud[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
}

/* Spoken-sentence highlight (CSS Custom Highlight API — browsers without it just
   speak with no highlight). Light + dark variants together, per the theme rules.
   (The EPUB reader's chapter highlight lives inside the chapter iframe — injected by
   EpubReadAloud.js, since the frame has no app tokens.) */
::highlight(cyb-read-aloud) {
    background-color: color-mix(in srgb, var(--selection-color) 85%, transparent);
}

:root[data-theme="dark"] ::highlight(cyb-read-aloud) {
    background-color: color-mix(in srgb, var(--note-card-active-border) 45%, transparent);
}

/* EPUB reader speaker button (same states, viewer-owned chrome). */
.epub-read-btn[data-read-aloud="speaking"],
.epub-read-btn[data-read-aloud="paused"] {
    color: var(--primary-color);
}

.epub-read-btn[data-read-aloud="speaking"] svg {
    animation: read-aloud-pulse 1.6s ease-in-out infinite;
}

/* ---- Sleep timer (EPUB reader) — button + popover ------------------------------------
   Owner: editor/EpubPreviewController.js (chrome) + editor/EpubReadAloud.js (state).
   Docs/000-epub-sleep-timer-reading-position-design.md §3.1 */

.epub-timer-btn.is-armed {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 35%, transparent);
    background: color-mix(in srgb, var(--primary-color) 10%, transparent);
}

.epub-timer-remaining {
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.epub-timer-remaining:not(:empty) {
    margin-left: 4px;
}

/* Popover panel — same in-flow family as the TOC panel. */
.epub-timer-popover {
    padding: 8px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-pane);
}

.epub-timer-popover.hidden {
    display: none;
}

.epub-timer-chips {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
    gap: 6px;
}

.epub-timer-chip {
    padding: 7px 10px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.epub-timer-chip:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
}

.epub-timer-chip.is-active {
    background: color-mix(in srgb, var(--primary-color) 20%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
    font-weight: 600;
}

.epub-timer-custom {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
}

.epub-timer-custom.hidden {
    display: none;
}

.epub-timer-custom-input {
    width: 96px;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: 7px;
    background: var(--bg-app);
    color: var(--text-main);
    font: inherit;
    font-size: 0.85rem;
}

.epub-timer-custom-set {
    border-color: var(--border-color);
}

/* ---- Reading speed (shared: note toolbar button + EPUB reader) ------------------------
   Owner: utils/ReadAloudSpeedControl.js (slider) · editor/ReadAloudController.js (note popover)
   · editor/EpubPreviewController.js (in-flow popover). Rate = one global setting (store.ttsRate),
   a 0.75×–1.5× slider (fine 0.05 step — only that band is useful for listening). */

/* The speed buttons render the current rate as text ("1×", "1.25×") — like the A−/A+ buttons. */
.cyb-tts-speed-btn {
    font-size: 0.82rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.cyb-tts-speed-btn[aria-disabled="true"] {
    opacity: 0.5;
    pointer-events: none;
}

.cyb-tts-speed-popover.hidden {
    display: none;
}

/* Note surface: a floating popover anchored under the toolbar button. */
.cyb-tts-speed-popover--floating {
    position: fixed;
    z-index: 1000;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-pane);
    box-shadow: var(--shadow-md);
}

/* EPUB surface: in-flow, mirroring the sleep-timer popover. */
.epub-speed-popover {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-pane);
}

/* Slider row: the range track flexes, the value badge sits to its right. */
.cyb-tts-speed-slider {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 200px;
}

.cyb-tts-speed-range {
    flex: 1 1 auto;
    min-width: 140px;
    height: 4px;
    cursor: pointer;
    accent-color: var(--primary-color);
}

.cyb-tts-speed-value {
    flex: 0 0 auto;
    min-width: 3.5ch;
    text-align: right;
    font-size: 0.9rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-main);
}
/* --- UTILS --- */
.menu-divider {
    height: 1px;
    background: var(--border-color);
    margin: 4px 0;
}
.icon-btn.icon-btn--text {
    border-radius: var(--radius-sm);
    padding: 6px 12px;
    font-size: 0.9rem;
    height: auto;
}
.icon-btn {
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    cursor: pointer;
    color: var(--text-main);
    height: var(--btn-height-compact);
    min-width: var(--btn-height-compact);
    padding: 0 var(--space-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}
.icon-btn:hover {
    color: var(--primary-color);
    border-color: var(--note-card-hover-border);
    background: var(--bg-pane);
    box-shadow: var(--shadow-sm);
    transform: translateY(-1px);
}
.icon-btn.primary { color: var(--primary-color); }
.icon-btn.danger {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 30%, var(--border-color));
    background: color-mix(in srgb, var(--danger-color) 5%, var(--bg-pane));
}

#btn-voice-to-text {
    position: relative;
    overflow: visible;
    isolation: isolate;
}

#btn-voice-to-text::after {
    content: '';
    position: absolute;
    inset: -5px;
    border-radius: calc(var(--radius-sm) + 4px);
    border: 2px solid transparent;
    opacity: 0;
    pointer-events: none;
}

#btn-voice-to-text svg {
    transition: transform var(--anim-fast) var(--anim-ease), filter var(--anim-fast) var(--anim-ease);
}

#btn-voice-to-text.is-disabled,
#btn-voice-to-text[aria-disabled="true"] {
    color: var(--text-muted);
    border-color: var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--note-card-hover-border) 8%);
    box-shadow: none;
    cursor: help;
    transform: none;
}

#btn-voice-to-text.is-disabled:hover,
#btn-voice-to-text[aria-disabled="true"]:hover {
    color: var(--text-muted);
    border-color: var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--note-card-hover-border) 8%);
    box-shadow: none;
    transform: none;
}

#btn-voice-to-text[aria-pressed="true"] {
    color: var(--on-accent);
    background: var(--primary-color);
    border-color: var(--primary-color);
    box-shadow: 0 8px 18px color-mix(in srgb, var(--primary-color) 35%, transparent);
}

#btn-voice-to-text[aria-pressed="true"]:hover {
    color: var(--on-accent);
    background: var(--primary-color);
    border-color: var(--primary-color);
}

#btn-voice-to-text[data-voice-to-text-tone="listening"] {
    box-shadow: 0 10px 24px color-mix(in srgb, var(--primary-color) 44%, transparent);
}

#btn-voice-to-text[data-voice-to-text-tone="listening"]::after {
    border-color: color-mix(in srgb, var(--primary-color) 42%, transparent);
    animation: voice-to-text-pulse 1.7s ease-out infinite;
}

#btn-voice-to-text[data-voice-to-text-tone="listening"] svg {
    filter: drop-shadow(0 1px 2px color-mix(in srgb, var(--mix-dark) 12%, transparent));
    animation: voice-to-text-mic-beat 1.2s ease-in-out infinite;
}

#btn-voice-to-text[data-voice-to-text-tone="unavailable"] {
    border-style: dashed;
}

@keyframes voice-to-text-pulse {
    0% {
        opacity: 0.72;
        transform: scale(0.94);
    }

    75% {
        opacity: 0;
        transform: scale(1.18);
    }

    100% {
        opacity: 0;
        transform: scale(1.2);
    }
}

@keyframes voice-to-text-mic-beat {
    0%,
    100% {
        transform: scale(1);
    }

    40% {
        transform: scale(1.08);
    }

    60% {
        transform: scale(0.98);
    }
}

.icon-btn.danger:hover {
    color: var(--on-accent);
    background: var(--danger-color);
    border-color: var(--danger-color);
    box-shadow: 0 8px 18px color-mix(in srgb, var(--danger-color) 30%, transparent);
}

.hidden { display: none !important; }
.visible-mobile { display: none; } /* Only for mobile override */
.desktop-only { display: inline-flex; }

/* --- TOASTS --- */
.app-toast-container {
    position: fixed;
    right: 16px;
    top: 78px;
    z-index: 5200;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}

@media (max-width: 768px) {
    .app-toast-container {
        top: 64px;
    }
}

.app-toast {
    min-width: 220px;
    max-width: 360px;
    padding: 10px 12px;
    border-radius: var(--radius-md);
    border: 1px solid color-mix(in srgb, var(--mix-light) 42%, transparent);
    background: var(--tooltip-bg);
    color: var(--tooltip-fg);
    box-shadow: var(--shadow-md);
    backdrop-filter: blur(8px);
    font-size: 0.88rem;
    line-height: 1.35;
    letter-spacing: 0.01em;
    white-space: pre-line;
    opacity: 0;
    transform: translateY(8px) scale(0.98);
    transition: opacity 160ms var(--anim-ease), transform 180ms var(--anim-ease);
}

.app-toast.show {
    opacity: 1;
    transform: translateY(0) scale(1);
}

.app-toast.hide {
    opacity: 0;
    transform: translateY(6px) scale(0.98);
}

.btn-primary-outline {
    width: 100%;
    height: var(--btn-height);
    padding: 0 var(--btn-pad-x);
    border: 1px solid var(--primary-color);
    background: var(--accent-gradient);
    box-shadow: 0 8px 18px color-mix(in srgb, var(--accent-gradient-start) 25%, transparent);
    color: var(--on-accent);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-weight: 600;
    font-size: var(--btn-font-size);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: transform var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease);
}
.btn-primary-outline:hover {
    transform: translateY(-1px);
    box-shadow: 0 10px 20px color-mix(in srgb, var(--accent-gradient-start) 32%, transparent);
}

.btn-ghost,
.simple-btn.ghost,
.glass-btn.ghost {
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
}

.btn-ghost:hover,
.simple-btn.ghost:hover,
.glass-btn.ghost:hover {
    background: var(--item-hover);
}

.btn-primary,
.simple-btn.primary,
.glass-btn.primary,
.btn-primary-outline {
    color: var(--on-accent);
}

a[data-qnt-link="1"].broken-link,
a[data-qnt-link="1"][data-qnt-link-broken="1"] {
    color: var(--danger-color);
    text-decoration-style: dashed;
}

.btn-danger,
.simple-btn.danger,
.glass-btn.danger {
    background: linear-gradient(135deg, color-mix(in srgb, var(--danger-color) 80%, var(--mix-light)), var(--danger-color));
    color: var(--on-accent);
    border-color: transparent;
    box-shadow: 0 8px 18px color-mix(in srgb, var(--danger-color) 30%, transparent);
}

.btn-danger:hover,
.simple-btn.danger:hover,
.glass-btn.danger:hover {
    transform: translateY(-1px);
    box-shadow: 0 10px 22px color-mix(in srgb, var(--danger-color) 35%, transparent);
}


/* ============================================================================
   051 — Blackout screen (read-aloud "screen off" surface)
   Owner: utils/BlackoutScreen.js · Docs/000-read-aloud-local-tts-exploration.md §4c-A
   DOCUMENTED COLOR EXCEPTION: this surface exists to emit no light — literal var(--mix-dark)
   and dim fixed whites, deliberately NOT theme tokens (a theme must never tint it;
   OLED pixels must be fully off).
   ============================================================================ */

/* While active, the page root is black too: Android paints the display-cutout letterbox
   strip from the page background during the immersive-mode transition — a light theme
   showed there as a lit bar at the old status-bar border. */
html.blackout-active,
html.blackout-active body {
    background: var(--mix-dark) !important;
}

/* The fullscreen backdrop behind the overlay — black in every compositing edge case. */
.blackout-screen::backdrop {
    background: var(--mix-dark);
}

.blackout-screen {
    position: fixed;
    inset: 0;
    z-index: 12000; /* above everything, including the brain-map's 10000 */
    background: var(--mix-dark);
    display: flex;
    align-items: center;
    justify-content: center;
    touch-action: none;
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
    cursor: default;
}

.blackout-reveal {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}

.blackout-reveal.is-shown {
    opacity: 1;
    pointer-events: auto;
}

.blackout-exit-btn {
    background: none;
    border: none;
    padding: 16px;
    cursor: pointer;
    border-radius: 50%;
}

.blackout-exit-btn img {
    display: block;
    width: 84px;
    height: 84px;
    border-radius: 22%;
    opacity: 0.9;
}

.blackout-exit-label {
    color: color-mix(in srgb, var(--mix-light) 55%, transparent);
    font-size: 0.9rem;
}

.blackout-timer-label {
    color: color-mix(in srgb, var(--mix-light) 35%, transparent);
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
}

.blackout-timer-label.hidden {
    display: none;
}
/* ============================================================================
   052 — Read Aloud mini-bar (global "now reading aloud" control)
   Owner: utils/ReadAloudMiniBar.js · fed by utils/ReadAloudHub.js
   A floating strip that appears whenever any read-aloud session is playing (note
   or foreground/background ebook), so it can be paused/stopped/opened from one place.
   Its own surface — deliberately NOT the music mini-player; both can show at once.
   ============================================================================ */

.cyb-ra-bar {
    position: fixed;
    /* Initial fallback only — the JS positions it (persisted spot or top-centered) before paint,
       and drag updates left/top. */
    top: 70px;
    left: 16px;
    z-index: 900;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: min(420px, calc(100vw - 32px));
    padding: 8px 10px 8px 12px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: var(--bg-pane);
    box-shadow: var(--shadow-md);
    color: var(--text-main);
    cursor: grab;          /* the body is a drag handle */
    user-select: none;     /* dragging must not select the title text */
    touch-action: none;    /* claim touch drags instead of letting the page scroll */
}

.cyb-ra-bar.is-dragging {
    cursor: grabbing;
    box-shadow: 0 12px 28px color-mix(in srgb, var(--text-main) 22%, transparent);
}

.cyb-ra-bar.hidden {
    display: none;
}

.cyb-ra-bar-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: var(--primary-color);
}

.cyb-ra-bar-glyph svg {
    animation: read-aloud-pulse 1.6s ease-in-out infinite; /* shared keyframe from 049-read-aloud.css */
}

.cyb-ra-bar-meta {
    display: flex;
    flex-direction: column;
    min-width: 0; /* let the title ellipsize instead of pushing the controls off-screen */
    flex: 1 1 auto;
    line-height: 1.25;
}

.cyb-ra-bar-title {
    font-size: 0.9rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cyb-ra-bar-subtitle {
    font-size: 0.78rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cyb-ra-bar-subtitle.hidden {
    display: none;
}

.cyb-ra-bar-controls {
    display: flex;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto;
}

.cyb-ra-bar-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 6px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
}

.cyb-ra-bar-btn:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
    color: var(--primary-color);
}

.cyb-ra-bar-btn.hidden {
    display: none;
}

/* "Open" is a text button — give it a little breathing room and a pill affordance. */
.cyb-ra-bar-open {
    margin-left: 4px;
    padding: 0 12px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    font-size: 0.82rem;
    font-weight: 600;
}

/* Narrow screens: allow nearly the full width (still JS-positioned + draggable, clamped to the edges). */
@media (max-width: 560px) {
    .cyb-ra-bar {
        max-width: calc(100vw - 16px);
    }
}
/* Native-backend chip: a small fixed pill shown when the app is booted on the Go SQLite backend
   (?nativeBoot=1 → <html data-storage-backend="native">). Shows which storage engine is live AND doubles
   as a one-tap "refresh the storage connection" button (rendered as a <button>) — the user's escape hatch
   when a note looks blank and the auto self-heal hasn't kicked in yet. See app.js
   refreshNativeBridgeConnectionFromChip and Docs/001-native-data-layer-port-plan.md §Phase N3. */
.cyb-native-badge {
    position: fixed;
    right: 10px;
    bottom: 10px;
    z-index: 1200;
    display: none;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--success-color) 20%, var(--bg-pane));
    border: 1px solid var(--success-color);
    color: var(--text-main);
    font: inherit;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    line-height: 1;
    box-shadow: var(--shadow-md);
    user-select: none;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}

:root[data-storage-backend="native"] .cyb-native-badge { display: inline-flex; }

.cyb-native-badge:hover { background: color-mix(in srgb, var(--success-color) 34%, var(--bg-pane)); }
.cyb-native-badge:active { transform: translateY(1px); }
.cyb-native-badge:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; }
.cyb-native-badge[disabled] { cursor: progress; }

.cyb-native-badge .cyb-native-badge-dot { font-size: 0.9em; line-height: 1; }

/* Checking: pulse the status dot while a manual connection check runs. */
.cyb-native-badge.is-checking .cyb-native-badge-dot {
    animation: cyb-native-badge-pulse 0.9s ease-in-out infinite;
}
@keyframes cyb-native-badge-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.2; }
}

/* Transient result flash after a manual check (~1.6s, cleared in JS). */
.cyb-native-badge.is-ok {
    border-color: var(--success-color);
    background: color-mix(in srgb, var(--success-color) 40%, var(--bg-pane));
}
.cyb-native-badge.is-fail {
    border-color: var(--danger-color);
    background: color-mix(in srgb, var(--danger-color) 30%, var(--bg-pane));
}

@media (prefers-reduced-motion: reduce) {
    .cyb-native-badge.is-checking .cyb-native-badge-dot { animation: none; }
    .cyb-native-badge { transition: none; }
}

/* --- Storage fail-loud banners ----------------------------------------------------------------------
   .cyb-bridge-banner  — NativeBridgeConnectionGuard: the Go sidecar became unreachable mid-session.
   .cyb-storage-banner — StorageFailureSurface: the SQLite worker stopped answering (stall watchdog).
   Same treatment for both: a persistent alert that must never be obscured.
   --- Native bridge disconnected banner (NativeBridgeConnectionGuard) --------------------------------
   A persistent, fail-loud alert shown when the native (Go sidecar) storage backend becomes unreachable
   mid-session. Bottom-fixed + centered so it never covers the top toolbar or navigation; slides up on
   enter. Danger-tinted via semantic tokens (both themes). */
.cyb-bridge-banner,
.cyb-storage-banner {
    position: fixed;
    left: 50%;
    bottom: 18px;
    transform: translate(-50%, calc(100% + 24px));
    z-index: 2147483000; /* above dialogs/overlays — a lost backend must never be obscured */
    display: flex;
    align-items: center;
    gap: 14px;
    max-width: min(720px, calc(100vw - 24px));
    padding: 12px 16px;
    border-radius: 12px;
    background: color-mix(in srgb, var(--danger-color) 16%, var(--bg-pane));
    border: 1px solid var(--danger-color);
    color: var(--text-main);
    box-shadow: var(--shadow-md);
    opacity: 0;
    transition: transform 0.22s ease, opacity 0.22s ease;
}

.cyb-bridge-banner.is-visible,
.cyb-storage-banner.is-visible {
    transform: translate(-50%, 0);
    opacity: 1;
}

.cyb-bridge-banner-icon,
.cyb-storage-banner-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    color: var(--danger-color);
    font-size: 1.15rem;
    line-height: 1;
}

.cyb-bridge-banner-icon svg,
.cyb-storage-banner-icon svg { width: 22px; height: 22px; }

.cyb-bridge-banner-text,
.cyb-storage-banner-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.cyb-bridge-banner-text strong,
.cyb-storage-banner-text strong { font-size: 0.92rem; font-weight: 700; }
.cyb-bridge-banner-text span,
.cyb-storage-banner-text span { font-size: 0.8rem; opacity: 0.85; }

.cyb-bridge-banner-actions,
.cyb-storage-banner-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
}

.cyb-bridge-banner-btn,
.cyb-storage-banner-btn {
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.cyb-bridge-banner-btn:hover,
.cyb-storage-banner-btn:hover { background: var(--item-hover); }
.cyb-bridge-banner-btn:disabled,
.cyb-storage-banner-btn:disabled { opacity: 0.6; cursor: default; }

/* Primary = the recovery action, so accent-tinted (not danger — the banner already carries the urgency). */
.cyb-bridge-banner-btn-primary,
.cyb-storage-banner-btn-primary {
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    border-color: var(--primary-color);
    color: var(--primary-color);
    font-weight: 700;
}

.cyb-bridge-banner-btn-primary:hover { background: color-mix(in srgb, var(--primary-color) 24%, var(--bg-pane)); }

@media (max-width: 620px) {
    .cyb-bridge-banner,
.cyb-storage-banner {
        flex-wrap: wrap;
        left: 12px;
        right: 12px;
        bottom: 12px;
        transform: translateY(calc(100% + 24px));
        max-width: none;
    }
    .cyb-bridge-banner.is-visible,
.cyb-storage-banner.is-visible { transform: translateY(0); }
    .cyb-bridge-banner-actions,
.cyb-storage-banner-actions { width: 100%; justify-content: flex-end; }
}
/* --- RESPONSIVE / MOBILE --- */
@media (max-width: 768px) {
    .mobile-header { display: flex; }
    
    .app-container {
        flex-direction: column;
        padding-top: 50px; /* Space for mobile header */
        position: relative;
    }

    /* Sidebar becomes a drawer */
    .sidebar {
        position: absolute;
        left: 0; 
        top: 0;
        bottom: 0;
        height: 100%;
        overflow: hidden;
        background: var(--bg-sidebar);
        color: var(--text-main);
        border-right: 1px solid var(--pane-divider);
        width: 85%;
        box-shadow: none;
        transform: translateX(calc(-100% - 16px));
        transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.22s ease;
        will-change: transform;
    }

    .workspace-selector #btn-settings {
        display: none;
    }

    .workspace-selector {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "db"
            "workspace";
    }
    .sidebar.open {
        transform: translateX(0);
        box-shadow: 2px 0 10px color-mix(in srgb, var(--mix-dark) 10%, transparent);
    }

    .sidebar.settings-only .sidebar-content,
    .sidebar.settings-only .resizer {
        display: none !important;
    }

    .sidebar-overlay {
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        background: color-mix(in srgb, var(--mix-dark) 30%, transparent);
        z-index: 25;
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: opacity 0.2s ease;
    }
    .sidebar-overlay.active {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }

    /* List takes full width initially */
    .note-list-pane {
        width: 100%;
        border-right: none;
        transition: transform 0.22s ease, opacity 0.18s ease;
    }

    /* Editor overlays the list */
    .editor-pane {
        position: fixed;
        top: 0; left: 0; right: 0; bottom: 0;
        z-index: 40;
        transform: translateX(100%);
        opacity: 0.98;
        transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease;
        will-change: transform;
        pointer-events: none;
    }
    .editor-pane.active {
        transform: translateX(0);
        opacity: 1;
        pointer-events: auto;
    }

    .visible-mobile { display: flex; }
    .desktop-only { display: none !important; }

    /* Hide resizers on mobile */
    .resizer { display: none; }
    
    /* Adjust Editor Padding for mobile */
    .editor-content-wrapper {
        padding: 16px 16px calc(92px + env(safe-area-inset-bottom, 0px));
    }

    .editor-toolbar {
        padding: 12px 12px 8px;
    }

    .editor-actions {
        gap: 6px;
    }

    .editor-actions-layout {
        gap: 4px;
    }

    .editor-actions-note {
        gap: 6px;
        flex-wrap: wrap;
        justify-content: flex-end;
    }

    .editor-meta-top {
        align-items: flex-start;
    }

    .editor-meta-bottom {
        align-items: flex-start;
        flex-wrap: wrap;
    }

    /* Give the save/edited status its own full-width line so the action buttons
       always start on a fresh line and wrap identically no matter how long the
       label is ("Saved" vs "Saved to Disk (12:34:56)"). Otherwise the label's
       changing width shifts where the buttons wrap, changing the row height and
       making the note content hop on every save. */
    .editor-meta-bottom .timestamp {
        flex: 1 1 100%;
    }

    .editor-actions-mobile-row {
        display: inline-flex;
    }

    .editor-meta-row {
        padding: 0 12px 10px;
        font-size: 0.78rem;
    }

    .note-title-input { font-size: 1.5rem; }

    /* Keep formatting actions accessible on mobile even when native
       Android text-selection menu is open near selected text. */
    .format-toolbar {
        position: fixed;
        left: 10px;
        right: 10px;
        bottom: calc(10px + env(safe-area-inset-bottom, 0px));
        top: auto;
        margin-bottom: 0;
        padding: 8px 10px;
        border: 1px solid var(--border-color);
        border-radius: 12px;
        background: color-mix(in srgb, var(--bg-editor-pane) 94%, var(--bg-pane) 6%);
        box-shadow: 0 10px 24px color-mix(in srgb, var(--mix-dark) 14%, transparent);
        z-index: 70;
        overflow-x: auto;
        overflow-y: hidden;
        white-space: nowrap;
        scrollbar-width: thin;
    }

    .format-toolbar-drag-handle {
        display: inline-flex;
    }

    .format-toolbar .fmt-sep {
        flex: 0 0 auto;
    }

    .format-toolbar .fmt-btn,
    .format-toolbar .icon-btn-small {
        flex: 0 0 auto;
    }
    
    /* Editor "Back" button styling */
    #btn-close-editor {
        position: absolute;
        top: 10px;
        left: 10px;
        background: white;
        border: none;
        display: flex;
        align-items: center;
        font-weight: 500;
        color: var(--primary-color);
        z-index: 50;
        padding: 5px 10px;
    }

    .ai-agent-chatbox {
        width: min(94vw, 420px);
        min-width: 280px;
        left: 3vw;
        resize: none;
    }

    .ai-agent-chat-header {
        cursor: default;
        touch-action: none;
    }

    .ai-agent-chat-drag-handle {
        display: inline-flex;
    }

    .ai-agent-chat-resize-handle {
        display: inline-flex;
    }

    .ai-agent-chat-input {
        min-height: 96px;
        font-size: 16px;
    }
}

@media (max-width: 768px) and (orientation: portrait) {
    .format-toolbar {
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
        white-space: normal;
        overflow-x: hidden;
        overflow-y: auto;
        max-height: 132px;
        padding: 8px 10px 10px;
    }

    .format-toolbar .fmt-btn,
    .format-toolbar .icon-btn-small {
        min-height: 30px;
        min-width: 30px;
        padding: 4px 5px;
    }

    .format-toolbar .fmt-sep {
        display: none;
    }
}

@media (min-width: 769px) and (max-width: 1220px) {
    .format-toolbar {
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
        white-space: normal;
        overflow-x: visible;
        overflow-y: visible;
        max-height: none;
    }

    .format-toolbar .fmt-sep {
        display: none;
    }
}

/* Reduced motion applies at every width, not only inside the mobile breakpoint: the pane
   slide/fade transitions are the ones a motion-sensitive user meets first. */
@media (prefers-reduced-motion: reduce) {
    .sidebar,
    .sidebar-overlay,
    .note-list-pane,
    .editor-pane {
        transition: none !important;
    }
}
/* --- CONTEXT MENU --- */
.context-menu {
    position: absolute;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    box-shadow: 0 4px 12px color-mix(in srgb, var(--mix-dark) 15%, transparent);
    border-radius: 6px;
    z-index: 1000;
    min-width: 160px;
    padding: 6px 0;
    opacity: 1;
    transform: translateY(0);
    transition: opacity var(--anim-fast) var(--anim-ease), transform var(--anim-base) var(--anim-ease);
}

.context-menu.has-close {
    position: absolute;
}

.context-menu-close {
    position: absolute;
    top: 4px;
    right: 6px;
    width: 20px;
    height: 20px;
    border: 1px solid color-mix(in srgb, var(--border-color) 90%, transparent);
    border-radius: 6px;
    background: color-mix(in srgb, var(--bg-pane) 88%, transparent);
    color: var(--text-muted);
    font-size: 15px;
    line-height: 1;
    display: none;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.context-menu-close:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

@media (max-width: 768px), (hover: none) and (pointer: coarse), (any-pointer: coarse) {
    .context-menu.has-close {
        padding-top: 26px;
    }

    .context-menu-close {
        display: inline-flex;
    }
}

body.touch-device-ui .context-menu.has-close {
    padding-top: 26px;
}

body.touch-device-ui .context-menu-close {
    display: inline-flex;
}

.menu-item {
    padding: 8px 16px;
    font-size: 0.9rem;
    cursor: pointer;
    color: var(--text-main);
    display: block;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}

.blogger-link-choice-title {
    padding: 6px 16px 8px;
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.blogger-link-choice-item {
    width: 100%;
    border: 0;
    background: transparent;
    text-align: left;
}

.blogger-link-choice-primary {
    font-weight: 600;
}

.blogger-link-choice-secondary {
    margin-top: 2px;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.blogger-link-choice-item:hover .blogger-link-choice-secondary,
.blogger-link-choice-item:focus-visible .blogger-link-choice-secondary {
    color: inherit;
}

.note-card-chip-blogger-action {
    appearance: none;
    -webkit-appearance: none;
    padding: 4px 8px;
    margin: 0;
    font: inherit;
    font-size: 0.68rem;
    letter-spacing: 0;
    line-height: 1;
    cursor: pointer;
}

.blogger-link-action-menu {
    min-width: 320px;
    max-height: min(276px, calc(100vh - 24px));
    overflow-y: auto;
    padding-bottom: 8px;
}

.blogger-link-action-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 10px;
    align-items: center;
    min-height: 52px;
    padding: 10px 16px;
    border: 1px solid transparent;
    border-radius: 10px;
}

.blogger-link-action-row + .blogger-link-action-row {
    border-top: 1px solid color-mix(in srgb, var(--border-color) 80%, transparent);
}

.blogger-link-action-row:hover {
    background: var(--item-hover);
    border-color: var(--border-color);
}

.blogger-link-action-row.is-selected {
    border-color: color-mix(in srgb, var(--primary-color) 35%, white 65%);
    background: color-mix(in srgb, var(--primary-color) 10%, white 90%);
}

.blogger-link-action-row:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 75%, white 25%);
    outline-offset: 1px;
}

.blogger-link-action-info {
    min-width: 0;
}

.blogger-link-action-buttons {
    display: flex;
    align-items: center;
    gap: 6px;
}

.blogger-link-action-btn {
    width: 28px;
    height: 28px;
    padding: 4px;
}

.blogger-link-action-btn.is-busy {
    animation: blogger-action-busy-flash 250ms steps(2, end) infinite;
    background: color-mix(in srgb, var(--primary-color) 18%, var(--bg-pane));
    color: var(--primary-color);
}

.blogger-link-action-btn.is-busy svg {
    transform-origin: center;
}

@keyframes blogger-action-busy-flash {
    0% {
        opacity: 1;
        transform: scale(1);
    }
    50% {
        opacity: 0.42;
        transform: scale(0.92);
    }
    100% {
        opacity: 1;
        transform: scale(1);
    }
}

.blogger-link-action-btn:hover:not(:disabled),
.blogger-link-action-btn:focus-visible {
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    color: var(--primary-color);
}

.blogger-link-action-btn:focus-visible,
.note-card-chip-blogger-action:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 45%, transparent);
    outline-offset: 2px;
}

.blogger-link-action-btn svg {
    width: 16px;
    height: 16px;
}
.menu-item:hover {
    background-color: var(--primary-color);
    color: white;
}
.menu-item.active {
    background-color: var(--primary-color);
    color: white;
}
.menu-item.danger:hover {
    background-color: var(--danger-color);
    color: white;
}

/* --- CONTEXT MENU SUBMENU (flyout) ---
   A parent row (e.g. folder "Import") that reveals a nested flyout of related actions to the
   side. The flyout is nested inside the parent .menu-item so it stays within the owning
   context menu (the outside-click close logic checks activeMenu.contains(target)). Visibility
   is toggled via the .hidden class in JS; positioning is set inline (flip near viewport edges). */
.menu-item.has-submenu {
    display: flex;
    align-items: center;
    gap: 16px;
    position: relative;
}

.menu-item.has-submenu > .mi-label {
    flex: 1 1 auto;
    min-width: 0;
}

.menu-item.has-submenu > .mi-chevron {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    margin-left: auto;
    opacity: 0.75;
}

.menu-item.has-submenu > .mi-chevron svg {
    width: 15px;
    height: 15px;
}

.context-submenu {
    position: absolute;
    top: -6px;
    left: 100%;
    margin-left: 2px;
    min-width: 220px;
    /* Never wider than the viewport — on narrow phones the flyout drops below its parent row
       (JS clamps its x into the viewport) and long labels wrap instead of overflowing. */
    max-width: calc(100vw - 12px);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    box-shadow: 0 4px 12px color-mix(in srgb, var(--mix-dark) 15%, transparent);
    border-radius: 6px;
    padding: 6px 0;
    z-index: 1001;
}

/* Submenu rows use plain text colors even while the parent row is hover-highlighted. */
.context-submenu .menu-item {
    color: var(--text-main);
}

.suggest-folder-card {
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-pane);
    padding: 10px;
    display: grid;
    gap: 5px;
}

.suggest-folder-card-heading {
    font-size: 0.93rem;
    font-weight: 700;
    color: var(--text-main);
}

.suggest-folder-card-breadcrumb {
    font-size: 0.78rem;
    color: var(--text-muted);
    /* Long folder paths must wrap instead of being clipped — break inside long
       segments too, since some paths have no spaces around their separators. */
    white-space: normal;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.suggest-folder-card-reason {
    font-size: 0.8rem;
    color: color-mix(in srgb, var(--text-main) 82%, var(--text-muted));
    line-height: 1.35;
}

.suggest-folder-card-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 2px;
}

.suggest-folder-move-btn {
    min-height: 30px;
    padding: 0 12px;
    font-size: 0.82rem;
}

/* Folder-search picker (Move note to folder) ----------------------------- */
.suggest-folder-search-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}

.suggest-folder-search-input {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 34px;
    padding: 0 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.9rem;
}

.suggest-folder-search-input:focus {
    outline: none;
    border-color: var(--primary-color);
}

.suggest-folder-scope-pill {
    flex: 0 0 auto;
    min-height: 34px;
    padding: 0 12px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: var(--bg-pane);
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}

.suggest-folder-scope-pill[aria-pressed="true"] {
    color: var(--primary-color);
    border-color: var(--primary-color);
}

.suggest-folder-scope-pill:disabled {
    cursor: default;
    opacity: 0.7;
}

/* --- SETTINGS MENU POLISH --- */
#settings-menu.context-menu {
    min-width: 220px;
    width: min(420px, calc(100vw - 28px));
    max-height: none;
    overflow: visible;
    padding: 8px;
    border-radius: 12px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    border: 1px solid color-mix(in srgb, var(--primary-color) 18%, var(--border-color));
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-pane) 8%);
    box-shadow: var(--shadow-md);
    transform-origin: top left;
}

#settings-menu.context-menu:not(.hidden) {
    animation: settingsMenuPop 170ms var(--anim-ease);
}

#settings-menu .menu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    border-radius: 8px;
    font-weight: 500;
    padding: 9px 12px;
    margin: 1px 0;
}

#settings-menu .mi-icon {
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    flex-shrink: 0;
    transition: color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

#settings-menu .mi-icon svg {
    width: 15px;
    height: 15px;
}

#settings-menu .mi-label {
    min-width: 0;
    flex: 1;
}

#settings-menu .mi-meta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    color: color-mix(in srgb, var(--text-muted) 86%, transparent);
    opacity: 0.82;
    transition: color var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease);
}

#settings-menu .mi-meta svg {
    width: 13px;
    height: 13px;
}

#settings-menu #menu-date-format:hover .mi-meta {
    color: var(--primary-color);
    opacity: 1;
}

#settings-menu .mi-chevron {
    width: 14px;
    height: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    transition: transform var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}

#settings-menu .has-submenu.open .mi-chevron {
    transform: rotate(90deg);
    color: var(--primary-color);
}

#settings-menu .menu-item:hover {
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    color: var(--primary-color);
}

#settings-menu .menu-item:hover .mi-icon {
    color: var(--primary-color);
    transform: translateX(1px);
}

#settings-menu .menu-item.danger:hover {
    background: color-mix(in srgb, var(--danger-color) 18%, var(--bg-pane));
    color: var(--danger-color);
}

#settings-menu .menu-item.danger:hover .mi-icon {
    color: var(--danger-color);
}

#settings-menu .settings-submenu {
    position: absolute;
    top: 0;
    left: calc(100% + 8px);
    min-width: 210px;
    padding: 8px;
    border-radius: 12px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    border: 1px solid color-mix(in srgb, var(--primary-color) 18%, var(--border-color));
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-pane) 8%);
    box-shadow: var(--shadow-md);
    animation: settingsMenuPop 160ms var(--anim-ease);
    z-index: 2;
}

#settings-menu .submenu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    border-radius: 8px;
    font-weight: 500;
    padding: 9px 12px;
    margin: 1px 0;
    cursor: pointer;
    color: var(--text-main);
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}

#settings-menu .submenu-item-checkbox {
    user-select: none;
}

#settings-menu .mi-check-indicator {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    border: 1.5px solid color-mix(in srgb, var(--text-muted) 64%, var(--border-color));
    background: color-mix(in srgb, var(--bg-pane) 88%, white 12%);
    position: relative;
}

#settings-menu .submenu-item-checkbox[aria-checked="true"] .mi-check-indicator {
    border-color: color-mix(in srgb, var(--primary-color) 64%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
}

#settings-menu .submenu-item-checkbox[aria-checked="true"] .mi-check-indicator::after {
    content: '';
    position: absolute;
    left: 4px;
    top: 1px;
    width: 4px;
    height: 8px;
    border-right: 2px solid var(--primary-color);
    border-bottom: 2px solid var(--primary-color);
    transform: rotate(45deg);
}

#settings-menu .submenu-item:hover {
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    color: var(--primary-color);
}

#settings-menu .submenu-item:hover .mi-icon {
    color: var(--primary-color);
    transform: translateX(1px);
}

#settings-menu .submenu-item.danger:hover {
    background: color-mix(in srgb, var(--danger-color) 18%, var(--bg-pane));
    color: var(--danger-color);
}

#settings-menu .submenu-item.danger:hover .mi-icon {
    color: var(--danger-color);
}

#settings-menu .menu-item.is-disabled,
#settings-menu .submenu-item.is-disabled {
    color: var(--text-muted);
    opacity: 0.6;
    cursor: not-allowed;
}

#settings-menu .menu-item.is-disabled:hover,
#settings-menu .submenu-item.is-disabled:hover {
    background: transparent;
    color: var(--text-muted);
}

#settings-menu .menu-item.is-disabled .mi-icon,
#settings-menu .submenu-item.is-disabled .mi-icon,
#settings-menu .menu-item.is-disabled:hover .mi-icon,
#settings-menu .submenu-item.is-disabled:hover .mi-icon {
    color: var(--text-muted);
    transform: none;
}

@media (max-width: 768px) {
    #settings-menu.context-menu {
        width: calc(100% - 20px);
        min-width: 0;
        max-height: calc(100vh - 170px);
        overflow-y: auto;
        overflow-x: hidden;
    }

    #settings-menu .settings-submenu {
        position: static;
        left: auto;
        top: auto;
        min-width: 0;
        margin: 6px 0 2px 18px;
        padding: 6px;
        box-shadow: none;
        border-radius: 10px;
        border: 1px solid var(--border-color);
        background: var(--bg-pane);
        border: 1px dashed color-mix(in srgb, var(--primary-color) 22%, var(--border-color));
        background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
        animation: none;
    }
}

#settings-menu .menu-divider {
    height: 1px !important;
    margin: 6px 2px !important;
    background: color-mix(in srgb, var(--primary-color) 16%, var(--border-color)) !important;
}

#settings-menu .settings-recent-section {
    padding: 4px 4px 6px;
}

#settings-menu .settings-recent-header {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    padding: 4px 8px 6px;
}

#settings-menu .settings-recent-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

#settings-menu .settings-recent-clear {
    margin-top: 6px;
    margin-left: 8px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.76rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    cursor: pointer;
    padding: 2px 0;
    text-decoration: underline;
    text-underline-offset: 2px;
    transition: color var(--anim-fast) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease);
}

#ai-preset-picker,
#ai-model-picker {
    min-width: 240px;
    max-width: min(420px, calc(100vw - 22px));
    max-height: min(62vh, 440px);
    overflow: auto;
    padding: 6px;
    border-radius: 12px;
    position: fixed;
    z-index: 5600;
}

.ai-preset-picker-item {
    display: flex;
    align-items: center;
    gap: 8px;
    border-radius: 8px;
    padding: 8px 10px;
    font-size: 0.88rem;
    cursor: pointer;
    color: var(--text-main);
}

.ai-preset-picker-item:hover {
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    color: var(--primary-color);
}

.ai-preset-picker-item.active {
    background: color-mix(in srgb, var(--primary-color) 18%, var(--bg-pane));
    color: var(--primary-color);
    font-weight: 600;
}

.ai-preset-manager-dialog {
    width: min(620px, calc(100vw - 24px));
    max-height: min(84vh, 860px);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    backdrop-filter: none;
    overflow: hidden;
}

.ai-preset-body {
    display: flex;
    flex-direction: column;
    gap: 0;
    flex: 1;
    min-height: 0;
    width: 100%;
    overflow: hidden;
    background: var(--bg-pane);
}

.ai-preset-left {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    width: 100%;
    overflow: hidden;
}

.ai-preset-toolbar {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
    width: 100%;
    align-items: center;
}

.ai-preset-toolbar-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ai-preset-toolbar .find-replace-input {
    flex: 1;
    min-width: 160px;
    margin: 0;
}

.ai-preset-toolbar.compact {
    margin-top: 8px;
    margin-bottom: 0;
}

.ai-preset-list {
    flex: 1;
    min-height: 0;
    max-height: calc((40px * 8) + (4px * 7) + 10px);
    overflow-y: auto;
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    padding: 4px 0;
    background: transparent;
}

.ai-preset-list-panel {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
    width: 100%;
    margin: 0;
    border: 1px solid color-mix(in srgb, var(--border-color) 70%, transparent);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    overflow: hidden;
}

.ai-preset-list-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 0;
    padding: 8px 0 0;
    position: static;
    border-top: 1px solid color-mix(in srgb, var(--border-color) 60%, transparent);
    background: var(--bg-pane);
}

.ai-preset-list-actions .icon-btn-small {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}

.ai-preset-list-actions .icon-btn-small:hover {
    background: var(--item-hover);
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
    transform: none;
}

.ai-preset-row {
    border-radius: 8px;
    padding: 8px 10px;
    min-height: 40px;
    cursor: grab;
    user-select: none;
    border: 1px solid transparent;
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-pane) 8%);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

.ai-preset-empty {
    padding: 12px;
    color: var(--text-muted);
    font-size: 0.9rem;
}

.ai-preset-row + .ai-preset-row {
    margin-top: 4px;
}

.ai-preset-row:hover {
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 28%, var(--border-color));
    transform: translateX(1px);
}

.ai-preset-row.active {
    border-color: color-mix(in srgb, var(--primary-color) 38%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
}

.ai-preset-row.selected {
    outline: 1px solid color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
}

.ai-preset-row.dragging {
    opacity: 0.5;
    cursor: grabbing;
}

/* Quick-picker mode (manager launched from the agent chat): a row click inserts its prompt,
   so signal the row body is clickable rather than just draggable. */
#ai-preset-manager-modal.is-pick-mode .ai-preset-row,
#ai-preset-manager-modal.is-pick-mode .ai-preset-row .name-wrap {
    cursor: pointer;
}

.ai-preset-row .name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-preset-row .name-wrap {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    flex: 1;
}

.ai-preset-row .chain-badge {
    flex: 0 0 auto;
    font-size: 0.72rem;
    line-height: 1;
    color: var(--text-muted);
    border: 1px solid color-mix(in srgb, var(--border-color) 75%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 88%, var(--selection-color) 12%);
    border-radius: 999px;
    padding: 3px 7px;
}

.ai-preset-row .meta {
    font-size: 0.74rem;
    color: var(--text-muted);
}

.ai-preset-row .actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ai-preset-active-toggle {
    width: 16px;
    height: 16px;
    accent-color: var(--primary-color);
    cursor: pointer;
    flex: 0 0 auto;
}

.ai-preset-edit-btn {
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-color);
    border-radius: 7px;
    background: var(--bg-pane);
    color: var(--text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex: 0 0 auto;
}

.ai-preset-edit-btn:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.ai-preset-totop-btn {
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-color);
    border-radius: 7px;
    background: var(--bg-pane);
    color: var(--text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex: 0 0 auto;
}

.ai-preset-totop-btn svg {
    width: 15px;
    height: 15px;
}

.ai-preset-totop-btn:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.ai-preset-delete-btn {
    width: 26px;
    height: 26px;
    border: 1px solid var(--border-color);
    border-radius: 7px;
    background: var(--bg-pane);
    color: var(--text-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex: 0 0 auto;
}

.ai-preset-delete-btn:hover {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 38%, var(--border-color));
}

.ai-preset-prompt {
    width: 100%;
    min-height: 280px;
    resize: vertical;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-pane);
    color: var(--text-main);
    padding: 10px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.84rem;
    line-height: 1.4;
    margin-bottom: 10px;
}

.ai-preset-edit-dialog {
    width: min(860px, calc(100vw - 24px));
    max-height: min(84vh, 860px);
}

.ai-preset-edit-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.ai-preset-chain-section {
    margin-top: 10px;
    border-top: 1px solid color-mix(in srgb, var(--border-color) 60%, transparent);
    padding-top: 10px;
}

.ai-preset-chain-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 8px;
}

.ai-chain-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 6px 8px;
    background: var(--bg-pane);
}

.ai-chain-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ai-chain-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ai-preset-chain-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.ai-preset-chain-controls .find-replace-input {
    margin: 0;
    flex: 1;
}

@media (max-width: 768px) {
    .ai-preset-body {
        grid-template-columns: 1fr;
        min-height: 0;
        max-height: calc(84vh - 130px);
        overflow: auto;
    }

    .ai-preset-manager-dialog {
        width: calc(100vw - 14px);
    }

    .ai-preset-list-panel {
        margin: 0;
    }

}

#settings-menu .settings-recent-clear:hover {
    color: var(--primary-color);
}

#settings-menu .settings-recent-clear:disabled {
    opacity: 0.45;
    cursor: default;
    text-decoration: none;
}

#settings-menu .settings-recent-empty {
    font-size: 0.84rem;
    color: var(--text-muted);
    padding: 6px 8px;
}

#settings-menu .recent-note-item {
    width: 100%;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 8px;
    padding: 7px 8px;
    text-align: left;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 2px;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

#settings-menu .recent-note-item:hover {
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--primary-color) 28%, var(--border-color));
    transform: translateX(1px);
}

#settings-menu .recent-note-title {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#settings-menu .recent-note-meta {
    font-size: 0.76rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@keyframes settingsMenuPop {
    from {
        opacity: 0;
        transform: translateY(-4px) scale(0.98);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* --- DRAG & DROP VISUALS --- */
.dragging {
    opacity: 0.5;
}

.drop-inside {
    background-color: var(--primary-alpha-10) !important;
    border-radius: 4px;
}

.drop-before {
    border-top: 2px solid var(--primary-color);
}
.drop-after {
    border-bottom: 2px solid var(--primary-color);
}

.icon-btn-small {
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    cursor: pointer;
    color: var(--text-main);
    height: var(--btn-height-compact);
    min-width: var(--btn-height-compact);
    padding: 0 var(--space-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}
.icon-btn-small:hover {
    color: var(--primary-color);
    border-color: var(--note-card-hover-border);
    background-color: var(--bg-pane);
    box-shadow: var(--shadow-sm);
    transform: translateY(-1px);
}

/* --- COLOR PICKER (Google Docs Style) --- */
.color-picker {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 6px;
    background: var(--bg-pane);
    border: 1px solid var(--border-color, var(--border-color));
    box-shadow: 0 4px 12px color-mix(in srgb, var(--mix-dark) 15%, transparent);
    border-radius: 8px;
    padding: 12px;
    z-index: 1000;
    min-width: 240px;
}

.c-sw {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    cursor: pointer;
    border: 1px solid color-mix(in srgb, var(--mix-dark) 10%, transparent);
    transition: transform 0.1s;
}
.c-sw:hover {
    transform: scale(1.2);
    border-color: var(--text-muted);
    z-index: 2;
    box-shadow: 0 2px 4px color-mix(in srgb, var(--mix-dark) 10%, transparent);
}

.c-sw.custom-swatch {
    overflow: visible;
}

.c-sw-delete {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 12px;
    height: 12px;
    border: 1px solid color-mix(in srgb, var(--mix-dark) 25%, transparent);
    border-radius: 50%;
    background: color-mix(in srgb, var(--mix-light) 95%, transparent);
    color: var(--text-main);
    font-size: 10px;
    line-height: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    padding: 0;
}

.c-sw.custom-swatch:hover .c-sw-delete,
.c-sw.custom-swatch:focus-within .c-sw-delete {
    opacity: 1;
    pointer-events: auto;
}

.c-sw-delete:hover {
    background: color-mix(in srgb, var(--danger-color) 10%, var(--bg-pane));
    border-color: color-mix(in srgb, var(--danger-color) 40%, transparent);
    color: var(--danger-color);
}


/* --- COLOR PICKER TICK & CUSTOM --- */
.c-sw { position: relative; }
.c-sw.selected::after {
    content: '';
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 6px;
    height: 10px;
    border-bottom: 2px solid white;
    border-right: 2px solid white;
    transform: translate(-50%, -60%) rotate(45deg);
    pointer-events: none;
    box-shadow: var(--shadow-sm);
}
.c-sw[data-color='#ffffff'].selected::after, /* literal-ok: swatch data and its tick */
.c-sw[data-color='#f3f3f3'].selected::after { /* literal-ok: swatch data and its tick */
    border-color: #333; /* literal-ok: swatch data and its tick */
    box-shadow: none; /* Dark tick for light bg */
} 


.custom-wrapper:hover { background: var(--item-hover); }

/* --- Popover structure (was inline styles in index.html; see utils/ColorPickerMarkup.js) --- */
.fmt-group--anchor {
    position: relative;
    display: inline-block;
}
.color-picker--modal {
    top: 100%;
    right: 0;
    left: auto;
    min-width: 210px;
}
.color-indicator {
    position: absolute;
    bottom: 4px;
    left: 6px;
    right: 6px;
    height: 3px;
    background-color: var(--text-editor);
    pointer-events: none;
}
.color-indicator--compact {
    bottom: 2px;
    left: 4px;
    right: 4px;
    height: 2px;
}
.color-picker-mode-toggle {
    display: flex;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 8px;
    padding-bottom: 4px;
}
.color-picker-mode-btn {
    flex: 1;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.8rem;
    padding: 4px;
    cursor: pointer;
    color: var(--text-muted);
}
.color-picker-mode-btn.active {
    font-weight: 600;
    color: var(--primary-color);
}
.color-picker-auto-row {
    margin-bottom: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.color-picker-auto-swatch {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px;
    border-radius: 4px;
    cursor: pointer;
}
.color-picker-auto-swatch:hover,
.color-picker-auto-swatch:focus-visible {
    background: var(--item-hover);
}
.color-picker-auto-dot {
    width: 18px;
    height: 18px;
    background: var(--bg-pane);
    position: relative;
    overflow: hidden;
    border-radius: 50%;
    border: 1px solid var(--border-color);
    flex: none;
}
.color-picker-auto-dot::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom right, transparent 48%, var(--danger-color) 48%, var(--danger-color) 52%, transparent 52%);
}
.color-picker-auto-label {
    font-size: 0.85rem;
    color: var(--text-main);
}
.color-picker-matrix {
    display: grid;
    grid-template-columns: repeat(10, 1fr);
    gap: 4px;
    margin-bottom: 8px;
}
.color-picker-footer {
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
}
.color-picker-footer-label {
    font-size: 0.75rem;
    color: var(--text-muted);
    margin-bottom: 4px;
    font-weight: 600;
    padding-left: 4px;
}
.color-picker-custom-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.color-picker-custom-trigger {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--item-hover);
    cursor: pointer;
}
.color-picker-custom-trigger-icon {
    width: 12px;
    height: 12px;
    color: var(--text-muted);
}
.color-picker-custom-modal {
    position: absolute;
    top: 0;
    background: var(--bg-pane);
    color: var(--text-main);
    padding: 12px;
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-md);
    border-radius: 4px;
    width: 200px;
}
.color-picker-custom-modal--right {
    left: 100%;
    margin-left: 8px;
}
.color-picker-custom-modal--left {
    right: 100%;
    margin-right: 8px;
}
.color-picker-custom-title {
    margin: 0 0 8px 0;
    font-size: 0.9rem;
    font-weight: 600;
}
.color-picker-custom-row {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
}
.color-picker-native-wrap {
    flex-grow: 1;
    height: 30px;
    background: var(--item-hover);
    border-radius: 4px;
    overflow: hidden;
    position: relative;
}
.color-picker-native-input {
    width: 120%;
    height: 120%;
    border: none;
    padding: 0;
    margin: -5px;
}
.color-picker-custom-check {
    height: 30px;
    width: 30px;
    background: var(--primary-color);
    color: var(--on-accent);
    border-radius: 4px;
}
.color-picker-hex-row {
    display: flex;
    gap: 4px;
    margin-bottom: 12px;
}
.color-picker-hex-label {
    font-size: 0.8rem;
    line-height: 24px;
}
.color-picker-hex-input {
    width: 70px;
    border: 1px solid var(--border-color);
    border-radius: 3px;
    padding: 2px 4px;
    font-size: 0.8rem;
    text-transform: uppercase;
    background: var(--bg-pane);
    color: var(--text-main);
}
.color-picker-custom-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
.color-picker-custom-cancel {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 0.8rem;
    cursor: pointer;
}
.color-picker-custom-ok {
    background: var(--primary-color);
    color: var(--on-accent);
    border: none;
    padding: 4px 12px;
    border-radius: 3px;
    font-size: 0.8rem;
    cursor: pointer;
}


/* --- EMOJI PICKER ---
   Feature-scoped popover for inserting emoji at the caret. Parallels 120-color-picker.css.
   Glyphs are OS-coloured; tokens drive only the surrounding chrome. Positioning (fixed +
   max-height) is applied at runtime by editor/EmojiPicker.js so the popover escapes the
   floating toolbar's overflow clip and fits the viewport on desktop + mobile. */

.emoji-picker {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 6px;
    width: 320px;
    max-width: calc(100vw - 16px);
    display: flex;
    flex-direction: column;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-md);
    border-radius: var(--radius-md);
    padding: 8px;
    z-index: 1000;
    overflow: hidden;
}

.emoji-picker.hidden {
    display: none;
}

/* Header skin-tone control (D3) — a single global radiogroup of Fitzpatrick swatches.
   Swatch background colours are emoji content (set inline from SkinTone.js), so tokens here
   drive only spacing, shape, and the selected/focus ring. */
.emoji-tone-row {
    display: flex;
    gap: 4px;
    flex: 0 0 auto;
    justify-content: flex-end;
    padding-bottom: 6px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border-color);
}

.emoji-tone {
    width: 20px;
    height: 20px;
    flex: 0 0 auto;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: 50%;
    cursor: pointer;
    opacity: 0.85;
    transition: transform 0.1s, opacity 0.1s, box-shadow 0.1s;
}

.emoji-tone:hover {
    opacity: 1;
    transform: scale(1.15);
}

.emoji-tone.is-active {
    opacity: 1;
    box-shadow: 0 0 0 2px var(--bg-pane), 0 0 0 4px var(--primary-color);
}

.emoji-tone:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

/* Tab strip — horizontal scroll when categories overflow (D6). */
.emoji-tabs {
    display: flex;
    gap: 2px;
    overflow-x: auto;
    overflow-y: hidden;
    flex: 0 0 auto;
    padding-bottom: 6px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border-color);
    scrollbar-width: thin;
}

.emoji-tab {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: none;
    border-radius: var(--radius-sm);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    opacity: 0.7;
    transition: background 0.1s, opacity 0.1s;
}

.emoji-tab:hover {
    background: var(--item-hover);
    opacity: 1;
}

.emoji-tab.is-active {
    opacity: 1;
    background: var(--selection-color);
    box-shadow: inset 0 -2px 0 var(--primary-color);
}

.emoji-tab:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: -2px;
    opacity: 1;
}

/* Grid host — one category grid visible at a time; vertical scroll within max-height. */
.emoji-grid-host {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    scrollbar-width: thin;
}

.emoji-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 2px;
}

.emoji-grid.hidden,
.emoji-empty.hidden {
    display: none;
}

.emoji-sw {
    aspect-ratio: 1 / 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: none;
    border-radius: var(--radius-sm);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: transform 0.1s, background 0.1s;
}

.emoji-sw:hover {
    background: var(--item-hover);
    transform: scale(1.2);
    z-index: 2;
}

.emoji-sw:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: -2px;
}

.emoji-empty {
    padding: 24px 12px;
    text-align: center;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* Mobile: bigger touch targets, fewer columns so cells stay tappable. */
@media (max-width: 768px) {
    .emoji-picker {
        width: 300px;
    }
    .emoji-grid {
        grid-template-columns: repeat(7, 1fr);
        gap: 4px;
    }
    .emoji-sw {
        font-size: 22px;
        min-height: 36px;
    }
    .emoji-tab {
        width: 34px;
        height: 34px;
    }
    .emoji-tone {
        width: 26px;
        height: 26px;
    }
}
/* --- TODO LIST --- */
ul.todo-list {
    list-style: none !important;
    padding-left: 0;
    margin-left: 0;
}

ul.todo-list li {
    display: list-item;
    margin-bottom: 4px;
    position: relative;
    list-style: none;
    padding-left: 28px;
    min-height: 22px;
}

ul.todo-list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.2em;
    width: 15px;
    height: 15px;
    border: 1.6px solid color-mix(in srgb, var(--text-muted) 65%, var(--border-color));
    border-radius: 4px;
    background: var(--bg-editor-pane);
    box-sizing: border-box;
    pointer-events: auto;
    cursor: pointer;
}

ul.todo-list li.completed::after {
    content: '';
    position: absolute;
    left: 4px;
    top: 0.45em;
    width: 7px;
    height: 4px;
    border-left: 2px solid var(--primary-color);
    border-bottom: 2px solid var(--primary-color);
    transform: rotate(-45deg);
    pointer-events: none;
}

ul.todo-list li.completed {
    text-decoration: line-through;
    color: color-mix(in srgb, var(--text-muted) 90%, var(--text-main));
}


/* --- THE CACHE BOARD (Kanban note kind) ---
   Feature-scoped styles for editor/CacheBoardController.js. The board mounts INTO the editor
   content wrapper (replacing the rich-text surface) for notes of kind 'kanban'; its dialogs,
   menus and toast are appended to <body>, so those selectors are global but `cb-`-prefixed.
   All chrome is token-driven; the green/orange/red schedule "tinge" maps to success/warning/
   danger (both themes — see 000-tokens-base.css). Desktop = resizable columns; mobile = a
   segmented tab switcher + swipe-to-advance (Docs/000-cache-board-requirements.md §9.2). */

/* When a board is mounted, hide the rich-text surface that shares the editor wrapper. */
.editor-content-wrapper.cache-board-mode > .note-title-row,
.editor-content-wrapper.cache-board-mode > #format-toolbar,
.editor-content-wrapper.cache-board-mode > .format-toolbar,
.editor-content-wrapper.cache-board-mode > #note-body,
.editor-content-wrapper.cache-board-mode > .note-editor,
.editor-content-wrapper.cache-board-mode #note-backlinks:not(.note-backlinks-floating),
.editor-content-wrapper.cache-board-mode .note-backlinks:not(.note-backlinks-floating) {
    display: none !important;
}

/* Focus mode + a board: columns need real estate, so fill the whole editor pane instead of the
   960px reading column (that column is meant for text notes — see body.focus-mode rule). Same
   override the Brain Map and Story Board use. */
body.focus-mode .editor-content-wrapper.cache-board-mode {
    max-width: none;
    margin: 0;
    padding: 0;
}

.cache-board {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
    color: var(--text-main);
    font-size: 0.95rem;
}

/* --- header --- */
.cb-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 2px 12px;
    flex-shrink: 0;
}
.cb-icon-btn {
    background: none;
    border: none;
    color: var(--text-main);
    cursor: pointer;
    font-size: 1.3rem;
    line-height: 1;
    padding: 6px 8px;
    border-radius: var(--radius-sm);
}
.cb-icon-btn:hover { background: var(--item-hover); }
.cb-board-name {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-main);
    font-size: 1.25rem;
    font-weight: 600;
    padding: 4px 8px;
}
.cb-board-name:hover { border-color: var(--border-color); }
.cb-board-name:focus { outline: none; border-color: var(--primary-color); background: var(--bg-app); }
.cb-sel-count {
    font-size: 0.8rem;
    color: var(--bg-app);
    background: var(--primary-color);
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 12px;
    cursor: pointer;
    flex-shrink: 0;
}
.cb-sel-count[hidden] { display: none; }

/* --- find-a-task search --- */
.cb-search { position: relative; flex-shrink: 0; width: 220px; max-width: 40%; }
.cb-search-input {
    width: 100%;
    background: var(--bg-app);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 7px 10px;
    font-size: 0.88rem;
    font-family: inherit;
}
.cb-search-input:focus { outline: none; border-color: var(--primary-color); }
.cb-search-results {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 4000;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 5px;
    max-height: 320px;
    overflow-y: auto;
}
.cb-search-results[hidden] { display: none; }
.cb-search-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.cb-search-item:hover,
.cb-search-item.cb-search-active { background: var(--item-hover); }
.cb-search-item-text { color: var(--text-main); font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-search-item-col { color: var(--text-muted); font-size: 0.72rem; flex-shrink: 0; }
.cb-search-empty { padding: 10px; color: var(--text-muted); font-size: 0.85rem; text-align: center; }

/* --- mobile tabs --- */
.cb-tabs {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
    margin-bottom: 10px;
}
.cb-tabs[hidden] { display: none; }
.cb-tab {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: var(--bg-sidebar);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    padding: 8px 6px;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.85rem;
}
.cb-tab-active {
    color: var(--text-main);
    border-color: var(--primary-color);
    background: var(--bg-pane);
}
.cb-tab-count {
    font-size: 0.72rem;
    background: var(--item-hover);
    color: var(--text-main);
    border-radius: 9px;
    padding: 1px 7px;
}
.cb-tab-active .cb-tab-count { background: var(--primary-color); color: var(--bg-app); }

/* --- columns --- */
.cb-columns {
    display: flex;
    flex: 1;
    min-height: 0;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 6px;
}
.cb-column {
    background: var(--bg-sidebar);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    padding: 10px;
    min-width: 180px;
    flex: 1 1 0;
    min-height: 0;
}
.cb-mobile .cb-columns { overflow-x: hidden; }
.cb-mobile .cb-column { min-width: 0; width: 100%; }

.cb-col-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;
    flex-shrink: 0;
}
.cb-col-title-wrap { display: flex; align-items: center; gap: 8px; min-width: 0; }
.cb-col-title {
    font-size: 0.95rem;
    margin: 0;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 700;
    color: var(--text-muted);
}
/* task count badge; shows "count/limit" when a WIP limit is set */
.cb-col-count {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--item-hover);
    border-radius: 999px;
    padding: 1px 8px;
    flex-shrink: 0;
}
/* over the WIP limit: header goes amber — advisory only, nothing is blocked */
.cb-col-over-limit .cb-col-title { color: var(--warning-color); }
.cb-col-over-limit .cb-col-count {
    background: color-mix(in srgb, var(--warning-color) 25%, transparent);
    color: var(--warning-color);
}
.cb-tab-over .cb-tab-count {
    background: color-mix(in srgb, var(--warning-color) 30%, transparent);
    color: var(--text-main);
}
.cb-add-btn {
    background: var(--item-hover);
    color: var(--text-main);
    border: none;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}
.cb-add-btn:hover { background: var(--primary-color); color: var(--bg-app); }

/* Archive pseudo-column: visually "storage, not work" — dashed frame, muted title.
   Cards inside carry .cb-card--archived (dimmed, no tinge). */
.cb-column-archive {
    background: transparent;
    border: 1px dashed var(--border-color);
}
.cb-column-archive .cb-col-title { opacity: 0.75; }
.cb-card--archived {
    opacity: 0.72;
    background: var(--bg-sidebar);
}
.cb-card--archived:hover { opacity: 1; }

.cb-resizer {
    width: 14px;
    margin: 0 2px;
    cursor: col-resize;
    flex-shrink: 0;
    display: flex;
    justify-content: center;
    align-self: stretch;
}
.cb-resizer::after {
    content: '';
    width: 2px;
    height: 100%;
    background: transparent;
    border-radius: 2px;
    transition: background-color var(--anim-fast, 0.15s) ease;
}
.cb-resizer:hover::after,
.cb-resizer.cb-resizing::after { background: var(--primary-color); }

.cb-dropzone {
    flex: 1;
    min-height: 60px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 4px;
    border: 2px dashed transparent;
    border-radius: var(--radius-sm);
    transition: border-color var(--anim-fast, 0.15s) ease;
}
.cb-dropzone.cb-dragover {
    border-color: var(--primary-color);
    background: color-mix(in srgb, var(--primary-color) 10%, transparent);
}

/* Dragging notes in from the note list adds linked tasks rather than moving a card — a green
   solid edge separates "this creates something" from the blue re-order cue above. */
.cb-dropzone.cb-dragover.cb-dragover-note {
    border-style: solid;
    border-color: var(--success-color);
    background: color-mix(in srgb, var(--success-color) 12%, transparent);
}

/* --- card --- */
.cb-card {
    position: relative;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 12px 34px 12px 14px;
    cursor: grab;
    user-select: none;
    box-shadow: var(--shadow-sm);
    line-height: 1.4;
    word-break: break-word;
    touch-action: pan-y;
    transition: transform 0.12s ease, box-shadow 0.2s ease, opacity 0.2s ease;
}
.cb-mobile .cb-card { cursor: pointer; }
.cb-card:active { cursor: grabbing; }
.cb-card.cb-dragging { opacity: 0.4; border-style: dashed; border-color: var(--primary-color); }
.cb-card-title { white-space: pre-wrap; font-weight: 500; }
.cb-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    margin-top: 8px;
}
.cb-chip {
    font-size: 0.72rem;
    padding: 2px 7px;
    border-radius: 10px;
    background: var(--item-hover);
    color: var(--text-main);
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.cb-chip-alarm { background: color-mix(in srgb, var(--warning-color) 28%, transparent); cursor: default; }
.cb-chip-link { cursor: pointer; background: color-mix(in srgb, var(--primary-color) 18%, transparent); }
.cb-chip-link:hover { background: color-mix(in srgb, var(--primary-color) 32%, transparent); }

/* --- board picker dialog (Add to Board) --- */
.cb-picker-tabs { display: flex; gap: 6px; margin-bottom: 12px; }
.cb-picker-tab {
    flex: 1;
    background: var(--bg-sidebar);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    padding: 8px 6px;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.85rem;
    font-family: inherit;
}
.cb-picker-tab-active { color: var(--text-main); border-color: var(--primary-color); background: var(--bg-pane); }
.cb-picker-search {
    width: 100%;
    box-sizing: border-box;
    font: inherit;
    color: var(--text-main);
    background: var(--bg-app);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 7px 10px;
    margin-bottom: 10px;
}
.cb-picker-search:focus { outline: none; border-color: var(--primary-color); }
.cb-picker-list { display: flex; flex-direction: column; gap: 6px; max-height: 320px; overflow-y: auto; margin-bottom: 14px; }
.cb-picker-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    text-align: left;
    background: var(--bg-app);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    cursor: pointer;
    color: var(--text-main);
    font-family: inherit;
    font-size: 0.92rem;
}
.cb-picker-item:hover { border-color: var(--primary-color); background: var(--item-hover); }
.cb-picker-item-title { font-weight: 500; flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-picker-item-meta { display: flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0; max-width: 55%; justify-content: flex-end; }
.cb-picker-item-crumb { font-size: 0.72rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cb-picker-item-ws { font-size: 0.72rem; color: var(--text-muted); flex-shrink: 0; }
.cb-picker-empty { color: var(--text-muted); padding: 14px 4px; }

/* Floating note hover-preview card (link picker). Lives inside the modal <dialog> so it
   renders in the top layer; never takes pointer events so hovering rows doesn't flicker. */
.note-preview-card {
    position: fixed;
    z-index: 100;
    width: 320px;
    max-height: 380px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 14px;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 10px 30px color-mix(in srgb, var(--mix-dark) 22%, transparent);
    pointer-events: none;
    overflow: hidden;
}
.note-preview-card.hidden { display: none; }
.note-preview-card__title { font-weight: 700; font-size: 0.95rem; color: var(--text-main); line-height: 1.3; }
.note-preview-card__body {
    position: relative;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--text-main);
    max-height: 280px;
    overflow: hidden;
    /* Fade the bottom edge to signal the preview is truncated. */
    -webkit-mask-image: linear-gradient(to bottom, var(--mix-dark) 80%, transparent);
    mask-image: linear-gradient(to bottom, var(--mix-dark) 80%, transparent);
}
.note-preview-card__body > :first-child { margin-top: 0; }
.note-preview-card__body img,
.note-preview-card__body video,
.note-preview-card__body table { max-width: 100%; }
.note-preview-card__body img { max-height: 140px; height: auto; }
.note-preview-card__muted { color: var(--text-muted); font-style: italic; }
.note-preview-card__stamps {
    font-size: 0.7rem;
    color: var(--text-muted);
    border-top: 1px solid var(--border-color);
    padding-top: 6px;
}
/* Single task-details icon: a "?" help badge whose hover tooltip lists every filled-in field.
   `cursor: help` signals the hover affordance. */
.cb-info-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border: 1px solid var(--border-color);
    border-radius: 50%;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1;
    color: var(--text-muted);
    cursor: help;
    transition: color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.cb-info-dot:hover { color: var(--text-main); border-color: var(--text-muted); }

/* manual sticky-note colour: a soft background tint from the user-chosen swatch (inline
   --cb-card-color). Background-only so it never collides with the due-date tinge (which uses
   box-shadow glow + border-color) or the selection outline/padding. */
.cb-card.cb-card--colored {
    background: color-mix(in srgb, var(--cb-card-color) 26%, var(--bg-pane));
}

/* schedule tinge glows (only when a due date exists) */
.cb-tinge-green  { box-shadow: 0 0 9px 1px color-mix(in srgb, var(--success-color) 55%, transparent); border-color: color-mix(in srgb, var(--success-color) 45%, var(--border-color)); }
.cb-tinge-orange { box-shadow: 0 0 10px 1px color-mix(in srgb, var(--warning-color) 60%, transparent); border-color: color-mix(in srgb, var(--warning-color) 50%, var(--border-color)); }
.cb-tinge-red    { box-shadow: 0 0 11px 2px color-mix(in srgb, var(--danger-color) 65%, transparent); border-color: color-mix(in srgb, var(--danger-color) 55%, var(--border-color)); }

@keyframes cbTingeFlash {
    0%, 100% { transform: scale(1); filter: brightness(1); }
    50%      { transform: scale(1.03); filter: brightness(1.5); }
}
.cb-card.cb-flash { animation: cbTingeFlash 250ms ease 3; }
@media (prefers-reduced-motion: reduce) { .cb-card.cb-flash { animation: none; } }

/* mobile swipe affordance */
.cb-card.cb-swipe-advance { box-shadow: 8px 0 0 -2px color-mix(in srgb, var(--success-color) 70%, transparent); }
.cb-card.cb-swipe-regress { box-shadow: -8px 0 0 -2px color-mix(in srgb, var(--text-muted) 60%, transparent); }

.cb-ellipsis-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    background: none;
    border: none;
    color: var(--text-main);
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
    padding: 0 5px;
    opacity: 0.55;
    border-radius: var(--radius-sm);
}
.cb-ellipsis-btn:hover { opacity: 1; background: var(--item-hover); }

.cb-card.cb-selected {
    outline: 2px solid var(--primary-color);
    outline-offset: 1px;
    padding-left: 26px;
}
.cb-card.cb-selected::before {
    content: '✓';
    position: absolute;
    top: 6px;
    left: 6px;
    font-size: 0.8rem;
    color: var(--primary-color);
    font-weight: 700;
    line-height: 1;
}

/* --- floating menus (appended to body) --- */
.cb-menu {
    position: fixed;
    z-index: 4000;
    min-width: 200px;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 6px;
}
.cb-menu[hidden] { display: none; }
.cb-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    color: var(--text-main);
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    font-size: 0.92rem;
    cursor: pointer;
}
/* .open = a parent row whose flyout submenu is showing; keep it highlighted like hover. */
.cb-menu-item:hover,
.cb-menu-item.open { background: var(--item-hover); }
.cb-menu-item.cb-danger { color: var(--danger-color); }
.cb-menu-item.cb-menu-disabled { opacity: 0.45; pointer-events: none; cursor: default; }
/* author display:block above beats the UA [hidden] rule, so hide per-open items explicitly */
.cb-menu-item[hidden] { display: none; }
.cb-menu-sep { height: 1px; background: var(--border-color); margin: 5px 4px; }

/* view-only (the split screen — Docs/000-split-app-kind-views-and-backlinks-plan.md): tasks select, copy and open
   their details, but nothing is added, dragged or renamed (column widths can still be adjusted, locally). The task menu
   keeps only its view items. */
.cache-board--readonly .cb-board-name { cursor: default; }
.cache-board--readonly .cb-board-name:hover,
.cache-board--readonly .cb-board-name:focus { border-color: transparent; background: transparent; }
.cache-board--readonly .cb-card,
.cache-board--readonly .cb-card:active { cursor: default; }
.cb-menu--readonly .cb-menu-sep { display: none; }

/* --- task colour swatch menu --- */
.cb-color-menu { min-width: 0; }
.cb-swatches { display: flex; gap: 6px; padding: 2px; }
.cb-swatch {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid var(--border-color);
    cursor: pointer;
    padding: 0;
    transition: transform var(--anim-fast) var(--anim-ease);
}
.cb-swatch:hover { transform: scale(1.12); }
.cb-swatch--none {
    background: var(--bg-app);
    color: var(--text-muted);
    font-size: 0.7rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* --- dialogs (appended to body) — mirror the app's standard modal (.modal-box) --- */
.cb-dialog {
    background: var(--bg-pane);
    color: var(--text-main);
    border: none;
    border-radius: 8px;
    padding: 24px;
    width: min(94vw, 560px);
    box-shadow: 0 10px 25px color-mix(in srgb, var(--mix-dark) 20%, transparent);
    /* Centre in the viewport like the app's modals (overrides any UA/global dialog margin). */
    inset: 0;
    margin: auto;
    max-height: 90vh;
    overflow-y: auto;
}
.cb-dialog::backdrop { background: color-mix(in srgb, var(--mix-dark) 50%, transparent); }

/* The Add/Edit Task dialog is user-resizable: drag the bottom-right corner. The controller
   persists the chosen width/height to app settings (survives refresh, restart, hard reset) and
   re-applies it via inline width/height. A native <dialog> only shows a resize grip when it is a
   scroll container, so overflow must be auto/hidden (not the base rule's overflow-y). min/max
   keep it usable and on-screen on small viewports even if a stored size is larger. */
.cb-dialog.cb-task-dialog {
    resize: both;
    overflow: auto;
    min-width: 360px;
    min-height: 340px;
    max-width: 96vw;
    max-height: 92vh;
}
.cb-dialog-title { margin: 0 0 16px; color: var(--text-main); font-size: 1.1rem; font-weight: 600; line-height: 1.3; }
.cb-dialog-hint { font-size: 0.85rem; color: var(--text-muted); margin: 0 0 12px; }

.cb-field { margin-bottom: 14px; position: relative; }
.cb-field label { display: block; font-size: 0.78rem; color: var(--text-muted); margin-bottom: 4px; }
.cb-field-row { display: flex; gap: 14px; }
.cb-field-row .cb-field { flex: 1; }
.cb-field-effort { max-width: 120px; }
.cb-dialog input[type=text],
.cb-dialog input[type=email],
.cb-dialog input[type=number],
.cb-dialog input[type=datetime-local],
.cb-dialog textarea,
.cb-dialog select,
.cb-bulk-input {
    width: 100%;
    background: var(--bg-app);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 9px 10px;
    font-family: inherit;
    font-size: 0.92rem;
}
.cb-dialog input:focus,
.cb-dialog textarea:focus,
.cb-dialog select:focus,
.cb-bulk-input:focus { outline: none; border-color: var(--primary-color); }
.cb-dialog textarea { resize: vertical; min-height: 140px; }
.cb-bulk-input { min-height: 180px; resize: vertical; }
.cb-computed { font-size: 0.7rem; color: var(--text-muted); margin-top: 3px; }
/* one-click due-date preset chips under the due input */
.cb-due-presets { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 5px; }
.cb-due-preset {
    background: var(--item-hover);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 3px 10px;
    font-size: 0.75rem;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
}
.cb-due-preset:hover { border-color: var(--primary-color); }
.cb-due-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 5px; }
.cb-alarm-btn {
    background: var(--item-hover);
    color: var(--text-muted);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 4px 9px;
    font-size: 0.78rem;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
}
.cb-alarm-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.cb-alarm-btn.cb-armed {
    background: color-mix(in srgb, var(--warning-color) 25%, transparent);
    color: var(--text-main);
    border-color: var(--warning-color);
}
/* Link-to-note control in the task editor: a pill button (+ clear) matching the alarm button. */
.cb-link-row { display: flex; align-items: center; gap: 8px; }
.cb-link-btn {
    background: var(--item-hover);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 4px 9px;
    font-size: 0.78rem;
    font-family: inherit;
    cursor: pointer;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cb-link-btn:hover { border-color: var(--primary-color); }
.cb-link-clear {
    background: none;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    cursor: pointer;
    font-size: 0.78rem;
    line-height: 1;
    padding: 4px 7px;
    flex-shrink: 0;
}
.cb-link-clear:hover { color: var(--danger-color); border-color: var(--danger-color); }
.cb-field-link[hidden] { display: none; }

.cb-meta-stamp { font-size: 0.7rem; color: var(--text-muted); margin-bottom: 14px; }

.cb-dialog-controls { display: flex; justify-content: flex-end; gap: 12px; margin-top: 8px; }
/* Match .simple-btn / .simple-btn.primary from 180-dialogs-overlays.css so board dialog
   buttons look exactly like the rest of the app's modals. */
.cb-btn {
    min-height: var(--btn-height);
    padding: 0 var(--btn-pad-x);
    border-radius: var(--radius-md);
    font-size: var(--btn-font-size);
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    transition: transform var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease);
}
.cb-btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.cb-btn-primary { background: var(--accent-gradient); color: var(--mix-light); border-color: transparent; box-shadow: 0 8px 18px color-mix(in srgb, var(--accent-gradient-start) 25%, transparent); }
.cb-btn-primary:hover { box-shadow: 0 10px 20px color-mix(in srgb, var(--accent-gradient-start) 32%, transparent); }
.cb-btn-cancel { background: var(--bg-pane); color: var(--text-main); }
.cb-btn-cancel:hover { background: var(--item-hover); }

/* autocomplete suggestion list (inside a field) */
.cb-ac-list {
    position: absolute;
    z-index: 5000;
    left: 0;
    right: 0;
    top: 100%;
    margin-top: 2px;
    background: var(--bg-pane);
    border: 1px solid var(--primary-color);
    border-radius: var(--radius-sm);
    max-height: 180px;
    overflow-y: auto;
    box-shadow: var(--shadow-md);
}
.cb-ac-list[hidden] { display: none; }
.cb-ac-item { padding: 8px 10px; cursor: pointer; font-size: 0.9rem; }
.cb-ac-item small { color: var(--text-muted); }
.cb-ac-item:hover, .cb-ac-item.cb-ac-active { background: var(--item-hover); }

/* configure-board dialog: one checkbox row per column, with a task count */
.cb-config-dialog { width: min(94vw, 430px); }
.cb-config-list { display: flex; flex-direction: column; gap: 6px; margin: 0 0 12px; }
.cb-config-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.cb-config-row:hover { background: var(--item-hover); }
.cb-config-check { flex-shrink: 0; width: 16px; height: 16px; cursor: pointer; accent-color: var(--primary-color); }
.cb-config-label { flex: 1; font-weight: 500; color: var(--text-main); }
.cb-config-count {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-app);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 1px 8px;
}
/* per-column WIP-limit input (blank = no limit). The input.cb-config-limit specificity is
   deliberate: it must beat the dialog-wide `.cb-dialog input[type=number] { width:100% }` rule. */
.cb-dialog input.cb-config-limit {
    width: 58px;
    flex-shrink: 0;
    text-align: center;
    background: var(--bg-app);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 4px 6px;
    font-size: 0.82rem;
    font-family: inherit;
}
.cb-dialog input.cb-config-limit:focus { outline: none; border-color: var(--primary-color); }
.cb-config-note { font-size: 0.8rem; color: var(--warning-color); margin: 0 0 10px; }
.cb-config-note[hidden] { display: none; }

/* archive toolbar: filter + view toggle */
.cb-archive-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}
.cb-archive-filter { position: relative; flex: 1 1 200px; min-width: 160px; }
.cb-archive-filter-input {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 30px 8px 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-app);
    color: var(--text-main);
    font-size: 0.9rem;
}
.cb-archive-filter-input:focus {
    outline: none;
    border-color: var(--primary-color);
}
.cb-archive-filter-clear {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border: none;
    background: none;
    color: var(--text-muted);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    border-radius: var(--radius-sm);
}
.cb-archive-filter-clear:hover { background: var(--item-hover); color: var(--text-main); }
.cb-archive-filter-clear[hidden] { display: none; }

.cb-archive-views {
    display: inline-flex;
    flex-shrink: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    overflow: hidden;
}
.cb-archive-view-btn {
    padding: 7px 14px;
    border: none;
    background: var(--bg-app);
    color: var(--text-muted);
    font-size: 0.86rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}
.cb-archive-view-btn + .cb-archive-view-btn { border-left: 1px solid var(--border-color); }
.cb-archive-view-btn:hover { background: var(--item-hover); color: var(--text-main); }
.cb-archive-view-btn.is-active { background: var(--primary-color); color: var(--mix-light); }

/* archive list */
.cb-archive-list { list-style: none; padding: 0; margin: 0 0 14px; max-height: 380px; overflow-y: auto; }
.cb-archive-list[hidden] { display: none; }
.cb-archive-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    margin-bottom: 6px;
}
.cb-archive-check { flex-shrink: 0; width: 16px; height: 16px; cursor: pointer; accent-color: var(--primary-color); }
.cb-archive-main { flex: 1; min-width: 0; }
.cb-archive-title { font-weight: 500; word-break: break-word; }
.cb-archive-sub { font-size: 0.74rem; color: var(--text-muted); margin-top: 3px; }
.cb-archive-menu-btn {
    background: none;
    border: none;
    color: var(--text-main);
    cursor: pointer;
    font-size: 1.2rem;
    line-height: 1;
    padding: 0 6px;
    opacity: 0.55;
    border-radius: var(--radius-sm);
    flex-shrink: 0;
}
.cb-archive-menu-btn:hover { opacity: 1; background: var(--item-hover); }
.cb-archive-empty { color: var(--text-muted); padding: 12px 4px; list-style: none; }

/* archive timeline: day-grouped sequence of archived tasks with a left rail */
.cb-archive-timeline { margin: 0 0 14px; max-height: 380px; overflow-y: auto; }
.cb-archive-timeline[hidden] { display: none; }
.cb-tl-group { position: relative; padding-left: 20px; }
/* the vertical rail runs through the dot centre (8px + 3px radius ≈ 11px) */
.cb-tl-group::before {
    content: "";
    position: absolute;
    left: 3px;
    top: 6px;
    bottom: 0;
    width: 2px;
    background: var(--border-color);
}
.cb-tl-group:last-child::before { bottom: auto; height: 14px; }
.cb-tl-date {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0 8px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text-main);
}
.cb-tl-dot {
    position: absolute;
    left: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--primary-color);
    box-shadow: 0 0 0 2px var(--bg-pane);
}
.cb-tl-date-label { flex: 0 0 auto; }
.cb-tl-count {
    flex: 0 0 auto;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-app);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 1px 7px;
}
.cb-tl-items { list-style: none; padding: 0; margin: 0 0 10px; max-height: none; overflow: visible; }

/* read-only task-data view (dialog + hover preview share these) */
.cb-taskdata-dialog { width: min(94vw, 440px); }
.cb-taskdata-heading {
    font-weight: 600;
    font-size: 0.98rem;
    color: var(--text-main);
    margin-bottom: 8px;
    word-break: break-word;
}
.cb-taskdata-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 4px 14px;
    margin: 0;
}
.cb-taskdata-dt { color: var(--text-muted); font-size: 0.8rem; }
.cb-taskdata-dd { margin: 0; color: var(--text-main); font-size: 0.85rem; word-break: break-word; }
.cb-taskdata-color { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 0.85rem; }
.cb-taskdata-color-label { color: var(--text-muted); font-size: 0.8rem; }
.cb-taskdata-swatch {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--border-color);
    flex-shrink: 0;
}
.cb-taskdata-color-val { color: var(--text-muted); }
.cb-taskdata-desc-label {
    margin: 12px 0 4px;
    color: var(--text-muted);
    font-size: 0.8rem;
    font-weight: 600;
}
.cb-taskdata-desc {
    color: var(--text-main);
    font-size: 0.85rem;
    white-space: pre-wrap;
    word-break: break-word;
    border-left: 2px solid var(--border-color);
    padding-left: 10px;
}

/* hover preview: floating read-only card of a task's info */
.cb-archive-hover {
    position: fixed;
    z-index: 7000;
    width: 300px;
    max-height: 60vh;
    overflow-y: auto;
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 12px 14px;
    pointer-events: none;
}
.cb-archive-hover[hidden] { display: none; }
.cb-archive-hover .cb-taskdata-desc { border-left-color: var(--border-color); }

/* --- toast --- */
.cb-toast {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 6000;
    display: flex;
    gap: 14px;
    align-items: center;
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 12px 16px;
    box-shadow: var(--shadow-md);
}
.cb-toast[hidden] { display: none; }
.cb-toast button {
    background: var(--primary-color);
    border: none;
    color: var(--on-accent);
    border-radius: var(--radius-sm);
    padding: 6px 12px;
    cursor: pointer;
    font-weight: 600;
}
.cb-toast button[hidden] { display: none; }
/* --- CODE BLOCKS --- */
pre {
    position: relative; /* Anchor for the Copy Button */
    background-color: var(--code-bg);
    color: var(--code-fg);
    padding: 12px;
    border-radius: 4px;
    overflow-x: auto;
    font-family: 'Consolas', 'Monaco', monospace;
    font-size: 0.9em;
    border: 1px solid var(--code-border);
    margin: 8px 0;
    white-space: pre; /* No wrapping, force scroll */
}

pre[data-qnt-code-wrap="soft"]:not(.code-as-text) {
    white-space: pre-wrap;
    overflow-x: hidden;
    overflow-wrap: anywhere;
}

pre.code-scroll-rail-active:not(.code-as-text) {
    margin-bottom: 0;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    overflow-x: hidden;
    -ms-overflow-style: none;
    scrollbar-width: none;
}

pre.code-scroll-rail-active:not(.code-as-text)::-webkit-scrollbar {
    height: 0;
}

.code-block-shell {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: stretch;
    margin: 8px 0;
}

.code-block-frame {
    display: flex;
    flex-direction: column;
}

.code-block-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.code-block-shell pre {
    margin: 0;
    border-left: none;
    border-radius: 0 4px 4px 0;
    line-height: 1.45;
}

.code-block-shell pre.code-scroll-rail-active:not(.code-as-text) {
    border-bottom-right-radius: 0;
}

.code-line-gutter {
    --code-line-number-digits: 2;
    min-width: calc(var(--code-line-number-digits) * 0.72em + 1.6rem);
    padding: 12px 8px 12px 10px;
    background: color-mix(in srgb, var(--code-bg) 86%, white 14%);
    border: 1px solid var(--code-border);
    border-right: none;
    border-radius: 4px 0 0 4px;
    color: color-mix(in srgb, var(--code-fg) 42%, transparent 58%);
    font-family: 'Consolas', 'Monaco', monospace;
    font-size: 0.9em;
    line-height: 1.45;
    text-align: right;
    user-select: none;
    pointer-events: none;
}

.code-line-gutter-inner {
    display: flex;
    flex-direction: column;
}

.code-line-gutter-row {
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    min-height: 1.45em;
}

.code-line-gutter-row::before {
    content: attr(data-line-number);
}

.code-actions {
    position: static;
    display: none;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 5px;
    margin: 0;
    opacity: 1;
    z-index: auto;
    pointer-events: auto;
}

.code-block-frame[data-qnt-code-toolbar-active="1"] > .code-actions,
.svg-embed[data-qnt-code-toolbar-active="1"] > .svg-embed-toolbar {
    position: fixed;
    display: inline-flex;
    left: var(--qnt-code-toolbar-float-left, auto);
    top: var(--qnt-code-toolbar-float-top, auto);
    right: auto;
    bottom: auto;
    margin: 0;
    padding: 4px;
    border-radius: 10px;
    z-index: 40;
    cursor: grab;
    touch-action: none;
    background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--bg-editor-pane) 98%, white 2%) 0%,
        color-mix(in srgb, var(--bg-editor-pane) 94%, white 6%) 74%,
        transparent 100%
    );
    box-shadow: 0 14px 32px color-mix(in srgb, var(--mix-dark) 18%, transparent);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

.code-block-frame[data-qnt-code-toolbar-active="1"] > .code-actions.is-dragging,
.svg-embed[data-qnt-code-toolbar-active="1"] > .svg-embed-toolbar.is-dragging {
    cursor: grabbing;
}

.code-actions + pre,
.code-actions + .code-block-shell {
    margin-top: 0;
}

.code-action-btn {
    background: var(--overlay-chrome-bg);
    color: white;
    border: 1px solid color-mix(in srgb, var(--mix-light) 14%, transparent);
    border-radius: 6px;
    padding: 4px 7px;
    font-size: 0.75rem;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    transition: background-color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}

/* Buttons toggled via the `hidden` attribute in JS (Run on non-runnable blocks; wrap / line-number
   in plain-text mode) must actually disappear. The attribute selector outranks the `display` above
   by specificity, so the UA [hidden] rule isn't lost to the author display. */
.code-action-btn[hidden] {
    display: none;
}

.code-action-btn:hover {
    background: var(--overlay-chrome-bg-strong);
    border-color: color-mix(in srgb, var(--mix-light) 28%, transparent);
    transform: translateY(-1px);
}

.code-action-btn[data-action="delete"]:hover {
    background: var(--overlay-danger-bg);
    border-color: var(--overlay-danger-border);
}

.code-action-btn svg {
    width: 14px;
    height: 14px;
}

.code-action-btn[data-action="toggle-wrap"] {
    min-width: 58px;
    justify-content: center;
}

.code-action-btn[data-action="toggle-lines"] {
    min-width: 86px;
    justify-content: center;
}

.code-scroll-rail {
    display: block;
    height: 14px;
    margin: -8px 0 8px;
    position: sticky;
    bottom: 0;
    overflow-x: auto;
    overflow-y: hidden;
    background: color-mix(in srgb, var(--code-bg) 92%, white 8%);
    border: 1px solid var(--code-border);
    border-top: none;
    border-radius: 0 0 4px 4px;
    z-index: 4;
    box-shadow: 0 -6px 16px color-mix(in srgb, var(--mix-dark) 8%, transparent);
}

.code-block-main > .code-scroll-rail {
    margin: 0;
}

.code-scroll-rail-spacer {
    display: block;
    height: 1px;
}

pre.code-as-text {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    padding: 0;
    margin: 0 0 10px 0;
    white-space: pre-wrap;
    font-family: inherit;
    font-size: 1rem;
    color: var(--text-editor);
}

.code-actions + pre.code-as-text {
    margin-top: 0;
}

code {
    font-family: 'Consolas', 'Monaco', monospace;
    background-color: var(--inline-code-bg);
    color: var(--inline-code-fg);
    padding: 2px 4px;
    border-radius: 3px;
}

pre code {
    background-color: transparent;
    color: inherit;
    padding: 0;
    border-radius: 0;
}

/* --- THE CACHE BRAIN MAP (mindmap note kind) ---
   Feature-scoped styles for editor/BrainMapController.js. The map mounts INTO the editor content
   wrapper (replacing the rich-text surface) for notes of kind 'mindmap'. A hybrid HTML+SVG world:
   HTML .brain-map-note divs sit over an SVG connector layer, both inside one transformed
   .brain-map-world so a single CSS transform pans/zooms everything together. Its node ⋯ menu is
   appended to <body>, so that selector is global but `brain-map-`-prefixed.
   All chrome is token-driven (no hardcoded colours). Spec: Docs/001-cache-brain-map-requirements.md. */

/* When a map is mounted, hide the rich-text surface that shares the editor wrapper. */
.editor-content-wrapper.brain-map-mode > .note-title-row,
.editor-content-wrapper.brain-map-mode > #format-toolbar,
.editor-content-wrapper.brain-map-mode > .format-toolbar,
.editor-content-wrapper.brain-map-mode > #note-body,
.editor-content-wrapper.brain-map-mode > .note-editor,
.editor-content-wrapper.brain-map-mode #note-backlinks:not(.note-backlinks-floating),
.editor-content-wrapper.brain-map-mode .note-backlinks:not(.note-backlinks-floating) {
    display: none !important;
}

/* Focus mode + a map: maps need real estate, so let the canvas fill the whole editor pane instead of
   the 960px reading column (that column is meant for text notes — see body.focus-mode rule). The
   sidebar + note list are already hidden by focus mode, so this gives the map the full window width. */
body.focus-mode .editor-content-wrapper.brain-map-mode {
    max-width: none;
    margin: 0;
    padding: 0;
}

.brain-map {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
    color: var(--text-main);
    font-size: 0.95rem;
    /* §13.8 sticky-note palette — a fixed "yellow paper" content treatment (like the node-colour
       swatches), feature-scoped here rather than a global token. Both themes provided. */
    --bm-sticky-bg: #fff7c2; /* literal-ok: sticky-note palette, fixed content treatment */
    --bm-sticky-edge: #ecd76a; /* literal-ok: sticky-note palette, fixed content treatment */
    --bm-sticky-text: #4a4320; /* literal-ok: sticky-note palette, fixed content treatment */
}
:root[data-theme="dark"] .brain-map {
    --bm-sticky-bg: #5a5020; /* literal-ok: sticky-note palette, fixed content treatment */
    --bm-sticky-edge: #7c6f2c; /* literal-ok: sticky-note palette, fixed content treatment */
    --bm-sticky-text: #f6edc2; /* literal-ok: sticky-note palette, fixed content treatment */
}

/* --- toolbar --- */
.brain-map-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-pane);
}
/* the map title doubles as a rename button — single click to edit (a pencil hint shows on hover) */
.brain-map-title {
    font: inherit;
    font-weight: 600;
    color: var(--text-main);
    margin-right: auto;
    cursor: text;
    max-width: 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 2px 8px;
    transition: background var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.brain-map-title::after {
    content: "✎";
    font-size: 0.85em;
    opacity: 0;
    transition: opacity var(--anim-fast) var(--anim-ease);
}
.brain-map-title:hover, .brain-map-title:focus-visible {
    background: var(--item-hover);
    border-color: var(--border-color);
    outline: none;
}
.brain-map-title:hover::after, .brain-map-title:focus-visible::after { opacity: 0.6; }
.brain-map-title-input {
    margin-right: auto;
    font: inherit;
    font-weight: 600;
    color: var(--text-main);
    background: var(--bg-app);
    border: 1px solid var(--primary-color);
    border-radius: var(--radius-sm);
    padding: 2px 6px;
}
.brain-map-tb-group { display: inline-flex; gap: 6px; align-items: center; }

/* --- find-a-node search --- */
.brain-map-search { position: relative; }
.brain-map-search-input {
    font: inherit;
    font-size: 0.85rem;
    color: var(--text-main);
    background: var(--bg-app);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 5px 9px;
    width: 150px;
}
.brain-map-search-input:focus { outline: none; border-color: var(--primary-color); }
.brain-map-search-results {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    z-index: 50;
    min-width: 180px;
    max-width: 280px;
    max-height: 260px;
    overflow-y: auto;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 4px;
}
.brain-map-search-row {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    color: var(--text-main);
    padding: 6px 9px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.brain-map-search-row:hover, .brain-map-search-row.active { background: var(--item-hover); }
.brain-map-search-empty { padding: 6px 9px; color: var(--text-muted); font-size: 0.82rem; }
.brain-map-btn {
    background: var(--bg-app);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 5px 10px;
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1.2;
}
.brain-map-btn:hover:not(:disabled) { background: var(--item-hover); }
.brain-map-btn:disabled { opacity: 0.4; cursor: default; }

/* --- viewport / world --- */
.brain-map-viewport {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    cursor: grab;
    outline: none;
    background-color: var(--bg-app);
    background-image: radial-gradient(circle, var(--border-color) 1px, transparent 1px);
    background-size: 28px 28px;
    touch-action: none;
    user-select: none;         /* pan / node drags must not highlight node text (edit textarea opts back in) */
    -webkit-user-select: none;
}
.brain-map-viewport.panning { cursor: grabbing; }
.brain-map-viewport--droptarget { box-shadow: inset 0 0 0 3px var(--primary-color); }
.brain-map-world { position: absolute; top: 0; left: 0; transform-origin: 0 0; }

.brain-map-edges { position: absolute; top: 0; left: 0; overflow: visible; pointer-events: none; }
.brain-map-edge { fill: none; stroke: var(--text-muted); stroke-width: 2; }
.brain-map-edge--linking { stroke: var(--primary-color); stroke-dasharray: 6 5; }
.brain-map-edge-handle {
    fill: var(--text-muted);
    opacity: 0.35;
    cursor: grab;
    pointer-events: all;             /* override #edges pointer-events:none */
    transition: opacity var(--anim-fast) var(--anim-ease), fill var(--anim-fast) var(--anim-ease);
}
.brain-map-edge-handle:hover { opacity: 1; fill: var(--primary-color); }
/* wide transparent hit path over each solid connector — easy to hover / Delete-to-detach (§13.7) */
.brain-map-edge-hit {
    fill: none;
    stroke: transparent;
    stroke-width: 14;
    pointer-events: stroke;
    cursor: pointer;            /* signals the connector is interactive (hover → red, Delete to detach) */
}
/* Hovering a solid edge highlights it red + thicker — the "press Delete to detach this branch" cue. */
.brain-map-edge--hover { stroke: var(--danger-color); stroke-width: 3; }

.brain-map-nodes { position: absolute; top: 0; left: 0; }

/* cross-links (§13.3): free-form directed, dashed, arrowed relationship edges */
.brain-map-xlink {
    fill: none;
    stroke: var(--primary-color);
    stroke-width: 2;
    stroke-dasharray: 7 5;
    opacity: 0.85;
}
.brain-map-xlink--drawing { opacity: 1; }
.brain-map-xlink-marker path { fill: var(--primary-color); }
.brain-map-xlink-hit {
    fill: none;
    stroke: transparent;
    stroke-width: 14;
    pointer-events: stroke;     /* the lines stay thin but are easy to hover / Delete+Click */
    cursor: pointer;            /* signals the link is interactive (hover → red, Delete to remove) */
}
/* Hovering a cross-link highlights it red + thicker — the "press Delete to remove this" affordance. */
.brain-map-xlink--hover { stroke: var(--danger-color); stroke-width: 3; opacity: 1; }
.brain-map-xlink-marker--hot path { fill: var(--danger-color); }
/* valid drop target while Ctrl+dragging a new cross-link */
.brain-map-note--xlink-target {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary-color) 40%, transparent), var(--shadow-md);
}
.brain-map--xlinking, .brain-map--xlinking .brain-map-note { cursor: crosshair; }

/* --- notes --- */
.brain-map-note {
    position: absolute;
    transform: translate(-50%, -50%);   /* left/top = node CENTER (set by JS) */
    /* width:max-content (capped by max-width) — without it, an absolutely-positioned node inside a
       zero-width container shrinks to MIN-content (one word per line) for long text. JS may set an
       explicit width (manual resize), which overrides both. */
    width: max-content;
    min-width: 90px;
    max-width: 240px;
    padding: 9px 12px;
    background: var(--bg-pane);
    color: var(--text-main);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    font-size: 0.9rem;
    line-height: 1.35;
    cursor: grab;
    transition: box-shadow var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.brain-map-note--root {
    background: color-mix(in srgb, var(--primary-color) 18%, var(--bg-pane));
    border-color: var(--primary-color);
    font-weight: 600;
    min-width: 120px;
}
.brain-map-note--floating { border-style: dashed; }
.brain-map-note.selected {
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary-color) 30%, transparent), var(--shadow-md);
}
.brain-map-note.dragging { cursor: grabbing; box-shadow: 0 12px 28px color-mix(in srgb, var(--mix-dark) 40%, transparent); }
.brain-map-note--link-target {
    border-color: var(--success-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--success-color) 40%, transparent), var(--shadow-md);
}
.brain-map--linking, .brain-map--linking .brain-map-note { cursor: grabbing; }

/* branch drag (long-press / Shift+drag): every node that will move together gets a lifted ring so the
   locked group is obvious; the held node briefly pulses when the branch locks. */
.brain-map-note--branch-lift {
    cursor: grabbing;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 45%, transparent), 0 10px 24px color-mix(in srgb, var(--mix-dark) 32%, transparent);
}
.brain-map-note--branch-armed { animation: brain-map-branch-pop 0.45s ease; }
@keyframes brain-map-branch-pop {
    /* keep the -50%,-50% centering transform (JS positions by node CENTER) while scaling */
    0% { transform: translate(-50%, -50%) scale(1); }
    45% { transform: translate(-50%, -50%) scale(1.07); }
    100% { transform: translate(-50%, -50%) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .brain-map-note--branch-armed { animation: none; }
}

/* tooltip on/off switch (next to "?") — a small pill toggle; off by default */
.brain-map-tip-toggle {
    position: relative;
    flex: 0 0 auto;
    align-self: center;
    width: 34px;
    height: 18px;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-muted) 25%, transparent);
    cursor: pointer;
    transition: background var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.brain-map-tip-toggle-knob {
    position: absolute;
    top: 50%;
    left: 2px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--bg-pane);
    transform: translateY(-50%);
    box-shadow: var(--shadow-sm, 0 1px 2px color-mix(in srgb, var(--mix-dark) 30%, transparent));
    transition: left var(--anim-fast) var(--anim-ease);
}
.brain-map-tip-toggle--on {
    background: var(--primary-color);
    border-color: var(--primary-color);
}
.brain-map-tip-toggle--on .brain-map-tip-toggle-knob { left: 18px; }

/* controls & gestures help — a floating, movable (drag the header), resizable (bottom-right grip),
   persisted dialog toggled by the toolbar "?" button. Non-modal: the canvas stays usable behind it. */
.brain-map-help {
    position: absolute;
    z-index: 30;
    display: flex;
    flex-direction: column;
    min-width: 260px;
    min-height: 180px;
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    overflow: hidden;          /* required for the native resize grip + lets the body scroll */
    resize: both;
}
.brain-map-help--dragging { user-select: none; }
.brain-map-help-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-color);
    cursor: move;
    touch-action: none;        /* let the header own the drag pointer on touch */
    user-select: none;
}
.brain-map-help-close {
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px 7px;
    border-radius: var(--radius-sm, 6px);
}
.brain-map-help-close:hover {
    color: var(--text-main);
    background: color-mix(in srgb, var(--text-main) 10%, transparent);
}
.brain-map-help-body {
    flex: 1 1 auto;
    padding: 4px 14px 14px;
    overflow: auto;
}
.brain-map-help dl { margin: 0; }
.brain-map-help-group { margin-top: 12px; }
.brain-map-help-group h4 {
    margin: 0 0 6px;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
}
.brain-map-help-row {
    display: grid;
    grid-template-columns: minmax(0, 46%) 1fr;
    gap: 10px;
    padding: 4px 0;
    align-items: baseline;
}
.brain-map-help-row dt { font-weight: 600; font-size: 0.82rem; }
.brain-map-help-row dd { margin: 0; color: var(--text-muted); font-size: 0.85rem; }
@media (max-width: 640px) {
    .brain-map-help-row { grid-template-columns: 1fr; gap: 2px; }
}

/* node colour: a left accent bar + subtle tint from the user-chosen swatch (inline --bm-node-accent) */
.brain-map-note--colored {
    border-left: 5px solid var(--bm-node-accent);
    background: color-mix(in srgb, var(--bm-node-accent) 14%, var(--bg-pane));
}

/* §13.8 sticky note: a paper-yellow comment card with a squared top-left and a folded bottom-right
   corner (the "dog-ear"). Still a full node — movable, linkable, deletable. */
.brain-map-note--sticky {
    background: var(--bm-sticky-bg);
    color: var(--bm-sticky-text);
    border-color: var(--bm-sticky-edge);
    border-radius: 2px 2px 2px 0;
    box-shadow: var(--shadow-sm);
}
.brain-map-note--sticky.brain-map-note--colored {
    /* a chosen swatch still tints, but keep the sticky paper base legible */
    background: color-mix(in srgb, var(--bm-node-accent) 16%, var(--bm-sticky-bg));
}
/* folded corner — at the TOP-LEFT (that corner is free; keeps the bottom-right clear for the resize
   grip and the right edge clear for the ＋). Decorative, so it never intercepts pointer events. */
.brain-map-note--sticky::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 14px;
    height: 14px;
    background: linear-gradient(315deg, transparent 50%, color-mix(in srgb, var(--bm-sticky-edge) 70%, var(--mix-dark)) 50%);
    border-bottom-right-radius: 3px;
    pointer-events: none;
}
.brain-map-note--sticky .brain-map-note-label.empty::after { color: var(--bm-sticky-text); }

/* flash when a search result is picked (respects reduced motion) */
@keyframes brain-map-flash {
    0%, 100% { box-shadow: var(--shadow-md); }
    50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary-color) 55%, transparent), var(--shadow-md); }
}
.brain-map-note--flash { animation: brain-map-flash 0.4s ease 3; }
@media (prefers-reduced-motion: reduce) {
    .brain-map-note--flash { animation: none; border-color: var(--primary-color); }
}

/* collapse / expand toggle — visible whenever a node has children. Centered on the right margin
   regardless of its (variable) width via right:0 + translateX(50%). */
.brain-map-collapse {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translate(50%, -50%);
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 10px;
    background: var(--bg-app);
    color: var(--text-muted);
    border: 1px solid var(--border-color);
    font-size: 0.72rem;
    line-height: 1;
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
}
.brain-map-note--haskids .brain-map-collapse { display: inline-flex; }
.brain-map-collapse:hover { color: var(--text-main); background: var(--item-hover); }
.brain-map-note--collapsed { border-style: dashed; }

.brain-map-note-label { pointer-events: none; min-height: 1em; white-space: pre-wrap; word-break: break-word; }

/* image nodes (§13.2): a downscaled thumbnail; the text label becomes an optional caption */
.brain-map-note-img { display: none; }
.brain-map-note--image { padding: 4px; min-width: 0; }
.brain-map-note--image .brain-map-note-img {
    display: block;
    max-width: 160px;
    max-height: 120px;
    border-radius: 6px;
    object-fit: contain;
    pointer-events: none;       /* clicks/drags act on the node, not the image */
}
.brain-map-note--image .brain-map-note-label { text-align: center; font-size: 0.8rem; margin-top: 4px; }
.brain-map-note--image .brain-map-note-label.empty { display: none; }
.brain-map-note--image .brain-map-note-label.empty::after { content: none; }
.brain-map-note-label.empty::after { content: "…"; opacity: 0.4; }
.brain-map-note-input {
    width: 100%;
    border: none;
    outline: none;
    resize: none;
    background: transparent;
    color: inherit;
    font: inherit;
    line-height: inherit;
    padding: 0;
    margin: 0;
    overflow: hidden;
    user-select: text;         /* re-enable inside the no-select viewport so editing can select text */
    -webkit-user-select: text;
}

/* on-node affordances: shown on hover / when selected */
.brain-map-note-menu,
.brain-map-add-btn,
.brain-map-link-dot { display: none; }
.brain-map-note:hover .brain-map-note-menu,
.brain-map-note.selected .brain-map-note-menu,
.brain-map-note:hover .brain-map-add-btn,
.brain-map-note.selected .brain-map-add-btn,
.brain-map-note:hover .brain-map-link-dot,
.brain-map-note.selected .brain-map-link-dot { display: flex; }

.brain-map-note-menu {
    position: absolute;
    top: -10px;
    right: -10px;
    width: 22px;
    height: 22px;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bg-app);
    color: var(--text-muted);
    border: 1px solid var(--border-color);
    font-size: 0.8rem;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
.brain-map-note-menu:hover { color: var(--text-main); background: var(--item-hover); }

/* add-child (+): floats just OUTSIDE the right edge (left:100% + a small gap), vertically centred.
   Being fully outside the box means it can never cover the bottom-right resize grip (which sits just
   inside the corner) — on ANY node height. Stacks below the collapse toggle when one is present. */
.brain-map-add-btn {
    position: absolute;
    left: 100%;
    top: 50%;
    margin-left: 7px;
    transform: translateY(-50%);
    width: 24px;
    height: 24px;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--primary-color);
    color: var(--on-accent);
    border: 2px solid var(--bg-app);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}
.brain-map-note--haskids .brain-map-add-btn { transform: translateY(calc(-50% + 26px)); }

/* manual width resize grip — the conventional bottom-right corner (where users expect it). The ＋
   button floats fully outside the right edge, so it no longer covers this grip on short nodes. */
.brain-map-resize {
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 12px;
    height: 12px;
    cursor: ew-resize;
    display: none;
    opacity: 0.55;
    background:
        linear-gradient(135deg, transparent 0 55%, var(--text-muted) 55% 65%, transparent 65% 78%, var(--text-muted) 78% 88%, transparent 88%);
}
.brain-map-note.selected .brain-map-resize,
.brain-map-note:hover .brain-map-resize { display: block; }
.brain-map-resize:hover { opacity: 1; }

/* the "string" anchor: drag onto another note to link (§10.2) */
.brain-map-link-dot {
    position: absolute;
    left: -11px;
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--bg-app);
    border: 2px solid var(--primary-color);
    cursor: grab;
    align-items: center;
    justify-content: center;
}
.brain-map-link-dot:active { cursor: grabbing; }

/* linked-note jump badge — only on nodes that carry a linkedNoteId */
.brain-map-note-jump {
    position: absolute;
    left: -8px;
    bottom: -8px;
    font-size: 0.7rem;
    cursor: pointer;
    display: none;
}
.brain-map-note--linked .brain-map-note-jump { display: inline; }

/* --- zoom readout + FAB --- */
.brain-map-zoom {
    position: absolute;
    right: 10px;
    bottom: 10px;
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    color: var(--text-muted);
    font-size: 0.75rem;
    pointer-events: none;
}
/* --- node ⋯ menu + hamburger (appended to <body>) --- */
.brain-map-menu {
    position: fixed;
    z-index: 10000;
    min-width: 170px;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 4px;
}
.brain-map-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    color: var(--text-main);
    padding: 7px 10px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 0.85rem;
}
.brain-map-menu-item:hover { background: var(--item-hover); }
.brain-map-menu-sep { height: 1px; background: var(--border-color); margin: 4px 6px; }

.brain-map-color-menu { min-width: 0; }
.brain-map-swatches { display: flex; gap: 6px; padding: 4px; }
.brain-map-swatch {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid var(--border-color);
    cursor: pointer;
    padding: 0;
}
.brain-map-swatch:hover { transform: scale(1.12); }
.brain-map-swatch--none { background: var(--bg-app); color: var(--text-muted); font-size: 0.7rem; line-height: 1; }

/* --- view-only (the split screen — Docs/000-split-app-kind-views-and-backlinks-plan.md) ---
   Nodes select, collapse and open their linked note, but never drag, add, link, reparent or resize, and
   the title is plain text (no rename hint). */
.brain-map--readonly .brain-map-title { cursor: default; }
.brain-map--readonly .brain-map-title::after { content: none; }
.brain-map--readonly .brain-map-title:hover,
.brain-map--readonly .brain-map-title:focus-visible { background: none; border-color: transparent; }
.brain-map--readonly .brain-map-note { cursor: default; }
.brain-map--readonly .brain-map-add-btn,
.brain-map--readonly .brain-map-link-dot,
.brain-map--readonly .brain-map-resize,
.brain-map--readonly .brain-map-edge-handle { display: none !important; }
.brain-map--readonly .brain-map-edge-hit,
.brain-map--readonly .brain-map-xlink-hit { cursor: default; }

/* --- toast --- */
.brain-map-toast {
    position: absolute;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%) translateY(8px);
    background: var(--text-main);
    color: var(--bg-app);
    padding: 8px 14px;
    border-radius: var(--radius-md);
    font-size: 0.82rem;
    box-shadow: var(--shadow-md);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}
.brain-map-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* --- THE CACHE STORY BOARD (storyboard note kind) ---
   Feature-scoped styles for editor/StoryBoardController.js. The board mounts INTO the editor content
   wrapper (replacing the rich-text surface) for notes of kind 'storyboard'. It is a stack of
   horizontal swim lanes on a pan/zoom camera: lane bands + absolutely-positioned card divs live
   inside one transformed .story-board-world, so a single CSS transform pans/zooms everything
   together (mirrors the Brain Map). Menus / present overlay / toasts are appended to <body>, so those
   selectors are global but `story-board-`-prefixed. All chrome is token-driven (no hardcoded colours
   except the documented sticky/status content treatments). Spec: Docs/002-cache-story-board-requirements.md. */

/* When a board is mounted, hide the rich-text surface that shares the editor wrapper. */
.editor-content-wrapper.story-board-mode > .note-title-row,
.editor-content-wrapper.story-board-mode > #format-toolbar,
.editor-content-wrapper.story-board-mode > .format-toolbar,
.editor-content-wrapper.story-board-mode > #note-body,
.editor-content-wrapper.story-board-mode > .note-editor,
.editor-content-wrapper.story-board-mode #note-backlinks:not(.note-backlinks-floating),
.editor-content-wrapper.story-board-mode .note-backlinks:not(.note-backlinks-floating) {
    display: none !important;
}

/* Focus mode + a board: give the canvas the whole editor pane (not the 960px text column). */
body.focus-mode .editor-content-wrapper.story-board-mode {
    max-width: none;
    margin: 0;
    padding: 0;
}

.story-board {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
    color: var(--text-main);
    font-size: 0.95rem;
    /* Card text is not a text document — dragging across cards shouldn't select it, and refocusing
       the window (alt-tab back) shouldn't restore a phantom selection across cards (§16.5). Edit
       fields re-enable selection below. */
    user-select: none;
    -webkit-user-select: none;
    /* Sticky-note palette — a fixed "yellow paper" content treatment (both themes). */
    --sb-sticky-bg: #fff7c2; /* literal-ok: sticky-note palette, fixed content treatment */
    --sb-sticky-edge: #ecd76a; /* literal-ok: sticky-note palette, fixed content treatment */
    --sb-sticky-text: #4a4320; /* literal-ok: sticky-note palette, fixed content treatment */
    /* Status-tag palette (card.color values) — fixed content treatment, both themes. */
    --sb-tag-draft: var(--warning-color);
    --sb-tag-progress: var(--primary-color);
    --sb-tag-final: var(--success-color);
    --sb-tag-accent: #8b5cf6; /* literal-ok: sticky-note palette, fixed content treatment */
}
:root[data-theme="dark"] .story-board {
    --sb-sticky-bg: #5a5020; /* literal-ok: sticky-note palette, fixed content treatment */
    --sb-sticky-edge: #7c6f2c; /* literal-ok: sticky-note palette, fixed content treatment */
    --sb-sticky-text: #f6edc2; /* literal-ok: sticky-note palette, fixed content treatment */
    --sb-tag-accent: #a78bfa; /* literal-ok: sticky-note palette, fixed content treatment */
}
/* re-enable text selection where the user is actually editing text (§16.5) */
.story-board input,
.story-board textarea {
    user-select: text;
    -webkit-user-select: text;
}

/* duration dialog slider (appended to <body>, so global but story-board-prefixed) */
.story-board-dialog-slider {
    width: 100%;
    accent-color: var(--primary-color);
    cursor: pointer;
    margin: 2px 0 4px;
}
.story-board-dialog-slider-ends {
    display: flex;
    justify-content: space-between;
    font-size: 0.72rem;
    color: var(--text-muted);
}

/* --- toolbar --- */
.story-board-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-pane);
    flex: 0 0 auto;
}
.story-board-title {
    font: inherit;
    font-weight: 600;
    color: var(--text-main);
    margin-right: auto;
    cursor: text;
    max-width: 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
}
.story-board-title::after {
    content: "✎";
    font-size: 0.8em;
    opacity: 0;
    transition: opacity var(--anim-fast) var(--anim-ease);
}
.story-board-title:hover {
    border-color: var(--border-color);
    background: var(--item-hover);
}
.story-board-title:hover::after { opacity: 0.6; }

/* view-only (the split screen — Docs/000-split-app-kind-views-and-backlinks-plan.md): cards select and open,
   but nothing renames, adds or drags, so the rename hint, add ghosts and lane menus go. */
.story-board--readonly .story-board-title { cursor: default; }
.story-board--readonly .story-board-title::after { content: none; }
.story-board--readonly .story-board-title:hover { border-color: transparent; background: transparent; }
.story-board--readonly .story-board-lane-title,
.story-board--readonly .story-board-card { cursor: default; }
.story-board--readonly .story-board-add-card,
.story-board--readonly .story-board-add-lane,
.story-board--readonly .story-board-lane-menu { display: none !important; }
.story-board-title-input,
.story-board-lane-rename {
    font: inherit;
    font-weight: 600;
    color: var(--text-main);
    padding: 4px 8px;
    border: 1px solid var(--primary-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
}
.story-board-tb-group {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.story-board-btn {
    font: inherit;
    font-size: 0.88rem;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 5px 10px;
    cursor: pointer;
    line-height: 1;
    transition: background var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.story-board-btn:hover:not(:disabled) { background: var(--item-hover); border-color: var(--pane-divider); }
.story-board-btn:disabled { opacity: 0.45; cursor: default; }
.story-board-btn[data-act="present"] { color: var(--primary-color); }
.story-board-runtime {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin-left: 4px;
    white-space: nowrap;
}

/* --- viewport / world --- */
.story-board-viewport {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    background:
        radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--border-color) 70%, transparent) 1px, transparent 0);
    background-size: 26px 26px;
    background-color: var(--bg-editor-pane);
    cursor: grab;
    touch-action: none;
    outline: none;
}
.story-board-viewport:active { cursor: grabbing; }
.story-board-world {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: 0 0;
    will-change: transform;
}
.story-board-lanes,
.story-board-cards {
    position: absolute;
    top: 0;
    left: 0;
}

/* --- lane bands --- */
.story-board-lane {
    position: absolute;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--bg-pane) 70%, transparent);
    box-shadow: var(--shadow-sm);
}
.story-board-lane--colored {
    border-left: 4px solid var(--sb-lane-accent, var(--primary-color));
}
.story-board-lane-header {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    box-sizing: border-box;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    border-right: 1px dashed var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 40%, transparent);
}
.story-board-lane-title {
    font-weight: 600;
    color: var(--text-main);
    cursor: text;
    word-break: break-word;
    line-height: 1.25;
}
.story-board-lane-dur {
    font-size: 0.78rem;
    color: var(--text-muted);
}
.story-board-lane-menu {
    margin-top: auto;
    align-self: flex-start;
    font: inherit;
    color: var(--text-muted);
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
}
.story-board-lane-menu:hover { background: var(--item-hover); color: var(--text-main); }
.story-board-add-lane {
    position: absolute;
    box-sizing: border-box;
    padding: 10px;
    font: inherit;
    font-size: 0.85rem;
    color: var(--text-muted);
    background: transparent;
    border: 1px dashed var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
}
.story-board-add-lane:hover { color: var(--primary-color); border-color: var(--primary-color); }

/* --- cards --- */
.story-board-card {
    position: absolute;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    box-shadow: var(--shadow-sm);
    cursor: grab;
    overflow: hidden;
    transition: box-shadow var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.story-board-card:hover { box-shadow: var(--shadow-md); }
/* Selected card = a clear outline + a lifted shadow border + a ✓ tick (parity with Cache Board
   task-select, §16.1). */
.story-board-card.selected {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary-color) 22%, transparent), var(--shadow-md);
}
/* the tick: hidden until selected, then a filled primary badge at the top-left corner */
.story-board-card-tick {
    position: absolute;
    top: 5px;
    left: 5px;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: var(--primary-color);
    color: var(--on-accent);
    font-size: 0.72rem;
    font-weight: 800;
    line-height: 17px;
    text-align: center;
    z-index: 3;
    display: none;
}
.story-board-card.selected .story-board-card-tick { display: block; }
/* when selected, slide the number badge right so it sits beside the tick instead of under it */
.story-board-card.selected .story-board-card-num { left: 27px; }
.story-board-card--dragging { opacity: 0.85; z-index: 50; cursor: grabbing; box-shadow: var(--shadow-md); }
.story-board-card--colored { border-left: 4px solid var(--sb-card-accent, var(--primary-color)); }
/* reserve room at the top for the corner number badge on non-image cards (no frame above the title) */
.story-board-card--numbered { padding-top: 28px; }
/* Sticky card = a paper sticky note pinned to the board (§16.4): warm paper, soft drop shadow, a
   faint hand-pinned tilt, and a red push-pin through the top. */
.story-board-card--sticky {
    background:
        linear-gradient(180deg, color-mix(in srgb, var(--sb-sticky-bg) 100%, var(--mix-light) 6%) 0%, var(--sb-sticky-bg) 22%);
    border-color: var(--sb-sticky-edge);
    color: var(--sb-sticky-text);
    border-radius: 3px;                 /* paper corners are crisper than the rounded cards */
    box-shadow: 2px 5px 12px color-mix(in srgb, var(--mix-dark) 20%, transparent);
    transform: rotate(-1.4deg);         /* casually pinned */
    padding-top: 22px;                  /* clearance for the pin head */
    overflow: visible;                  /* let the pin sit above the top edge */
}
/* keep the tilt from being cancelled while dragging, but drop it when the grid re-lays cards out */
.story-board-card--sticky.story-board-card--dragging { transform: rotate(-1.4deg); }
.story-board-card--sticky.story-board-card--numbered { padding-top: 30px; }
.story-board-card--sticky .story-board-card-title,
.story-board-card--sticky .story-board-card-body { color: var(--sb-sticky-text); }
/* the red push-pin: a domed head with a highlight, sitting through the top of the note */
.story-board-card--sticky::before {
    content: "";
    position: absolute;
    top: -8px;
    left: 50%;
    width: 16px;
    height: 16px;
    transform: translateX(-50%);
    border-radius: 50%;
    background: radial-gradient(circle at 34% 30%, #ff9a9a 0%, #e6392f 52%, #a5160f 100%); /* literal-ok: push-pin, fixed content treatment */
    box-shadow: 0 3px 4px rgba(20, 24, 34, 0.4), inset 0 -1px 2px rgba(120, 0, 0, 0.5); /* literal-ok: push-pin, fixed content treatment */
    z-index: 4;
    pointer-events: none;
}
/* a tiny stem/glint under the pin head so it reads as pushed in */
.story-board-card--sticky::after {
    content: "";
    position: absolute;
    top: 4px;
    left: 50%;
    width: 3px;
    height: 6px;
    transform: translateX(-50%);
    background: color-mix(in srgb, var(--sb-sticky-edge) 70%, #8a6a1a 30%); /* literal-ok: sticky-note palette, fixed content treatment */
    border-radius: 0 0 2px 2px;
    z-index: 3;
    pointer-events: none;
}

.story-board-card-num {
    position: absolute;
    top: 6px;
    left: 6px;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--on-accent);
    background: var(--primary-color);
    border-radius: var(--radius-sm);
    padding: 1px 6px;
    line-height: 1.4;
    z-index: 2;
}
.story-board-card-menu,
.story-board-card-link {
    position: absolute;
    top: 4px;
    font: inherit;
    color: var(--text-muted);
    background: color-mix(in srgb, var(--bg-pane) 70%, transparent);
    border: none;
    cursor: pointer;
    padding: 2px 5px;
    border-radius: var(--radius-sm);
    line-height: 1;
    opacity: 0;
    transition: opacity var(--anim-fast) var(--anim-ease);
    z-index: 2;
}
.story-board-card-menu { right: 4px; }
.story-board-card-link { right: 28px; }
.story-board-card:hover .story-board-card-menu,
.story-board-card:hover .story-board-card-link,
.story-board-card.selected .story-board-card-menu,
.story-board-card.selected .story-board-card-link { opacity: 1; }
.story-board-card-menu:hover,
.story-board-card-link:hover { background: var(--item-hover); color: var(--text-main); }

.story-board-card-frame {
    width: 100%;
    background: color-mix(in srgb, var(--text-muted) 15%, transparent);
    border-radius: var(--radius-sm);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.story-board-card-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.story-board-card-frame-empty { font-size: 0.78rem; color: var(--text-muted); }

/* Attached-links chip (Docs/004): compact indicator on the card; opens the Edit card dialog. The card's
   own content stays the face — links never take it over. */
.story-board-card-links {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 2px;
    padding: 1px 7px 1px 5px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: var(--bg-app);
    color: var(--text-muted);
    font-size: 0.72rem;
    line-height: 1.4;
    cursor: pointer;
    transition: background var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.story-board-card-links:hover { background: var(--item-hover); border-color: var(--primary-color); color: var(--text-main); }
.story-board-card-links-n { font-weight: 700; color: var(--text-main); }

/* Edit card dialog — links section */
.sb-ce-hint { color: var(--text-muted); font-weight: 400; }
.sb-links-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 4px; }
.sb-links-add {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-app);
    color: var(--text-main);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}
.sb-links-add:hover { background: var(--item-hover); border-color: var(--primary-color); }
.sb-links-list { display: flex; flex-direction: column; gap: 6px; max-height: 240px; overflow-y: auto; }
.sb-links-empty { color: var(--text-muted); font-size: 0.82rem; padding: 8px 2px; }
.sb-link-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
}
.sb-link-icon { flex: 0 0 auto; font-size: 1rem; }
.sb-link-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.86rem; }
.sb-link-meta { flex: 0 0 auto; font-size: 0.72rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.sb-link-open, .sb-link-del {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 0.9rem;
    line-height: 1;
    transition: background var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}
.sb-link-open:hover { background: var(--item-hover); color: var(--primary-color); }
.sb-link-del:hover { background: var(--item-hover); color: var(--danger-color); }

/* Media lightbox — full-screen player for a linked still/scene video. */
.story-board-lightbox {
    position: fixed;
    inset: 0;
    z-index: 6200;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 32px;
    box-sizing: border-box;
    background: color-mix(in srgb, var(--mix-dark) 82%, transparent);
    backdrop-filter: blur(4px);
}
.story-board-lightbox-body {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
    max-height: 82vh;
}
.story-board-lightbox-media {
    max-width: 100%;
    max-height: 82vh;
    border-radius: var(--radius-md);
    box-shadow: 0 24px 70px color-mix(in srgb, var(--mix-dark) 50%, transparent);
    background: var(--mix-dark);
}
.story-board-lightbox-close {
    position: absolute;
    top: 16px;
    right: 20px;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--bg-pane) 15%, transparent);
    color: var(--on-accent);
    font-size: 1.1rem;
    cursor: pointer;
}
.story-board-lightbox-close:hover { background: color-mix(in srgb, var(--mix-light) 28%, transparent); }
.story-board-lightbox-audio { width: min(90vw, 480px); }
.story-board-lightbox-cap { color: color-mix(in srgb, var(--mix-light) 82%, transparent); font-size: 0.86rem; }
.story-board-card-title {
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1.25;
    color: var(--text-main);
    word-break: break-word;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.story-board-card-ph { color: var(--text-muted); font-weight: 400; }
.story-board-card-body {
    font-size: 0.82rem;
    line-height: 1.35;
    color: var(--text-muted);
    white-space: pre-wrap;
    word-break: break-word;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
}
.story-board-card-meta,
.story-board-card-dialogue {
    font-size: 0.74rem;
    color: var(--text-muted);
    border-top: 1px dashed var(--border-color);
    padding-top: 4px;
    word-break: break-word;
}
.story-board-card-dialogue { font-style: italic; }
.story-board-card-dur {
    position: absolute;
    bottom: 4px;
    right: 6px;
    font-size: 0.72rem;
    color: var(--text-muted);
    background: color-mix(in srgb, var(--bg-pane) 70%, transparent);
    border-radius: var(--radius-sm);
    padding: 0 4px;
}

/* inline edit form */
.story-board-card--editing { cursor: default; z-index: 40; }
.story-board-edit-title,
.story-board-edit-body {
    font: inherit;
    width: 100%;
    box-sizing: border-box;
    color: var(--text-main);
    background: var(--bg-pane);
    border: 1px solid var(--primary-color);
    border-radius: var(--radius-sm);
    padding: 4px 6px;
}
.story-board-edit-title { font-weight: 600; }
.story-board-edit-body { resize: vertical; min-height: 54px; }

/* trailing "add card" ghost slot */
.story-board-add-card {
    position: absolute;
    box-sizing: border-box;
    font-size: 1.4rem;
    color: var(--text-muted);
    background: transparent;
    border: 1px dashed var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
    opacity: 0.5;
    transition: opacity var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.story-board-add-card:hover { opacity: 1; color: var(--primary-color); border-color: var(--primary-color); }

/* drop marker during a card drag */
.story-board-drop-marker {
    position: absolute;
    width: 4px;
    border-radius: 2px;
    background: var(--primary-color);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 30%, transparent);
    pointer-events: none;
    z-index: 45;
}

/* zoom badge */
.story-board-zoom {
    position: absolute;
    right: 10px;
    bottom: 10px;
    font-size: 0.78rem;
    color: var(--text-muted);
    background: color-mix(in srgb, var(--bg-pane) 80%, transparent);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 2px 8px;
    pointer-events: none;
}

/* --- context / ⋯ menus (appended to body) --- */
.story-board-menu {
    position: fixed;
    z-index: 10000;
    min-width: 190px;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 5px;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.story-board-menu-item {
    font: inherit;
    font-size: 0.9rem;
    text-align: left;
    color: var(--text-main);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    padding: 7px 10px;
    cursor: pointer;
    white-space: nowrap;
}
.story-board-menu-item:hover { background: var(--item-hover); }
.story-board-menu-item.danger { color: var(--danger-color); }
.story-board-menu-sep {
    height: 1px;
    background: var(--border-color);
    margin: 4px 2px;
}

/* --- present / animatic overlay (appended to body) --- */
.story-board-present {
    position: fixed;
    inset: 0;
    z-index: 10001;
    background: rgba(8, 12, 20, 0.94); /* literal-ok: canvas HUD is dark in both themes */
    display: flex;
    align-items: center;
    justify-content: center;
    color: #f4f7fb; /* literal-ok: canvas HUD is dark in both themes */
}
.story-board-present-stage {
    max-width: 82vw;
    max-height: 78vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
.story-board-present-frame {
    width: min(82vw, 1200px);
    max-height: 78vh;
    background: var(--mix-dark);
    border-radius: var(--radius-md);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.story-board-present-frame img { width: 100%; height: 100%; object-fit: contain; }
.story-board-present-text {
    max-width: 720px;
    padding: 40px 48px;
    text-align: center;
}
.story-board-present-text.sticky {
    background: var(--sb-sticky-bg);
    color: var(--sb-sticky-text);
    border-radius: var(--radius-md);
}
.story-board-present-text h2 { margin: 0 0 16px; font-size: 1.8rem; }
.story-board-present-text p { margin: 0; font-size: 1.1rem; line-height: 1.5; white-space: pre-wrap; }
.story-board-present-caption {
    position: absolute;
    bottom: 40px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: 1rem;
    color: #cdd6e4; /* literal-ok: canvas HUD is dark in both themes */
}
.story-board-present-progress {
    position: absolute;
    top: 24px;
    right: 32px;
    font-size: 0.85rem;
    color: #9aa7bb; /* literal-ok: canvas HUD is dark in both themes */
}
.story-board-present-close {
    position: absolute;
    top: 20px;
    left: 24px;
    font-size: 1.3rem;
    color: #cdd6e4; /* literal-ok: canvas HUD is dark in both themes */
    background: transparent;
    border: none;
    cursor: pointer;
}
.story-board-present-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    font-size: 2.6rem;
    color: #cdd6e4; /* literal-ok: canvas HUD is dark in both themes */
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0 24px;
}
.story-board-present-nav:hover { color: var(--mix-light); }
.story-board-present-nav.prev { left: 8px; }
.story-board-present-nav.next { right: 8px; }

/* --- toast --- */
.story-board-toast {
    position: fixed;
    bottom: 24px;
    left: 50%;
    transform: translateX(-50%) translateY(10px);
    z-index: 10002;
    background: var(--text-main);
    color: var(--bg-pane);
    font-size: 0.85rem;
    padding: 8px 16px;
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    opacity: 0;
    transition: opacity var(--anim-base) var(--anim-ease), transform var(--anim-base) var(--anim-ease);
    pointer-events: none;
}
.story-board-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* --- mobile --- */
.story-board--mobile .story-board-toolbar { gap: 6px; padding: 6px 8px; }
.story-board--mobile .story-board-title { max-width: 46%; }
.story-board--mobile .story-board-btn { padding: 5px 8px; }
.story-board--mobile .story-board-card-menu,
.story-board--mobile .story-board-card-link { opacity: 1; }
/* --- APP-KIND BACKLINKS (floating bottom dialog) ---
   Shared by the Cache Board / Brain Map / Story Board note kinds. The rich-text backlinks
   section (#note-backlinks — built by editor.js _ensureBacklinksSection, filled by
   refreshBacklinks) is reused verbatim: editor.js adds .note-backlinks-floating while an
   app-kind controller is mounted, and the board slices' hide rules exempt that variant.
   The header doubles as a collapse toggle (editor.js) so the dialog can shrink to a pill
   and stop covering the board/canvas underneath. Loads after 135/145/146 so it extends
   their wrapper modes. Owner JS: editor.js. */

/* Anchor the absolutely-positioned dialog to the editor wrapper in app-kind modes. */
.editor-content-wrapper.cache-board-mode,
.editor-content-wrapper.brain-map-mode,
.editor-content-wrapper.story-board-mode {
    position: relative;
}

.note-backlinks.note-backlinks-floating {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    width: min(480px, calc(100% - 20px));
    max-height: 46%;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 8px 12px 10px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: var(--bg-pane);
    box-shadow: 0 8px 28px color-mix(in srgb, var(--mix-dark) 28%, transparent);
    /* Above static board chrome (≤100); below board dialogs/menus (≥4000). */
    z-index: 1200;
}

/* Same specificity as the floating rule but later in this file, so .hidden still wins
   (the base .note-backlinks.hidden rule lives in an earlier slice and would lose). */
.note-backlinks.note-backlinks-floating.hidden {
    display: none;
}

.note-backlinks-floating .note-backlinks-header {
    cursor: pointer;
    user-select: none;
    margin-bottom: 6px;
}

.note-backlinks-floating .note-backlinks-header::after {
    content: "▾";
    color: var(--text-muted);
    font-size: 0.8rem;
}

.note-backlinks-floating.collapsed .note-backlinks-header::after {
    content: "▸";
}

.note-backlinks-floating .note-backlinks-list {
    max-height: none; /* the section's max-height governs; the list just scrolls */
    overflow-y: auto;
    min-height: 0;
}

.note-backlinks-floating.collapsed .note-backlinks-list {
    display: none;
}

.note-backlinks-floating.collapsed {
    width: auto;
    min-width: 150px;
}

/* --- Eye toggle (floating mode only) --- */
.note-backlinks .note-backlinks-eye {
    display: none;
}

.note-backlinks-floating .note-backlinks-eye {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
}

.note-backlinks-floating .note-backlinks-eye:hover {
    color: var(--text-main);
    background: var(--item-hover);
}

.note-backlinks-floating .note-backlinks-eye svg {
    width: 15px;
    height: 15px;
}

/* Eye off: the dialog shrinks to just the eye button so it can be restored in place.
   Transient — editor.js resets to shown on every note open. Placed after the .collapsed
   rules (same specificity) so eye-off wins when both classes are present. */
.note-backlinks-floating.backlinks-eye-off {
    width: auto;
    min-width: 0;
    padding: 6px;
}

.note-backlinks-floating.backlinks-eye-off .note-backlinks-title,
.note-backlinks-floating.backlinks-eye-off .note-backlinks-list {
    display: none;
}

.note-backlinks-floating.backlinks-eye-off .note-backlinks-header {
    margin-bottom: 0;
    cursor: default;
}

.note-backlinks-floating.backlinks-eye-off .note-backlinks-header::after {
    content: none;
}
/* --- THE CACHE CALENDAR (calendar note kind) ---
   Feature-scoped styles for editor/CalendarController.js. The calendar mounts INTO the editor content
   wrapper (replacing the rich-text surface) for notes of kind 'calendar'. Unlike the board/map/story
   app-kinds it is NOT a pan/zoom canvas — it is a deterministic grid (month) / time-grid (week/day) /
   list (agenda) laid out from date math. Context menus are appended to <body>, so those selectors are
   global but `cyb-cal-`-prefixed. All chrome is token-driven; the category palette maps colour ids to
   semantic tokens (both themes). Spec: Docs/003-cache-calendar-requirements.md. */

/* When a calendar is mounted, hide the rich-text surface that shares the editor wrapper. */
.editor-content-wrapper.cyb-cal-mode > .note-title-row,
.editor-content-wrapper.cyb-cal-mode > #format-toolbar,
.editor-content-wrapper.cyb-cal-mode > .format-toolbar,
.editor-content-wrapper.cyb-cal-mode > #note-body,
.editor-content-wrapper.cyb-cal-mode > .note-editor,
.editor-content-wrapper.cyb-cal-mode #note-backlinks:not(.note-backlinks-floating),
.editor-content-wrapper.cyb-cal-mode .note-backlinks:not(.note-backlinks-floating) {
    display: none !important;
}
body.focus-mode .editor-content-wrapper.cyb-cal-mode {
    max-width: none;
    margin: 0;
    padding: 0;
}

.cyb-cal {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
    color: var(--text-main);
    font-size: 0.9rem;
    user-select: none;
    -webkit-user-select: none;
    /* Category palette — colour id → base colour. blue/green/orange/red reuse semantic tokens;
       purple/teal/grey are fixed content treatments (both themes provided). */
    --cyb-c-blue: var(--primary-color);
    --cyb-c-green: var(--success-color);
    --cyb-c-orange: var(--warning-color);
    --cyb-c-red: var(--danger-color);
    --cyb-c-purple: #8b5cf6; /* literal-ok: calendar category palette, fixed content colours */
    --cyb-c-teal: #0d9488; /* literal-ok: calendar category palette, fixed content colours */
    --cyb-c-grey: #6b7280; /* literal-ok: calendar category palette, fixed content colours */
    --cyb-hour-h: 48px;
}
:root[data-theme="dark"] .cyb-cal {
    --cyb-c-purple: #a78bfa; /* literal-ok: calendar category palette, fixed content colours */
    --cyb-c-teal: #2dd4bf; /* literal-ok: calendar category palette, fixed content colours */
    --cyb-c-grey: #9ca3af; /* literal-ok: calendar category palette, fixed content colours */
}
.cyb-cal input,
.cyb-cal textarea,
.cyb-cal select { user-select: text; -webkit-user-select: text; }

/* colour resolver: any element carrying [data-color] exposes --cyb-ev */
.cyb-cal [data-color="blue"] { --cyb-ev: var(--cyb-c-blue); }
.cyb-cal [data-color="green"] { --cyb-ev: var(--cyb-c-green); }
.cyb-cal [data-color="orange"] { --cyb-ev: var(--cyb-c-orange); }
.cyb-cal [data-color="red"] { --cyb-ev: var(--cyb-c-red); }
.cyb-cal [data-color="purple"] { --cyb-ev: var(--cyb-c-purple); }
.cyb-cal [data-color="teal"] { --cyb-ev: var(--cyb-c-teal); }
.cyb-cal [data-color="grey"] { --cyb-ev: var(--cyb-c-grey); }

/* ---------- toolbar ---------- */
.cyb-cal-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
    flex-wrap: wrap;
}
.cyb-cal-title {
    font-size: 1.05rem;
    font-weight: 650;
    color: var(--text-main);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 3px 8px;
    cursor: text;
    max-width: 240px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cyb-cal-title:hover { background: var(--item-hover); border-color: var(--border-color); }
.cyb-cal-title::after { content: " ✎"; opacity: 0; font-size: 0.8em; }
.cyb-cal-title:hover::after { opacity: 0.5; }
/* view-only (the split screen — Docs/000-split-app-kind-views-and-backlinks-plan.md): the title is plain text and
   timed events have no resize grip. */
.cyb-cal--readonly .cyb-cal-title { cursor: default; }
.cyb-cal--readonly .cyb-cal-title::after { content: none; }
.cyb-cal--readonly .cyb-cal-title:hover { background: transparent; border-color: transparent; }
.cyb-cal--readonly .cyb-cal-tg-resize { display: none; }
.cyb-cal-title-input {
    font-size: 1.05rem;
    font-weight: 650;
    padding: 3px 8px;
    border: 1px solid var(--primary-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
    color: var(--text-main);
    max-width: 240px;
}
.cyb-cal-nav { display: inline-flex; align-items: center; gap: 6px; }
.cyb-cal-range { font-weight: 600; margin-left: 6px; min-width: 140px; }
.cyb-cal-spacer { flex: 1 1 auto; }
.cyb-cal-quickadd {
    padding: 5px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    min-width: 180px;
    font-size: 0.85rem;
}
.cyb-cal-quickadd:focus { outline: none; border-color: var(--primary-color); }
.cyb-cal-views { display: inline-flex; border: 1px solid var(--border-color); border-radius: var(--radius-md); overflow: hidden; }
.cyb-cal-views .cyb-cal-btn { border: none; border-radius: 0; border-left: 1px solid var(--border-color); }
.cyb-cal-views .cyb-cal-btn:first-child { border-left: none; }
.cyb-cal-btn {
    padding: 5px 11px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    cursor: pointer;
    font-size: 0.85rem;
    line-height: 1.2;
}
.cyb-cal-btn:hover { background: var(--item-hover); }
.cyb-cal-btn.is-active { background: var(--primary-color); color: var(--mix-light); border-color: var(--primary-color); }
.cyb-cal-btn.cyb-cal-primary { background: var(--primary-color); color: var(--mix-light); border-color: var(--primary-color); font-weight: 600; }
.cyb-cal-btn.cyb-cal-primary:hover { background: var(--primary-hover); }
.cyb-cal-icon { padding: 5px 9px; font-size: 1rem; }

/* ---------- legend ---------- */
.cyb-cal-legend { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 12px; border-bottom: 1px solid var(--border-color); align-items: center; }
.cyb-cal-legend-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 9px; border: 1px solid var(--border-color); border-radius: 999px;
    background: var(--bg-pane); color: var(--text-main); cursor: pointer; font-size: 0.8rem;
}
.cyb-cal-legend-chip.is-off { opacity: 0.42; text-decoration: line-through; }
.cyb-cal-swatch { width: 11px; height: 11px; border-radius: 3px; background: var(--cyb-ev, var(--primary-color)); }
.cyb-cal-legend-manage { margin-left: auto; background: transparent; border: none; color: var(--text-muted); cursor: pointer; font-size: 0.8rem; }
.cyb-cal-legend-manage:hover { color: var(--text-main); }

/* ---------- body ---------- */
.cyb-cal-body { flex: 1 1 auto; min-height: 0; overflow: hidden; outline: none; display: flex; }
.cyb-cal-body > * { flex: 1 1 auto; min-height: 0; }

/* ---------- MONTH ---------- */
.cyb-cal-month { display: flex; flex-direction: column; height: 100%; }
.cyb-cal-weekhead { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--border-color); }
.cyb-cal-weekhead-cell { padding: 6px 8px; font-size: 0.72rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.cyb-cal-grid { flex: 1 1 auto; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: 1fr; min-height: 0; }
.cyb-cal-cell {
    border-right: 1px solid var(--border-color);
    border-bottom: 1px solid var(--border-color);
    padding: 3px 4px;
    min-height: 0;
    overflow: hidden;
    cursor: pointer;
    display: flex; flex-direction: column;
    background: var(--bg-pane);
}
.cyb-cal-cell:nth-child(7n) { border-right: none; }
.cyb-cal-cell.is-outside { background: var(--bg-list-pane); color: var(--text-muted); }
.cyb-cal-cell.is-weekend:not(.is-outside) { background: color-mix(in srgb, var(--bg-list-pane) 55%, var(--bg-pane)); }
.cyb-cal-cell:hover { background: var(--item-hover); }
.cyb-cal-cell.is-drop { outline: 2px dashed var(--primary-color); outline-offset: -2px; }
.cyb-cal-cell.cyb-cal-range-sel { background: var(--selection-color); outline: 1px solid var(--primary-color); outline-offset: -1px; }
.cyb-cal-cell.cyb-cal-range-sel.is-today { background: var(--selection-color); }
.cyb-cal-cell.is-droptarget { outline: 2px solid var(--primary-color); outline-offset: -2px; background: var(--selection-color); }
.cyb-cal-cell-head { display: flex; justify-content: flex-end; }
.cyb-cal-cell-num { font-size: 0.78rem; color: var(--text-muted); padding: 1px 4px; border-radius: 999px; }
.cyb-cal-cell.is-today .cyb-cal-cell-num { background: var(--primary-color); color: var(--mix-light); font-weight: 700; }
.cyb-cal-cell-items { display: flex; flex-direction: column; gap: 2px; overflow: hidden; min-height: 0; }

.cyb-cal-event {
    display: flex; align-items: center; gap: 4px;
    border: none; text-align: left; cursor: pointer;
    padding: 1px 5px; border-radius: 4px;
    font-size: 0.76rem; line-height: 1.35;
    background: color-mix(in srgb, var(--cyb-ev, var(--primary-color)) 16%, var(--bg-pane));
    color: var(--text-main);
    border-left: 3px solid var(--cyb-ev, var(--primary-color));
    overflow: hidden; white-space: nowrap;
}
.cyb-cal-event.is-allday { background: var(--cyb-ev, var(--primary-color)); color: var(--mix-light); border-left: none; }
.cyb-cal-event.is-selected { outline: 2px solid var(--primary-color); outline-offset: 1px; }
.cyb-cal-event-time { font-weight: 600; opacity: 0.85; }
.cyb-cal-event-title { overflow: hidden; text-overflow: ellipsis; }
.cyb-cal-event-rep { opacity: 0.7; }

.cyb-cal-note-chip {
    display: flex; align-items: center; gap: 4px;
    border: 1px dashed var(--border-color); text-align: left; cursor: pointer;
    padding: 1px 5px; border-radius: 4px; font-size: 0.74rem;
    background: var(--bg-list-pane); color: var(--text-main);
    overflow: hidden; white-space: nowrap;
}
.cyb-cal-note-chip:hover { background: var(--item-hover); border-color: var(--primary-color); }
.cyb-cal-note-chip.is-dead { opacity: 0.55; font-style: italic; }
.cyb-cal-note-title { overflow: hidden; text-overflow: ellipsis; }
.cyb-cal-note-open { margin-left: auto; opacity: 0.5; }
.cyb-cal-more { border: none; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 0.72rem; text-align: left; padding: 1px 5px; }
.cyb-cal-more:hover { color: var(--primary-color); }

/* ---------- TIME GRID (week / day) ---------- */
.cyb-cal-timegrid { display: flex; flex-direction: column; height: 100%; --cyb-gutter-w: 56px; }
.cyb-cal-tg-header { display: grid; grid-template-columns: var(--cyb-gutter-w) repeat(var(--cyb-day-count), 1fr); border-bottom: 1px solid var(--border-color); }
.cyb-cal-tg-corner { }
.cyb-cal-tg-daybtn {
    display: flex; flex-direction: column; align-items: center; gap: 1px;
    padding: 5px; border: none; border-left: 1px solid var(--border-color);
    background: var(--bg-pane); color: var(--text-main); cursor: pointer;
}
.cyb-cal-tg-daybtn:hover { background: var(--item-hover); }
.cyb-cal-tg-dow { font-size: 0.68rem; color: var(--text-muted); text-transform: uppercase; }
.cyb-cal-tg-dom { font-size: 1.1rem; font-weight: 600; }
.cyb-cal-tg-daybtn.is-today .cyb-cal-tg-dom { background: var(--primary-color); color: var(--on-accent); border-radius: 999px; width: 1.7em; height: 1.7em; display: flex; align-items: center; justify-content: center; }

.cyb-cal-tg-allday { display: grid; grid-template-columns: var(--cyb-gutter-w) repeat(var(--cyb-day-count), 1fr); border-bottom: 1px solid var(--border-color); min-height: 24px; max-height: 88px; overflow-y: auto; }
.cyb-cal-tg-allday-label { font-size: 0.66rem; color: var(--text-muted); padding: 3px; text-align: right; }
.cyb-cal-tg-allday-cell { border-left: 1px solid var(--border-color); padding: 2px; display: flex; flex-direction: column; gap: 2px; }

.cyb-cal-tg-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: grid; grid-template-columns: var(--cyb-gutter-w) 1fr; position: relative; }
.cyb-cal-tg-gutter { }
.cyb-cal-tg-hour { position: relative; border-bottom: 1px solid transparent; }
.cyb-cal-tg-hourlabel { position: absolute; top: -7px; right: 6px; font-size: 0.66rem; color: var(--text-muted); background: var(--bg-editor-pane); padding: 0 2px; }
.cyb-cal-tg-cols { display: grid; grid-template-columns: repeat(var(--cyb-day-count), 1fr); }
.cyb-cal-tg-col { position: relative; border-left: 1px solid var(--border-color); }
.cyb-cal-tg-line { position: absolute; left: 0; right: 0; border-top: 1px solid var(--border-color); opacity: 0.5; pointer-events: none; }
.cyb-cal-tg-now { position: absolute; left: 0; right: 0; border-top: 2px solid var(--danger-color); z-index: 4; pointer-events: none; }
.cyb-cal-tg-now::before { content: ""; position: absolute; left: -3px; top: -4px; width: 7px; height: 7px; border-radius: 50%; background: var(--danger-color); }

.cyb-cal-tg-event {
    position: absolute; overflow: hidden; text-align: left; cursor: pointer;
    border: 1px solid color-mix(in srgb, var(--cyb-ev, var(--primary-color)) 60%, transparent);
    border-left: 3px solid var(--cyb-ev, var(--primary-color));
    background: color-mix(in srgb, var(--cyb-ev, var(--primary-color)) 22%, var(--bg-pane));
    color: var(--text-main); border-radius: 4px; padding: 2px 5px; z-index: 3;
    display: flex; flex-direction: column; gap: 1px; font-size: 0.72rem;
}
.cyb-cal-tg-event.is-selected { outline: 2px solid var(--primary-color); outline-offset: 1px; z-index: 5; }
.cyb-cal-tg-event-time { font-weight: 600; opacity: 0.85; }
.cyb-cal-tg-event-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cyb-cal-tg-resize { position: absolute; left: 0; right: 0; bottom: 0; height: 7px; cursor: ns-resize; }
.cyb-cal-tg-createpreview { position: absolute; left: 2px; right: 2px; z-index: 4; pointer-events: none; border-radius: 4px; border: 1px dashed var(--primary-color); background: color-mix(in srgb, var(--primary-color) 20%, var(--bg-pane)); }
/* Touch long-press feedback: the moment a hold arms a create/move drag, the target lights up so the
   user sees create-mode is live. A plain (un-held) drag scrolls the day and never triggers these. */
.cyb-cal-tg-col.is-armed { background: color-mix(in srgb, var(--primary-color) 12%, transparent); }
.cyb-cal-tg-event.is-dragging { outline: 2px solid var(--primary-color); outline-offset: 1px; opacity: 0.9; z-index: 6; }

/* ---------- AGENDA ---------- */
.cyb-cal-agenda { overflow-y: auto; padding: 6px 12px; height: 100%; }
.cyb-cal-agenda-empty { color: var(--text-muted); padding: 24px; text-align: center; }
.cyb-cal-agenda-day { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border-color); }
.cyb-cal-agenda-date { flex: 0 0 46px; text-align: center; }
.cyb-cal-agenda-dom { display: block; font-size: 1.3rem; font-weight: 700; }
.cyb-cal-agenda-mon { display: block; font-size: 0.66rem; color: var(--text-muted); text-transform: uppercase; }
.cyb-cal-agenda-dow { display: block; font-size: 0.66rem; color: var(--text-muted); }
.cyb-cal-agenda-day.is-today .cyb-cal-agenda-dom { color: var(--primary-color); }
.cyb-cal-agenda-list { flex: 1 1 auto; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cyb-cal-agenda-item { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: var(--bg-pane); cursor: pointer; text-align: left; color: var(--text-main); }
.cyb-cal-agenda-item:hover { background: var(--item-hover); }
.cyb-cal-agenda-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--cyb-ev, var(--primary-color)); flex: 0 0 auto; }
.cyb-cal-agenda-when { flex: 0 0 72px; color: var(--text-muted); font-size: 0.8rem; }
.cyb-cal-agenda-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- event dialog ---------- */
/* Resizable + persistable (drag the bottom-right corner; size saved to settings). The box is a flex
   column: header + actions stay pinned while the form scrolls. */
/* .modal-box.cyb-cal-dialog: raise specificity so width beats the base .modal-box{width:400px}
   (148 loads before 180 in the cascade, so a single-class selector would lose). */
.modal-box.cyb-cal-dialog {
    width: min(94vw, 480px);
    gap: 12px;
    resize: both;
    overflow: hidden;
    min-width: 340px;
    min-height: 320px;
    max-width: 96vw;
    max-height: 92vh;
}
.cyb-cal-dialog-hd { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cyb-cal-dialog-actions { flex: 0 0 auto; justify-content: space-between; }
/* Identity block (title + all-day + category): pinned above the tabs, so it shows on every tab. */
.cyb-cal-dialog-ident { flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px; }
/* Tab strip: shared segmented-pill component (.app-tabs / .app-tab, see 180-dialogs-overlays.css);
   only the pinned-in-column behaviour is calendar-specific. */
.cyb-cal-tabs { flex: 0 0 auto; }
/* Tab panels (only the active one shown). display:flex would beat [hidden]; hide it explicitly. */
.cyb-cal-form { display: flex; flex-direction: column; flex: 1 1 auto; overflow-y: auto; min-height: 0; padding-right: 2px; }
.cyb-cal-panel { display: flex; flex-direction: column; gap: 10px; }
.cyb-cal-panel[hidden] { display: none; }
.cyb-cal-f-sublbl { font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); margin-top: 2px; }
.cyb-cal-f-sublbl:first-child { margin-top: 0; }
.cyb-cal-f-sound-block { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; padding-top: 10px; border-top: 1px dashed var(--border-color); }
/* Scope to the whole dialog (not just .cyb-cal-form) so the pinned Title + Category in the identity
   block get the same rounded, bordered treatment as the fields inside the tab panels. */
.cyb-cal-dialog input[type="text"],
.cyb-cal-dialog textarea,
.cyb-cal-dialog input[type="date"],
.cyb-cal-dialog input[type="time"],
.cyb-cal-dialog input[type="number"],
.cyb-cal-dialog select {
    padding: 6px 9px; border: 1px solid var(--border-color); border-radius: var(--radius-sm);
    background: var(--bg-pane); color: var(--text-main); font-size: 0.88rem; box-sizing: border-box;
}
.cyb-cal-f-title { font-size: 1.05rem !important; font-weight: 600; }
.cyb-cal-f-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cyb-cal-f-lbl { font-size: 0.78rem; color: var(--text-muted); }
.cyb-cal-f-check { display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; }
.cyb-cal-f-to { color: var(--text-muted); }
.cyb-cal-f-interval-wrap { font-size: 0.82rem; color: var(--text-muted); display: inline-flex; align-items: center; gap: 5px; }
.cyb-cal-f-interval { width: 56px; }
.cyb-cal-f-byday { display: flex; gap: 4px; }
/* These rows carry display:flex, which beats the UA [hidden] rule — gate hiding explicitly so the
   weekday picker and the recurrence-ends row actually collapse for non-recurring events. */
.cyb-cal-f-byday[hidden], .cyb-cal-f-ends[hidden] { display: none; }
.cyb-cal-f-day { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border: 1px solid var(--border-color); border-radius: 50%; font-size: 0.72rem; cursor: pointer; }
.cyb-cal-f-day input { display: none; }
.cyb-cal-f-day.is-on { background: var(--primary-color); color: var(--mix-light); border-color: var(--primary-color); }
.cyb-cal-f-until { width: 150px; }
.cyb-cal-f-count { width: 64px; }
.cyb-cal-f-body { resize: vertical; }
.cyb-cal-f-reminders { display: flex; flex-direction: column; gap: 4px; }
.cyb-cal-f-remind-row { display: flex; gap: 6px; align-items: center; }
.cyb-cal-f-remind-row select { flex: 1 1 auto; }
.cyb-cal-f-remind-x { flex: 0 0 auto; background: transparent; border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-muted); cursor: pointer; padding: 4px 9px; }
.cyb-cal-f-remind-x:hover { color: var(--danger-color); border-color: var(--danger-color); }
.cyb-cal-f-remind-none { font-size: 0.8rem; color: var(--text-muted); font-style: italic; }
.cyb-cal-f-remind-add { align-self: flex-start; background: transparent; border: none; color: var(--primary-color); cursor: pointer; font-size: 0.82rem; padding: 2px 0; }
.cyb-cal-f-remind-add:hover { text-decoration: underline; }
/* alert sound (§13 Q5) — a single dropdown chooses the source; picking a note/playlist/file opens a
   picker, and the chosen item's name + a ▶ preview appear beside it. */
.cyb-cal-f-sound-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.cyb-cal-f-sound-sel { flex: 0 0 auto; }
.cyb-cal-f-sound-name { flex: 1 1 100px; min-width: 0; font-size: 0.82rem; color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cyb-cal-f-sound-name:empty { flex: 0 0 0; }
.cyb-cal-f-sound-preview { flex: 0 0 auto; background: var(--bg-pane); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-main); cursor: pointer; padding: 4px 9px; font-size: 0.8rem; }
.cyb-cal-f-sound-preview:hover { background: var(--item-hover); border-color: var(--primary-color); }

/* playlist picker (Docs/006 §7) — appended to <body> as a modal */
.cyb-cal-plpick { display: flex; flex-direction: column; gap: 2px; }
.cyb-cal-plpick-group { font-size: 0.72rem; font-weight: 650; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); padding: 8px 4px 2px; }
.cyb-cal-plpick-item { display: block; width: 100%; text-align: left; padding: 8px 10px; border: 1px solid transparent; background: transparent; color: var(--text-main); cursor: pointer; border-radius: var(--radius-sm); font-size: 0.88rem; }
.cyb-cal-plpick-item:hover { background: var(--item-hover); border-color: var(--border-color); }
.cyb-cal-plpick-empty { padding: 14px 6px; color: var(--text-muted); font-style: italic; }
/* top row: All-day + Category share one line */
.cyb-cal-f-toprow { justify-content: flex-start; }
.cyb-cal-f-toprow-gap { flex: 1 1 auto; }
.cyb-cal-f-toprow .cyb-cal-f-color { flex: 0 0 auto; min-width: 120px; }

.cyb-cal-f-links { display: flex; flex-direction: column; gap: 4px; }
.cyb-cal-f-link-row { display: flex; gap: 6px; align-items: center; }
.cyb-cal-f-link-url { flex: 2 1 auto; min-width: 0; }
.cyb-cal-f-link-label { flex: 1 1 90px; min-width: 0; }
.cyb-cal-f-link-open, .cyb-cal-f-link-x { flex: 0 0 auto; background: var(--bg-pane); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-main); cursor: pointer; padding: 6px 9px; }
.cyb-cal-f-link-open:hover { background: var(--item-hover); border-color: var(--primary-color); }
.cyb-cal-f-link-x { color: var(--text-muted); }
.cyb-cal-f-link-x:hover { color: var(--danger-color); border-color: var(--danger-color); }
.cyb-cal-f-link-none { font-size: 0.8rem; color: var(--text-muted); font-style: italic; }
.cyb-cal-f-link-add { align-self: flex-start; background: transparent; border: none; color: var(--primary-color); cursor: pointer; font-size: 0.82rem; padding: 2px 0; }
.cyb-cal-f-link-add:hover { text-decoration: underline; }

.cyb-cal-event-link { cursor: pointer; opacity: 0.85; }
.cyb-cal-event-link:hover { opacity: 1; }

/* event links pick dialog (external + note links) */
.cyb-cal-links-list { display: flex; flex-direction: column; gap: 4px; }
.cyb-cal-linkrow { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; padding: 8px 10px; border: 1px solid var(--border-color); background: var(--bg-pane); color: var(--text-main); border-radius: var(--radius-sm); cursor: pointer; }
.cyb-cal-linkrow:hover { background: var(--item-hover); border-color: var(--primary-color); }
.cyb-cal-linkrow-ico { flex: 0 0 auto; font-size: 1rem; }
.cyb-cal-linkrow-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.cyb-cal-linkrow-label { font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cyb-cal-linkrow-sub { font-size: 0.75rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cyb-cal-linkrow-go { flex: 0 0 auto; color: var(--text-muted); }
.cyb-cal-linkrow:hover .cyb-cal-linkrow-go { color: var(--primary-color); }

.cyb-cal-f-noteref { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.cyb-cal-f-noteref-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px; border: 1px solid var(--border-color); border-radius: 999px; font-size: 0.8rem; max-width: 100%; }
.cyb-cal-f-noteref-x, .cyb-cal-f-noteref-add { background: transparent; border: 1px solid var(--border-color); border-radius: 6px; cursor: pointer; color: var(--text-main); font-size: 0.8rem; padding: 3px 8px; }
.cyb-cal-f-noteref-x { border: none; padding: 0 4px; }

.cyb-cal-cats .cyb-cal-cat-row { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.cyb-cal-cat-label { flex: 1 1 auto; }

/* ---------- YEAR view (§13 Q2) — 12-month heat-map overview ---------- */
.cyb-cal-year {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
    padding: 14px;
    align-content: start;
}
.cyb-cal-year-month {
    display: flex;
    flex-direction: column;
    gap: 4px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 8px;
    background: var(--bg-pane);
}
.cyb-cal-year-mname {
    font-weight: 650;
    font-size: 0.85rem;
    color: var(--text-main);
    cursor: pointer;
    padding: 1px 3px;
    border-radius: var(--radius-sm);
}
.cyb-cal-year-mname:hover { background: var(--item-hover); color: var(--primary-color); }
.cyb-cal-year-dow { display: grid; grid-template-columns: repeat(7, 1fr); }
.cyb-cal-year-dow-cell { text-align: center; font-size: 0.6rem; color: var(--text-muted); padding-bottom: 2px; }
.cyb-cal-year-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
.cyb-cal-year-cell {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.66rem;
    color: var(--text-main);
    background: transparent;
    border: none;
    border-radius: 999px;
    cursor: pointer;
    position: relative;
    padding: 0;
}
.cyb-cal-year-cell:hover:not(.is-outside) { background: var(--item-hover); }
.cyb-cal-year-cell.is-outside { color: transparent; cursor: default; pointer-events: none; }
.cyb-cal-year-cell.is-today { background: var(--primary-color); color: var(--mix-light); font-weight: 700; }
.cyb-cal-year-cell.is-marked:not(.is-today)::after {
    content: "";
    position: absolute;
    bottom: 1px;
    left: 50%;
    transform: translateX(-50%);
    width: 4px; height: 4px;
    border-radius: 999px;
    background: var(--primary-color);
}

/* ---------- context menu (appended to <body>) ---------- */
.cyb-cal-menu {
    position: fixed; z-index: 10000; min-width: 180px;
    background: var(--bg-pane); border: 1px solid var(--border-color);
    border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: 4px;
}
.cyb-cal-menu-item { display: block; width: 100%; text-align: left; padding: 7px 10px; border: none; background: transparent; color: var(--text-main); cursor: pointer; font-size: 0.85rem; border-radius: var(--radius-sm); }
.cyb-cal-menu-item:hover { background: var(--item-hover); }
.cyb-cal-menu-sep { height: 1px; background: var(--border-color); margin: 4px 2px; }

/* ---------- mobile ---------- */
.cyb-cal--mobile .cyb-cal-toolbar { gap: 5px; padding: 6px 8px; }
/* Year view is desktop-only — a 12-month grid is too cramped on a phone (also guarded in JS). */
.cyb-cal--mobile .cyb-cal-views [data-view="year"] { display: none; }
.cyb-cal--mobile .cyb-cal-quickadd { order: 5; flex: 1 1 100%; min-width: 0; }
.cyb-cal--mobile .cyb-cal-title { max-width: 120px; }
@media (max-width: 768px) {
    .cyb-cal-cell-items { gap: 1px; }
    .cyb-cal-event, .cyb-cal-note-chip { font-size: 0.68rem; }
    .cyb-cal-range { min-width: 0; }
    .cyb-cal-year { grid-template-columns: repeat(2, 1fr); gap: 10px; padding: 10px; }
    /* Manual resize is awkward on a phone: full-width sheet, let content flow. */
    .modal-box.cyb-cal-dialog { resize: none; width: min(96vw, 480px); min-width: 0; max-height: 88vh; }
    .cyb-cal-dialog .app-tab { font-size: 0.76rem; padding: 6px 4px; }
}
@media (max-width: 1100px) and (min-width: 769px) {
    .cyb-cal-year { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 460px) {
    .cyb-cal-year { grid-template-columns: 1fr; }
}
/* App-kind loading placeholder (utils/LazyAppKind.js): shown in the editor pane while a Cache Board /
   Brain Map / Story Board / Calendar controller module loads on its first open. Reuses the database
   loading spinner. */
.app-kind-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    min-height: 40vh;
    padding: 32px 16px;
    color: var(--text-muted);
    font-size: 0.95rem;
}

.app-kind-loading--error {
    color: var(--danger-color);
    text-align: center;
    max-width: 44ch;
    margin: 0 auto;
}
/* --- SVG EMBED (CODE + IMAGE MODES) --- */
.svg-embed {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 8px 0;
}

.svg-embed > pre[data-qnt-svg-source="1"],
.svg-embed > .code-block-shell {
    margin: 0;
}

.svg-embed-toolbar {
    position: static;
    align-self: flex-end;
    margin: 0;
    opacity: 1;
    pointer-events: auto;
    z-index: auto;
    transition: none;
}

.svg-embed .svg-embed-tool-btn[data-action="toggle-wrap"] {
    min-width: 58px;
    justify-content: center;
}

.svg-embed .svg-embed-tool-btn[data-action="toggle-lines"] {
    min-width: 86px;
    justify-content: center;
}

.svg-embed-preview {
    display: none;
    margin: 0;
    position: relative;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: color-mix(in srgb, var(--bg-pane) 96%, var(--bg-pane) 4%);
    padding: 10px;
    min-height: 180px;
    overflow: hidden;
}

.svg-embed-preview [data-qnt-svg-preview="1"] {
    display: block;
    width: 100%;
    max-width: 100%;
    height: clamp(180px, 42vh, 520px);
    margin: 0;
    user-select: none;
    -webkit-user-select: none;
}

.svg-embed-preview [data-qnt-svg-preview="1"] > svg {
    display: block;
    width: 100%;
    height: 100%;
    pointer-events: none;
    shape-rendering: geometricPrecision;
    text-rendering: geometricPrecision;
    transition: transform 120ms linear;
}

@media (max-width: 768px) {
    .svg-embed-preview {
        min-height: 150px;
    }

    .svg-embed-preview [data-qnt-svg-preview="1"] {
        height: clamp(150px, 34vh, 360px);
    }
}

.svg-embed.svg-embed-mode-image pre[data-qnt-svg-source="1"] {
    display: none;
}

.svg-embed.svg-embed-mode-image .code-block-shell,
.svg-embed.svg-embed-mode-image .code-scroll-rail {
    display: none;
}

.svg-embed.svg-embed-mode-code .svg-embed-tool-btn[data-action="fit"],
.svg-embed.svg-embed-mode-code .svg-embed-tool-btn[data-action="expand"],
.svg-embed.svg-embed-mode-code .svg-embed-tool-btn[data-action="focus"] {
    display: none;
}

.svg-embed.svg-embed-mode-image .svg-embed-tool-btn[data-action="toggle-wrap"],
.svg-embed.svg-embed-mode-image .svg-embed-tool-btn[data-action="toggle-lines"] {
    display: none;
}

.svg-embed.svg-embed-mode-image .svg-embed-preview {
    display: block;
    cursor: grab;
    touch-action: none;
}

.svg-embed.svg-embed-mode-image.svg-embed-inline-expanded .svg-embed-preview {
    min-height: min(70vh, 820px);
}

.svg-embed.svg-embed-mode-image.svg-embed-inline-expanded .svg-embed-preview [data-qnt-svg-preview="1"] {
    height: min(70vh, 820px);
}

.svg-embed.svg-embed-mode-image .svg-embed-preview [data-qnt-svg-preview="1"] {
    cursor: grab;
    touch-action: none;
}

.svg-embed-zoom-badge {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 5;
    min-width: 54px;
    padding: 4px 8px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
    text-align: center;
    color: var(--overlay-chrome-fg);
    background: var(--overlay-chrome-bg);
    border: 1px solid color-mix(in srgb, var(--overlay-chrome-fg) 45%, transparent);
    pointer-events: none;
    backdrop-filter: blur(2px);
}

.svg-embed.svg-embed-mode-code .svg-embed-zoom-badge {
    display: none;
}

.svg-embed.svg-embed-pan-active .svg-embed-preview,
.svg-embed.svg-embed-pan-active .svg-embed-preview [data-qnt-svg-preview="1"] {
    cursor: grabbing;
}

.svg-embed.svg-embed-preview-contrast .svg-embed-preview {
    border-color: color-mix(in srgb, var(--text-main) 22%, var(--border-color));
    background:
        linear-gradient(135deg, var(--overlay-chrome-bg-strong), var(--overlay-chrome-bg)),
        repeating-linear-gradient(
            45deg,
            color-mix(in srgb, var(--mix-light) 8%, transparent) 0,
            color-mix(in srgb, var(--mix-light) 8%, transparent) 10px,
            color-mix(in srgb, var(--mix-dark) 8%, transparent) 10px,
            color-mix(in srgb, var(--mix-dark) 8%, transparent) 20px
        );
}

.svg-embed.svg-embed-preview-contrast .svg-embed-preview [data-qnt-svg-preview="1"] {
    filter: drop-shadow(0 0 1px color-mix(in srgb, var(--mix-dark) 45%, transparent));
}

.svg-focus-overlay {
    position: fixed;
    inset: 0;
    z-index: 2200;
    background: var(--overlay-scrim);
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: 24px;
    backdrop-filter: blur(2px);
}

.svg-focus-surface {
    position: relative;
    width: min(1500px, 100%);
    height: 100%;
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-pane) 8%);
    border: 1px solid color-mix(in srgb, var(--border-color) 80%, var(--bg-pane) 20%);
    border-radius: 12px;
    box-shadow: 0 16px 42px color-mix(in srgb, var(--mix-dark) 28%, transparent);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.svg-focus-close {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 30;
    width: 34px;
    height: 34px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: color-mix(in srgb, var(--bg-pane) 90%, var(--bg-pane) 10%);
    color: var(--text-main);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
}

.svg-focus-close:hover {
    background: var(--item-hover);
}

.svg-focus-body {
    flex: 1;
    min-height: 0;
    padding: 18px;
}

.svg-embed.svg-embed-focus-shell {
    margin: 0;
    height: 100%;
}

.svg-embed.svg-embed-focus-shell .svg-embed-toolbar {
    display: none;
}

.svg-embed.svg-embed-focus-shell .svg-embed-preview {
    min-height: 100%;
    height: 100%;
}

.svg-embed.svg-embed-focus-shell .svg-embed-preview [data-qnt-svg-preview="1"] {
    height: min(78vh, 1040px);
    max-height: 100%;
}

.svg-embed.svg-embed-focus-active .svg-embed-toolbar {
    opacity: 1;
}

@media (max-width: 768px) {
    .svg-focus-overlay {
        padding: 10px;
    }

    .svg-focus-surface {
        border-radius: 10px;
    }

    .svg-focus-body {
        padding: 10px;
    }

    .svg-embed.svg-embed-focus-shell .svg-embed-preview [data-qnt-svg-preview="1"] {
        height: min(72vh, 760px);
    }
}




/* --- FONT SIZE SPINNER --- */
.font-size-control {
    display: flex;
    align-items: center;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    height: 30px;
    overflow: hidden;
    margin-right: 8px;
    flex: 0 0 auto;
    flex-shrink: 0;
    min-width: 82px;
}
.font-size-btn {
    width: 24px;
    height: 100%;
    flex: 0 0 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--text-main);
}
.font-size-btn:hover {
    background-color: var(--item-hover);
}
.font-size-input {
    width: 32px;
    min-width: 32px;
    flex: 0 0 32px;
    height: 100%;
    border: none;
    border-left: 1px solid var(--border-color);
    border-right: 1px solid var(--border-color);
    text-align: center;
    font-size: 0.9rem;
    color: var(--text-main);
    outline: none;
    background: var(--bg-pane);
    appearance: textfield;
    -moz-appearance: textfield;
}
.font-size-input::-webkit-outer-spin-button,
.font-size-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}


/* --- MEDIA CARDS (Images/Video) --- */
.media-card {
    position: relative;
    display: inline-block;
    max-width: 100%;
    margin: 8px 0;
    transition: outline 0.2s;
    vertical-align: top; /* Prevents weird line-height alignment issues */
}

.media-card-fit-width {
    display: block;
    width: 100%;
    max-width: 100%;
}

.media-card img, 
.media-card video {
    display: block;
    max-width: 100%;
    height: auto;
}

.media-card audio {
    display: block;
    max-width: 100%;
}

.media-card-fit-width img {
    width: 100%;
    max-width: 100%;
    height: auto;
}

.media-card.selected {
    outline: 2px solid var(--primary-color);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary-color) 20%, transparent);
}

/* --- IMAGE DISPLAY PRESETS ---
   Mutually-exclusive layout states keyed off data-display-preset so the sanitizer only has to
   preserve one attribute across paste round-trips (see editor/Sanitizer.js). width:fit-content
   hugs the image; an explicit inline resize width (style="width:…") still wins, so a preset
   preserves a user-resized image (max-width still caps it). */

/* Center-block — the readable "middle": full-width text above and below, image centered. */
.media-card[data-display-preset="align-center"] {
    display: block;
    max-width: 100%;
    width: fit-content;
    margin-left: auto;
    margin-right: auto;
}

/* Float — image sits in the flow; prose wraps down its side and reclaims full width below it
   (native reflow, unlike a rigid column — see the float-vs-column analysis). Capped at 50% so
   the text gutter stays readable. Mobile collapses these to a block (responsive override below). */
.media-card[data-display-preset="float-left"],
.media-card[data-display-preset="float-right"] {
    width: fit-content;
    max-width: 50%;
}

.media-card[data-display-preset="float-left"] {
    float: left;
    margin: 4px 18px 10px 0;
}

.media-card[data-display-preset="float-right"] {
    float: right;
    margin: 4px 0 10px 18px;
}

/* Active layout button reflects the card's current preset. */
.media-card[data-display-preset="float-left"] .align-left-btn,
.media-card[data-display-preset="align-center"] .align-center-btn,
.media-card[data-display-preset="float-right"] .align-right-btn,
.media-card[data-display-preset="fit-note-width"] .fit-width-btn {
    color: var(--primary-color);
}

/* Image caption — plain text below the image. It lives inside the card, so it wraps to the
   card width and composes with the float/center/fit presets. Edited via the caption toolbar
   button (MediaHandler); materialized into a real <figcaption> by the Blogger export. */
.media-caption {
    margin-top: 6px;
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--text-muted);
    text-align: center;
    word-break: break-word;
}

/* Active caption button when the card already carries a caption. */
.media-card:has(.media-caption) .caption-btn {
    color: var(--primary-color);
}

.media-card:is([data-mime^="audio/"], [data-mime^="video/"]) {
    border: 1px solid transparent;
    border-radius: 12px;
    transition: border-color var(--anim-base) var(--anim-ease), box-shadow var(--anim-base) var(--anim-ease), background-color var(--anim-base) var(--anim-ease);
}

.media-card:is([data-mime^="audio/"], [data-mime^="video/"]) :where(audio, video) {
    border-radius: 10px;
}

.media-card:is([data-mime^="audio/"], [data-mime^="video/"]).selected {
    outline: none;
    border-color: color-mix(in srgb, var(--primary-color) 58%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    box-shadow: inset 0 0 0 1px var(--primary-alpha-38), 0 8px 18px var(--primary-alpha-10);
    animation: pdfAttachmentSelectionPulse 240ms var(--anim-ease);
}

@keyframes pdfAttachmentSelectionPulse {
    0% {
        box-shadow: inset 0 0 0 0 color-mix(in srgb, var(--primary-color) 0%, transparent), 0 0 0 0 color-mix(in srgb, var(--primary-color) 0%, transparent);
    }
    60% {
        box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--primary-color) 34%, transparent), 0 0 0 6px color-mix(in srgb, var(--primary-color) 12%, transparent);
    }
    100% {
        box-shadow: inset 0 0 0 1px var(--primary-alpha-38), 0 8px 18px var(--primary-alpha-10);
    }
}

.file-attachment {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 88%, var(--item-hover));
    color: var(--text-main);
    box-sizing: border-box;
}

.media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded).selected {
    outline: none;
    box-shadow: none;
}

.media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded) .file-attachment.pdf-attachment {
    width: 300px;
    max-width: 100%;
    justify-content: flex-start;
    transition: border-color var(--anim-base) var(--anim-ease), box-shadow var(--anim-base) var(--anim-ease), background-color var(--anim-base) var(--anim-ease);
}

.media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded) .file-attachment.pdf-attachment .file-attachment-copy {
    overflow: hidden;
}

.media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded) .file-attachment.pdf-attachment .file-attachment-name,
.media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded) .file-attachment.pdf-attachment .file-attachment-kind {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded).selected .file-attachment.pdf-attachment {
    border-color: color-mix(in srgb, var(--primary-color) 58%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
    box-shadow: inset 0 0 0 1px var(--primary-alpha-38), 0 8px 18px var(--primary-alpha-10);
    animation: pdfAttachmentSelectionPulse 240ms var(--anim-ease);
}

.media-card[data-mime="application/pdf"].pdf-preview-expanded {
    display: block;
    width: 100%;
    max-width: 100%;
}

.media-card[data-mime="application/pdf"].pdf-preview-expanded.selected {
    outline: none;
    box-shadow: none;
}

.media-card[data-mime="application/pdf"].pdf-preview-expanded .file-attachment.pdf-attachment {
    display: none;
}

.media-card[data-mime="application/pdf"].pdf-preview-expanded .pdf-preview-runtime {
    margin-top: 0;
}

.file-attachment-main {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1 1 auto;
    min-width: 0;
}

.file-attachment-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    flex: 0 0 auto;
    border-radius: 10px;
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    color: var(--primary-color);
}

.file-attachment-icon svg {
    width: 18px;
    height: 18px;
}

.file-attachment-copy {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.file-attachment-name {
    font-weight: 600;
    overflow-wrap: anywhere;
}

.file-attachment-kind {
    font-size: 0.78rem;
    color: var(--text-muted);
}

.file-attachment-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    flex-wrap: wrap;
}

.file-attachment-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 34px;
    padding: 7px 12px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 18%, var(--border-color));
    border-radius: 9px;
    background: var(--bg-pane);
    color: var(--text-main);
    text-decoration: none;
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.file-attachment-action:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 48%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

.file-attachment-action svg {
    width: 16px;
    height: 16px;
}

.file-attachment-action span {
    white-space: nowrap;
}

.pdf-preview-expanded .file-attachment {
    border-color: color-mix(in srgb, var(--primary-color) 36%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 8%, var(--bg-pane));
}

.pdf-preview-runtime {
    position: relative;
    width: 100%;
    margin-top: 10px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    overflow: hidden;
    background: var(--bg-pane);
    box-sizing: border-box;
}

.pdf-preview-menu {
    /* Override the shared .code-actions base (position: static; display: none),
       which the code-block floating-toolbar refactor introduced. Without these
       the PDF toolbar stays display:none in every state (the hover/touch/focus
       reveals only flip opacity), so the focus + zoom + page controls are
       unreachable. position:absolute is required for top/right to take effect. */
    position: absolute;
    display: flex;
    top: 6px;
    right: 6px;
    opacity: 0;
    pointer-events: none;
    z-index: 8;
    transition: opacity 120ms ease;
    max-width: calc(100% - 12px);
    flex-wrap: wrap;
}

.pdf-preview-nav-group {
    display: inline-flex;
    align-items: center;
    gap: 0;
    background: var(--overlay-chrome-bg);
    border: 1px solid color-mix(in srgb, var(--mix-light) 14%, transparent);
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 4px 12px color-mix(in srgb, var(--mix-dark) 18%, transparent);
}

.pdf-preview-nav-group .pdf-preview-tool-btn,
.pdf-preview-nav-group .pdf-preview-page-chip {
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    min-height: 26px;
}

.pdf-preview-nav-group .pdf-preview-tool-btn {
    padding: 4px 6px;
    min-width: 28px;
    justify-content: center;
}

.pdf-preview-nav-group .pdf-preview-tool-btn + .pdf-preview-tool-btn,
.pdf-preview-nav-group .pdf-preview-tool-btn + .pdf-preview-page-chip,
.pdf-preview-nav-group .pdf-preview-page-chip + .pdf-preview-tool-btn {
    border-left: 1px solid color-mix(in srgb, var(--mix-light) 12%, transparent);
}

.pdf-preview-nav-group .pdf-preview-tool-btn:hover,
.pdf-preview-nav-group .pdf-preview-page-chip:hover {
    background: var(--overlay-chrome-bg-strong);
    transform: none;
}

.pdf-preview-nav-group .pdf-preview-tool-btn:disabled:hover {
    background: transparent;
}

.pdf-preview-tool-btn-text {
    font-weight: 700;
    letter-spacing: -0.04em;
    font-size: 0.72rem;
    line-height: 1;
    min-width: 30px;
    padding-inline: 7px;
}

.pdf-preview-runtime:hover .pdf-preview-menu,
.pdf-preview-runtime:focus-within .pdf-preview-menu {
    opacity: 1;
    pointer-events: auto;
}

body.touch-device-ui .pdf-preview-runtime .pdf-preview-menu {
    opacity: 1;
    pointer-events: auto;
}

.pdf-preview-tool-btn[data-action="delete"]:hover {
    background: var(--overlay-danger-bg);
    border-color: var(--overlay-danger-border);
}

.pdf-preview-tool-btn:disabled {
    opacity: 0.45;
    cursor: default;
    transform: none;
}

.pdf-preview-tool-btn:disabled:hover {
    background: var(--overlay-chrome-bg);
    border-color: color-mix(in srgb, var(--mix-light) 14%, transparent);
    color: white;
    transform: none;
}

.pdf-preview-page-chip {
    min-height: 26px;
    padding: 4px 8px;
    cursor: default;
    user-select: none;
    white-space: nowrap;
    font-weight: 600;
    font-size: 0.72rem;
}

.pdf-preview-stage {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    min-height: 180px;
    max-height: min(70vh, 820px);
    overflow: auto;
    -ms-overflow-style: none;
    scrollbar-width: none;
    padding: 12px;
    background: linear-gradient(180deg, var(--bg-pane) 0%, var(--item-hover) 100%);
    box-sizing: border-box;
}

.pdf-preview-stage::-webkit-scrollbar {
    width: 0;
    height: 0;
}

.pdf-preview-canvas {
    display: block;
    max-width: none;
    flex: 0 0 auto;
    height: auto;
    transform-origin: center top;
    will-change: transform;
    backface-visibility: hidden;
    border: 1px solid color-mix(in srgb, var(--border-color) 82%, var(--bg-pane));
    border-radius: 8px;
    box-shadow: 0 10px 24px color-mix(in srgb, var(--mix-dark) 14%, transparent);
    background: var(--bg-pane);
}

.pdf-preview-status {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    max-width: min(320px, calc(100% - 32px));
    padding: 10px 14px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--mix-light) 96%, transparent);
    border: 1px solid color-mix(in srgb, var(--border-color) 88%, var(--bg-pane));
    color: var(--text-main);
    font-size: 0.9rem;
    text-align: center;
    box-shadow: 0 8px 18px color-mix(in srgb, var(--mix-dark) 12%, transparent);
}

.pdf-preview-status.is-hidden {
    display: none;
}

.pdf-preview-status.is-error {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 35%, var(--border-color));
}

.pdf-focus-overlay {
    position: fixed;
    inset: 0;
    z-index: 2200;
    background: var(--overlay-scrim);
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: 24px;
    backdrop-filter: blur(2px);
}

.pdf-focus-surface {
    position: relative;
    width: min(1500px, 100%);
    height: 100%;
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-pane) 8%);
    border: 1px solid color-mix(in srgb, var(--border-color) 80%, var(--bg-pane) 20%);
    border-radius: 12px;
    box-shadow: 0 16px 42px color-mix(in srgb, var(--mix-dark) 28%, transparent);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.pdf-focus-close {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 30;
    width: 34px;
    height: 34px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: color-mix(in srgb, var(--bg-pane) 90%, var(--bg-pane) 10%);
    color: var(--text-main);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
}

.pdf-focus-close:hover {
    background: var(--item-hover);
}

.pdf-focus-body {
    flex: 1;
    min-height: 0;
    padding: 18px;
}

.pdf-preview-runtime.pdf-preview-focus-shell {
    height: 100%;
    margin-top: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
}

.pdf-preview-runtime.pdf-preview-focus-shell .pdf-preview-menu {
    opacity: 1;
    pointer-events: auto;
    right: 54px;
}

.pdf-preview-runtime.pdf-preview-focus-shell .pdf-preview-stage {
    height: 100%;
    min-height: 0;
    max-height: none;
}

/* Resize Handle */
.resize-handle {
    position: absolute;
    width: 14px;
    height: 14px;
    background: white;
    border: 2px solid var(--primary-color);
    border-radius: 50%;
    z-index: 10;
    display: none;
    box-shadow: 0 2px 4px color-mix(in srgb, var(--mix-dark) 20%, transparent);
    touch-action: none;
}

.media-card.selected .resize-handle {
    display: block;
}

.resize-handle.se {
    bottom: -7px;
    right: -7px;
    cursor: nwse-resize;
}

@media (max-width: 768px) {
    /* Float wrap leaves an unreadable text gutter on a phone — collapse to a left-aligned
       block so the image and prose each get the full column width. */
    .media-card[data-display-preset="float-left"],
    .media-card[data-display-preset="float-right"] {
        float: none;
        max-width: 100%;
        margin: 8px auto 8px 0;
    }

    .file-attachment {
        flex-direction: column;
        align-items: stretch;
    }

    .file-attachment-actions {
        justify-content: stretch;
    }

    .file-attachment-action {
        flex: 1 1 auto;
    }

    .pdf-preview-menu {
        opacity: 1;
        pointer-events: auto;
    }

    .pdf-preview-stage {
        max-height: min(62vh, 640px);
        padding: 10px;
    }

    .pdf-focus-overlay {
        padding: 10px;
    }

    .pdf-focus-surface {
        border-radius: 10px;
    }

    .pdf-focus-body {
        padding: 10px;
    }

    .pdf-preview-runtime.pdf-preview-focus-shell .pdf-preview-menu {
        right: 50px;
    }

    .resize-handle {
        width: 20px;
        height: 20px;
    }

    .resize-handle.se {
        bottom: -10px;
        right: -10px;
    }
}

/* Float Toolbar */
.media-toolbar {
    position: absolute;
    top: 8px;
    right: 8px;
    /* Reset previous centering */
    left: auto;
    transform: none;
    
    background-color: var(--overlay-chrome-bg); /* Slight transparency */
    color: white;
    padding: 6px 8px;
    border-radius: 6px;
    display: none;
    gap: 8px;
    z-index: 100;
    box-shadow: 0 4px 12px color-mix(in srgb, var(--mix-dark) 25%, transparent);
    backdrop-filter: blur(4px);
}

.media-card.selected .media-toolbar {
    display: flex;
    animation: fadeIn 0.2s;
}

/* Doc-card toolbars (PDF + plain attachments) are always visible. EPUB cards are excluded:
   their floating menu is selection-driven via the .selected rule above — click the object
   to show it, and MediaHandler deselects after a function is chosen so it hides again.
   (.epub-attachment is stamped on every EPUB card, incl. legacy no-MIME ones, on render.) */
.media-card:not(.pdf-preview-expanded):not(:has(.file-attachment.epub-attachment)) .media-toolbar.media-toolbar-pdf {
    display: flex;
    animation: fadeIn 0.2s;
}

.media-card[data-mime="application/pdf"].pdf-preview-expanded .media-toolbar {
    display: none;
}

/* While the EPUB reader is expanded the card shows the reader's own chrome (incl. close),
   so the floating menu stays hidden even though reader clicks keep the card selected —
   mirrors the pdf-preview-expanded rule above. */
.media-card.epub-preview-expanded .media-toolbar {
    display: none;
}

@media (min-width: 769px) {
    .media-card[data-mime="application/pdf"]:not(.pdf-preview-expanded) {
        max-width: 100%;
    }

    .media-card:not(.pdf-preview-expanded) .media-toolbar.media-toolbar-pdf {
        top: -14px;
        right: 10px;
        left: auto;
    }

    .media-card:is([data-mime^="audio/"], [data-mime^="video/"]) .media-toolbar {
        top: -14px;
        right: 10px;
        left: auto;
    }
}

/* Removed Arrow 
.media-toolbar::after { ... } 
*/

.media-tool-btn {
    background: none;
    border: none;
    color: var(--overlay-chrome-fg);
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: color 0.2s;
}

.media-tool-btn:hover {
    color: white;
}
.media-tool-btn svg {
    width: 16px;
    height: 16px;
}
.media-tool-btn.delete-btn:hover {
    color: var(--danger-color);
}

.media-tool-btn.media-info-btn,
.media-tool-btn.pdf-info-btn {
    font-size: 0.92rem;
    font-weight: 700;
    width: 16px;
    height: 16px;
    line-height: 1;
}

.media-card[data-mime="application/pdf"] .resize-handle {
    display: none !important;
}

.media-info-tooltip {
    position: fixed;
    z-index: 6000;
    width: min(340px, calc(100vw - 20px));
    max-width: 340px;
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    border: 1px solid color-mix(in srgb, var(--primary-color) 24%, var(--border-color));
    border-left: 3px solid var(--primary-color);
    border-radius: 10px;
    box-shadow: var(--shadow-md);
    padding: 10px 12px;
    font-size: 0.82rem;
    color: var(--text-main);
    opacity: 0;
    transform: translateY(4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
    pointer-events: auto;
}

.media-info-tooltip::before {
    content: '';
    position: absolute;
    top: -14px;
    left: 0;
    right: 0;
    height: 14px;
}

.media-info-tooltip.visible {
    opacity: 1;
}

.media-info-tooltip-title {
    font-weight: 700;
    font-size: 0.88rem;
    margin-bottom: 8px;
    word-break: break-word;
}

.media-info-tooltip-section {
    display: grid;
    gap: 5px;
}

.media-info-tooltip-section + .media-info-tooltip-section {
    margin-top: 9px;
    padding-top: 9px;
    border-top: 1px solid color-mix(in srgb, var(--primary-color) 14%, var(--border-color));
}

.media-info-tooltip-heading {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.media-info-tooltip-row {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 8px;
    align-items: start;
}

.media-info-tooltip-label {
    color: var(--text-muted);
    font-weight: 600;
}

.media-info-tooltip-value {
    min-width: 0;
    word-break: break-word;
}

.media-info-tooltip-empty {
    color: var(--text-muted);
    line-height: 1.45;
}

/* Media-toolbar entrance. No horizontal component: the toolbar rests right-anchored with
   transform:none, so an X offset here would show it shifted for the animation's duration
   and then visibly snap sideways when the animation ends (the -50% was a relic of the old
   centered-toolbar layout). */
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}


/* --- LIGHTBOX --- */
.lightbox-overlay {
    position: fixed;
    z-index: 2000;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: color-mix(in srgb, var(--mix-dark) 90%, transparent);
    display: flex;
    justify-content: center;
    align-items: center;
    backdrop-filter: blur(5px);
    /* We drive pinch/drag zoom ourselves — keep the browser's own touch
       gestures (scroll, pull-to-refresh) off the viewer. */
    touch-action: none;
    overflow: hidden;
}

.lightbox-overlay.hidden {
    display: none;
}

.lightbox-content {
    max-width: 90%;
    max-height: 90vh;
    box-shadow: 0 4px 20px color-mix(in srgb, var(--mix-dark) 50%, transparent);
    border-radius: 4px;
    object-fit: contain;
    transform-origin: center center;
    will-change: transform;
    /* Pan handles dragging; suppress the native image drag-ghost. */
    -webkit-user-drag: none;
    user-select: none;
}

.lightbox-close {
    position: absolute;
    top: 20px;
    right: 30px;
    font-size: 40px;
    font-weight: bold;
    color: var(--overlay-chrome-fg);
    background: none;
    border: none;
    cursor: pointer;
    transition: 0.3s;
    line-height: 1;
    z-index: 2001;
}

.lightbox-close:hover,
.lightbox-close:focus {
    color: color-mix(in srgb, var(--overlay-chrome-fg) 75%, transparent);
    text-decoration: none;
    cursor: pointer;
}


/* EPUB reader (Feature A) — the in-note scroll viewer. Feature-owned surface, prefixed
   .epub-preview-* / .epub-focus-*; mirrors the PDF preview runtime. Driven by semantic theme
   tokens so it themes with the app; the chapter *content* is themed separately inside the iframe
   (see EpubPreviewController.readerCss). */

/* Attachment chip (book) — parallels .file-attachment.pdf-attachment. */
.file-attachment.epub-attachment {
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
}
.file-attachment.epub-attachment .file-attachment-icon {
    color: var(--primary-color);
}

/* Reader runtime container (appended inside the media card on expand). */
.epub-preview-runtime {
    display: flex;
    flex-direction: column;
    width: 100%;
    margin-top: 8px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: var(--bg-pane);
    overflow: hidden;
}

/* Toolbar */
.epub-preview-menu {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 6px 8px;
    border-bottom: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 88%, var(--text-main) 4%);
    flex-wrap: wrap;
}
.epub-preview-nav-group,
.epub-preview-tools {
    display: flex;
    align-items: center;
    gap: 4px;
    /* The nav group now carries 6 controls + the chapter label — on a phone-width card
       it must wrap onto a second line, never clip its last buttons off the edge. */
    flex-wrap: wrap;
    min-width: 0;
}
.epub-preview-chapter-label {
    font-size: 0.85rem;
    color: var(--text-muted);
    padding: 0 6px;
    max-width: 46vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.epub-preview-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 30px;
    height: 30px;
    padding: 0 7px;
    border: 1px solid transparent;
    border-radius: 7px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
    font-weight: 600;
}
.epub-preview-btn:hover {
    background: color-mix(in srgb, var(--primary-color) 14%, transparent);
    border-color: color-mix(in srgb, var(--primary-color) 30%, var(--border-color));
}
.epub-preview-btn:disabled {
    opacity: 0.4;
    cursor: default;
    background: transparent;
    border-color: transparent;
}
.epub-preview-btn svg {
    width: 16px;
    height: 16px;
}

/* Off-screen holder for a parked (still-playing) reader — visibility:hidden rather than
   display:none so the live chapter iframe keeps full layout/scroll behavior while hidden. */
.epub-parking-holder {
    position: fixed;
    left: -10000px;
    top: 0;
    width: 400px;
    height: 400px;
    overflow: hidden;
    visibility: hidden;
    pointer-events: none;
}

/* Table of contents panel */
.epub-preview-toc {
    max-height: 240px;
    overflow-y: auto;
    padding: 6px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-pane);
}
.epub-toc-item {
    display: block;
    width: 100%;
    text-align: left;
    padding: 7px 10px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
    font-size: 0.9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.epub-toc-item:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
}
.epub-toc-item.is-active {
    background: color-mix(in srgb, var(--primary-color) 20%, transparent);
    font-weight: 600;
}

/* Recent pages popover — the last N reading/listening places, TOC visual family. */
.epub-history-panel {
    max-height: 260px;
    overflow-y: auto;
    padding: 6px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-pane);
}
.epub-history-panel.hidden { display: none; }
.epub-history-item {
    display: block;
    width: 100%;
    text-align: left;
    padding: 7px 10px;
    border: none;
    border-radius: 6px;
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
    font: inherit;
    font-size: 0.9rem;
}
.epub-history-item:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
}
.epub-history-item-title {
    display: block;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.epub-history-item-snippet {
    display: block;
    color: var(--text-editor-muted);
    font-size: 0.82rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.epub-history-empty {
    padding: 10px 12px;
    color: var(--text-editor-muted);
    font-size: 0.88rem;
}

/* Stage + rendered chapter iframe */
.epub-preview-stage {
    position: relative;
    background: var(--bg-pane);
}
.epub-preview-runtime.epub-theme-dark .epub-preview-stage {
    background: #17141f; /* literal-ok: EPUB night theme, fixed reading palette */
}

/* Reader dark theme — independent of the app theme (the user can read dark inside a light
   app), toggled as .epub-theme-dark on the runtime host by applyReaderStyle(). Every chrome
   rule here and in 049-read-aloud.css (timer popover/chips/input) consumes semantic tokens,
   so re-valuing the tokens on the themed host re-themes the entire chrome — menu, buttons,
   TOC, popovers — with no per-element dark rules. Fixed hex values are the reader-content
   palette from EpubPreviewController.readerCss (#17141f page / #d9d5e0 ink / #9db4ff accent)
   — a documented fixed-treatment exception, like the stage rule above. */
.epub-preview-runtime.epub-theme-dark {
    --bg-pane: #1c1826; /* literal-ok: EPUB night theme, fixed reading palette */
    --bg-app: #141020; /* literal-ok: EPUB night theme, fixed reading palette */
    --border-color: #332c44; /* literal-ok: EPUB night theme, fixed reading palette */
    --text-main: #d9d5e0; /* literal-ok: EPUB night theme, fixed reading palette */
    --text-muted: #9a93a8; /* literal-ok: EPUB night theme, fixed reading palette */
    --primary-color: #9db4ff; /* literal-ok: EPUB night theme, fixed reading palette */
    color-scheme: dark;
}

.epub-preview-frame {
    display: block;
    width: 100%;
    height: min(70vh, 760px);
    border: 0;
    background: transparent;
}
.epub-preview-status {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    background: var(--bg-pane);
    pointer-events: none;
}
.epub-preview-status.hidden { display: none; }
.epub-preview-toc.hidden { display: none; }

/* Full-screen overlay — solid background (deliberately NO backdrop-filter to avoid the stacked
   glass-overlay GPU freeze). Sized with dynamic viewport height + safe-area insets so the reader
   toolbar stays fully visible on mobile (100vh ignores the browser URL bar / notch, which pushed the
   menu off-screen). Fallback to 100vh where dvh is unsupported. */
.epub-focus-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    z-index: 2200;
    background: var(--bg-app, #0e0c14); /* literal-ok: EPUB night theme, fixed reading palette */
    display: flex;
    box-sizing: border-box;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
/* The overlay is the shell's PARENT, so the token re-values above can't reach it; only its
   safe-area padding strips are visible around a dark shell — match the dark page color. */
.epub-focus-overlay:has(.epub-theme-dark) {
    background: #17141f; /* literal-ok: EPUB night theme, fixed reading palette */
}
.epub-preview-runtime.epub-preview-focus-shell {
    margin-top: 0;
    border: 0;
    border-radius: 0;
    flex: 1;
    min-height: 0;   /* let the column shrink so the stage (not the menu) absorbs the height */
    height: 100%;
}
/* Toolbar keeps its natural height (even wrapped to two rows on a narrow phone); the stage fills the
   rest and the frame fills the stage — no fragile calc() that assumes a one-row 48px menu. */
.epub-preview-focus-shell .epub-preview-menu {
    flex: 0 0 auto;
}
.epub-preview-focus-shell .epub-preview-stage {
    flex: 1 1 auto;
    min-height: 0;
}
.epub-preview-focus-shell .epub-preview-frame {
    height: 100%;
}

@media (max-width: 720px) {
    /* Tighter label so the row of controls survives intact on narrow cards. */
    .epub-preview-chapter-label { max-width: 24vw; }
    .epub-preview-frame { height: min(72vh, 640px); }
}
/* --- RENAME MODAL --- */

.modal-overlay {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    background: color-mix(in srgb, var(--mix-dark) 50%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    /* Visibility snaps ON instantly (0s) so dialogs can focus an input in the
       same tick they un-hide — a transitioning `visibility: hidden` silently
       swallows focus() calls. The fade-out keeps working via the delayed
       visibility flip on .hidden below. */
    transition: opacity 0.18s ease, visibility 0s;
}

.modal-overlay.hidden {
    display: flex !important;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.18s ease, visibility 0s linear 0.18s;
}

.modal-box {
    background: var(--bg-pane);
    width: 400px;
    padding: 24px;
    border-radius: 8px;
    box-shadow: 0 10px 25px color-mix(in srgb, var(--mix-dark) 20%, transparent);
    display: flex;
    flex-direction: column;
    gap: 16px;
    transform: translateY(0) scale(1);
    transition: transform 0.2s ease, opacity 0.2s ease;
    opacity: 1;
}

.modal-overlay.hidden .modal-box {
    transform: translateY(8px) scale(0.98);
    opacity: 0;
}

.modal-title {
    font-size: 1.1rem;
    font-weight: 600;
    line-height: 1.3;
}

.modal-body {
    line-height: 1.5;
}

/* ============================================================================
   Segmented "pill" tabs — the app STANDARD for tabbed dialogs. Reuse these
   classes (not a feature-local copy) whenever a dialog splits content into tabs.
   Markup:
     <div class="app-tabs" role="tablist">
       <button type="button" class="app-tab is-active" role="tab"
               aria-selected="true" data-tab="key">Label</button> …
     </div>
     <!-- one panel per tab; JS toggles .is-active + aria-selected + panel[hidden] -->
   Track is a soft inset (--tab-track-bg); the active tab is a raised surface pill
   (--tab-active-bg) with an accent label. Fully theme-token driven.
   ============================================================================ */

.app-tabs {
    display: flex;
    justify-content: space-between;
    gap: var(--space-1);
    padding: var(--space-1);
    background: var(--tab-track-bg);
    border-radius: 999px;
}

.app-tab {
    /* Content-width pills, evenly distributed across the track (the active pill hugs its label). */
    flex: 0 1 auto;
    min-width: 0;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 999px;
    color: var(--text-muted);
    cursor: pointer;
    padding: 6px 14px;
    font-size: 0.85rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease);
}

.app-tab:hover:not(.is-active) { color: var(--text-main); }

.app-tab.is-active {
    background: var(--tab-active-bg);
    color: var(--primary-color);
    border-color: var(--border-color);
    box-shadow: var(--shadow-sm);
}

.app-tab:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 1px; }

.modal-field-label {
    display: block;
    margin-bottom: 8px;
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text-main);
}

.modal-input {
    min-height: 40px;
    max-height: 100px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    padding: 8px;
    border-radius: 4px;
    font-family: inherit;
    font-size: 1rem;
}

.modal-input:focus {
    outline: 2px solid var(--primary-color);
    border-color: transparent;
}

.modal-toolbar {
    display: flex;
    gap: 8px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 8px;
    margin-bottom: 8px;
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 8px;
}

.modal-actions > button {
    min-height: 38px;
}

.simple-btn {
    min-height: var(--btn-height);
    padding: 0 var(--btn-pad-x);
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: var(--btn-font-size);
    font-weight: 600;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    transition: transform var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}

.simple-btn.primary {
    background: var(--accent-gradient);
    color: white;
    border-color: transparent;
    box-shadow: 0 8px 18px color-mix(in srgb, var(--accent-gradient-start) 25%, transparent);
}

.simple-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}

.simple-btn.primary:hover {
    box-shadow: 0 10px 20px color-mix(in srgb, var(--accent-gradient-start) 32%, transparent);
}

/* --- GLASSMORPHISM SYSTEM DIALOG --- */

/* The --glass-* tokens live in 000-tokens-base.css with the rest of the theme tokens. */

.modal-overlay.glass-overlay {
    background: var(--glass-overlay-bg);
    backdrop-filter: blur(3px);
    z-index: 5000;
}

/* Dark theme: every glass dialog surface below swaps its white rim for the glass rim + a
   deeper shadow so the dark sheet still separates from the dark backdrop. The surfaces
   themselves are theme-aware via color-mix(var(--bg-pane)) in their base rules. */

:root[data-theme="dark"] #rename-modal .rename-glass-dialog,
:root[data-theme="dark"] #confirm-modal .glass-dialog,
:root[data-theme="dark"] #find-replace-modal .find-replace-glass-dialog,
:root[data-theme="dark"] #import-progress-modal .import-progress-glass-dialog,
:root[data-theme="dark"] .gdrive-folder-import-dialog,
:root[data-theme="dark"] .gdrive-folder-picker-dialog,
:root[data-theme="dark"] #db-loading-overlay .db-loading-glass-dialog,
:root[data-theme="dark"] #data-manager-modal .data-manager-glass-dialog {
    border-color: var(--glass-border);
    box-shadow: var(--glass-shadow);
}

#rename-modal.modal-overlay.glass-overlay {
    z-index: 5600;
}

/* Theme-aware glass (whole dialog family): mixing --bg-pane toward transparent reproduces the
   original white glass exactly in light mode (bg-pane is var(--mix-light) there) and yields dark glass under
   data-theme="dark", where the text tokens already flip — the surfaces must flip with them.
   The dark rim/shadow for these dialogs lives in one shared override further down. */

#rename-modal .rename-glass-dialog {
    width: min(94vw, 560px);
    background: color-mix(in srgb, var(--bg-pane) 90%, transparent);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
}

#rename-modal .rename-glass-dialog.rename-glass-dialog-compact {
    width: min(92vw, 320px);
    padding: 20px;
    gap: 12px;
}

#rename-modal .rename-glass-dialog.rename-glass-dialog-compact .modal-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

#rename-modal .rename-glass-dialog.rename-glass-dialog-compact .modal-field-label {
    margin-bottom: 0;
}

#rename-modal .rename-glass-dialog .modal-title {
    color: var(--text-main);
}

#rename-modal .rename-glass-dialog .modal-toolbar {
    border-bottom: 1px solid var(--border-color);
}

#rename-modal .rename-glass-dialog .icon-btn-small {
    color: var(--text-main);
}

#rename-modal .rename-glass-dialog .icon-btn-small:hover {
    color: var(--primary-color);
    background-color: var(--item-hover);
}

.modal-overlay .modal-header .icon-btn-small {
    color: color-mix(in srgb, var(--text-main) 90%, var(--text-main) 10%);
    border-color: color-mix(in srgb, var(--border-color) 70%, var(--mix-dark) 30%);
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--mix-dark) 8%);
}

.modal-overlay .modal-header .icon-btn-small:hover {
    color: color-mix(in srgb, var(--text-main) 70%, var(--primary-color) 30%);
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
    background: color-mix(in srgb, var(--item-hover) 80%, var(--mix-dark) 20%);
}

#rename-modal .rename-glass-dialog .modal-input {
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    border-radius: 10px;
}

#rename-modal .rename-glass-dialog .modal-input.modal-input-single-line {
    min-height: 20px;
    max-height: 44px;
    overflow-y: hidden;
    white-space: nowrap;
}

#rename-modal .rename-glass-dialog .modal-input:focus {
    outline: 2px solid var(--primary-color);
    border-color: transparent;
}

#rename-modal .rename-glass-dialog .modal-actions {
    margin-top: 10px;
}

#rename-modal .rename-glass-dialog.rename-glass-dialog-compact .modal-actions {
    margin-top: 4px;
}

#rename-modal .rename-glass-dialog .glass-btn-cancel {
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
}

#rename-modal .rename-glass-dialog .glass-btn-cancel:hover {
    background: var(--item-hover);
}

#confirm-modal .glass-dialog {
    width: min(92vw, 460px);
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 90%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 22px;
    gap: 14px;
}

#confirm-modal.modal-overlay.glass-overlay {
    z-index: 5600;
}

/* The AI Models and AI Preset Manager dialogs are launched from the floating Agent
   Chat (z-index 5200) via its gear menu, so they must stack ABOVE it — otherwise the
   modal opens behind the chat and its backdrop can't block interaction with it. Same
   treatment as #rename-modal / #confirm-modal above. */

#ai-model-manager-modal.modal-overlay.glass-overlay,
#ai-preset-manager-modal.modal-overlay.glass-overlay {
    z-index: 5600;
}

/* The AI Preset *editor* opens stacked on top of the Preset Manager (both are glass
   overlays). Two fixes in one rule:
   1. Stacking: the base overlay is z-index 5000, but the manager is 5600 — so without
      this the editor would open BEHIND its own manager. Lift it above (5700).
   2. Freeze: it must NOT add a second full-viewport backdrop-filter. Two stacked blurs
      compositing at once can stall Chrome's compositor/GPU into a hard freeze (worse
      under an unstable GPU path, e.g. --enable-unsafe-webgpu). The manager beneath
      already supplies the glass blur, so the editor's blur is redundant — drop it and
      keep the dim via the overlay background alone. */

#ai-preset-edit-modal.modal-overlay.glass-overlay {
    z-index: 5700;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

#confirm-modal .glass-dialog .modal-title {
    color: var(--text-main);
    font-size: 1.16rem;
    letter-spacing: 0.01em;
    font-weight: 700;
}

#confirm-modal .glass-dialog-message {
    margin: 0;
    color: var(--text-main);
    font-size: 0.96rem;
    line-height: 1.45;
    white-space: pre-line;
}

#confirm-modal .glass-dialog-actions {
    margin-top: 8px;
    justify-content: flex-end;
    gap: 10px;
}

.glass-btn {
    border-radius: var(--radius-md);
    min-height: var(--btn-height);
    min-width: 108px;
    padding: 0 var(--btn-pad-x);
    font-size: var(--btn-font-size);
    font-weight: 600;
    cursor: pointer;
    transition: transform var(--anim-fast) var(--anim-ease), box-shadow var(--anim-base) var(--anim-ease), opacity var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}

.dialog-body {
    line-height: 1.5;
}

.dialog-footer button,
.modal-actions .glass-btn,
.modal-actions .simple-btn {
    min-height: 38px;
}

.log-dialog[open] {
    animation: dialogPopIn 0.18s ease;
}

@keyframes dialogPopIn {
    from {
        opacity: 0;
        transform: translate(-50%, -46%) scale(0.98);
    }
    to {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
    }
}

@media (max-width: 768px) {
    .modal-box {
        width: min(94vw, 560px);
        padding: 16px;
        gap: 12px;
    }

    .modal-title {
        font-size: 1.05rem;
    }

    .modal-actions {
        gap: 8px;
    }

    .modal-actions .glass-btn,
    .modal-actions .simple-btn,
    .dialog-footer button {
        min-height: 42px;
        padding: 10px 14px;
        font-size: 0.92rem;
    }
}

.glass-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--mix-light) 82%, transparent);
    outline-offset: 2px;
}

.glass-btn-cancel {
    background: color-mix(in srgb, var(--bg-pane) 94%, var(--bg-pane) 6%);
    border: 1px solid color-mix(in srgb, var(--border-color) 82%, var(--mix-dark) 18%);
    color: color-mix(in srgb, var(--text-main) 92%, var(--text-main) 8%);
}

.glass-btn-cancel:hover {
    background: var(--item-hover);
}

#confirm-modal .glass-btn-cancel {
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
}

#confirm-modal .glass-btn-cancel:hover {
    background: var(--item-hover);
}

#find-replace-modal .glass-btn-cancel {
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    opacity: 1;
}

#find-replace-modal .glass-btn-cancel:hover {
    background: var(--item-hover);
}

#find-replace-modal .glass-btn:disabled {
    opacity: 1;
    cursor: pointer;
}

#confirm-modal .glass-btn:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--accent-gradient-start) 65%, transparent);
}

/* --- FIND / REPLACE MODAL --- */

#find-replace-modal .find-replace-glass-dialog {
    --fr-scale: 1;
    width: min(94vw, 620px);
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 68%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: calc(20px * var(--fr-scale));
    gap: calc(12px * var(--fr-scale));
}

#find-replace-modal {
    background: transparent;
    backdrop-filter: none;
    pointer-events: none;
}

#find-replace-modal .find-replace-glass-dialog {
    position: fixed;
    top: 92px;
    right: 20px;
    left: auto;
    width: min(94vw, 620px);
    min-width: 240px;
    min-height: 150px;
    max-width: calc(100vw - 16px);
    max-height: calc(100vh - 16px);
    /* Resizing is via the custom .fnav-resize-handle gripper (touch-friendly);
       the native resize handle is replaced. */
    resize: none;
    /* Header + tab strip stay fixed; only the active panel scrolls so the
       Find & Navigate tabs never scroll out of view. */
    overflow: hidden;
    display: flex;
    flex-direction: column;
    pointer-events: auto;
}

/* No scale/translate pop-in transform on this dialog: getBoundingClientRect would
   reflect the transformed box, baking an offset into the saved drag position and
   causing it to creep on each reopen. The dialog is draggable; the pop-in isn't needed. */

#find-replace-modal .find-replace-glass-dialog,
.modal-overlay.hidden .find-replace-glass-dialog {
    transform: none;
}

#find-replace-modal .find-replace-header,
#find-replace-modal .fnav-tabs {
    flex: 0 0 auto;
}

#find-replace-modal .fnav-panel {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}

.find-replace-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: calc(10px * var(--fr-scale));
    cursor: move;
    user-select: none;
    touch-action: none;
}

.find-replace-body {
    display: flex;
    flex-direction: column;
    gap: calc(10px * var(--fr-scale));
}

.find-replace-field {
    display: flex;
    flex-direction: column;
    gap: calc(6px * var(--fr-scale));
}

.find-replace-inline-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: calc(10px * var(--fr-scale));
}

.find-replace-inline-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: clamp(0.72rem, calc(0.86rem * var(--fr-scale)), 0.86rem);
    color: var(--text-main);
}

.find-replace-label {
    font-size: clamp(0.72rem, calc(0.84rem * var(--fr-scale)), 0.84rem);
    font-weight: 600;
    color: var(--text-muted);
}

.find-replace-input {
    min-height: clamp(30px, calc(38px * var(--fr-scale)), 38px);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: calc(8px * var(--fr-scale)) calc(10px * var(--fr-scale));
    font-family: inherit;
    font-size: clamp(0.75rem, calc(0.95rem * var(--fr-scale)), 0.95rem);
    color: var(--text-main);
    background: var(--bg-pane);
}

.find-replace-input:focus {
    outline: 2px solid color-mix(in srgb, var(--accent-gradient-start) 60%, transparent);
    border-color: transparent;
}

.find-replace-options {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: calc(12px * var(--fr-scale));
    margin-top: 2px;
}

.find-wrap-label {
    display: inline-flex;
    align-items: center;
    gap: calc(6px * var(--fr-scale));
    color: var(--text-main);
    font-size: clamp(0.72rem, calc(0.9rem * var(--fr-scale)), 0.9rem);
}

.find-replace-status {
    font-size: clamp(0.72rem, calc(0.86rem * var(--fr-scale)), 0.86rem);
    color: var(--text-muted);
}

.find-replace-actions-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: calc(8px * var(--fr-scale));
    align-items: stretch;
}

.find-replace-actions-row .glass-btn {
    min-width: 0;
    min-height: clamp(28px, calc(40px * var(--fr-scale)), 40px);
    width: 100%;
    justify-self: stretch;
    font-size: clamp(0.72rem, calc(0.95rem * var(--fr-scale)), 0.95rem);
    padding: 0 clamp(6px, calc(10px * var(--fr-scale)), 12px);
}

#find-replace-one,
#find-replace-all {
    grid-column: span 2;
}

/* Find matches are painted with the CSS Custom Highlight API (see
   editor/FindNavigateDialog.js) so a query with thousands of hits costs no DOM
   mutation inside the contenteditable. Both layers use existing semantic tokens,
   so light + dark come along for free. `::highlight()` only accepts colour,
   background-color, text-decoration and text-shadow — no radius or box-shadow. */
::highlight(cyb-find-match) {
    background-color: color-mix(in srgb, var(--status-pinned-bg) 70%, transparent);
}

::highlight(cyb-find-active) {
    background-color: var(--warning-color);
}

/* Browsers without the Custom Highlight API fall back to wrapping the ACTIVE
   match only (one element, not thousands). Kept for that path, and to style any
   stale marker left in older content. */
mark.find-match {
    background: color-mix(in srgb, var(--status-pinned-bg) 70%, transparent);
    color: inherit;
    border-radius: 3px;
    padding: 0 1px;
}

mark.find-match.active {
    background: var(--warning-color);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--warning-color) 35%, transparent);
}

@media (max-width: 768px) {
    .find-replace-actions-row {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    #find-replace-one,
    #find-replace-all {
        grid-column: span 1;
    }
}

/* --- IMPORT PROGRESS MODAL --- */

#import-progress-modal {
    z-index: 5100 !important;
}

#import-progress-modal.import-progress-foreground {
    z-index: 7000 !important;
}

#import-progress-modal .import-progress-glass-dialog {
    width: min(94vw, 720px);
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 92%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 18px;
    gap: 12px;
}

.import-progress-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.import-progress-current {
    display: grid;
    gap: 4px;
    font-size: 0.9rem;
    color: var(--text-main);
}

.import-progress-track {
    position: relative;
    width: 100%;
    height: 12px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-muted) 18%, transparent);
    overflow: hidden;
    border: 1px solid color-mix(in srgb, var(--text-muted) 24%, transparent);
}

#import-progress-modal.import-progress-running .import-progress-track::after {
    content: '';
    position: absolute;
    top: 0;
    left: -35%;
    width: 35%;
    height: 100%;
    border-radius: inherit;
    background: linear-gradient(90deg, color-mix(in srgb, var(--accent-gradient-start) 0%, transparent), color-mix(in srgb, var(--accent-gradient-start) 45%, transparent), color-mix(in srgb, var(--accent-gradient-end) 0%, transparent));
    animation: importProgressTrackSweep 1.25s ease-in-out infinite;
    pointer-events: none;
}

.import-progress-bar {
    width: 0%;
    height: 100%;
    border-radius: 999px;
    background: var(--accent-gradient-h);
    transition: width 0.18s ease;
}

.import-progress-bar.import-progress-bar-running {
    background: linear-gradient(
        120deg,
        var(--accent-gradient-start) 0%,
        var(--accent-gradient-start) 34%,
        color-mix(in srgb, var(--accent-gradient-end) 60%, var(--mix-light)) 48%,
        var(--accent-gradient-start) 62%,
        var(--accent-gradient-end) 100%
    );
    background-size: 220% 100%;
    animation: importProgressSweep 1.1s linear infinite;
}

@keyframes importProgressSweep {
    0% {
        background-position: 180% 0;
    }
    100% {
        background-position: -40% 0;
    }
}

@keyframes importProgressTrackSweep {
    0% {
        left: -35%;
    }
    100% {
        left: 100%;
    }
}

.import-progress-stats {
    display: flex;
    gap: 12px;
    justify-content: space-between;
    color: var(--text-muted);
    font-size: 0.86rem;
}

.import-progress-log {
    min-height: 140px;
    max-height: min(40vh, 300px);
    overflow: auto;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--bg-pane) 65%, transparent);
    padding: 8px 10px;
    font-size: 0.82rem;
    line-height: 1.35;
}

.import-progress-log-entry {
    margin-bottom: 4px;
    color: var(--text-main);
}

.import-progress-log-entry.warn {
    color: var(--warning-color);
}

.import-progress-log-entry.error {
    color: var(--danger-color);
}

.import-progress-realtime {
    display: grid;
    gap: 4px;
    border: 1px dashed color-mix(in srgb, var(--text-muted) 45%, transparent);
    border-radius: 10px;
    background: color-mix(in srgb, var(--bg-pane) 55%, transparent);
    padding: 8px 10px;
    font-size: 0.8rem;
    line-height: 1.35;
    color: var(--text-muted);
}

.import-progress-live-line {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.import-progress-live-line strong {
    color: var(--text-main);
    font-weight: 600;
}

#import-progress-live-errors.import-progress-live-has-errors {
    color: var(--danger-color);
}

#import-progress-modal .glass-btn-cancel {
    background: var(--bg-pane);
    color: var(--text-main);
    border: 1px solid var(--border-color);
    opacity: 1;
}

#import-progress-modal .glass-btn-cancel:hover {
    background: var(--item-hover);
}

#import-progress-modal .glass-btn-cancel:disabled,
#import-progress-modal .icon-btn-small:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.glass-btn-confirm {
    border: 1px solid color-mix(in srgb, var(--mix-light) 24%, transparent);
    color: var(--on-accent);
    box-shadow: 0 0 0 color-mix(in srgb, var(--mix-dark) 0%, transparent);
}

.glass-btn-confirm.variant-blue {
    background: linear-gradient(135deg, var(--glass-confirm-blue-start), var(--glass-confirm-blue-end));
    box-shadow: 0 8px 24px color-mix(in srgb, var(--accent-gradient-start) 42%, transparent);
}

.glass-btn-confirm.variant-orange {
    background: linear-gradient(135deg, var(--glass-confirm-orange-start), var(--glass-confirm-orange-end));
    box-shadow: 0 8px 24px color-mix(in srgb, var(--warning-color) 38%, transparent);
}

.glass-btn-confirm.variant-red {
    background: linear-gradient(135deg, var(--glass-confirm-red-start), var(--glass-confirm-red-end));
    box-shadow: 0 8px 24px color-mix(in srgb, var(--danger-color) 40%, transparent);
}

.glass-btn-confirm:hover {
    transform: translateY(-1px);
}

/* Disabled glass buttons (e.g. Delete File after the PC file has been removed) read as inert:
   muted, no lift on hover, no pointer. */

.glass-btn:disabled,
.glass-btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: default;
    box-shadow: none;
    filter: grayscale(0.35);
}

.glass-btn:disabled:hover,
.glass-btn[aria-disabled="true"]:hover {
    transform: none;
}

/* Icon consistency */

button svg,
.icon-btn svg,
.icon-btn-small svg,
.btn-primary-outline svg,
.simple-btn svg,
.glass-btn svg {
    width: var(--icon-size);
    height: var(--icon-size);
    display: inline-block;
    vertical-align: middle;
    stroke-width: var(--icon-stroke);
}
/* Google Drive dialogs: folder import / export, folder picker, package import, the transfer wait
   dialog and its mascot. Split out of 180-dialogs-overlays.css (Phase 10); shared glass/modal rules stay there. */

.gdrive-folder-import-dialog {
    width: min(96vw, 1040px);
    max-height: min(92vh, calc(100dvh - 24px));
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 92%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 18px;
    gap: 14px;
    overflow: hidden;
}

.gdrive-folder-import-body {
    display: grid;
    gap: 14px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 4px;
    -webkit-overflow-scrolling: touch;
}

.gdrive-folder-import-meta {
    color: var(--text-main);
    font-size: 0.95rem;
}

.gdrive-folder-import-config-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 180px;
    gap: 14px;
    align-items: end;
}

.gdrive-folder-import-field {
    display: grid;
    gap: 6px;
    color: var(--text-muted);
    font-size: 0.86rem;
}

.gdrive-folder-import-source-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 10px;
    align-items: center;
}

.gdrive-folder-import-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-main);
    font-size: 0.9rem;
}

.gdrive-folder-import-toggle input {
    width: 16px;
    height: 16px;
}

.gdrive-folder-import-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.gdrive-folder-import-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--accent-gradient-start) 22%, transparent);
    background: color-mix(in srgb, var(--accent-gradient-start) 6%, transparent);
    color: var(--text-main);
    font-size: 0.84rem;
}

.gdrive-folder-import-track {
    display: none;
    width: min(560px, 100%);
    justify-self: center;
}

.gdrive-folder-import-status {
    min-height: 1.4em;
    color: var(--success-color);
    font-family: "Courier New", Courier, monospace;
    font-size: 0.94rem;
}

.gdrive-folder-import-status.ok {
    color: var(--success-color);
}

.gdrive-folder-import-status.warn {
    color: var(--warning-color);
}

.gdrive-folder-import-status.error {
    color: var(--danger-color);
}

.gdrive-folder-import-panels {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
}

.gdrive-folder-import-panel {
    display: grid;
    gap: 8px;
}

.gdrive-folder-import-panel h4 {
    margin: 0;
    color: var(--text-main);
    font-size: 1rem;
}

.gdrive-folder-import-summary,
.gdrive-folder-import-warnings {
    min-height: 170px;
    max-height: min(34vh, 320px);
    overflow: auto;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: color-mix(in srgb, var(--bg-pane) 68%, transparent);
    padding: 12px 14px;
    color: var(--text-main);
    font-size: 0.86rem;
    line-height: 1.45;
}

.gdrive-folder-import-summary > div,
.gdrive-folder-import-warnings > div {
    margin-bottom: 6px;
}

.gdrive-folder-import-running .gdrive-folder-import-track {
    display: block;
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent-gradient-start) 12%, transparent), 0 0 22px color-mix(in srgb, var(--accent-gradient-start) 12%, transparent);
}

.gdrive-folder-import-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
    flex-shrink: 0;
}

.gdrive-folder-export-dialog {
    width: min(94vw, 820px);
    max-height: min(88vh, calc(100dvh - 28px));
    padding: 14px;
    gap: 10px;
}

.gdrive-folder-export-dialog .gdrive-folder-import-body {
    gap: 10px;
}

.gdrive-folder-export-dialog .gdrive-folder-import-panels {
    gap: 10px;
}

.gdrive-folder-export-dialog .gdrive-folder-import-summary,
.gdrive-folder-export-dialog .gdrive-folder-import-warnings {
    min-height: 120px;
    max-height: min(24vh, 220px);
    padding: 10px 12px;
}

.gdrive-folder-export-dialog .gdrive-folder-picker-current {
    padding: 10px 12px;
    border-radius: 12px;
}

.gdrive-folder-picker-dialog {
    width: min(94vw, 760px);
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 94%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 18px;
    gap: 14px;
}

.gdrive-folder-picker-body {
    display: grid;
    gap: 12px;
}

.gdrive-folder-picker-nav {
    display: flex;
    align-items: center;
    gap: 8px;
}

.gdrive-folder-picker-nav .icon-btn-small {
    min-width: 36px;
    width: 36px;
    padding-inline: 0;
}

.gdrive-folder-picker-nav .icon-btn-small:disabled {
    opacity: 0.42;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.gdrive-folder-picker-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.gdrive-folder-picker-crumb {
    border: 0;
    background: color-mix(in srgb, var(--accent-gradient-start) 8%, transparent);
    color: var(--text-main);
    padding: 6px 10px;
    border-radius: 999px;
    cursor: pointer;
    font-size: 0.86rem;
}

.gdrive-folder-picker-crumb:disabled {
    cursor: default;
    background: color-mix(in srgb, var(--accent-gradient-start) 16%, transparent);
    color: var(--primary-color);
}

.gdrive-folder-picker-sep {
    color: var(--text-muted);
    font-size: 0.86rem;
}

.gdrive-folder-picker-current {
    display: grid;
    gap: 4px;
    padding: 12px 14px;
    border-radius: 14px;
    border: 1px solid color-mix(in srgb, var(--accent-gradient-start) 14%, transparent);
    background: linear-gradient(180deg, color-mix(in srgb, var(--accent-gradient-start) 6%, transparent), color-mix(in srgb, var(--accent-gradient-start) 2%, transparent));
}

.gdrive-folder-picker-current-label {
    color: var(--text-muted);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.gdrive-folder-picker-current-name {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-main);
    font-size: 1rem;
    font-weight: 700;
}

.gdrive-folder-picker-current-name svg {
    color: var(--warning-color);
}

.gdrive-folder-picker-current-id {
    color: var(--text-muted);
    font-size: 0.82rem;
    word-break: break-all;
}

.gdrive-folder-picker-status {
    min-height: 1.4em;
    color: var(--success-color);
    font-family: "Courier New", Courier, monospace;
    font-size: 0.92rem;
}

.gdrive-folder-picker-status.error {
    color: var(--danger-color);
}

.gdrive-folder-picker-list {
    display: grid;
    gap: 8px;
    min-height: 240px;
    max-height: min(48vh, 460px);
    overflow: auto;
    padding-right: 2px;
}

.gdrive-folder-picker-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 12px;
    align-items: center;
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--border-color);
    border-radius: 14px;
    background: color-mix(in srgb, var(--bg-pane) 78%, transparent);
    color: var(--text-main);
    cursor: pointer;
    text-align: left;
    transition: border-color var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease);
}

.gdrive-folder-picker-row:hover {
    border-color: color-mix(in srgb, var(--accent-gradient-start) 32%, transparent);
    background: color-mix(in srgb, var(--accent-gradient-start) 6%, transparent);
    box-shadow: 0 10px 24px color-mix(in srgb, var(--accent-gradient-start) 12%, transparent);
    transform: translateY(-1px);
}

.gdrive-folder-picker-row-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--warning-color);
}

.gdrive-folder-picker-row-main {
    display: grid;
    gap: 4px;
    min-width: 0;
}

.gdrive-folder-picker-row-name {
    font-size: 0.94rem;
    font-weight: 600;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gdrive-folder-picker-row-meta {
    color: var(--text-muted);
    font-size: 0.8rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.gdrive-folder-picker-row-action {
    color: var(--primary-color);
    font-size: 0.84rem;
    font-weight: 700;
}

.gdrive-package-import-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.gdrive-package-import-trash-btn {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 28%, transparent);
    background: color-mix(in srgb, var(--danger-color) 6%, transparent);
}

.gdrive-package-import-trash-btn:hover {
    color: var(--on-accent);
    border-color: color-mix(in srgb, var(--danger-color) 45%, transparent);
    background: var(--danger-color);
}

.gdrive-package-import-trash-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.gdrive-folder-picker-empty {
    display: grid;
    place-items: center;
    min-height: 180px;
    border: 1px dashed color-mix(in srgb, var(--accent-gradient-start) 24%, transparent);
    border-radius: 14px;
    background: color-mix(in srgb, var(--accent-gradient-start) 3%, transparent);
    color: var(--text-muted);
    font-size: 0.9rem;
}

.gdrive-folder-picker-loading .gdrive-folder-picker-row,
.gdrive-folder-picker-loading .gdrive-folder-picker-crumb {
    pointer-events: none;
}

@media (max-width: 860px) {
    .gdrive-folder-import-dialog {
        width: min(98vw, 1040px);
        max-height: min(94vh, calc(100dvh - 12px));
        padding: 14px;
        gap: 12px;
    }

    .gdrive-folder-import-config-row,
    .gdrive-folder-import-panels {
        grid-template-columns: 1fr;
    }

    .gdrive-folder-import-track {
        width: 100%;
    }

    .gdrive-folder-import-source-row {
        grid-template-columns: 1fr;
    }

    .gdrive-folder-import-body {
        padding-right: 2px;
    }

    .gdrive-folder-import-actions {
        display: grid;
        grid-template-columns: 1fr;
    }

    .gdrive-folder-import-actions .glass-btn {
        width: 100%;
    }

    .gdrive-folder-export-dialog {
        width: min(98vw, 820px);
        max-height: min(92vh, calc(100dvh - 12px));
        padding: 12px;
    }

    .gdrive-folder-export-dialog .gdrive-folder-import-summary,
    .gdrive-folder-export-dialog .gdrive-folder-import-warnings {
        min-height: 100px;
        max-height: min(20vh, 180px);
    }

    .gdrive-folder-picker-nav {
        flex-wrap: wrap;
    }

    .gdrive-folder-picker-row {
        grid-template-columns: auto minmax(0, 1fr);
    }

    .gdrive-folder-picker-row-action {
        display: none;
    }

    .gdrive-package-import-file-list .gdrive-folder-picker-row {
        grid-template-columns: auto minmax(0, 1fr) auto;
    }

    .gdrive-package-import-file-list .gdrive-folder-picker-row-action {
        display: inline-flex;
    }

    .gdrive-package-import-file-list .gdrive-package-import-row-select-label {
        display: none;
    }
}

.gdrive-wait-dialog {
    text-align: center;
}

.gdrive-wait-message {
    margin: 0;
    color: var(--text-main);
    font-size: 0.98rem;
}

/* Running stopwatch for long Google Drive transfers so the duration is visible. */

.gdrive-wait-elapsed {
    margin: 0;
    color: var(--text-main);
    opacity: 0.7;
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
}

/* Determinate/indeterminate progress for long Google Drive transfers (e.g. DB restore). */

.gdrive-wait-progress {
    width: min(420px, 80vw);
    gap: 6px;
}

.gdrive-wait-progress-track {
    position: relative;
    height: 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--primary-color) 14%, var(--bg-pane));
    border: 1px solid color-mix(in srgb, var(--primary-color) 24%, var(--border-color));
    overflow: hidden;
}

.gdrive-wait-progress-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0%;
    border-radius: 999px;
    background: var(--primary-color);
    transition: width 0.15s ease;
}

.gdrive-wait-progress.is-indeterminate .gdrive-wait-progress-fill {
    width: 35%;
    transition: none;
    animation: gdriveWaitIndeterminate 1.1s ease-in-out infinite;
}

@keyframes gdriveWaitIndeterminate {
    0% { left: -35%; }
    100% { left: 100%; }
}

.gdrive-wait-progress-detail {
    color: var(--text-main);
    opacity: 0.82;
    font-size: 0.82rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.gdrive-wait-stream {
    width: min(420px, 80vw);
    min-height: 120px;
    max-height: 160px;
    overflow: hidden;
    border-radius: 10px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 28%, var(--border-color));
    background:
        linear-gradient(180deg, rgba(13, 24, 18, 0.86), rgba(7, 16, 11, 0.92)), /* literal-ok: transfer log is a fixed terminal treatment */
        repeating-linear-gradient(
            180deg,
            rgba(80, 255, 150, 0.08), /* literal-ok: transfer log is a fixed terminal treatment */
            rgba(80, 255, 150, 0.08) 1px, /* literal-ok: transfer log is a fixed terminal treatment */
            transparent 1px,
            transparent 3px
        );
    color: #7cffb6; /* literal-ok: transfer log is a fixed terminal treatment */
    font-family: Consolas, Menlo, Monaco, monospace;
    font-size: 0.76rem;
    line-height: 1.32;
    letter-spacing: 0.01em;
    white-space: pre;
    padding: 8px 10px;
    box-shadow: inset 0 0 0 1px rgba(124, 255, 182, 0.08); /* literal-ok: transfer log is a fixed terminal treatment */
    text-shadow: 0 0 6px rgba(124, 255, 182, 0.25); /* literal-ok: transfer log is a fixed terminal treatment */
}

.gdrive-wait-robot-track {
    position: relative;
    width: min(320px, 72vw);
    height: 68px;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--primary-color) 25%, var(--border-color));
    background: color-mix(in srgb, var(--bg-pane) 93%, var(--bg-pane) 7%);
    overflow: hidden;
}

.gdrive-wait-motion-lines {
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(
        90deg,
        transparent,
        transparent 12px,
        color-mix(in srgb, var(--text-muted) 36%, transparent) 12px,
        color-mix(in srgb, var(--text-muted) 36%, transparent) 16px
    );
    animation: gdriveTrackShift 520ms linear infinite;
    opacity: 0.55;
}

/* literal-ok-block: the Drive mascot is a fixed character treatment (see the note above) */
/* --- Bender-style mascot (Futurama homage). A fixed character treatment, so the metallic
   greys + visor/eye colours below are intentional literal values, not theme tokens (per the
   documented "fixed brand/character treatment" exception). Built from absolutely-positioned
   spans: antenna, domed head (visor band + two eyes + grille mouth), cylinder body with a
   chest panel, and two swinging legs. The robot walks in place while the floor scrolls. --- */

.gdrive-wait-robot {
    position: absolute;
    left: 38%;
    top: 16px;
    width: 44px;
    height: 48px;
    animation: gdriveRobotBob 360ms ease-in-out infinite;
}

.gdrive-r-head,
.gdrive-r-body,
.gdrive-r-leg,
.gdrive-r-eye,
.gdrive-r-mouth,
.gdrive-r-antenna {
    position: absolute;
    display: block;
}

.gdrive-r-antenna {
    left: calc(50% - 1.5px);
    top: -7px;
    width: 3px;
    height: 9px;
    border-radius: 2px;
    background: linear-gradient(#c7ced7, #8b929c);
}

.gdrive-r-antenna::after {                      /* antenna ball */
    content: "";
    position: absolute;
    left: 50%;
    top: -5px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    transform: translateX(-50%);
    background: radial-gradient(circle at 35% 30%, #f1f5fa, #aab1bb 70%);
    box-shadow: 0 0 6px color-mix(in srgb, var(--primary-color) 60%, transparent);
}

/* The head holds two stacked faces — a front face and a real side-profile face. Every so often the
   front face snaps shut (squash to a sliver) and the profile opens — one clean turn, then one back.
   No gradual rotation through in-between angles. */

.gdrive-r-head {
    left: 9px;
    top: 2px;
    width: 26px;
    height: 19px;
}

/* Shared domed face plate (front + side both use it as the head shell). The two are stacked and
   swapped by an INSTANT opacity cut (step-end) — no rotation, squash, or fade. */

.gdrive-r-face {
    position: absolute;
    inset: 0;
    border-radius: 12px 12px 6px 6px;           /* domed top, like Bender's head */
    background: linear-gradient(160deg, #e6ebf1 4%, #bcc3cd 52%, #969da7 100%);
    border: 1px solid #7d8590;
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--mix-light) 55%, transparent), inset 0 -2px 3px color-mix(in srgb, var(--mix-dark) 18%, transparent);
}

.gdrive-r-face-front {
    animation: gdriveFaceFront 13s step-end infinite;
}

.gdrive-r-face-side {
    opacity: 0;                                  /* hidden until the instant switch */
    border-radius: 11px 10px 7px 6px;           /* rounder back-of-head, flatter face front */
    animation: gdriveFaceSide 13s step-end infinite;
}

/* --- Front face: full visor band with two eyes + grille --- */

.gdrive-r-face-front::before {                  /* dark visor band carrying the eyes */
    content: "";
    position: absolute;
    left: 3px;
    right: 3px;
    top: 6px;
    height: 8px;
    border-radius: 4px;
    background: linear-gradient(#3a4150, #232936);
    box-shadow: inset 0 1px 2px color-mix(in srgb, var(--mix-dark) 50%, transparent);
}

/* --- Side face: profile, looking forward (right). Visor + features sit toward the front edge,
   the back of the head is smooth dome. --- */

.gdrive-r-face-side::before {                   /* visor wrapping toward the front of the face */
    content: "";
    position: absolute;
    left: 8px;
    right: 2px;
    top: 6px;
    height: 8px;
    border-radius: 3px 4px 4px 3px;
    background: linear-gradient(#3a4150, #232936);
    box-shadow: inset 0 1px 2px color-mix(in srgb, var(--mix-dark) 50%, transparent);
}

.gdrive-r-face-side::after {                    /* brow/face-plate edge defining the front of the face */
    content: "";
    position: absolute;
    right: 1.5px;
    top: 4px;
    bottom: 4px;
    width: 1.5px;
    border-radius: 1px;
    background: linear-gradient(#c9d0d9, #8b929c);
}

.gdrive-r-eye {
    top: 7px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: radial-gradient(circle at 40% 35%, var(--bg-pane) 38%, #cfd6df 62%, #aeb6c0 100%);
    box-shadow: 0 0 4px color-mix(in srgb, var(--primary-color) 50%, transparent);
    z-index: 2;
    transform-origin: center;
    animation: gdriveBenderBlink 3.4s ease-in-out infinite;
}

.gdrive-r-eye::after {                           /* pupil */
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 2.4px;
    height: 2.4px;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: #1b2330;
}

.gdrive-r-eye-left { left: 6px; }

.gdrive-r-eye-right { right: 6px; }

.gdrive-r-eye-profile { right: 4.5px; }          /* single eye toward the front of the profile */

.gdrive-r-mouth {                                /* grille / teeth */
    left: 6px;
    right: 6px;
    bottom: 1.5px;
    height: 3px;
    border-radius: 1.5px;
    background: repeating-linear-gradient(90deg, #2b313c, #2b313c 1.5px, #aeb6c0 1.5px, #aeb6c0 3px);
    z-index: 2;
}

.gdrive-r-mouth-profile {                        /* grille sits at the front edge in profile */
    left: auto;
    right: 2.5px;
    width: 7px;
    bottom: 2px;
}

.gdrive-r-body {
    left: 11px;
    top: 21px;
    width: 22px;
    height: 17px;
    border-radius: 6px;
    background: linear-gradient(160deg, #e2e7ed 4%, #b6bdc7 55%, #8f97a1 100%);
    border: 1px solid #7d8590;
    box-shadow: inset 0 1px 0 color-mix(in srgb, var(--mix-light) 50%, transparent), inset 0 -2px 3px color-mix(in srgb, var(--mix-dark) 16%, transparent);
}

.gdrive-r-body::before {                         /* chest panel / door */
    content: "";
    position: absolute;
    left: 5px;
    right: 5px;
    top: 4px;
    bottom: 4px;
    border-radius: 3px;
    border: 1px solid color-mix(in srgb, #6f7782 60%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mix-light) 25%, transparent);
}

.gdrive-r-leg {
    bottom: 4px;
    width: 4px;
    height: 9px;
    border-radius: 2px;
    background: linear-gradient(#aab1bb, #7f868f);
    transform-origin: top center;
}

.gdrive-r-leg::after {                           /* foot (toe points forward = walk direction) */
    content: "";
    position: absolute;
    left: -1px;
    bottom: -3px;
    width: 8px;
    height: 4px;
    border-radius: 2px 3px 3px 2px;
    background: linear-gradient(#9aa1ab, #6f7782);
    border: 1px solid #6c747e;
}

.gdrive-r-leg-left {
    left: 14px;
    animation: gdriveLegLeft 320ms ease-in-out infinite;
}

.gdrive-r-leg-right {
    right: 14px;
    animation: gdriveLegRight 320ms ease-in-out infinite;
}

/* Arms hang from a shoulder ball-joint that bridges onto the body's top corner, so they read as
   attached (not floating). Segmented gradient = Bender's coiled-tube arms. They pivot at the
   shoulder (transform-origin top center). */

.gdrive-r-arm {
    position: absolute;
    top: 23px;
    width: 3.5px;
    height: 12px;
    border-radius: 2px;
    background: repeating-linear-gradient(180deg, #c6cdd6 0, #c6cdd6 1.6px, #8b929c 1.6px, #8b929c 2.6px);
    border: 1px solid #7d8590;
    transform-origin: top center;
}

.gdrive-r-arm::before {                          /* shoulder ball-joint (overlaps the body corner) */
    content: "";
    position: absolute;
    left: 50%;
    top: -3px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    transform: translateX(-50%);
    background: radial-gradient(circle at 38% 32%, #e7ecf1, #969da7 80%);
    border: 1px solid #7d8590;
    z-index: 1;
}

.gdrive-r-arm::after {                           /* hand */
    content: "";
    position: absolute;
    left: 50%;
    bottom: -2px;
    width: 5px;
    height: 5px;
    border-radius: 50% 50% 40% 40%;
    transform: translateX(-50%);
    background: radial-gradient(circle at 40% 35%, #e3e8ee, #9aa1ab 75%);
    border: 1px solid #7d8590;
}

/* Sit the shoulder ball right on each top corner of the body (body spans ~x11–33). */

.gdrive-r-arm-left {
    left: 8px;
    animation: gdriveArmLeft 320ms ease-in-out infinite;
}

.gdrive-r-arm-right {
    right: 8px;
    animation: gdriveArmRight 320ms ease-in-out infinite;
}

@keyframes gdriveTrackShift {
    from { background-position: 0 0; }
    to { background-position: -16px 0; }
}

@keyframes gdriveRobotBob {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-1.5px); }
}

@keyframes gdriveLegLeft {
    0%, 100% { transform: rotate(24deg); }
    50% { transform: rotate(-24deg); }
}

@keyframes gdriveLegRight {
    0%, 100% { transform: rotate(-24deg); }
    50% { transform: rotate(24deg); }
}

/* Arms swing gently from the shoulder, opposite their same-side leg, for a natural gait. */

@keyframes gdriveArmLeft {
    0%, 100% { transform: rotate(-11deg); }
    50% { transform: rotate(11deg); }
}

@keyframes gdriveArmRight {
    0%, 100% { transform: rotate(11deg); }
    50% { transform: rotate(-11deg); }
}

@keyframes gdriveBenderBlink {
    0%, 92%, 100% { transform: scaleY(1); }
    96% { transform: scaleY(0.14); }
}

/* Face front most of the cycle, then turn to a near-profile (looking the way he walks), hold it for
   a few strides, and turn back. perspective() gives the turn some depth. */

/* Instant cut, no in-between frames (step-end): front view, then snap to profile, hold, snap back. */

@keyframes gdriveFaceFront {
    0% { opacity: 1; }                           /* facing forward */
    72% { opacity: 0; }                          /* instantly gone — profile shows */
    92% { opacity: 1; }                          /* instantly back to front */
    100% { opacity: 1; }
}

@keyframes gdriveFaceSide {
    0% { opacity: 0; }                           /* hidden while facing forward */
    72% { opacity: 1; }                          /* instant switch to profile */
    92% { opacity: 0; }                          /* instant switch back to front */
    100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .gdrive-wait-robot,
    .gdrive-r-face-front,
    .gdrive-r-face-side,
    .gdrive-r-leg-left,
    .gdrive-r-leg-right,
    .gdrive-r-arm-left,
    .gdrive-r-arm-right,
    .gdrive-r-eye,
    .gdrive-wait-motion-lines { animation: none; }
}
/* end literal-ok-block */
/* Blogger publish dialog. Split out of 180-dialogs-overlays.css (Phase 10). */

.blogger-publish-dialog {
    border-radius: 16px;
    padding: 18px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.blogger-publish-body {
    display: grid;
    gap: 12px;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

.blogger-publish-workbench-scroller {
    min-width: 0;
}

.blogger-publish-workbench {
    display: grid;
    gap: 12px;
}

.blogger-publish-panel {
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: var(--bg-pane);
    padding: 12px;
    display: grid;
    gap: 10px;
}

.blogger-publish-target-panel {
    gap: 6px;
}

.blogger-publish-meta-label {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.blogger-publish-target-value {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-main);
    word-break: break-word;
}

.blogger-publish-linkage-panel {
    gap: 6px;
}

.blogger-publish-linkage-summary {
    font-size: 0.96rem;
    color: var(--text-main);
}

.blogger-publish-linkage-detail {
    font-size: 0.88rem;
    color: var(--text-muted);
    line-height: 1.45;
    word-break: break-word;
}

.blogger-publish-linkage-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    margin-top: 4px;
}

.blogger-publish-remove-link-btn {
    flex: 0 0 auto;
}

.blogger-publish-linkage-remove-hint {
    flex: 1 1 180px;
    min-width: 0;
    font-size: 0.82rem;
    color: var(--text-muted);
    line-height: 1.35;
}

.blogger-publish-main {
    display: grid;
    grid-template-columns: minmax(0, 1.7fr) minmax(280px, 1fr);
    gap: 12px;
    align-items: start;
}

.blogger-publish-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.blogger-publish-panel-title {
    font-size: 1rem;
}

.blogger-publish-panel-meta {
    font-size: 0.82rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.blogger-publish-panel-hint {
    font-size: 0.84rem;
    color: var(--text-muted);
    line-height: 1.4;
}

.blogger-publish-blog-list {
    display: grid;
    gap: 8px;
    max-height: 320px;
    overflow-y: auto;
    padding-right: 2px;
}

.blogger-publish-blog-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: 10px;
    align-items: start;
    padding: 10px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-app);
    cursor: pointer;
    transition: border-color var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

.blogger-publish-blog-row:hover {
    border-color: color-mix(in srgb, var(--primary-color) 28%, var(--border-color));
    box-shadow: var(--shadow-sm);
    transform: translateY(-1px);
}

.blogger-publish-blog-row.is-selected {
    border-color: var(--primary-color);
    background: color-mix(in srgb, var(--primary-color) 8%, var(--bg-pane));
}

.blogger-publish-blog-row.is-linked {
    border-color: color-mix(in srgb, var(--primary-color) 18%, var(--border-color));
}

.blogger-publish-blog-checkbox-wrap {
    display: flex;
    align-items: center;
    min-height: 100%;
    padding-top: 2px;
}

.blogger-publish-blog-checkbox {
    width: 16px;
    height: 16px;
}

.blogger-publish-blog-content {
    display: grid;
    gap: 4px;
    min-width: 0;
}

.blogger-publish-blog-name-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.blogger-publish-blog-name {
    font-size: 0.96rem;
    color: var(--text-main);
}

.blogger-publish-blog-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--primary-color) 12%, var(--bg-pane));
    color: var(--primary-color);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.blogger-publish-blog-url,
.blogger-publish-blog-description {
    font-size: 0.84rem;
    color: var(--text-muted);
    word-break: break-word;
}

.blogger-publish-blog-action-hint {
    font-size: 0.8rem;
    color: var(--primary-color);
}

.blogger-publish-blog-open {
    align-self: center;
    width: 32px;
    height: 32px;
    padding: 0;
    color: var(--text-muted);
}

.blogger-publish-blog-open:hover:not(:disabled) {
    color: var(--primary-color);
}

.blogger-publish-blog-open svg {
    width: 16px;
    height: 16px;
}

.blogger-publish-blog-open:disabled svg {
    opacity: 0.45;
}

.blogger-publish-empty-state {
    font-size: 0.9rem;
    color: var(--text-muted);
    padding: 8px 0;
}

.blogger-publish-retention-grid {
    display: grid;
    gap: 10px;
}

.blogger-publish-retention-field {
    display: grid;
    gap: 6px;
}

.blogger-publish-retention-state {
    font-size: 0.88rem;
    color: var(--text-muted);
    line-height: 1.45;
}

.blogger-publish-warning-panel {
    gap: 8px;
}

.blogger-publish-status {
    min-height: 20px;
    font-size: 0.9rem;
    color: var(--text-main);
}

.blogger-publish-status.is-error {
    color: var(--danger-color);
}

.blogger-publish-status.is-ok {
    color: var(--primary-color);
}

.blogger-publish-warning-list {
    display: grid;
    gap: 6px;
    max-height: 160px;
    overflow-y: auto;
    color: var(--text-muted);
    font-size: 0.88rem;
    line-height: 1.45;
}

.blogger-publish-actions {
    justify-content: space-between;
    gap: 10px;
    align-items: center;
}

.blogger-publish-actions-left,
.blogger-publish-actions-right {
    display: inline-flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
}

.blogger-publish-connection-group {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.blogger-publish-google-btn {
    width: 38px;
    height: 38px;
    border-radius: 10px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 1rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}

.blogger-publish-google-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-sm);
}

.blogger-publish-google-btn.is-connected {
    color: var(--on-accent);
    border-color: var(--success-color);
    background: linear-gradient(135deg, color-mix(in srgb, var(--success-color) 80%, var(--mix-light)), var(--success-color));
    box-shadow: 0 8px 18px color-mix(in srgb, var(--success-color) 28%, transparent);
}

.blogger-publish-google-btn.is-busy {
    color: var(--on-accent);
    border-color: var(--primary-color);
    background: linear-gradient(135deg, color-mix(in srgb, var(--primary-color) 70%, var(--mix-light)), var(--primary-color));
    box-shadow: 0 8px 18px color-mix(in srgb, var(--primary-color) 24%, transparent);
}

.blogger-publish-google-btn.is-disconnected {
    color: var(--text-main);
    border-color: var(--border-color);
    background: var(--bg-pane);
}
    .blogger-publish-google-btn.is-busy {
    animation: spin 0.95s linear infinite;
}

.blogger-publish-connection-text {
    min-width: 98px;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.blogger-publish-mode-cluster {
    display: grid;
    gap: 6px;
    justify-items: end;
}

.blogger-publish-mode-group {
    display: inline-grid;
    gap: 4px;
}

.blogger-publish-mode-option {
    display: inline-flex;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    font-size: 0.9rem;
    color: var(--text-main);
}

.blogger-publish-selection-hint {
    min-height: 18px;
    font-size: 0.82rem;
    color: var(--text-muted);
}

.blogger-publish-primary-action {
    min-width: 130px;
}

.blogger-publish-primary-action:disabled,
.blogger-publish-primary-action.is-disabled,
.blogger-publish-primary-action:disabled:hover,
.blogger-publish-primary-action.is-disabled:hover {
    cursor: not-allowed;
    opacity: 0.58;
    color: color-mix(in srgb, var(--mix-light) 86%, transparent);
    background: linear-gradient(135deg, color-mix(in srgb, var(--text-muted) 92%, transparent), color-mix(in srgb, var(--text-muted) 75%, var(--mix-dark)));
    box-shadow: none;
    transform: none;
    filter: saturate(0.7);
}

@media (max-width: 760px) {
    .blogger-publish-workbench-scroller {
        overflow: visible;
        padding-bottom: 0;
    }

    .blogger-publish-workbench {
        min-width: 0;
    }

    .blogger-publish-main {
        grid-template-columns: 1fr;
    }

    .blogger-publish-blog-list {
        max-height: min(34vh, 280px);
    }

    .blogger-publish-actions {
        flex-direction: column;
        align-items: stretch;
    }

    .blogger-publish-actions-left,
    .blogger-publish-actions-right {
        width: 100%;
        justify-content: flex-start;
    }

    .blogger-publish-actions-right {
        display: grid;
        gap: 8px;
    }

    .blogger-publish-controls {
        width: 100%;
        justify-items: start;
    }

    .blogger-publish-mode-cluster {
        justify-items: start;
    }

    .blogger-publish-primary-action {
        min-width: 0;
        width: 100%;
    }

    .blogger-publish-actions-right > .glass-btn {
        width: 100%;
    }
}
/* Data Manager dialog: database list, native / local tabs, Drive backup maintenance, in-use states,
   large-DB loading overlay. Split out of 180-dialogs-overlays.css (Phase 10). */

/* --- DATA MANAGER MODAL --- */

#data-manager-modal.modal-overlay.glass-overlay {
    z-index: 4900;
}

#data-manager-modal .data-manager-glass-dialog {
    position: relative;
    width: min(94vw, 760px);
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 92%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 18px;
    gap: 12px;
}

.data-manager-close-corner {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 2;
}

.data-manager-body {
    position: relative;
    display: grid;
    /* Single column pinned to the container width (floor 0) so a long native-DB folder path in the panel head
       ellipsizes instead of auto-growing the column and pushing the head-action buttons outside the dialog. */
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
}

.data-manager-toolbar {
    display: grid;
    grid-template-columns: auto auto minmax(180px, 1fr);
    gap: 8px;
    align-items: center;
}

/* --- Data Manager: Native / Local tabs (H4) --- */

/* The shared .app-tabs uses justify-content:space-between (built for full-width tab sets); constrain the
   track to its content so two tabs read as a compact segmented control instead of spreading to the edges. */

.data-manager-tabs {
    width: fit-content;
    max-width: 100%;
    justify-content: flex-start;
    margin-bottom: 12px;
}

.data-manager-panel {
    min-width: 0; /* let the panel shrink to its grid track so the head/list ellipsize rather than overflow */
}

.data-manager-panel[hidden] {
    display: none;
}

.data-manager-native-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.data-manager-native-folder {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.8rem;
    color: var(--text-muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.data-manager-native-head-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

.data-manager-local-warning {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-bottom: 12px;
    padding: 10px 12px;
    border: 1px solid var(--warning-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--warning-color) 12%, transparent);
    color: var(--text-main);
    font-size: 0.84rem;
    line-height: 1.35;
}

.data-manager-local-warning svg {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    color: var(--warning-color);
    margin-top: 1px;
}

.data-manager-list {
    min-height: 280px;
    max-height: min(56vh, 460px);
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--bg-pane) 65%, transparent);
    padding: 10px;
}

.data-manager-row {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid transparent;
}

.data-manager-row + .data-manager-row {
    margin-top: 6px;
}

.data-manager-row:hover {
    background: var(--item-hover);
    border-color: var(--border-color);
}

.data-manager-row:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--primary-color) 75%, var(--bg-pane) 25%);
    outline-offset: 1px;
}

.data-manager-row-main {
    min-width: 0;
}

.data-manager-row-title {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.data-manager-row-meta {
    margin-top: 2px;
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.data-manager-row-status {
    margin-top: 4px;
    font-size: 0.78rem;
    color: var(--primary-color);
    font-weight: 600;
}

.data-manager-row-active {
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--bg-pane) 65%);
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane) 90%);
}

/* A database open in ANOTHER tab: informational (muted amber), distinct from the primary "active here"
   accent above. Both --warning-color variants are theme-defined, so this reads correctly in light + dark. */

.data-manager-row-active-elsewhere {
    border-color: color-mix(in srgb, var(--warning-color) 30%, var(--bg-pane) 70%);
    background: color-mix(in srgb, var(--warning-color) 7%, var(--bg-pane) 93%);
}

.data-manager-row-status-elsewhere {
    color: var(--warning-color);
}

.data-manager-row-actions {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.data-manager-row-actions .icon-btn-small {
    width: 28px;
    height: 28px;
    padding: 4px;
}

.data-manager-row-actions .icon-btn-small svg {
    width: 16px;
    height: 16px;
}

/* The launch (play) control for the active database: shown but non-actionable, tinted to read as
   "this is the current database" rather than a dimmed/unavailable button. */

.data-manager-row-actions .icon-btn-small[data-action="switch"].is-active {
    color: var(--success-color);
    opacity: 1;
    cursor: default;
}

.data-manager-row-actions button[data-action="more"] {
    display: none;
}

@media (hover: hover) and (pointer: fine) {
    .data-manager-row-actions button[data-action="details"] {
        display: none;
    }
}

@media (max-width: 1100px) {
    .data-manager-row {
        grid-template-columns: 1fr;
        align-items: start;
    }

    .data-manager-row-actions {
        margin-top: 6px;
        justify-content: flex-start;
        flex-wrap: wrap;
    }
}

.data-manager-empty {
    color: var(--text-muted);
    font-size: 0.9rem;
    padding: 8px;
}

.data-manager-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

.data-manager-actions .data-manager-actions-splitter {
    margin-right: auto;
}

.data-manager-gdrive-toggle {
    border-color: color-mix(in srgb, var(--danger-color) 86%, transparent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--danger-color) 48%, transparent), 0 0 9px color-mix(in srgb, var(--danger-color) 68%, transparent), inset 0 0 6px color-mix(in srgb, var(--danger-color) 24%, transparent);
}

.data-manager-gdrive-toggle .data-manager-gdrive-glyph {
    font-size: 0.92rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: var(--success-color);
    line-height: 1;
}

.data-manager-gdrive-toggle.is-connected {
    border-color: color-mix(in srgb, var(--success-color) 88%, transparent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--success-color) 50%, transparent), 0 0 10px color-mix(in srgb, var(--success-color) 78%, transparent), inset 0 0 7px color-mix(in srgb, var(--success-color) 28%, transparent);
}

.data-manager-gdrive-toggle.is-connected:hover {
    border-color: color-mix(in srgb, var(--success-color) 90%, transparent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--success-color) 56%, transparent), 0 0 12px color-mix(in srgb, var(--success-color) 84%, transparent), inset 0 0 9px color-mix(in srgb, var(--success-color) 34%, transparent);
}

.data-manager-gdrive-toggle.is-disconnected,
.data-manager-gdrive-toggle.is-disconnected:hover {
    border-color: color-mix(in srgb, var(--danger-color) 90%, transparent);
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--danger-color) 52%, transparent), 0 0 11px color-mix(in srgb, var(--danger-color) 82%, transparent), inset 0 0 7px color-mix(in srgb, var(--danger-color) 32%, transparent);
}

.data-manager-gdrive-toggle.is-offline,
.data-manager-gdrive-maintenance.is-offline {
    opacity: 0.55;
    filter: grayscale(0.2);
    cursor: not-allowed;
}

.data-manager-gdrive-maintenance span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.data-manager-gdrive-maintenance svg {
    width: 16px;
    height: 16px;
}

.data-manager-tooltip {
    position: absolute;
    max-width: min(360px, 86vw);
    background: var(--tooltip-bg);
    color: var(--tooltip-fg);
    border: 1px solid color-mix(in srgb, var(--mix-light) 22%, transparent);
    border-radius: 10px;
    box-shadow: 0 10px 24px color-mix(in srgb, var(--mix-dark) 32%, transparent);
    padding: 10px 12px;
    font-size: 0.82rem;
    line-height: 1.45;
    z-index: 5200;
    pointer-events: none;
}

.data-manager-tooltip-title {
    font-weight: 700;
    margin-bottom: 4px;
}

.data-manager-tooltip-line {
    opacity: 0.92;
}

.gdrive-maint-body {
    display: grid;
    gap: 12px;
}

.gdrive-maint-retention-wrap {
    display: grid;
    gap: 8px;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 10px;
}

.gdrive-maint-retention-control {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.gdrive-maint-keep-input {
    width: 84px;
    text-align: center;
    font-weight: 700;
}

.gdrive-maint-retention-control .icon-btn-small {
    width: 32px;
    min-width: 32px;
    height: 32px;
    font-size: 1rem;
    font-weight: 700;
}

.gdrive-maint-retention-state {
    font-size: 0.82rem;
    opacity: 0.88;
}

.gdrive-maint-list-wrap {
    display: grid;
    gap: 8px;
}

.gdrive-maint-list-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.gdrive-maint-grid {
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--bg-pane) 45%, transparent);
    padding: 6px;
    max-height: 296px;
    overflow-y: auto;
    display: grid;
    gap: 6px;
}

.gdrive-maint-row {
    display: grid;
    grid-template-columns: 1fr auto auto;
    align-items: center;
    gap: 6px;
    min-height: 52px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: color-mix(in srgb, var(--bg-pane) 72%, transparent);
}

.gdrive-maint-row.is-selected {
    border-color: color-mix(in srgb, var(--primary-color) 50%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--primary-color) 20%, transparent);
}

.gdrive-maint-row-main {
    border: 0;
    background: transparent;
    text-align: left;
    padding: 8px 10px;
    display: grid;
    gap: 2px;
    min-width: 0;
    cursor: pointer;
}

.gdrive-maint-name {
    color: var(--text-main);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gdrive-maint-meta {
    font-size: 0.78rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gdrive-maint-delete-btn svg {
    width: 14px;
    height: 14px;
}

.gdrive-maint-info-btn {
    display: none;
    font-weight: 700;
}

.gdrive-maint-grid-help {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.gdrive-maint-empty {
    color: var(--text-muted);
    font-size: 0.9rem;
    padding: 10px;
    text-align: center;
}

@media (max-width: 768px) {
    #data-manager-modal .data-manager-glass-dialog {
        width: min(96vw, 760px);
        max-height: 92vh;
    }

    .data-manager-toolbar {
        grid-template-columns: auto auto minmax(0, 1fr);
    }

    .data-manager-list {
        min-height: 220px;
        max-height: 50vh;
    }

    .data-manager-row {
        grid-template-columns: 1fr auto;
        padding: 11px 10px;
    }

    .data-manager-row-main {
        min-width: 0;
    }

    .data-manager-row-meta {
        display: none;
    }

    .data-manager-row-actions button[data-action="switch"],
    .data-manager-row-actions button[data-action="details"],
    .data-manager-row-actions button[data-action="rename"],
    .data-manager-row-actions button[data-action="delete"],
    .data-manager-row-actions button[data-action="download"],
    .data-manager-row-actions button[data-action="import"] {
        display: none;
    }

    .data-manager-row-actions button[data-action="more"] {
        display: inline-flex;
    }

    .data-manager-row-actions {
        gap: 0;
    }

    .data-manager-tooltip {
        display: none !important;
    }

    .gdrive-maint-list-header {
        flex-wrap: wrap;
    }

    .gdrive-maint-grid {
        max-height: 296px;
    }

    .gdrive-maint-row {
        grid-template-columns: 1fr auto auto;
    }

    .gdrive-maint-info-btn {
        display: inline-flex;
    }

    .gdrive-maint-grid-help {
        display: none;
    }
}

@media (hover: none) and (pointer: coarse), (any-pointer: coarse) {
    .data-manager-row-actions .icon-btn-small {
        width: 36px;
        height: 36px;
        padding: 6px;
    }

    .data-manager-row-actions .icon-btn-small svg {
        width: 18px;
        height: 18px;
    }

    .gdrive-maint-info-btn {
        display: inline-flex;
    }

    .gdrive-maint-grid-help {
        display: none;
    }
}

.data-manager-mobile-sheet-overlay {
    z-index: 5205;
    align-items: flex-end;
}

.data-manager-mobile-sheet {
    width: min(100vw, 520px);
    border-top-left-radius: 18px;
    border-top-right-radius: 18px;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-bottom: none;
    box-shadow: 0 -14px 36px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 12px;
    display: grid;
    gap: 10px;
    outline: none;
}

.data-manager-mobile-sheet-title {
    font-size: 0.98rem;
    font-weight: 700;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.data-manager-mobile-sheet-actions {
    display: grid;
    gap: 6px;
}

.data-manager-mobile-sheet-btn {
    width: 100%;
    min-height: 42px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.95rem;
    font-weight: 600;
    text-align: left;
    padding: 10px 12px;
}

.data-manager-mobile-sheet-btn:disabled {
    opacity: 0.55;
}

.data-manager-mobile-sheet-btn.danger {
    color: var(--danger-color);
}

.data-manager-mobile-sheet-footer {
    display: flex;
    justify-content: flex-end;
}

/* --- LARGE DB LOADING OVERLAY --- */

#db-loading-overlay .db-loading-glass-dialog {
    width: min(86vw, 420px);
    text-align: center;
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 94%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: 22px;
    display: grid;
    gap: 10px;
    justify-items: center;
}

.db-loading-spinner {
    width: 28px;
    height: 28px;
    border: 3px solid color-mix(in srgb, var(--accent-gradient-start) 25%, transparent);
    border-top-color: var(--accent-gradient-start);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

.db-loading-progress-track {
    width: min(320px, 72vw);
    height: 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-muted) 18%, transparent);
    border: 1px solid color-mix(in srgb, var(--text-muted) 24%, transparent);
    overflow: hidden;
}

.db-loading-progress-bar {
    width: 0%;
    height: 100%;
    border-radius: 999px;
    background: var(--accent-gradient-h);
    transition: width 0.18s ease;
}

.db-loading-progress-percent {
    font-size: 0.88rem;
    font-weight: 600;
    color: var(--text-main);
    letter-spacing: 0.01em;
}

.db-loading-time-grid {
    display: grid;
    gap: 4px;
    font-size: 0.82rem;
    color: var(--text-muted);
}
/* Export dialogs: Export Note (grouped options, EPUB metadata and cover), Export Folder, subfolder
   depth row. Split out of 180-dialogs-overlays.css (Phase 10). */

/* --- SUBFOLDER DEPTH ROW (Include Subfolders + levels spinner) ---
   Rendered in the enhanced export dialog's folder mode (NoteExportDialogFlow) — both the
   folder HTML and folder Text formats share it. */

.subfolder-depth-row {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--border-color);
}

.subfolder-depth-opt {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.9rem;
    color: var(--text-editor);
    cursor: pointer;
}

.subfolder-depth-levels-label {
    color: var(--text-editor-muted);
}

.subfolder-depth-levels {
    width: 58px;
    padding: 4px 6px;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--bg-app);
    color: var(--text-editor);
    font: inherit;
    font-size: 0.9rem;
}

.subfolder-depth-levels:disabled,
.subfolder-depth-row input[type="checkbox"]:disabled {
    opacity: 0.45;
    cursor: default;
}

/* ===== Export Note dialog — readable, grouped layout ===================================
   Choices render as full-width selectable row-cards (radio + label) instead of inline radios
   that wrap into an unreadable run-on line. Section headers give clear grouping/hierarchy. */

.note-export-dialog {
    width: min(460px, 94vw);
}

.note-export-dialog-body {
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* Top-level groups are separated by a light divider; the first (Export Type) has none. */

.note-export-dialog-body > .note-export-dialog-section {
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--border-color);
}

.note-export-dialog-body > .note-export-dialog-section:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
}

.note-export-dialog-section-title {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    margin: 0 0 var(--space-2);
}

/* Secondary titles inside a group (e.g. "Media Packaging", "Resolution") get spacing above. */

.note-export-dialog-section .note-export-dialog-section-title:not(:first-child) {
    margin-top: var(--space-3);
}

.note-export-dialog-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0;
}

/* Each option is a selectable card row. */

.note-export-dialog-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.92rem;
    line-height: 1.3;
    cursor: pointer;
    transition: border-color var(--anim-fast) var(--anim-ease),
        background var(--anim-fast) var(--anim-ease),
        box-shadow var(--anim-fast) var(--anim-ease);
}

.note-export-dialog-option:hover {
    background: var(--item-hover);
    border-color: color-mix(in srgb, var(--primary-color) 32%, var(--border-color));
}

/* Selected: accent ring + tint. :has() is fine in this Chromium-targeted PWA. */

.note-export-dialog-option:has(input:checked) {
    border-color: var(--primary-color);
    background: var(--selection-color);
    box-shadow: inset 0 0 0 1px var(--primary-color);
}

.note-export-dialog-option input[type="radio"],
.note-export-dialog-option input[type="checkbox"] {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--primary-color);
    cursor: pointer;
}

.note-export-dialog-option.is-disabled,
.note-export-dialog-option[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    background: var(--bg-pane);
}

.note-export-dialog-option.is-disabled:hover,
.note-export-dialog-option[aria-disabled="true"]:hover {
    border-color: var(--border-color);
    background: var(--bg-pane);
}

/* Helper captions under a group. */

.note-export-dialog-subhint,
.note-export-dialog-hint,
.note-export-dialog-inline-hint,
.note-export-dialog-media-summary {
    font-size: 0.8rem;
    color: var(--text-muted);
    line-height: 1.45;
    margin-top: var(--space-2);
}

.note-export-dialog-warning {
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--warning-color);
    background: color-mix(in srgb, var(--warning-color) 12%, var(--bg-pane));
    border: 1px solid color-mix(in srgb, var(--warning-color) 35%, var(--border-color));
    border-radius: var(--radius-sm);
    padding: 8px 10px;
    margin-top: var(--space-2);
}

/* Two-step flow: "Back" returns from a type's options to the type picker; sits at the far left. */

.note-export-dialog-back {
    margin-right: auto;
}

/* Single-note export: "Open in new tab" preview toggle, sits below the HTML variant choice. */

.note-export-dialog-newtab {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0 4px;
    cursor: pointer;
}

.note-export-dialog-newtab.is-disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* EPUB export metadata fields (title / author / language). */

.note-export-dialog-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 8px 0;
}

.note-export-dialog-field-label {
    font-size: 0.85rem;
    color: var(--text-muted);
}

.note-export-dialog-input {
    width: 100%;
    box-sizing: border-box;
    padding: 7px 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: var(--bg-pane);
    color: var(--text-main);
    font: inherit;
}

.note-export-dialog-input:focus {
    outline: none;
    border-color: color-mix(in srgb, var(--primary-color) 45%, var(--border-color));
}

.note-export-dialog-input-short {
    max-width: 140px;
}

.note-export-dialog-textarea {
    resize: vertical;
    min-height: 56px;
    font: inherit;
    line-height: 1.4;
}

/* EPUB cover picker (choose image, or fall back to a generated title page). */

.epub-cover-picker {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.epub-cover-picker .epub-cover-name {
    font-size: 0.85rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 220px;
}

/* ===== Export Folder dialog — single-step format picker ================================
   Consolidates the four folder context-menu export entries into one dialog. Shares the
   note-export-dialog row-card visuals; each format is a card with a title + one-line
   description so the choice is self-explanatory. */

.folder-export-dialog {
    width: min(460px, 94vw);
}

.folder-export-dialog-intro {
    margin: 0 0 var(--space-3);
}

/* Title + description stack, so align the radio to the top of the card rather than centered. */

.folder-export-dialog-option {
    align-items: flex-start;
}

.folder-export-dialog-option input[type="radio"] {
    margin-top: 2px;
}

.folder-export-dialog-option-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.folder-export-dialog-option-title {
    font-weight: 600;
}

.folder-export-dialog-option-desc {
    font-size: 0.8rem;
    color: var(--text-muted);
    line-height: 1.4;
}
/* ==========================================================================
   Unified Import Filter dialog (Import Files… + Import File Links…)
   Owner: utils/ImportFilterDialog.js
   Reuses the shared .modal-box / .glass-* dialog chrome from 180-dialogs-overlays.
   All values via semantic tokens.
   ========================================================================== */

.import-filter-dialog {
    width: min(560px, 94vw);
}

.import-filter-body {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Folder picker row ------------------------------------------------------- */
.import-filter-source-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.import-filter-pick {
    flex: 0 0 auto;
    min-width: 44px;
    font-weight: 600;
}

.import-filter-source-path {
    flex: 1 1 auto;
    min-width: 0;
}

/* Restored folder whose permission lapsed — clickable to reload. */
.import-filter-source-path.import-filter-source-reload {
    cursor: pointer;
    border-color: var(--primary-color);
}

.import-filter-recurse-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Mode selector ----------------------------------------------------------- */
.import-filter-mode-group {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.import-filter-mode-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    color: var(--text-main);
}

.import-filter-mode-block {
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 12px 14px;
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-app));
}

/* Footer actions: Edit File Types (icon) anchored to the left margin, Close + View on the right. */
.import-filter-actions {
    justify-content: space-between;
    align-items: center;
}

.import-filter-edit-presets.icon-btn-small {
    flex: 0 0 auto;
}

.import-filter-actions-buttons {
    display: flex;
    gap: 8px;
}

/* Category grid (dynamic from the catalog) -------------------------------- */
.import-filter-category-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px 18px;
    margin-top: 10px;
    padding-left: 24px;
}

.import-filter-category {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-main);
}

/* Disabled (inactive mode) sections read as muted ------------------------- */
.import-filter-mode-block:not(.is-active) .import-filter-category-grid,
.import-filter-mode-block:not(.is-active) .import-filter-custom-row {
    opacity: 0.5;
}

.import-filter-empty,
.import-filter-history-empty {
    color: var(--text-muted);
    font-size: 0.88rem;
}

/* Custom mode ------------------------------------------------------------- */
.import-filter-custom-row {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    margin-top: 10px;
    padding-left: 24px;
}

.import-filter-custom-field {
    flex: 1 1 auto;
    min-width: 0;
}

/* History popover --------------------------------------------------------- */
.import-filter-history {
    position: relative;
    flex: 0 0 auto;
}

.import-filter-history-menu {
    position: absolute;
    right: 0;
    bottom: calc(100% + 6px);
    z-index: 5;
    min-width: 200px;
    max-width: 320px;
    max-height: 240px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    padding: 6px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    box-shadow: var(--shadow-md);
}

.import-filter-history-item {
    text-align: left;
    padding: 7px 9px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-main);
    font: inherit;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.import-filter-history-item:hover {
    background: var(--selection-color);
}

/* Content controls (Import Files… only) ----------------------------------- */
.import-filter-content-controls {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.import-filter-content-controls .gdrive-folder-import-field {
    flex: 1 1 140px;
}

/* Status line ------------------------------------------------------------- */
.import-filter-status {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-muted);
    font-size: 0.9rem;
}

/* Scanning spinner — a subtle motion cue while the folder/bridge is traversed. */
.import-filter-spinner {
    display: none;
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    border: 2px solid color-mix(in srgb, var(--border-color) 70%, transparent);
    border-top-color: var(--primary-color);
    border-radius: 50%;
    animation: import-filter-spin 0.7s linear infinite;
}

.import-filter-status.is-scanning .import-filter-spinner {
    display: inline-block;
}

@keyframes import-filter-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .import-filter-spinner { animation-duration: 1.6s; }
}

/* ==========================================================================
   Filtered Files overlay (View → select / trim → Proceed)
   ========================================================================== */
.import-filter-view-dialog {
    width: min(620px, 96vw);
    display: flex;
    flex-direction: column;
}

.import-filter-view-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-height: 0;
}

.import-filter-view-banner {
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--danger-color) 12%, var(--bg-pane));
    color: var(--text-main);
    font-size: 0.88rem;
}

/* Search box to find a file in a long filtered list. */
.import-filter-view-search {
    display: flex;
}

.import-filter-view-search-input {
    width: 100%;
}

.import-filter-view-search-empty {
    padding: 16px 8px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.88rem;
}

.import-filter-view-table-wrap {
    max-height: 48vh;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

.import-filter-view-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

.import-filter-view-table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    text-align: left;
    padding: 9px 12px;
    background: var(--bg-sidebar);
    color: var(--text-main);
    border-bottom: 1px solid var(--border-color);
}

.import-filter-view-table tbody td {
    padding: 7px 12px;
    border-bottom: 1px solid color-mix(in srgb, var(--border-color) 60%, transparent);
    color: var(--text-main);
}

.import-filter-view-path {
    max-width: 0;
    width: 82%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

.import-filter-view-check {
    width: 18%;
    text-align: center;
    white-space: nowrap;
}

/* Subfolder quick-exclude rows at the top of the Filtered Files list (rendered only when
   Include Subfolders is ticked): tick/untick a folder to include/exclude its files. */
.import-filter-view-folder-row td {
    background: color-mix(in srgb, var(--bg-sidebar) 55%, transparent);
}

.import-filter-view-folder-path {
    font-weight: 600;
}

.import-filter-view-folder-icon {
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-right: 7px;
    vertical-align: -2px;
}

.import-filter-view-folder-icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

.import-filter-view-all {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 600;
}

.import-filter-view-empty {
    text-align: center;
    color: var(--text-muted);
    padding: 24px 12px;
}

.import-filter-view-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.import-filter-view-summary {
    color: var(--text-muted);
    font-size: 0.88rem;
}

.import-filter-view-buttons {
    display: flex;
    gap: 8px;
}
/* ============================================================================
   Maintenance App (dev-only DB tooling) — tabbed shell, resizable panel,
   per-action progress feedback. Scoped under #maintenance-app-panel.maint-app.
   Launch: Ctrl+`  (see utils/GlobalShortcutBindings.js)
   Owner: utils/MaintenanceAppRuntime.js
   ========================================================================== */

#maintenance-app-panel.maint-app {
    position: relative;
    width: min(820px, calc(100vw - 32px));
    max-width: calc(100vw - 24px);
    max-height: calc(100vh - 24px);
    min-width: 420px;
    min-height: 320px;
    padding: 0;
    gap: 0;
    box-sizing: border-box;
    overflow: hidden;
}

/* When a stored position is applied, the panel is pulled out of the overlay's
   flex-centering and positioned against the viewport. */
#maintenance-app-panel.maint-app.maint-app--positioned {
    position: fixed;
    margin: 0;
}

.maint-app__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px 12px;
    border-bottom: 1px solid var(--border-color);
    cursor: grab;
    user-select: none;
    touch-action: none;
}
.maint-app__header.maint-app__header--dragging { cursor: grabbing; }
.maint-app__header-titles { display: grid; gap: 4px; }

/* --- Persistent DB status strip --------------------------------------- */
.maint-app__strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 16px;
    padding: 10px 20px;
    background: var(--bg-pane);
    border-bottom: 1px solid var(--border-color);
    font-size: 0.86rem;
}
.maint-app__stat { display: inline-flex; align-items: baseline; gap: 6px; }
.maint-app__stat-label { color: var(--text-muted); }
.maint-app__stat-value { font-weight: 600; color: var(--text-main); }
.maint-app__strip-refresh { margin-left: auto; }

/* --- Tab strip -------------------------------------------------------- */
.maint-tablist {
    display: flex;
    gap: 4px;
    padding: 8px 16px 0;
    border-bottom: 1px solid var(--border-color);
}
.maint-tab {
    appearance: none;
    border: 1px solid transparent;
    border-bottom: none;
    background: transparent;
    color: var(--text-muted);
    font: inherit;
    font-weight: 600;
    padding: 8px 14px;
    border-radius: 8px 8px 0 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: background 0.12s ease, color 0.12s ease;
}
.maint-tab:hover { color: var(--text-main); background: color-mix(in srgb, var(--text-muted) 8%, transparent); }
.maint-tab[aria-selected="true"] {
    color: var(--text-main);
    background: var(--bg-pane);
    border-color: var(--border-color);
    margin-bottom: -1px;
}
.maint-tab:focus-visible { outline: 2px solid var(--primary-color); outline-offset: -2px; }
.maint-tab--danger[aria-selected="true"] { color: var(--danger-color); }
.maint-tab__warn { font-size: 0.9em; }

/* --- Body / panels ---------------------------------------------------- */
.maint-app__body {
    flex: 1 1 auto;
    overflow: auto;
    padding: 16px 20px;
    display: block;
}
.maint-tabpanel { display: grid; gap: 12px; }
.maint-tabpanel[hidden] { display: none; }

.maint-card {
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 12px;
    display: grid;
    gap: 8px;
}
.maint-card__inner {
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 10px;
    display: grid;
    gap: 8px;
    background: var(--bg-pane);
}
.maint-card--danger { border-color: var(--danger-color); }
.maint-danger-banner {
    font-size: 0.85rem;
    color: var(--danger-color);
    font-weight: 600;
}

.maint-app__actions {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    padding: 12px 20px 16px;
    border-top: 1px solid var(--border-color);
}

/* --- Progress bars ---------------------------------------------------- */
.maint-progress {
    display: none;
    grid-template-columns: 1fr;
    gap: 4px;
    margin-top: 2px;
}
.maint-progress.maint-progress--active { display: grid; }
.maint-progress__track {
    position: relative;
    height: 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--text-muted) 22%, transparent);
    overflow: hidden;
}
.maint-progress__bar {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0%;
    background: var(--primary-color);
    border-radius: 999px;
    transition: width 0.25s linear;
}
.maint-progress__bar.maint-progress__bar--done { background: var(--success-color); }
.maint-progress__bar.maint-progress__bar--fail { background: var(--danger-color); }
.maint-progress__label {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* Indeterminate (first run, no timing baseline yet) */
.maint-progress--indeterminate .maint-progress__bar {
    width: 35%;
    animation: maint-progress-indeterminate 1.1s ease-in-out infinite;
}
@keyframes maint-progress-indeterminate {
    0%   { left: -35%; }
    100% { left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
    .maint-progress--indeterminate .maint-progress__bar {
        animation: none;
        width: 100%;
        opacity: 0.5;
    }
    .maint-progress__bar { transition: none; }
}

/* --- Resize grip ------------------------------------------------------ */
.maint-resize-grip {
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 18px;
    height: 18px;
    cursor: nwse-resize;
    touch-action: none;
    background:
        linear-gradient(135deg, transparent 0 45%, var(--border-color) 45% 55%, transparent 55% 70%, var(--border-color) 70% 80%, transparent 80%);
    opacity: 0.8;
}
.maint-resize-grip:hover { opacity: 1; }

@media (max-width: 640px) {
    .maint-resize-grip { display: none; }
    #maintenance-app-panel.maint-app { min-width: 0; width: calc(100vw - 16px); }
    .maint-app__header { cursor: default; }
}
/* ==========================================================================
   File Types preset editor ("Edit Presets")
   Owner: utils/FileTypeCatalogDialog.js
   Reuses .modal-box / .glass-* chrome from 180-dialogs-overlays. Semantic tokens only.
   ========================================================================== */

.file-type-catalog-dialog {
    width: min(560px, 94vw);
    display: flex;
    flex-direction: column;
}

.file-type-catalog-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 0;
}

/* Toolbar ----------------------------------------------------------------- */
.ftc-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
}

.ftc-toolbar .icon-btn-small {
    flex: 0 0 auto;
}

/* Active state for the sort toggle. */
.ftc-sort-toggle.is-active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
}

.ftc-category-select {
    flex: 1 1 auto;
    min-width: 220px;       /* roomier now that the toolbar uses compact icon buttons */
    margin-left: 4px;
}

/* File-type list ---------------------------------------------------------- */
.ftc-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 46vh;
    overflow-y: auto;
    padding: 4px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: color-mix(in srgb, var(--bg-pane) 92%, var(--bg-app));
}

.ftc-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 11px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
}

.ftc-item-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    flex: 1 1 auto;
}

.ftc-ext {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-weight: 600;
    color: var(--text-main);
}

.ftc-desc {
    color: var(--text-muted);
    font-size: 0.86rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ftc-edit-input {
    margin-top: 2px;
}

.ftc-item-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
}

/* Render-kind picker: compact select shared by each row and the add-row. */
.ftc-render {
    flex: 0 0 auto;
    width: 104px;
    min-width: 104px;
    padding-block: 4px;
    font-size: 0.84rem;
}

.ftc-empty {
    color: var(--text-muted);
    font-size: 0.88rem;
    padding: 16px 8px;
    text-align: center;
}

/* Add row ----------------------------------------------------------------- */
.ftc-add-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.ftc-new-ext {
    flex: 0 0 38%;
    min-width: 0;
}

.ftc-new-desc {
    flex: 1 1 auto;
    min-width: 0;
}

/* The add-row render select keeps the shared compact width (.ftc-render). */

.ftc-add-filetype {
    flex: 0 0 auto;
}

/* Collapsed: hide the inputs so only the + reveal button shows. */
.ftc-add-row.ftc-add-collapsed .find-replace-input {
    display: none;
}

/* Footer actions ---------------------------------------------------------- */
.ftc-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.ftc-actions-left {
    display: flex;
    gap: 8px;
}

.ftc-actions-left .icon-btn-small {
    flex: 0 0 auto;
}
/* 187-suno-import.css
 * SUNO import feature. Two surfaces, both feature-scoped:
 *  1) .suno-import-dialog — the purpose-built import dialog (song multi-select).
 *  2) .suno-* note-body blocks — how an imported song note renders in the editor.
 * All colours are semantic tokens (light + dark handled by :root token sets). */

/* ---- 1. Import dialog --------------------------------------------------- */

.suno-import-dialog .suno-import-subtitle {
    margin: 0 0 var(--space-2);
    font-size: 0.86rem;
    color: var(--text-muted);
}

.suno-import-dialog .suno-import-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

/* Choose-folder empty state */
.suno-choose {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    text-align: center;
    padding: clamp(1.5rem, 6vh, 3rem) 1rem;
}
.suno-choose-icon {
    width: 48px;
    height: 48px;
    color: var(--primary-color);
    opacity: 0.85;
}
.suno-choose-icon svg { width: 100%; height: 100%; }
.suno-choose .suno-hint,
.suno-import-dialog .suno-hint {
    font-size: 0.82rem;
    color: var(--text-muted);
    margin: 0;
}
.suno-import-dialog .suno-error { color: var(--danger-color); }
.suno-loading {
    padding: clamp(1.5rem, 6vh, 3rem) 1rem;
    text-align: center;
    color: var(--text-muted);
}

/* Folder row — mirrors the shared importer's .import-filter-source-row so both
 * dialogs pick folders the same way: "..." button, current folder, then the
 * in-dialog list of export folders found inside it. */
.suno-source-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}
.suno-source-row.hidden { display: none; }
.suno-source-pick {
    flex: 0 0 auto;
    min-width: 44px;
    font-weight: 600;
}
.suno-source-path {
    flex: 1 1 auto;
    min-width: 0;
    cursor: pointer; /* clicking reloads the folder (re-grants a lapsed permission) */
}
.suno-source-browse {
    flex: 0 0 auto;
    white-space: nowrap;
}
.suno-source-browse.hidden { display: none; }

/* Export-folder chooser (one row per dated export inside the picked folder) */
.suno-folder-search { margin-bottom: var(--space-2); }
.suno-folder-list {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 120px;
    max-height: 52vh;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    padding: var(--space-1);
}
.suno-folder-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: 8px 10px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-main);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.suno-folder-row:hover { background: var(--item-hover); }
.suno-folder-row:focus-visible { outline: 2px solid var(--primary-color); outline-offset: -2px; }
.suno-folder-icon {
    flex: 0 0 auto;
    display: inline-flex;
    width: 18px;
    height: 18px;
    color: var(--primary-color);
}
.suno-folder-icon svg { width: 100%; height: 100%; }
.suno-folder-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Toolbar */
.suno-toolbar {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    margin-bottom: var(--space-2);
    flex-wrap: wrap;
}
.suno-toolbar .suno-search { flex: 1 1 220px; min-width: 0; }
.suno-mini-btn {
    padding: 4px 10px;
    min-height: 0;
    height: var(--btn-height-compact, 30px);
    font-size: 0.82rem;
    flex: 0 0 auto;
}
.suno-playlist-opt {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.82rem;
    color: var(--text-muted);
    cursor: pointer;
    flex: 0 0 auto;
}
.suno-playlist-opt.is-disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* Copy / Link segmented control */
.suno-mode-toggle {
    display: inline-flex;
    flex: 0 0 auto;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg-pane);
}
.suno-mode-btn {
    padding: 4px 12px;
    min-height: 0;
    height: var(--btn-height-compact, 30px);
    font-size: 0.82rem;
    border: none;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
}
.suno-mode-btn + .suno-mode-btn { border-left: 1px solid var(--border-color); }
.suno-mode-btn:hover { background: var(--item-hover); }
.suno-mode-btn.is-active {
    background: var(--primary-color);
    color: var(--on-accent); /* text-on-accent: matches the app-wide primary-button convention */
    font-weight: 600;
}

/* Song list */
.suno-song-list {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 120px;
    max-height: 52vh;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    padding: var(--space-1);
}
.suno-group { margin-bottom: var(--space-2); }
.suno-group-header {
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 6px 8px;
    background: color-mix(in srgb, var(--primary-color) 8%, var(--bg-pane));
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-weight: 600;
}
.suno-group-name { flex: 1 1 auto; }
.suno-group-count {
    flex: 0 0 auto;
    font-size: 0.78rem;
    color: var(--text-muted);
    background: var(--bg-app);
    border-radius: 999px;
    padding: 1px 8px;
}

.suno-song-row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-2);
    padding: 6px 8px 6px 22px;
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.suno-song-row:hover { background: var(--item-hover); }
.suno-song-text { display: grid; gap: 1px; min-width: 0; }
.suno-song-title {
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.suno-song-meta {
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.suno-song-badges { flex: 0 0 auto; display: inline-flex; gap: 4px; }
.suno-badge {
    font-size: 0.7rem;
    padding: 1px 7px;
    border-radius: 999px;
    white-space: nowrap;
}
.suno-badge-karaoke {
    background: color-mix(in srgb, var(--success-color) 18%, transparent);
    color: var(--success-color);
    border: 1px solid color-mix(in srgb, var(--success-color) 40%, transparent);
}
.suno-skipped-note, .suno-empty { margin-top: var(--space-2); font-size: 0.82rem; color: var(--text-muted); }
.suno-storage-note { margin-top: var(--space-1); font-size: 0.8rem; color: var(--text-muted); }
.suno-storage-note.suno-storage-warn { color: var(--warning-color); font-weight: 500; }

/* Progress + done */
.suno-progress, .suno-done {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding: clamp(1.5rem, 5vh, 2.5rem) 0.5rem;
}
.suno-progress-bar {
    height: 8px;
    border-radius: 999px;
    background: var(--bg-app);
    overflow: hidden;
    border: 1px solid var(--border-color);
}
.suno-progress-fill {
    height: 100%;
    background: var(--primary-color);
    transition: width var(--anim-fast, 120ms) var(--anim-ease, ease);
}
.suno-progress-label { text-align: center; }
.suno-progress-counts, .suno-progress-label { color: var(--text-muted); }
.suno-done-headline { font-size: 1.1rem; font-weight: 600; text-align: center; }
.suno-done .glass-dialog-message { text-align: center; }
.suno-error-list { margin-top: var(--space-2); font-size: 0.82rem; color: var(--text-muted); }
.suno-error-list ul { margin: var(--space-1) 0 0; padding-left: 1.2rem; }

/* ---- 2. Imported-song note body ---------------------------------------- */

.suno-import-marker { display: none !important; }

.suno-section { margin: 1.1rem 0; }
.suno-section-label {
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 0.4rem;
}
.suno-lyrics-body .suno-lyric-section { margin-top: 0.7rem; }
.suno-lyrics-body .suno-lyric-section:first-child { margin-top: 0; }
.suno-lyric-blank { min-height: 0.6em; }

.suno-style-body {
    white-space: pre-wrap;
    background: var(--bg-pane);
    border-left: 3px solid var(--primary-color);
    border-radius: var(--radius-sm);
    padding: 0.6rem 0.85rem;
    font-size: 0.92rem;
    color: var(--text-main);
}

.suno-details-table { border-collapse: collapse; font-size: 0.9rem; }
.suno-details-table th {
    text-align: left;
    font-weight: 500;
    color: var(--text-muted);
    padding: 3px 14px 3px 0;
    vertical-align: top;
    white-space: nowrap;
}
.suno-details-table td { padding: 3px 0; color: var(--text-main); }
.suno-details-table code {
    background: var(--inline-code-bg, var(--code-bg));
    color: var(--inline-code-fg, var(--code-fg));
    padding: 1px 5px;
    border-radius: 3px;
    font-size: 0.85em;
}

/* ---- Karaoke synced lyrics (note body) --------------------------------- */

.suno-karaoke .suno-section-label::after {
    content: " · tap a line to jump";
    color: var(--text-placeholder, var(--text-muted));
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
}
/* Only advertise interactivity once the runtime has wired it up. */
.suno-karaoke:not(.suno-karaoke-live) .suno-section-label::after { content: ""; }

.suno-karaoke-body {
    position: relative; /* offsetTop anchor for auto-scroll */
    max-height: 22rem;
    overflow-y: auto;
    scroll-behavior: smooth;
    padding-right: 4px;
}

.suno-kline {
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    transition: background-color var(--anim-fast, 120ms) var(--anim-ease, ease);
}
.suno-kline-seek { cursor: pointer; }
.suno-kline-seek:hover { background: var(--item-hover); }
.suno-kline-section { margin-top: 0.7rem; font-weight: 600; }
.suno-kline-section:first-child { margin-top: 0; }

/* Current line: soft accent wash so you can follow along at a glance. */
.suno-kline.is-current-line {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
}

.suno-word {
    transition: color var(--anim-fast, 120ms) var(--anim-ease, ease);
    border-radius: 3px;
}
/* The word being sung right now. */
.suno-word.is-active {
    color: var(--primary-color);
    font-weight: 600;
    background: color-mix(in srgb, var(--primary-color) 16%, transparent);
}

/* ---- Linked audio card (Link mode: plays live from disk) --------------- */

.suno-linked-audio {
    margin: 8px 0;
}
.suno-linked-audio-player audio {
    width: 100%;
    display: block;
}
/* Reconnect / permission-regrant affordance, shown by the SunoFileLink runtime
 * only when a linked file can't be resolved without a user gesture. */
.suno-linked-audio-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-top: 6px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
}
.suno-linked-audio-status[hidden] { display: none; }
.suno-linked-audio-msg {
    flex: 1 1 200px;
    min-width: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}
.suno-linked-audio-relink { flex: 0 0 auto; }

/* ---- Note-list cover thumbnail (album-grid feel) ----------------------- */
/* Applied in-place by hydrateNoteListCovers to song notes (audio + image).
 * The card's original children move into .note-card-body; the cover sits left. */
.note-card.note-card-has-thumb {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 10px;
    align-items: start;
}
.note-card-thumb {
    width: 48px;
    height: 48px;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg-app);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
}
.note-card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.note-card-body { min-width: 0; }

/* ---- Responsive -------------------------------------------------------- */
@media (max-width: 640px) {
    .suno-song-list { max-height: 46vh; }
    .suno-folder-list { max-height: 46vh; }
    .suno-song-meta { white-space: normal; }
    .suno-toolbar .suno-mini-btn { flex: 1 1 auto; }
    /* Narrow screens: let the folder row wrap rather than crushing the path field. */
    .suno-source-row { flex-wrap: wrap; }
    .suno-source-path { flex: 1 1 100%; order: -1; }
}
/* --- SHARE LINK DIALOG (utils/ShareLinkFlow.js) ---
   Share a Brain Map as a view-only link from the user's Google Drive. Builds on the shared glass dialog
   (180-dialogs-overlays.css) and the export dialog input (184-export-dialogs.css); only share-specific layout here. */

.share-link-dialog {
    width: min(580px, calc(100vw - 32px));
}

/* Buttons toggle with the `hidden` attribute; .glass-btn sets its own display, which would otherwise win. */
.share-link-dialog [hidden] {
    display: none !important;
}

.share-link-dialog-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.share-link-dialog-intro {
    margin: 0;
}

.share-link-dialog-note,
.share-link-dialog-folder {
    font-weight: 600;
}

.share-link-dialog-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.share-link-dialog-url {
    flex: 1 1 260px;
    min-width: 0;
    font-size: 0.85rem;
}

.share-link-dialog-stop {
    color: var(--danger-color);
}

.share-link-dialog-hint {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.82rem;
}

.share-link-dialog-status {
    min-height: 1.3em;
    color: var(--text-muted);
    font-size: 0.86rem;
}

.share-link-dialog-status[data-tone="busy"] {
    color: var(--text-main);
}

.share-link-dialog-status[data-tone="success"] {
    color: var(--success-color);
}

.share-link-dialog-status[data-tone="error"] {
    color: var(--danger-color);
}

.share-link-dialog-warnings {
    margin: 6px 0 0;
    padding-left: 18px;
    color: var(--warning-color);
    font-size: 0.82rem;
}

.share-link-dialog-actions {
    justify-content: space-between;
}
/* ==========================================================================
   Settings → Licence panel
   Owner: utils/licence/LicencePanelDialog.js
   Reuses .modal-box / .glass-* chrome from 180-dialogs-overlays and the shared
   .app-tabs pills. Semantic tokens only.
   ========================================================================== */

.licence-panel-dialog {
    width: min(560px, 94vw);
    display: flex;
    flex-direction: column;
}

.licence-panel-body {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 0;
    overflow-y: auto;
}

/* There is no global [hidden] reset, and a flex panel would otherwise stay
   visible when hidden (see agent.md, Shared UI Components). */
.licence-panel-dialog .lp-panel[hidden] {
    display: none;
}

.licence-panel-dialog .lp-panel {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Status ------------------------------------------------------------------ */
.licence-panel-dialog .lp-headline {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--text-main);
}

.licence-panel-dialog .lp-updates,
.licence-panel-dialog .lp-lid,
.licence-panel-dialog .lp-hint {
    font-size: 0.85rem;
    color: var(--text-muted);
}

.licence-panel-dialog .lp-lid code {
    font-family: ui-monospace, monospace;
    color: var(--text-main);
}

.licence-panel-dialog .lp-subtitle {
    margin: 6px 0 0;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.licence-panel-dialog .lp-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.licence-panel-dialog .lp-cta .glass-btn {
    text-decoration: none;
}

/* The storefront link. Deliberately quieter than the CTAs above it: it is a way out to support,
   the legal pages and the bridge download, not a thing being sold. */
.licence-panel-dialog .lp-website {
    margin-top: 10px;
    font-size: 0.85em;
}

.licence-panel-dialog .lp-website a {
    color: var(--text-muted);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.licence-panel-dialog .lp-website a:hover {
    color: var(--accent);
    text-decoration: underline;
}

/* Feature list ------------------------------------------------------------ */
.licence-panel-dialog .lp-features,
.licence-panel-dialog .lp-licences {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.licence-panel-dialog .lp-feature {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-size: 0.88rem;
    color: var(--text-muted);
}

.licence-panel-dialog .lp-feature.is-granted {
    color: var(--text-main);
    border-color: color-mix(in srgb, var(--success-color) 45%, var(--border-color));
    background: color-mix(in srgb, var(--success-color) 8%, transparent);
}

.licence-panel-dialog .lp-feature-mark {
    display: inline-flex;
    width: 16px;
    color: var(--success-color);
}

.licence-panel-dialog .lp-feature-note {
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--text-muted);
}

/* Stored keys ------------------------------------------------------------- */
.licence-panel-dialog .lp-licence {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "main actions" "meta actions";
    gap: 2px 8px;
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
}

.licence-panel-dialog .lp-licence-main { grid-area: main; }
.licence-panel-dialog .lp-licence-meta {
    grid-area: meta;
    font-size: 0.8rem;
    color: var(--text-muted);
}

.licence-panel-dialog .lp-licence-actions {
    grid-area: actions;
    display: flex;
    align-items: center;
    gap: 4px;
}

.licence-panel-dialog .lp-licence-id {
    margin-left: 6px;
    font-family: ui-monospace, monospace;
    font-size: 0.78rem;
    color: var(--text-muted);
}

/* Activate ---------------------------------------------------------------- */
.licence-panel-dialog .lp-paste {
    width: 100%;
    resize: vertical;
    font-family: ui-monospace, monospace;
    font-size: 0.8rem;
    word-break: break-all;
}

.licence-panel-dialog .lp-activate-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.licence-panel-dialog .lp-activate-result {
    margin: 0;
    min-height: 1.2em;
    font-size: 0.85rem;
}

.licence-panel-dialog .lp-activate-result.is-ok { color: var(--success-color); }
.licence-panel-dialog .lp-activate-result.is-error { color: var(--danger-color); }
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }

/* --- FOCUS MODE --- */
body.focus-mode .sidebar,
body.focus-mode .note-list-pane,
body.focus-mode .resizer {
    display: none !important;
}

body.focus-mode .editor-pane {
    width: 100%;
    flex: 1 1 auto;
}

body.focus-mode .editor-content-wrapper {
    max-width: 960px;
    margin: 0 auto;
    padding-left: 48px;
    padding-right: 48px;
}

#btn-focus-mode.active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}
/* ==========================================================================
   Document bookmarks — line markers + navigation
   See Docs/000-document-bookmarks-navigation-design.md
   ========================================================================== */

/* --- Editor left gutter ---------------------------------------------------
   The bookmark indicator needs space to the left of the text, but #note-body
   clips overflow-x (it scrolls vertically), so a negative-margin glyph would be
   hidden. We move part of the editor's left inset from the wrapper onto the body
   itself (a real internal gutter), and pad the title + backlinks to match, so the
   text column does not move. Reserved on every line → no shift when toggling. */
:root { --qnt-editor-gutter: 28px; }

.editor-content-wrapper { padding-left: 14px; }
.note-title-input { padding-left: var(--qnt-editor-gutter); }
.note-editor { padding-left: var(--qnt-editor-gutter); }
.note-backlinks { padding-left: var(--qnt-editor-gutter); }

/* Pointer affordance: while the cursor is in the clickable left gutter (where a click
   toggles a block bookmark), show a pointer so it reads as "click here". The class is
   toggled by BookmarkNavigator on mousemove (X within the gutter, minus the text dead-zone). */
.note-editor.bm-gutter-hover { cursor: pointer; }

/* --- Toggle button active state (formatting toolbar) --------------------- */
#btn-bookmark-toggle.is-active {
    color: var(--primary-color);
    background: var(--item-hover);
}

/* --- In-document margin indicator on bookmarked blocks ------------------- */
/* CSS-only glyph in the left gutter; never part of the note content, so it does
   not appear in exports, search, or word counts. */
.note-editor [data-qnt-bookmark] {
    position: relative;
}

.note-editor [data-qnt-bookmark]::before {
    content: "";
    position: absolute;
    left: -26px;
    top: 0.35em;
    width: 14px;
    height: 16px;
    background-color: var(--primary-color);
    -webkit-mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    pointer-events: none;
    opacity: 0.9;
}

:root {
    --qnt-bookmark-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black'%3E%3Cpath d='M6 3a2 2 0 0 0-2 2v16l8-5 8 5V5a2 2 0 0 0-2-2z'/%3E%3C/svg%3E");
}

/* --- Code blocks --------------------------------------------------------
   A bookmarked <pre> scrolls horizontally (overflow:auto), which clips a
   negative-offset glyph. The enclosing .code-block-frame sits at the gutter and
   does not clip, so render the indicator there instead and hide the clipped one. */
.note-editor pre[data-qnt-bookmark]::before {
    display: none;
}

.note-editor .code-block-frame:has(pre[data-qnt-bookmark]) {
    position: relative;
}

.note-editor .code-block-frame:has(pre[data-qnt-bookmark])::before {
    content: "";
    position: absolute;
    left: -26px;
    top: 10px;
    width: 14px;
    height: 16px;
    background-color: var(--primary-color);
    -webkit-mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    pointer-events: none;
    opacity: 0.9;
    z-index: 1;
}

/* --- Per-line indicators (multi-line paragraphs) ------------------------
   A paragraph with <br> line breaks stores bookmarked line indices in
   data-qnt-bm-lines and gets one transient glyph per line, positioned by pixel
   offset. The glyph is contenteditable="false" + pointer-events:none, so the
   gutter mousedown (which toggles by Y) handles clicks and the caret never lands
   in it. Stripped from saved/exported HTML; regenerated on load/edit/resize. */
.note-editor [data-qnt-bm-lines] { position: relative; }

.note-editor .qnt-bm-line-indicator {
    position: absolute;
    left: -26px;
    width: 14px;
    height: 16px;
    margin-top: 2px;
    background-color: var(--primary-color);
    -webkit-mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    pointer-events: none;
    opacity: 0.9;
    user-select: none;
}

.note-editor .qnt-bm-line-indicator.is-flash {
    animation: qnt-bookmark-line-flash 1s var(--anim-ease, ease);
}

@keyframes qnt-bookmark-line-flash {
    0%, 100% { opacity: 0.9; transform: scale(1); }
    30% { opacity: 1; transform: scale(1.4); }
}

/* --- Find & Navigate hub tab strip -------------------------------------- */
.fnav-tabs {
    display: flex;
    gap: 4px;
    padding: 8px 16px 0;
}

.fnav-tab {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 7px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.85rem;
    cursor: pointer;
    transition: background var(--anim-fast, 140ms) var(--anim-ease, ease);
}

.fnav-tab svg { width: 15px; height: 15px; }
.fnav-tab span { line-height: 1; }
.fnav-tab:hover { background: var(--item-hover); }

.fnav-tab.is-active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
    background: var(--item-hover);
}

/* Accent (Replace) and danger (Clear all) variants of the icon nav button. */
.fnav-navbtn.fnav-navbtn-accent {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}
.fnav-navbtn.fnav-navbtn-accent:hover {
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
}
.fnav-navbtn.fnav-navbtn-danger:hover {
    color: var(--danger-color);
    border-color: color-mix(in srgb, var(--danger-color) 40%, var(--border-color));
}

/* Mobile: icon-only tabs (tooltips/aria-label keep them explained). */
@media (max-width: 768px) {
    .fnav-tab span { display: none; }
    .fnav-tab { padding: 8px 6px; }
}

/* Touch-friendly resize gripper (bottom-right), modelled on the music panel. */
.fnav-resize-handle {
    position: absolute;
    right: 4px;
    bottom: 4px;
    width: 22px;
    height: 22px;
    padding: 0;
    border: none;
    background: transparent;
    color: transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: nwse-resize;
    touch-action: none;
    z-index: 6;
    appearance: none;
    -webkit-appearance: none;
}

.fnav-resize-handle::before {
    content: '';
    display: block;
    width: 14px;
    height: 14px;
    background: linear-gradient(135deg,
        transparent 0 50%,
        color-mix(in srgb, var(--text-muted) 86%, transparent) 50% 56%,
        transparent 56% 68%,
        color-mix(in srgb, var(--text-muted) 86%, transparent) 68% 74%,
        transparent 74% 86%,
        color-mix(in srgb, var(--text-muted) 86%, transparent) 86% 92%,
        transparent 92% 100%);
    opacity: 0.9;
}

.fnav-resize-handle:hover::before,
.find-replace-glass-dialog.is-resizing .fnav-resize-handle::before {
    background: linear-gradient(135deg,
        transparent 0 50%,
        color-mix(in srgb, var(--primary-color) 82%, transparent) 50% 56%,
        transparent 56% 68%,
        color-mix(in srgb, var(--primary-color) 82%, transparent) 68% 74%,
        transparent 74% 86%,
        color-mix(in srgb, var(--primary-color) 82%, transparent) 86% 92%,
        transparent 92% 100%);
}

@media (max-width: 768px) {
    .fnav-resize-handle { width: 32px; height: 32px; right: 2px; bottom: 2px; }
    .fnav-resize-handle::before { width: 19px; height: 19px; }
}

.fnav-empty {
    padding: 22px 10px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.9rem;
}

/* --- Navigation panels (Bookmarks / Headings) --------------------------- */
/* Keep the scope/nav controls fixed; scroll only the list. Scoped under the
   modal id so it overrides the generic .fnav-panel scroll rule. */
#find-replace-modal .fnav-panel:has(.fnav-list) {
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
#find-replace-modal .fnav-panel .fnav-list {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}

.fnav-navrow {
    display: flex;
    align-items: center;
    gap: 4px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 8px;
}

/* In the Search tab the nav row has no list beneath it — drop the divider. */
#find-replace-modal [data-fnav-panel="search"] .fnav-navrow {
    border-bottom: none;
    margin-bottom: 0;
}

.fnav-navbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
    background: transparent;
    color: var(--text-main);
    cursor: pointer;
}
.fnav-navbtn svg { width: 16px; height: 16px; }
.fnav-navbtn:hover { background: var(--item-hover); }

.fnav-counter {
    flex: 1;
    text-align: center;
    font-size: 0.82rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.fnav-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    outline: none;
}

.fnav-item {
    display: flex;
    align-items: baseline;
    gap: 8px;
    width: 100%;
    text-align: left;
    padding: 6px 8px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 6px);
    background: transparent;
    color: var(--text-main);
    font-size: 0.9rem;
    cursor: pointer;
}
.fnav-item:hover { background: var(--item-hover); }
.fnav-item.is-active {
    background: var(--item-hover);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.fnav-item-num {
    flex: 0 0 auto;
    min-width: 1.4em;
    text-align: right;
    color: var(--text-muted);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}

.fnav-item-text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Headings outline: indent by level. */
.fnav-item-l2 { padding-left: 26px; }
.fnav-item-l3 { padding-left: 44px; }

/* Headings scope toggle (H1 only / All levels). */
.fnav-scope {
    display: flex;
    gap: 4px;
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
}

.fnav-scopebtn {
    flex: 1;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.82rem;
    cursor: pointer;
}
.fnav-scopebtn:hover { background: var(--item-hover); }
.fnav-scopebtn.is-active {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
    background: var(--item-hover);
}

/* --- Jump flash (F2 / navigator) ---------------------------------------- */
@keyframes qnt-bookmark-flash {
    from { background-color: var(--selection-color); }
    to   { background-color: transparent; }
}

.note-editor .qnt-bookmark-flash {
    animation: qnt-bookmark-flash 1s var(--anim-ease, ease);
    border-radius: var(--radius-sm, 6px);
}
/* ==========================================================================
   Code-block line bookmarks — Notepad++-style markers in the line-number gutter
   See Docs/000-code-block-line-bookmarks-gutter-design.md
   ==========================================================================
   The line-number gutter (140-code-blocks.css) is otherwise inert
   (pointer-events: none). Clicking a line number toggles a per-line bookmark on
   the <pre> (data-qnt-bm-lines); the bookmarked rows get an accent number + a
   bookmark glyph. The gutter itself is transient runtime UI, so these marks never
   serialize into saved/exported note HTML. */

/* Make the line-number rows clickable while keeping their text unselectable.
   The mousedown listener lives on the gutter; rows must be hit targets for it to
   fire through the gutter's pointer-events:none. */
.code-line-gutter-row {
    position: relative;
    pointer-events: auto;
    cursor: pointer;
}

.code-line-gutter-row:hover {
    color: var(--text-main);
}

/* Hover affordance: a faint bookmark glyph on un-bookmarked lines hints "clickable". */
.code-line-gutter-row:not(.is-bookmarked):hover::after {
    content: "";
    position: absolute;
    left: -4px;
    top: 50%;
    transform: translateY(-50%);
    width: 10px;
    height: 12px;
    background-color: var(--primary-color);
    opacity: 0.32;
    -webkit-mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    pointer-events: none;
}

/* Bookmarked line: accent the number and pin a solid bookmark glyph at the left. */
.code-line-gutter-row.is-bookmarked {
    color: var(--primary-color);
    font-weight: 600;
}

.code-line-gutter-row.is-bookmarked::after {
    content: "";
    position: absolute;
    left: -4px;
    top: 50%;
    transform: translateY(-50%);
    width: 11px;
    height: 13px;
    background-color: var(--primary-color);
    opacity: 0.95;
    -webkit-mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    mask: var(--qnt-bookmark-glyph) center / contain no-repeat;
    pointer-events: none;
}

/* Jump flash (F2 / navigator) — pulse the row so the landed line is obvious. */
.code-line-gutter-row.is-flash {
    animation: qnt-code-line-bm-flash 1s var(--anim-ease, ease);
    border-radius: 4px;
}

@keyframes qnt-code-line-bm-flash {
    from { background-color: var(--selection-color); }
    to { background-color: transparent; }
}
/* ==========================================================================
   Import YouTube Transcript dialog
   Owner: utils/YouTubeTranscriptDialog.js  (flow: utils/YouTubeTranscriptImportFlow.js)
   Reuses the shared .modal-box / .glass-* dialog chrome from 180-dialogs-overlays.
   All values via semantic tokens.
   ========================================================================== */

.yt-transcript-dialog {
    width: min(520px, 94vw);
}

.yt-transcript-body {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* URL input row: field + inline Paste fallback button --------------------- */
.yt-transcript-url-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.yt-transcript-url-input {
    flex: 1 1 auto;
    min-width: 0;
}

.yt-transcript-paste {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* Destination checkbox ---------------------------------------------------- */
.yt-transcript-dest-row {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-main);
}

/* When there is no open note, the "insert into current note" choice is gone:
   the checkbox is forced on + disabled and reads as muted. */
.yt-transcript-dest-row.is-locked {
    opacity: 0.6;
}

.yt-transcript-dest-hint {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin: -6px 0 0 24px;
}

/* Generate Summary (AI) — only rendered when AI integration is configured ---- */
.yt-transcript-summary-row {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-main);
}

/* Disabled when the AI Integration master switch is off. */
.yt-transcript-summary-row.is-locked {
    opacity: 0.6;
}

.yt-transcript-summary-hint {
    color: var(--text-muted);
    font-size: 0.85rem;
    margin: -6px 0 0 24px;
}

/* Status line (loading / error / done) ------------------------------------ */
.yt-transcript-status {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 1.2em;
    color: var(--text-muted);
    font-size: 0.9rem;
    overflow-wrap: anywhere;
}

.yt-transcript-status.is-error {
    color: var(--danger-color);
}

.yt-transcript-spinner {
    display: none;
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    border: 2px solid color-mix(in srgb, var(--border-color) 70%, transparent);
    border-top-color: var(--primary-color);
    border-radius: 50%;
    animation: yt-transcript-spin 0.7s linear infinite;
}

.yt-transcript-status.is-loading .yt-transcript-spinner {
    display: inline-block;
}

@keyframes yt-transcript-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .yt-transcript-spinner { animation-duration: 1.6s; }
}
/* ==========================================================================
   Unified link dialog — Note + Web URL tabs
   See Docs/000-unified-link-refactor-and-undo-design.md
   Tab strip reuses the shared .fnav-tabs/.fnav-tab pattern (195-bookmarks.css).
   ========================================================================== */

.link-dialog-glass-dialog {
    width: min(460px, calc(100vw - 32px));
    display: flex;
    flex-direction: column;
    max-height: min(560px, calc(100vh - 48px));
}

.link-dialog-tabs {
    padding: 8px 16px 0;
}

.link-dialog-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
    overflow: hidden;
}

.link-dialog-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}
.link-dialog-panel.hidden { display: none; }

/* --- Note tab: search + results ---------------------------------------- */
.link-dialog-search-wrap {
    position: relative;
    flex: 0 0 auto;
}
.link-dialog-search-wrap #link-dialog-search { width: 100%; }

.link-dialog-results {
    margin-top: 8px;
    flex: 1 1 auto;
    min-height: 120px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
    outline: none;
}

.link-dialog-result {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    padding: 7px 9px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm, 6px);
    background: transparent;
    color: var(--text-main);
    font-size: 0.9rem;
    cursor: pointer;
}
.link-dialog-result:hover { background: var(--item-hover); }
.link-dialog-result.is-active {
    background: var(--item-hover);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.link-dialog-result-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    color: var(--text-muted);
}
.link-dialog-result-icon svg { width: 16px; height: 16px; }

.link-dialog-result-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.link-dialog-result-title {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.link-dialog-result-crumb {
    font-size: 0.74rem;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Create-missing row sits last and reads as an action, not a target. */
.link-dialog-result.link-dialog-create .link-dialog-result-icon,
.link-dialog-result.link-dialog-create .link-dialog-result-title {
    color: var(--primary-color);
}

.link-dialog-empty {
    padding: 22px 10px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.9rem;
}

/* --- Web URL tab ------------------------------------------------------- */
.link-dialog-panel[data-link-panel="url"] { gap: 0; }

/* Hide the Apply button on the Note tab (selection is the action there). */
.link-dialog-glass-dialog[data-active-tab="note"] #link-dialog-apply { display: none; }

@media (max-width: 768px) {
    .link-dialog-glass-dialog { width: calc(100vw - 24px); max-height: calc(100vh - 32px); }
    /* Only two short tabs here — keep their text labels (override fnav icon-only). */
    .link-dialog-tabs .fnav-tab span { display: inline; }
}
/* Google Drive restore backup picker — touch/click list (replaces the legacy <select>).
   Feature-scoped under .gdrive-restore-*; all colours come from semantic theme tokens so it
   adapts to light/dark automatically. */
.gdrive-restore-body {
    display: grid;
    gap: 8px;
}

.gdrive-restore-label {
    font-size: 0.82rem;
    color: var(--text-muted);
}

.gdrive-restore-list {
    list-style: none;
    margin: 0;
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    max-height: min(52vh, 360px);
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: var(--bg-pane);
    -webkit-overflow-scrolling: touch;
}

.gdrive-restore-list:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

.gdrive-restore-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 9px 12px;
    min-height: 44px;            /* comfortable touch target */
    justify-content: center;
    border-radius: 8px;
    border: 1px solid transparent;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}

.gdrive-restore-item:hover {
    background: var(--item-hover);
}

.gdrive-restore-item.is-selected {
    background: color-mix(in srgb, var(--primary-color) 16%, transparent);
    border-color: var(--primary-color);
}

.gdrive-restore-item-name {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gdrive-restore-item-meta {
    font-size: 0.76rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
    .gdrive-restore-list {
        max-height: 56vh;
    }

    .gdrive-restore-item-name {
        font-size: 0.86rem;
    }

    .gdrive-restore-item-meta {
        font-size: 0.72rem;
    }
}
/* ===========================================================================
   DATABASE-IN-USE CHOOSER
   Centered modal shown when a tab targets a database another tab already holds.
   A distinct surface from the Data Manager (it can render on a tab whose boot
   was aborted before the app shell wired up), so it owns its own styling here.
   Centering comes from the base .modal-overlay (align/justify: center); this
   slice only styles the dialog card and its controls.
   =========================================================================== */
.db-in-use-chooser-overlay {
    z-index: 5600;
}

.db-in-use-chooser {
    width: min(94vw, 460px);
    max-height: min(80vh, 640px);
    display: grid;
    gap: 12px;
    padding: 20px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 28%, transparent);
    outline: none;
    overflow-y: auto;
}

.db-in-use-chooser-title {
    font-size: 1.12rem;
    font-weight: 700;
    color: var(--text-main);
}

.db-in-use-chooser-message {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.92rem;
    line-height: 1.45;
}

.db-in-use-chooser-list {
    display: grid;
    gap: 8px;
}

.db-in-use-chooser-btn {
    width: 100%;
    min-height: 44px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.95rem;
    font-weight: 600;
    text-align: left;
    padding: 10px 14px;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease;
}

.db-in-use-chooser-btn:hover {
    background: var(--item-hover);
    border-color: var(--primary-color);
}

/* Busy row: a database open in another tab. Listed (so the user sees why it
   isn't offered) but not selectable. Muted + a warning-toned status label. */
.db-in-use-chooser-btn-busy {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    cursor: default;
    opacity: 0.72;
}

.db-in-use-chooser-btn-busy:hover {
    background: var(--bg-pane);
    border-color: var(--border-color);
}

.db-in-use-chooser-btn-status {
    flex: 0 0 auto;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--warning-color);
    white-space: nowrap;
}

.db-in-use-chooser-create {
    border-style: dashed;
}

.db-in-use-chooser-create-row {
    display: flex;
    gap: 8px;
}

.db-in-use-chooser-create-row input {
    flex: 1;
    min-width: 0;
    min-height: 40px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
    color: var(--text-main);
    padding: 6px 10px;
    font-size: 0.95rem;
}

.db-in-use-chooser-create-row input:focus {
    outline: none;
    border-color: var(--primary-color);
}

.db-in-use-chooser-footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 8px;
}

/* Accent (primary) footer action — e.g. the recovery dialog's "Choose another database…".
   Mirrors the app's on-accent convention (white text on --primary-color). */
.db-in-use-chooser-footer .db-in-use-chooser-primary {
    background: var(--primary-color);
    border-color: var(--primary-color);
    color: var(--on-accent);
}

.db-in-use-chooser-footer .db-in-use-chooser-primary:hover {
    filter: brightness(1.05);
}

/* Recovery message keeps the bridge's \n\n line breaks readable. */
.db-in-use-chooser-message.db-in-use-chooser-message-pre {
    white-space: pre-wrap;
}
/* =========================================================================
   REFERENCE COLUMN — read-only side-by-side notes (desktop/tablet only)
   Owner stylesheet for the dockable reference column that renders one or
   more pinned notes beside the editor as read-only snapshots.
   Selectors are scoped under .ref-col / .editor-main-row to avoid global
   collisions. Drives all color via semantic tokens (no hardcoded values).
   ========================================================================= */

/* Row wrapper: editor + resizer + reference column sit side by side inside
   the existing .editor-pane (which is a flex column). */
.editor-main-row {
    display: flex;
    flex: 1 1 auto;
    min-height: 0; /* let children scroll instead of overflowing the pane */
    position: relative;
}

/* The existing editor keeps flexing to fill the remaining space. */
.editor-main-row > .editor-content-wrapper {
    flex: 1 1 auto;
    min-width: 0;
}

/* The column. Visibility is driven by the [hidden] attribute (set in JS) plus
   the .is-collapsed class — the explicit display:none beats the author display
   rule below. The panel can now be open while empty (Split "Add" flow), so
   .is-empty no longer forces it hidden; it only styles the empty state. */
.ref-col {
    position: relative;
    flex: 0 0 auto;
    width: var(--reference-width, 50%);
    min-width: 220px;
    max-width: 60%;
    display: flex;
    flex-direction: column;
    height: 100%;
    background: var(--bg-pane);
    border-left: 1px solid var(--pane-divider, var(--border-color));
    overflow: hidden;
}

.ref-col[hidden],
.ref-col.is-collapsed {
    display: none;
}

/* Focus ring: the split is the target for plain note-list clicks. reference-column.js sets
   [data-split-focused] on a click inside the split and clears it on a click in the editor.
   Drawn by an overlay pseudo-element so it sits above the header/note backgrounds without
   shifting layout. */
.ref-col::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 30;
    pointer-events: none;
    box-shadow: inset 0 0 0 2px var(--pane-focus-ring);
    opacity: 0;
    transition: opacity var(--anim-fast) var(--anim-ease);
}

.ref-col[data-split-focused="true"]::after {
    opacity: 1;
}

/* Split focus command lock (utils/SplitFocusCommandPolicy.js): editor commands that would change the
   editor's note are dimmed while the split has focus. The format bar is `inert`; locked note-bar
   buttons keep their tooltip (which says why) — except a toggle that is on, which can still be switched off. */
#format-toolbar[data-split-locked="true"] {
    opacity: 0.4;
    filter: grayscale(0.7);
}

.editor-actions [data-split-locked="true"]:not([aria-pressed="true"]) {
    opacity: 0.35;
    cursor: not-allowed;
}

/* Drop target while notes are dragged over the split (they are added on drop). */
.ref-col.is-drop-target {
    box-shadow: inset 0 0 0 2px var(--primary-color);
    background: var(--primary-alpha-06);
}

/* Unlike the sidebar/list resizers (absolutely positioned at a pane's right
   edge), the reference resizer is an IN-FLOW flex item sitting between the
   editor and the column. This keeps it pinned to the real boundary even when
   the column hits its max-width clamp or the window is resized — the absolute
   `right: var(--reference-width)` approach desynced on resize. */
#resizer-reference {
    position: relative;
    top: auto;
    left: auto;
    right: auto;
    height: auto;
    align-self: stretch;
    flex: 0 0 5px;
}

/* Show the resizer only when the column is actually visible. */
#editor-pane:not(.has-reference) #resizer-reference {
    display: none;
}

/* Single show/hide toggle handle. In-flow flex item so it stays pinned to the
   real boundary: when the column is open it sits at the column's left edge; when
   collapsed (column + resizer hidden) the editor's flex-grow pushes it to the
   right edge — i.e. where the old "show" tab lived. */
.ref-col-toggle {
    flex: 0 0 auto;
    align-self: center;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    width: 18px;
    min-height: 52px;
    margin: 0 2px;
    padding: 8px 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-muted);
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: color var(--anim-fast) var(--anim-ease), background-color var(--anim-fast) var(--anim-ease);
}

.ref-col-toggle[hidden] {
    display: none;
}

.ref-col-toggle:hover {
    background: var(--item-hover);
    color: var(--text-main);
}

.ref-col-toggle__glyph {
    font-size: 1rem;
    line-height: 1;
}

.ref-col-toggle__count {
    font-size: 0.68rem;
    font-weight: 700;
    min-width: 15px;
    text-align: center;
    border-radius: 999px;
    padding: 1px 3px;
    background: var(--primary-color);
    color: var(--on-accent);
}

.ref-col-toggle__count[hidden] {
    display: none;
}

/* Desktop/tablet only — never a mobile surface. */
@media (max-width: 768px) {
    .ref-col,
    #resizer-reference,
    .ref-col-toggle {
        display: none !important;
    }
}

/* ---- Header ---- */
.ref-col__header {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-muted);
}

/* ---- Header switcher: dropdown of the notes added to the split ---- */
.ref-col__switcher {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

.ref-col__switcher-btn {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    box-sizing: border-box;
    padding: 6px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.82rem;
    text-align: left;
    cursor: pointer;
    transition: background-color var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}

.ref-col__switcher-btn:hover {
    background: var(--item-hover);
}

.ref-col__switcher-btn:focus-visible,
.ref-col__switcher-btn[aria-expanded="true"] {
    outline: none;
    border-color: var(--primary-color);
}

.ref-col__switcher-label {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ref-col__switcher-label.is-placeholder {
    color: var(--text-muted);
}

.ref-col__switcher-count {
    flex: 0 0 auto;
    min-width: 18px;
    padding: 1px 5px;
    border-radius: 999px;
    background: var(--primary-alpha-14);
    color: var(--text-main);
    font-size: 0.68rem;
    font-weight: 700;
    text-align: center;
}

.ref-col__switcher-count[hidden] {
    display: none;
}

.ref-col__switcher-caret {
    flex: 0 0 auto;
    color: var(--text-muted);
    font-size: 0.75rem;
}

/* Menu: absolutely positioned under the switcher button, overlaying the displayed note.
   z-index clears the note view; the column itself never clips it vertically. */
.ref-col__switcher-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 320px;
    overflow-y: auto;
    padding: 4px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    box-shadow: var(--shadow-md, var(--shadow-sm));
}

.ref-col__switcher-menu[hidden] {
    display: none;
}

.ref-col__switcher-menu:focus {
    outline: none;
}

.ref-col__switcher-option {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 4px 4px 6px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-main);
    cursor: pointer;
}

.ref-col__switcher-option:hover,
.ref-col__switcher-option.is-active {
    background: var(--item-hover);
    border-color: color-mix(in srgb, var(--primary-color) 40%, var(--border-color));
}

.ref-col__switcher-check {
    flex: 0 0 1em;
    color: var(--primary-color);
    font-weight: 700;
    text-align: center;
}

.ref-col__switcher-text {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.ref-col__switcher-title,
.ref-col__switcher-crumb {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ref-col__switcher-title {
    font-size: 0.86rem;
}

.ref-col__switcher-option.is-displayed .ref-col__switcher-title {
    font-weight: 600;
}

.ref-col__switcher-crumb {
    font-size: 0.72rem;
    color: var(--text-muted);
}

.ref-col__switcher-remove {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 0.95rem;
    line-height: 1;
}

.ref-col__switcher-remove:hover {
    background: var(--bg-pane);
    color: var(--danger-color);
}

.ref-col__switcher-footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 2px;
    padding-top: 4px;
    border-top: 1px solid var(--border-color);
}

.ref-col__switcher-clear {
    padding: 5px 8px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
}

.ref-col__switcher-clear:hover,
.ref-col__switcher-clear.is-active {
    background: var(--item-hover);
    color: var(--danger-color);
}

.ref-col__switcher-empty {
    padding: 10px 8px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.82rem;
}

/* Screen-reader-only focus announcement ("Split screen has focus" / "Editor has focus"). */
.ref-col__sr-status {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ---- Scrollable stack of pinned items ---- */
.ref-col__stack {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 10px;
}

/* ---- A single pinned note ---- */
.ref-col__item {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-editor-pane);
    overflow: hidden;
}

.ref-col__item-bar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 6px 6px 10px;
    border-bottom: 1px solid var(--border-color);
    background: color-mix(in srgb, var(--bg-pane) 70%, var(--bg-editor-pane));
}

.ref-col__item-title {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.86rem;
    font-weight: 600;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ref-col__item-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 0.95rem;
    line-height: 1;
    transition: background-color var(--anim-fast) var(--anim-ease), color var(--anim-fast) var(--anim-ease);
}

.ref-col__item-btn:hover {
    background: var(--item-hover);
    color: var(--text-main);
}

/* The item buttons are display:inline-flex, which beats the [hidden] attribute — so hidden
   controls (e.g. the Back button before any in-pane navigation) need an explicit rule. */
.ref-col__item-btn[hidden] {
    display: none;
}

/* Back button: slightly larger glyph, and it reads as a nav affordance rather than a plain icon. */
.ref-col__item-back {
    font-size: 1.15rem;
}

.ref-col__item-btn.is-danger:hover {
    color: var(--danger-color);
}

/* "Preview" marker: the note is shown in the split but not in its list. */
.ref-col__item-badge {
    flex: 0 0 auto;
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--primary-alpha-14);
    color: var(--primary-color);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.ref-col__item-badge[hidden] {
    display: none;
}

/* 🔒 View-only marker: the split never edits (⤢ opens the note in the editor). */
.ref-col__item-lock {
    flex: 0 0 auto;
    font-size: 0.72rem;
    line-height: 1;
    opacity: 0.7;
    cursor: help;
    user-select: none;
}

/* Note-list marker for the card currently shown in the split screen (note-list.js sets it from the
   split's onDisplayChange). A dashed inset outline in the split's ring colour ties the card to the
   pane without touching the card's own border/shadow states (active, selected, pinned, hover). */
.note-card.is-split-shown {
    outline: 2px dashed color-mix(in srgb, var(--pane-focus-ring) 65%, transparent);
    outline-offset: -4px;
}

/* Read-only rendered note body. Reuses .note-editor typography for parity
   with the live editor, but is never contenteditable. */
.ref-col__item-body {
    padding: 12px 14px;
    overflow-x: auto;
    font-size: 0.92rem;
    color: var(--text-editor, var(--text-main));
    user-select: text;
}

.ref-col__item-body.note-editor {
    /* neutralize any min-height the editable surface assumes */
    min-height: 0;
    /* Reserve the same left gutter the editor uses so whole-block bookmark glyphs
       (195-bookmarks.css renders them at left:-26px, relative to the block) aren't
       clipped by the body's own padding. Scoped to the column body only — never the
       shared .note-editor / --qnt-editor-gutter rule. */
    padding-left: var(--qnt-editor-gutter, 28px);
}

/* ---- View-only app-kind editor (Board / Map / Story / Calendar) in the split ----
   The item and its body fill the pane so the editor's height:100% root gets a definite height;
   the backlinks footer stays below the editor. */
.ref-col__item.is-app-view {
    flex: 1 1 auto;
    min-height: 0;
}

.ref-col__item-body.ref-col__app-host {
    position: relative;
    flex: 1 1 auto;
    min-height: 320px;
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}

.ref-col__app-host > * {
    flex: 1 1 auto;
    min-height: 0;
}

/* ---- Split-note Find & Navigate hub (#ref-fnav-modal) --------------------
   A read-only twin of the editor's #find-replace-modal, opened by the 🔖 item-bar button. It
   reuses the shared .find-replace-* / .fnav-* / mark.find-match classes (defined globally in
   180-dialogs-overlays.css & 195-bookmarks.css) for identical look & behavior; only the id-scoped
   layout the editor keeps private is replicated here. Non-blocking + non-dimming (like the editor's
   Find) and docked LEFT so the reference column on the right stays visible while you navigate. */
#ref-fnav-modal {
    background: transparent;
    backdrop-filter: none;
    pointer-events: none; /* clicks pass through the backdrop — the split stays interactive */
}

#ref-fnav-modal .find-replace-glass-dialog {
    --fr-scale: 1;
    position: fixed;
    top: 92px;
    left: 20px;
    right: auto;
    width: min(94vw, 560px);
    min-width: 240px;
    min-height: 150px;
    max-width: calc(100vw - 16px);
    max-height: calc(100vh - 16px);
    overflow: hidden;         /* header + tabs stay put; only the active panel scrolls */
    display: flex;
    flex-direction: column;
    pointer-events: auto;     /* but the dialog itself is interactive */
    border-radius: var(--glass-radius);
    border: 1px solid color-mix(in srgb, var(--bg-pane) 65%, transparent);
    background: color-mix(in srgb, var(--bg-pane) 68%, transparent);
    backdrop-filter: blur(var(--glass-surface-blur));
    box-shadow: 0 18px 50px color-mix(in srgb, var(--mix-dark) 24%, transparent);
    padding: calc(20px * var(--fr-scale));
    gap: calc(12px * var(--fr-scale));
    transform: none;          /* no pop-in transform (fixed-position dialog) */
}

#ref-fnav-modal .find-replace-header,
#ref-fnav-modal .fnav-tabs {
    flex: 0 0 auto;
}

/* Header is the drag handle (base .find-replace-header already sets cursor:move + touch-action:none). */

#ref-fnav-modal .fnav-panel {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}

/* Keep the nav/scope controls fixed; scroll only the list (mirrors the editor hub's rule). */
#ref-fnav-modal .fnav-panel:has(.fnav-list) {
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

#ref-fnav-modal .fnav-panel .fnav-list {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
}

/* Search tab: the nav row is the last element with no list beneath it — drop the divider. */
#ref-fnav-modal [data-reffnav-panel="search"] .fnav-navrow {
    border-bottom: none;
    margin-bottom: 0;
}

/* ---- Backlinks footer (collapsible; rows reuse the editor's .note-backlink-* styles) ---- */
.ref-col__backlinks {
    border-top: 1px solid var(--border-color);
    padding: 4px 8px 8px;
}

.ref-col__backlinks-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 5px 4px;
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    cursor: pointer;
    transition: color var(--anim-fast) var(--anim-ease);
}

.ref-col__backlinks-toggle:hover {
    color: var(--text-main);
}

.ref-col__backlinks-caret {
    font-size: 0.7rem;
    width: 0.8em;
    text-align: center;
}

.ref-col__backlinks-list {
    padding: 4px 2px 2px;
}

/* .note-backlinks-list is display:flex, so the [hidden] attribute needs an explicit override. */
.ref-col__backlinks-list[hidden] {
    display: none;
}

/* ---- App-kind placeholder (kanban / mindmap) ---- */
.ref-col__placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 22px 14px;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.85rem;
}

.ref-col__placeholder-kind {
    font-weight: 600;
    color: var(--text-main);
}

/* ---- Empty/loading states ---- */
.ref-col__empty,
.ref-col__item-loading {
    padding: 16px 14px;
    color: var(--text-muted);
    font-size: 0.85rem;
    text-align: center;
}

/* ---- Split "add a note" empty state (panel opened with nothing pinned) ---- */
.ref-col__empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 28px 16px;
    text-align: center;
    color: var(--text-muted);
}

.ref-col__empty-msg {
    margin: 0;
    font-size: 0.88rem;
}
/* ============================================================================
   220 — Quick-search typed operators (Docs/000-quick-search-operators-design.md)
   Owns: operator autocomplete popover (.search-op-suggest), active-mode chip bar
   (.search-mode-bar), media search-result rows (.note-card-media), and the
   bin-result highlight. Semantic tokens only; primary-derived tints use
   color-mix so both themes are covered by the one declaration.
   ============================================================================ */

/* --- Active-mode chip bar (under the search input) --- */

.search-mode-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 6px;
}

.search-mode-bar[hidden] {
    display: none !important;
}

.search-mode-chip {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--primary-color);
    background: color-mix(in srgb, var(--primary-color) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--primary-color) 45%, transparent);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.search-mode-clear {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.95rem;
    line-height: 1;
    cursor: pointer;
}

.search-mode-clear:hover {
    background: var(--item-hover);
    color: var(--text-main);
}

/* --- Operator autocomplete popover (anchored inside #search-input-wrap) --- */

.search-op-suggest {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 900;
    max-height: 320px;
    overflow-y: auto;
    background: var(--bg-pane);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 4px;
}

.search-op-suggest[hidden] {
    display: none !important;
}

.search-op-suggest-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    width: 100%;
    padding: 6px 8px;
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-main);
    font-size: 0.82rem;
    text-align: left;
    cursor: pointer;
}

.search-op-suggest-row:hover,
.search-op-suggest-row.is-active {
    background: var(--item-hover);
}

.search-op-suggest-op {
    flex: 0 0 auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-weight: 600;
    color: var(--primary-color);
}

.search-op-suggest-hint {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.search-op-suggest-footer {
    margin-top: 4px;
    padding: 6px 8px;
    border-top: 1px solid var(--border-color);
    color: var(--text-muted);
    font-size: 0.72rem;
    line-height: 1.4;
}

/* --- Media search-result rows --- */

.note-card-media .media-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.note-card-media .media-row-thumb {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm);
    background: var(--item-hover);
    border: 1px solid var(--border-color);
    font-size: 1.2rem;
    overflow: hidden;
    position: relative;
}

.note-card-media .media-row-thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.note-card-media .media-row-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.note-card-media .media-row-filename {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.note-card-media .media-row-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.note-card-media .media-row-mime {
    max-width: 55%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.note-card-media .media-row-size {
    flex: 0 0 auto;
    font-size: 0.72rem;
    color: var(--text-muted);
}

.note-card-media .media-row-note {
    font-size: 0.75rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* --- bin: result highlight (Bin view opened from a bin: search hit) --- */

.bin-item.bin-item-highlight {
    animation: bin-item-highlight-flash 1.6s ease-out 1;
    border-color: var(--primary-color);
}

@keyframes bin-item-highlight-flash {
    0% { background: color-mix(in srgb, var(--primary-color) 22%, transparent); }
    100% { background: transparent; }
}
/* ===========================================================================
   Collection Gallery (audience #3) — global full-screen media library overlay.
   Owner: utils/CollectionGalleryController.js. Feature-scoped under .cyb-gallery-*.
   Single overlay layer + solid/scrim backgrounds (NO stacked backdrop-filter) so
   the in-overlay viewer never triggers the double-backdrop GPU freeze.
   All colour via semantic tokens (000-tokens-base.css) → light + dark for free.
   =========================================================================== */

.cyb-gallery-overlay {
    position: fixed;
    inset: 0;
    z-index: 3000;
    display: flex;
    flex-direction: column;
    background: var(--bg-app);
    color: var(--text-main);

    /* Feature-scoped scrim for controls that float ON TOP of a thumbnail. These sit over arbitrary user
       imagery, not over a themed surface, so they stay dark in both themes on purpose — a light chip on a
       light photo is unreadable. Kept as tokens rather than inline values so every floating tile control
       reads from one place. */
    --cyb-gallery-tile-scrim: color-mix(in srgb, var(--mix-dark) 55%, transparent);
    --cyb-gallery-tile-scrim-hover: color-mix(in srgb, var(--mix-dark) 78%, transparent);
    --cyb-gallery-tile-scrim-text: var(--mix-light);
}
.cyb-gallery-overlay.hidden { display: none; }

/* ---- header ---- */
.cyb-gallery-header {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border-color);
    flex: 0 0 auto;
}
.cyb-gallery-title { margin: 0; font-size: 1.1rem; font-weight: 600; }
.cyb-gallery-count { color: var(--text-muted); font-size: 0.85rem; white-space: nowrap; }
.cyb-gallery-search { margin-left: auto; flex: 0 1 340px; }
.cyb-gallery-search-input {
    width: 100%;
    height: var(--btn-height-compact, 32px);
    padding: 0 var(--space-3);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.9rem;
}
.cyb-gallery-search-input::placeholder { color: var(--text-placeholder); }
.cyb-gallery-search-input:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 1px; }
.cyb-gallery-close { flex: 0 0 auto; }

/* ---- tabs (reuse shared .app-tabs) + tag bar ---- */
/* Keep the shared .app-tabs pill track compact (content-width) rather than stretching
   edge-to-edge — its own justify-content:space-between would otherwise fling the pills apart. */
.cyb-gallery-tabs {
    flex: 0 0 auto;
    width: max-content;
    max-width: calc(100% - (var(--space-4) * 2));
    margin: var(--space-2) var(--space-4) 0;
}
.cyb-gallery-tagbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-4);
    border-bottom: 1px solid var(--border-color);
    flex: 0 0 auto;
    max-height: 6.5rem;
    overflow-y: auto;
}
.cyb-gallery-tagbar.hidden { display: none; }
.cyb-gallery-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    padding: 0.25em 0.7em;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: var(--bg-pane);
    color: var(--text-main);
    font-size: 0.82rem;
    cursor: pointer;
    transition: background var(--anim-fast) var(--anim-ease), border-color var(--anim-fast) var(--anim-ease);
}
.cyb-gallery-tag:hover { background: var(--item-hover); }
.cyb-gallery-tag.active { background: var(--primary-color); border-color: var(--primary-color); color: var(--mix-light); }
.cyb-gallery-tag-count { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.cyb-gallery-tag.active .cyb-gallery-tag-count { color: color-mix(in srgb, var(--mix-light) 85%, transparent); }

/* ---- body + grid ---- */
.cyb-gallery-body { flex: 1 1 auto; min-height: 0; position: relative; overflow: hidden; display: flex; }
/* FIXED-SIZE tiles that simply flow and wrap — deliberately the dumbest layout that
   can work. Every dimension below is explicit (tile width AND thumbnail height come
   from the --cyb-gallery-tile token), so nothing can stretch, shrink, collapse, or
   overlap no matter how the window resizes: changing the viewport only changes how
   many tiles fit per row. Earlier grid/minmax + aspect-ratio approaches let the
   engine negotiate sizes and every negotiation path had a failure mode. */
.cyb-gallery-grid {
    --cyb-gallery-tile: 176px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: flex-start;
    align-items: flex-start;
    gap: var(--space-3);
    padding: var(--space-4);
    /* The browser's own scroll anchoring fights our spacer resizes and shows up as visible jumps. We keep
       the scroll position correct ourselves — spacers are exact — so this must be off. */
    overflow-anchor: none;
    /* Reserve the scrollbar track permanently. Without this, emptying the grid to rebuild it hides the
       scrollbar, which widens the content box, which re-fires the ResizeObserver watching that width, which
       rebuilds the grid again — an observer feedback loop ("undelivered notifications"). A stable gutter
       means the column count cannot depend on how much is currently rendered. */
    scrollbar-gutter: stable;
}
.cyb-gallery-grid.hidden { display: none; }

.cyb-gallery-tile {
    position: relative;
    width: var(--cyb-gallery-tile);
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    gap: 0.4em;
    padding: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    cursor: pointer;
    overflow: hidden;
    text-align: left;
    transition: border-color var(--anim-fast) var(--anim-ease), box-shadow var(--anim-fast) var(--anim-ease), transform var(--anim-fast) var(--anim-ease);
}
.cyb-gallery-tile:hover { border-color: var(--primary-color); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
.cyb-gallery-tile:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; }

.cyb-gallery-thumb {
    position: relative;
    width: 100%;
    /* Explicit square: content box is tile width minus the 1px tile borders. A fixed
       height (not aspect-ratio) so the thumb can never be compressed by the meta row
       or any container sizing negotiation. */
    height: calc(var(--cyb-gallery-tile) - 2px);
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-list-pane);
    overflow: hidden;
}
.cyb-gallery-thumb-glyph { font-size: 2rem; color: var(--text-muted); }
.cyb-gallery-thumb.loaded .cyb-gallery-thumb-glyph { display: none; }
.cyb-gallery-thumb-media { width: 100%; height: 100%; object-fit: cover; display: block; }
.cyb-gallery-tile.kind-audio .cyb-gallery-thumb-media { object-fit: cover; }

.cyb-gallery-tile-meta { padding: 0 0.55em 0.55em; min-width: 0; }
.cyb-gallery-tile-title {
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* ALWAYS rendered, even with nothing to say. Every tile must be exactly the same height: the windowed
   renderer measures one tile and derives every row position and spacer height from it, so a tile that grows
   only when it happens to carry an artist would desynchronise every row below it. min-height reserves the
   line whether or not there is text in it. */
.cyb-gallery-tile-sub {
    font-size: 0.76rem;
    line-height: 1.3;
    min-height: 1.3em;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Stand-ins for the rows the window is not rendering. A 100% flex basis forces a clean wrap, so the rows
   above and below pack exactly as if their tiles were there — which is what keeps the scrollbar honest and
   the scroll position correct without any measure-and-restore.
   Both spacers are ALWAYS in the DOM, even at zero height: they are flex lines, so removing one would drop
   a row-gap and change the total scroll height. Constant beats minimal here. */
.cyb-gallery-spacer {
    flex: 0 0 100%;
    width: 100%;
    height: 0;
    margin: 0;
    padding: 0;
    pointer-events: none;
}

.cyb-gallery-tile-goto {
    position: absolute;
    top: 0.35em;
    right: 0.35em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9em;
    height: 1.9em;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--mix-dark) 55%, transparent);
    color: var(--on-accent);
    opacity: 0;
    transition: opacity var(--anim-fast) var(--anim-ease);
}
.cyb-gallery-tile:hover .cyb-gallery-tile-goto,
.cyb-gallery-tile:focus-within .cyb-gallery-tile-goto { opacity: 1; }
.cyb-gallery-tile-goto :is(svg, i) { width: 0.95em; height: 0.95em; }

/* ---- playlist cover controls (owner: utils/PlaylistCoverArt.js via the gallery tile) ----
   Top-RIGHT: the top-left corner is .cyb-gallery-tile-kindbadge ("Playlist"), which is exactly what these
   tiles always carry, and the top-right .cyb-gallery-tile-goto is the "open the note this lives in" button
   — which a playlist never has, because a playlist belongs to no note. Above the badge's z-index so the
   two can never trade places. Hidden until the tile is hovered or holds focus, same as the goto button: a
   grid of playlists should read as pictures, not as a grid of buttons. On a touch device there is no hover,
   so `any-hover: none` keeps them permanently visible at reduced opacity rather than unreachable. */
.cyb-gallery-tile-coverctl {
    position: absolute;
    z-index: 2;
    top: 0.35em;
    right: 0.35em;
    display: flex;
    gap: 0.25em;
    opacity: 0;
    transition: opacity var(--anim-fast) var(--anim-ease);
}
.cyb-gallery-tile:hover .cyb-gallery-tile-coverctl,
.cyb-gallery-tile:focus-within .cyb-gallery-tile-coverctl { opacity: 1; }
@media (any-hover: none) {
    .cyb-gallery-tile-coverctl { opacity: 0.8; }
}
.cyb-gallery-tile-coverbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9em;
    height: 1.9em;
    border-radius: var(--radius-sm);
    background: var(--cyb-gallery-tile-scrim);
    color: var(--cyb-gallery-tile-scrim-text);
    cursor: pointer;
    line-height: 1;
}
.cyb-gallery-tile-coverbtn:hover { background: var(--cyb-gallery-tile-scrim-hover); }
.cyb-gallery-tile-coverbtn:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 1px; }
.cyb-gallery-tile-coverbtn[hidden] { display: none; }
.cyb-gallery-tile-coverbtn :is(svg, i) { width: 0.95em; height: 0.95em; }
.cyb-gallery-tile-coverclear { font-size: 1.05em; }

/* ---- empty state ---- */
.cyb-gallery-empty {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    color: var(--text-muted);
    text-align: center;
    padding: var(--space-4);
}
.cyb-gallery-empty.hidden { display: none; }
.cyb-gallery-empty p { margin: 0; }
.cyb-gallery-empty-hint { font-size: 0.85rem; max-width: 32ch; }

/* ---- now-playing strip (audio preview) ---- */
.cyb-gallery-nowplaying {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    border-top: 1px solid var(--border-color);
    background: var(--bg-pane);
    flex: 0 0 auto;
}
.cyb-gallery-nowplaying.hidden { display: none; }
.cyb-gallery-nowplaying-cover {
    width: 44px; height: 44px; flex: 0 0 auto;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-sm);
    background: var(--bg-list-pane);
    color: var(--text-muted);
    overflow: hidden;
}
.cyb-gallery-nowplaying-cover img { width: 100%; height: 100%; object-fit: cover; }
.cyb-gallery-nowplaying-meta { min-width: 0; flex: 0 1 auto; }
.cyb-gallery-nowplaying-title { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cyb-gallery-nowplaying-artist { font-size: 0.8rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cyb-gallery-nowplaying-audio { flex: 1 1 auto; min-width: 120px; max-width: 520px; }
.cyb-gallery-nowplaying-stop { flex: 0 0 auto; }

/* ---- in-overlay viewer (images/video) — scrim, single layer ---- */
.cyb-gallery-viewer {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--mix-dark) 90%, transparent);
}
.cyb-gallery-viewer.hidden { display: none; }
.cyb-gallery-viewer-stage {
    max-width: 92vw;
    max-height: 84vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cyb-gallery-viewer-media { max-width: 92vw; max-height: 84vh; object-fit: contain; border-radius: var(--radius-sm); }
.cyb-gallery-viewer-caption {
    position: absolute;
    bottom: var(--space-3);
    left: 50%;
    transform: translateX(-50%);
    max-width: 80vw;
    color: var(--on-accent);
    background: color-mix(in srgb, var(--mix-dark) 50%, transparent);
    padding: 0.3em 0.8em;
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Viewer controls sit on the dark scrim — force a dark translucent chip so the white
   glyphs read (the base .icon-btn has a light surface background). */
.cyb-gallery-viewer-close,
.cyb-gallery-viewer-nav {
    position: absolute;
    color: var(--on-accent);
    background: color-mix(in srgb, var(--mix-dark) 50%, transparent);
    border: 1px solid transparent;
}
.cyb-gallery-viewer-close { top: var(--space-3); right: var(--space-3); }
.cyb-gallery-viewer-nav {
    top: 50%;
    transform: translateY(-50%);
    width: 2.6em; height: 2.6em;
}
.cyb-gallery-viewer-nav.prev { left: var(--space-3); }
.cyb-gallery-viewer-nav.next { right: var(--space-3); }
.cyb-gallery-viewer-close:hover,
.cyb-gallery-viewer-nav:hover { background: color-mix(in srgb, var(--mix-light) 15%, transparent); }

/* ---- responsive: tighter grid on small screens (mobile uses the same overlay) ---- */
@media (max-width: 768px) {
    .cyb-gallery-header { flex-wrap: wrap; gap: var(--space-2); }
    .cyb-gallery-search { flex-basis: 100%; order: 3; margin-left: 0; }
    /* Smaller fixed tile for phones: 152px gives 2 big thumbnails on a ~360–400px
       screen and 3 on a ~500px+ screen, with the grid centring the remainder. The tile
       stays a fixed size — it never stretches — so resizing/rotating only changes how
       many fit per row, never the tile's dimensions. */
    .cyb-gallery-grid { --cyb-gallery-tile: 152px; gap: var(--space-2); padding: var(--space-2); }
    .cyb-gallery-nowplaying-audio { max-width: none; }
}

/* ---- link-mode audio (SUNO "Link" imports) ----
   These songs live on disk, not in the DB, so the library can hold items the app
   can't currently reach: a FileSystemDirectoryHandle loses read permission between
   browser sessions. The notice bar owns the re-grant gesture; the tile badge marks
   which items it applies to. Warning accent only — no new tokens, the surface is
   the normal pane so the bar reads as informative rather than as an error. */
.cyb-gallery-link-notice {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    background: var(--bg-pane);
    border-bottom: 1px solid var(--border-color);
    border-left: 3px solid var(--warning-color);
}
.cyb-gallery-link-notice.hidden { display: none; }
.cyb-gallery-link-notice-msg {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
}
.cyb-gallery-link-notice-btn { flex: 0 0 auto; white-space: nowrap; }

/* ---- playlist cards ---- */
/* A playlist is a COLLECTION, not a file — the tile has to say so before it's read. Two cues do it:
   a "Playlist" pill, and two offset edges across the top of the cover (the universal "stack of things"
   shorthand). Both are OVERLAYS on the existing tile: the fixed tile/thumb geometry above is what makes
   this grid immune to layout negotiation, so nothing here touches width, height or flow. */
.cyb-gallery-tile.kind-playlist .cyb-gallery-thumb { background: var(--selection-color); }
.cyb-gallery-tile.kind-playlist .cyb-gallery-thumb-glyph {
    font-size: 2.6rem;
    color: var(--primary-color);
}
.cyb-gallery-tile.kind-playlist .cyb-gallery-thumb::before,
.cyb-gallery-tile.kind-playlist .cyb-gallery-thumb::after {
    content: '';
    position: absolute;
    height: 4px;
    border-radius: 0 0 var(--radius-sm) var(--radius-sm);
    pointer-events: none;
}
/* Back sheet (narrowest, flush with the top edge), then the one in front of it. */
.cyb-gallery-tile.kind-playlist .cyb-gallery-thumb::before {
    top: 0;
    left: 16%;
    right: 16%;
    background: var(--pane-divider);
}
.cyb-gallery-tile.kind-playlist .cyb-gallery-thumb::after {
    top: 4px;
    left: 9%;
    right: 9%;
    background: var(--border-color);
}
.cyb-gallery-tile-kindbadge {
    position: absolute;
    /* Above the thumb: both are positioned, so without this the later-in-DOM thumb paints over it. */
    z-index: 1;
    top: var(--space-1);
    left: var(--space-1);
    padding: 0.15em 0.5em;
    border-radius: var(--radius-sm);
    background: var(--primary-color);
    color: var(--on-accent); /* on-accent text: the accent is a fixed brand color in both themes */
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.5;
}

/* Unreachable link-mode tile: dim the artwork and stamp a corner badge, so a tap that
   opens the re-grant prompt instead of playing is not a surprise. */
.cyb-gallery-tile[data-link-state] .cyb-gallery-thumb { opacity: 0.55; }
.cyb-gallery-tile[data-link-state] .cyb-gallery-tile-title { color: var(--text-muted); }
.cyb-gallery-tile-linkbadge {
    position: absolute;
    top: var(--space-1);
    left: var(--space-1);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.5em;
    height: 1.5em;
    border-radius: var(--radius-sm);
    background: var(--warning-color);
    color: var(--bg-pane);
    font-size: 0.8rem;
    line-height: 1;
}
/* ===========================================================================
   Playlist Cover Picker — modal grid of the library's images.
   Owner: utils/PlaylistCoverPickerDialog.js. Feature-scoped under .cyb-coverpick-*.
   Rides the shared .modal-overlay / .modal-box / .glass-dialog shell; everything
   below is the grid, the tiles and the footer that shell does not provide.
   All colour via semantic tokens (000-tokens-base.css) → light + dark for free.
   =========================================================================== */

/* Compound selector on purpose: `.modal-overlay.glass-overlay` in 180-dialogs-overlays.css pins every glass
   overlay to z-index 5000, and a single-class rule loses to it on specificity no matter which file comes
   later. 5600 clears BOTH surfaces that open this picker — the media library overlay (3000) and the music
   panel shell (5150), a floating panel that would otherwise paint over the dialog's own header. */
.modal-overlay.glass-overlay.cyb-coverpick-overlay {
    z-index: 5600;
}

.cyb-coverpick-dialog {
    width: min(94vw, 720px);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
}

.cyb-coverpick-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    min-height: 0;      /* lets the grid below actually scroll instead of stretching the dialog */
    overflow: hidden;
}

.cyb-coverpick-lede {
    margin: 0;
}

.cyb-coverpick-search {
    width: 100%;
}

/* auto-fill, not auto-fit: a search that matches one image should leave a normal-sized tile rather than
   stretching it across the whole dialog.
   grid-auto-rows + align-content are LOAD-BEARING, not tidiness. A grid whose container height is capped
   (max-height here, and flex-shrink from the dialog above) will squeeze its auto-sized rows to fit rather
   than overflow: at 60 tiles every row collapsed to a ~12px strip with its label clipped away, and only
   grew back once enough rows existed to force a scrollbar. `max-content` rows can never be compressed and
   `start` packing stops them being stretched the other way, so the container scrolls at any row count. */
.cyb-coverpick-grid {
    flex: 1 1 auto;
    min-height: 8rem;
    max-height: 52vh;
    overflow-y: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    grid-auto-rows: max-content;
    align-content: start;
    gap: var(--space-2);
    padding: var(--space-1);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-app);
}

.cyb-coverpick-tile {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 4px;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: var(--bg-pane);
    color: var(--text-main);
    cursor: pointer;
    text-align: left;
    overflow: hidden;
}
.cyb-coverpick-tile:hover {
    border-color: var(--border-color);
    background: var(--item-hover);
}
.cyb-coverpick-tile:focus-visible { outline: 2px solid var(--primary-color); outline-offset: 2px; }
.cyb-coverpick-tile[aria-selected="true"] {
    border-color: color-mix(in srgb, var(--primary-color) 55%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 12%, var(--bg-pane));
}

/* Square well, so a grid of mixed aspect ratios still reads as rows. The glyph behind the picture is what
   a tile shows while its thumbnail is being minted, and what it keeps if the image cannot be decoded.
   `flex: 0 0 auto` so the tile's column flex can never shrink the square away — the same collapse the grid
   rules above defend against, one level down. */
.cyb-coverpick-thumb {
    position: relative;
    flex: 0 0 auto;
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-sm);
    background: var(--bg-app);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cyb-coverpick-thumb::before {
    content: '▦';
    color: var(--text-muted);
    font-size: 1.5rem;
    line-height: 1;
}
.cyb-coverpick-thumb-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.cyb-coverpick-tile-label {
    font-size: 0.78rem;
    line-height: 1.25;
    color: var(--text-muted);
    /* Two lines then ellipsis: filenames are long and a tile must not grow to fit one. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

.cyb-coverpick-status {
    font-size: 0.82rem;
    color: var(--text-muted);
    min-height: 1.1em;
}

.cyb-coverpick-more {
    align-self: center;
}
.cyb-coverpick-more.hidden { display: none; }

.cyb-coverpick-footer {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-4);
    border-top: 1px solid var(--border-color);
}
.cyb-coverpick-spacer { flex: 1 1 auto; }
.cyb-coverpick-remove { color: var(--danger-color); }
.cyb-coverpick-remove.hidden { display: none; }

/* Phones: the footer's five controls cannot share one line, and the grid gets the height back. */
@media (max-width: 560px) {
    .cyb-coverpick-grid {
        grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
        max-height: 46vh;
    }
    .cyb-coverpick-footer {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }
    .cyb-coverpick-spacer { display: none; }
}
/* Folder tree (was the root-level tree.css linked from index.html; pulled into the build in Phase 10). */

/* --- Tree Component Styles --- */

.tree-component {
    padding-bottom: 20px;
}

.tree-list {
    list-style: none;
    padding-left: 0;
    margin: 0;
}

.tree-list.nested-list {
    padding-left: 18px; /* Indentation */
    margin-left: 4px;
    border-left: 1px solid color-mix(in srgb, var(--mix-dark) 5%, transparent); /* Optional guide line */
    display: block;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transform: translateY(-2px);
    transition: max-height 180ms cubic-bezier(.2,.8,.2,1), opacity 150ms ease, transform 180ms cubic-bezier(.2,.8,.2,1);
}

.tree-list.nested-list.expanded {
    max-height: 99999px;
    opacity: 1;
    transform: translateY(0);
    overflow: visible;
}

.tree-list.nested-list.collapsed {
    max-height: 0;
    opacity: 0;
    transform: translateY(-2px);
}

/* Item Wrapper */
.tree-item {
    margin-bottom: 1px;
}

/* Content Row */
.tree-content {
    display: flex;
    align-items: center;
    padding: 6px 8px;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text-main);
    user-select: none;
    position: relative; /* For Pseudo-elements if needed */
    transition: background-color 140ms cubic-bezier(.2,.8,.2,1), color 140ms cubic-bezier(.2,.8,.2,1), box-shadow 140ms cubic-bezier(.2,.8,.2,1);
}

.tree-content-actions {
    display: inline-flex;
    align-items: center;
    margin-left: 6px;
    flex-shrink: 0;
}

.tree-menu-btn {
    width: 28px;
    height: 28px;
    border: 1px solid color-mix(in srgb, var(--border-color) 88%, transparent);
    border-radius: 7px;
    background: color-mix(in srgb, var(--bg-pane) 86%, transparent);
    color: var(--text-muted);
    font-size: 16px;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.tree-menu-btn:hover {
    color: var(--primary-color);
    border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border-color));
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-pane));
}

.tree-content:hover {
    background-color: var(--item-hover);
}

.tree-item.active > .tree-content {
    background-color: var(--selection-color);
    color: var(--primary-color);
    font-weight: 500;
    box-shadow: inset 0 0 0 1px var(--primary-alpha-18);
}

.tree-item.selected > .tree-content {
    background-color: color-mix(in srgb, var(--primary-color) 12%, transparent);
    color: var(--primary-color);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--primary-color) 22%, transparent);
}

.tree-item.active.selected > .tree-content {
    background-color: var(--primary-alpha-18);
}

/* Dragging Source */
.tree-item.dragging > .tree-content {
    opacity: 0.5;
    background: var(--item-hover);
}

.tree-item.gdrive-tree-folder > .tree-content {
    background-image:
        linear-gradient(90deg,
            rgba(66, 133, 244, 0.12) 0%, /* literal-ok: Google Drive brand colours */
            rgba(66, 133, 244, 0.12) 24%, /* literal-ok: Google Drive brand colours */
            rgba(52, 168, 83, 0.12) 24%, /* literal-ok: Google Drive brand colours */
            rgba(52, 168, 83, 0.12) 48%, /* literal-ok: Google Drive brand colours */
            rgba(251, 188, 5, 0.12) 48%, /* literal-ok: Google Drive brand colours */
            rgba(251, 188, 5, 0.12) 72%, /* literal-ok: Google Drive brand colours */
            rgba(234, 67, 53, 0.12) 72%, /* literal-ok: Google Drive brand colours */
            rgba(234, 67, 53, 0.12) 100%), /* literal-ok: Google Drive brand colours */
        linear-gradient(135deg,
            color-mix(in srgb, var(--mix-light) 12%, transparent) 0%,
            color-mix(in srgb, var(--mix-light) 12%, transparent) 25%,
            color-mix(in srgb, var(--mix-light) 2%, transparent) 25%,
            color-mix(in srgb, var(--mix-light) 2%, transparent) 50%,
            color-mix(in srgb, var(--mix-light) 12%, transparent) 50%,
            color-mix(in srgb, var(--mix-light) 12%, transparent) 75%,
            color-mix(in srgb, var(--mix-light) 2%, transparent) 75%,
            color-mix(in srgb, var(--mix-light) 2%, transparent) 100%);
    background-size: 100% 100%, 10px 10px;
    box-shadow: inset 0 0 0 1px rgba(66, 133, 244, 0.14); /* literal-ok: Google Drive brand colours */
}

.tree-item.gdrive-tree-folder > .tree-content:hover {
    background-image:
        linear-gradient(90deg,
            rgba(66, 133, 244, 0.18) 0%, /* literal-ok: Google Drive brand colours */
            rgba(66, 133, 244, 0.18) 24%, /* literal-ok: Google Drive brand colours */
            rgba(52, 168, 83, 0.18) 24%, /* literal-ok: Google Drive brand colours */
            rgba(52, 168, 83, 0.18) 48%, /* literal-ok: Google Drive brand colours */
            rgba(251, 188, 5, 0.18) 48%, /* literal-ok: Google Drive brand colours */
            rgba(251, 188, 5, 0.18) 72%, /* literal-ok: Google Drive brand colours */
            rgba(234, 67, 53, 0.18) 72%, /* literal-ok: Google Drive brand colours */
            rgba(234, 67, 53, 0.18) 100%), /* literal-ok: Google Drive brand colours */
        linear-gradient(135deg,
            color-mix(in srgb, var(--mix-light) 18%, transparent) 0%,
            color-mix(in srgb, var(--mix-light) 18%, transparent) 25%,
            color-mix(in srgb, var(--mix-light) 4%, transparent) 25%,
            color-mix(in srgb, var(--mix-light) 4%, transparent) 50%,
            color-mix(in srgb, var(--mix-light) 18%, transparent) 50%,
            color-mix(in srgb, var(--mix-light) 18%, transparent) 75%,
            color-mix(in srgb, var(--mix-light) 4%, transparent) 75%,
            color-mix(in srgb, var(--mix-light) 4%, transparent) 100%);
}

.tree-item.gdrive-tree-folder > .tree-content .tree-icon {
    position: relative;
    width: 22px;
    height: 22px;
    margin-right: 8px;
    justify-content: center;
    color: var(--on-accent);
    border-radius: 7px;
    background:
        linear-gradient(135deg,
            #4285f4 0%, /* literal-ok: Google Drive brand colours */
            #4285f4 26%, /* literal-ok: Google Drive brand colours */
            #34a853 26%, /* literal-ok: Google Drive brand colours */
            #34a853 52%, /* literal-ok: Google Drive brand colours */
            #fbbc05 52%, /* literal-ok: Google Drive brand colours */
            #fbbc05 78%, /* literal-ok: Google Drive brand colours */
            #ea4335 78%, /* literal-ok: Google Drive brand colours */
            #ea4335 100%); /* literal-ok: Google Drive brand colours */
    box-shadow:
        0 1px 2px color-mix(in srgb, var(--mix-dark) 14%, transparent),
        inset 0 0 0 1px color-mix(in srgb, var(--mix-light) 28%, transparent);
}

.tree-item.gdrive-tree-folder > .tree-content .tree-icon::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: linear-gradient(135deg, color-mix(in srgb, var(--mix-light) 28%, transparent), color-mix(in srgb, var(--mix-light) 4%, transparent));
    pointer-events: none;
}

.tree-item.gdrive-tree-folder > .tree-content .tree-icon svg {
    position: relative;
    z-index: 1;
}

.tree-item.gdrive-tree-folder > .tree-content .label {
    font-weight: 500;
}

.tree-item.gdrive-tree-folder.active > .tree-content,
.tree-item.gdrive-tree-folder.selected > .tree-content,
.tree-item.gdrive-tree-folder.active.selected > .tree-content {
    background-image: none;
}

.tree-item.gdrive-tree-folder.active > .tree-content .tree-icon,
.tree-item.gdrive-tree-folder.selected > .tree-content .tree-icon,
.tree-item.gdrive-tree-folder.active.selected > .tree-content .tree-icon {
    color: var(--on-accent);
}

/* Drop Targets */
.tree-content.drop-inside {
    background-color: var(--primary-alpha-10);
    outline: 2px dashed var(--primary-color);
    outline-offset: -2px;
}

.tree-content.drop-before {
    border-top: 2px solid var(--primary-color);
}

.tree-content.drop-after {
    border-bottom: 2px solid var(--primary-color);
}

/* Icons */
.tree-icon {
    display: flex;
    align-items: center;
    margin-right: 6px;
    color: var(--text-muted);
}
.tree-icon svg {
    width: 16px;
    height: 16px;
}

.tree-item.active > .tree-content .tree-icon {
    color: var(--primary-color);
}

/* Toggle (+/-) */
.tree-toggle {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    width: 16px;
    height: 16px;
    margin-right: 4px;
    font-family: monospace;
    font-weight: bold;
    color: var(--text-muted);
    border-radius: 2px;
    transition: background-color 140ms cubic-bezier(.2,.8,.2,1), color 140ms cubic-bezier(.2,.8,.2,1);
}
.tree-toggle:hover {
    background: color-mix(in srgb, var(--mix-dark) 10%, transparent);
    color: var(--text-main);
}
.tree-toggle.placeholder {
    visibility: hidden;
}

/* Label */
.label {
    flex-grow: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (max-width: 768px), (hover: none) and (pointer: coarse), (any-pointer: coarse) {
    .tree-content-actions {
        display: inline-flex;
    }

    .tree-menu-btn {
        display: inline-flex;
    }
}

body.touch-device-ui .tree-content-actions {
    display: inline-flex;
}

body.touch-device-ui .tree-menu-btn {
    display: inline-flex;
}
/* Log viewer + database viewer dialogs (was the root-level log-viewer.css linked from index.html; pulled into the build in Phase 10). */

/* Log Viewer Styles */
.overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: color-mix(in srgb, var(--mix-dark) 50%, transparent);
    z-index: 2000;
    display: flex;
    justify-content: center;
    align-items: center;
}

.overlay.hidden {
    display: none !important;
}

.log-viewer-modal {
    width: 90%;
    max-width: 1000px;
    height: 80vh;
    background: var(--bg-pane);
    color: var(--text-main);
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    box-shadow: 0 10px 25px color-mix(in srgb, var(--mix-dark) 20%, transparent);
}

.log-header {
    padding: 16px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.log-controls {
    display: flex;
    gap: 10px;
    align-items: center;
}

.log-controls input {
    padding: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    border-radius: 4px;
    font-size: 0.9rem;
}

.log-controls select {
    padding: 6px;
    border: 1px solid var(--border-color);
    background: var(--bg-pane);
    color: var(--text-main);
    border-radius: 4px;
    font-size: 0.9rem;
}

.log-content {
    flex: 1;
    overflow: auto;
    padding: 0;
}

.log-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
    table-layout: fixed;
}

.log-table th, .log-table td {
    padding: 8px 12px;
    text-align: left;
    border-bottom: 1px solid var(--border-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.log-table th {
    background: var(--bg-sidebar);
    position: sticky;
    top: 0;
    border-bottom: 2px solid var(--border-color);
    z-index: 10;
}

.log-table tbody tr:hover {
    background-color: var(--item-hover);
    cursor: pointer;
}

.log-table tbody tr.selected {
    background-color: var(--selection-color);
}

.log-table .level-ERROR { color: var(--danger-color); font-weight: bold; }
.log-table .level-WARN { color: var(--warning-color); font-weight: bold; }
.log-table .level-INFO { color: var(--primary-color); }

.log-footer {
    padding: 8px 16px;
    border-top: 1px solid var(--border-color);
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* Database viewer specific layout */
#db-viewer-overlay .db-viewer-modal {
    width: 90%;
    height: 90%;
    max-width: 1200px;
}

#db-viewer-overlay .db-controls {
    flex-grow: 1;
    justify-content: flex-end;
    gap: 10px;
    min-width: 0;
}

#db-viewer-overlay .db-table-select {
    min-width: 180px;
}

#db-viewer-overlay .db-query-input {
    flex: 1 1 420px;
    min-width: 220px;
    margin: 0;
}

#db-viewer-overlay .db-log-content {
    overflow: auto;
}

#db-viewer-overlay .db-log-table {
    width: 100%;
    border-collapse: collapse;
}

#db-viewer-overlay .db-log-footer {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 10px;
}

#db-viewer-overlay .db-pagination {
    display: flex;
    gap: 6px;
    align-items: center;
    min-width: 0;
}

#db-viewer-overlay #db-page-info {
    font-size: 0.9rem;
    margin: 0 8px;
    min-width: 100px;
    text-align: center;
}

#db-viewer-overlay #db-status {
    min-width: 0;
    font-size: 0.85rem;
    color: var(--text-muted);
    text-align: right;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#db-viewer-overlay .db-close-footer-btn {
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 4px 12px;
    font-size: 0.9rem;
}

/* Log Detail Dialog */
.log-dialog {
    padding: 0;
    border: none;
    background: var(--bg-pane);
    color: var(--text-main);
    border-radius: 8px;
    box-shadow: 0 10px 25px color-mix(in srgb, var(--mix-dark) 30%, transparent);
    width: 600px;
    max-width: 90vw;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    position: fixed;
    z-index: 2100;
}

.log-dialog::backdrop {
    background: color-mix(in srgb, var(--mix-dark) 40%, transparent);
}

.dialog-header {
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: var(--bg-sidebar);
}

.dialog-body {
    padding: 16px;
    max-height: 60vh;
    overflow-y: auto;
}

.detail-row {
    margin-bottom: 8px;
}

.detail-section {
    margin-top: 12px;
}

.detail-section strong {
    display: block;
    margin-bottom: 4px;
}

.code-block {
    background: var(--code-bg);
    color: var(--code-fg);
    padding: 10px;
    border-radius: 4px;
    font-family: monospace;
    font-size: 0.85rem;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 150px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
}

.dialog-footer {
    padding: 12px 16px;
    border-top: 1px solid var(--border-color);
    text-align: right;
    background: var(--bg-sidebar);
}

/* DB row details */
.db-row-detail-dialog {
    width: min(820px, 95vw);
}

#db-maintenance-dialog {
    width: min(500px, 92vw);
}

#db-maintenance-dialog .dialog-body {
    max-height: min(62vh, 520px);
}

.db-row-detail-body {
    max-height: 70vh;
}

.db-row-detail-meta {
    margin-bottom: 12px;
    font-size: 0.85rem;
    color: var(--text-muted);
}

.db-row-detail-fields {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
}

.db-detail-item {
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 10px;
    background: var(--bg-pane);
}

.db-detail-key {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text-muted);
    margin-bottom: 6px;
    letter-spacing: 0.02em;
}

.db-detail-value {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 0.9rem;
    line-height: 1.35;
}

.db-detail-object {
    margin-top: 8px;
    background: var(--code-bg);
    color: var(--code-fg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 8px;
    white-space: pre-wrap;
    word-break: break-word;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
    font-size: 0.82rem;
    max-height: 240px;
    overflow: auto;
}

@media (max-width: 768px) {
    #db-viewer-overlay .db-viewer-modal {
        width: 96vw;
        height: 92vh;
        max-width: none;
    }

    #db-viewer-overlay .log-header {
        padding: 12px;
        gap: 10px;
        align-items: stretch;
        flex-direction: column;
    }

    #db-viewer-overlay .log-header h2 {
        margin: 0;
        font-size: 1.15rem;
        line-height: 1.2;
    }

    #db-viewer-overlay .db-controls {
        display: grid;
        grid-template-columns: 1fr auto auto auto;
        gap: 8px;
        align-items: center;
    }

    #db-viewer-overlay .db-table-select {
        min-width: 0;
        width: 100%;
    }

    #db-viewer-overlay .db-query-input {
        grid-column: 1 / -1;
        min-width: 0;
        width: 100%;
    }

    #db-viewer-overlay .log-content {
        min-height: 0;
    }

    #db-viewer-overlay .db-log-footer {
        grid-template-columns: 1fr auto;
        grid-template-areas:
            'status status'
            'pager close';
        gap: 8px;
        padding: 10px 12px;
    }

    #db-viewer-overlay #db-status {
        grid-area: status;
        text-align: left;
        white-space: normal;
        overflow: visible;
        text-overflow: initial;
        line-height: 1.25;
        font-size: 0.8rem;
    }

    #db-viewer-overlay .db-pagination {
        grid-area: pager;
        overflow-x: auto;
        padding-bottom: 2px;
    }

    #db-viewer-overlay #db-page-info {
        min-width: 86px;
        margin: 0 4px;
        font-size: 0.86rem;
    }

    #db-viewer-overlay .db-close-footer-btn {
        grid-area: close;
        justify-self: end;
        min-height: 38px;
        padding: 6px 12px;
    }

    #db-viewer-overlay .db-pagination .icon-btn-small {
        min-width: 36px;
        min-height: 36px;
    }

    #db-maintenance-dialog {
        width: 96vw;
        max-width: 96vw !important;
        max-height: 90dvh;
        border-radius: 12px;
    }

    #db-maintenance-dialog .dialog-header {
        padding: 10px 12px;
    }

    #db-maintenance-dialog .dialog-header h3 {
        margin: 0;
        font-size: 1rem;
        line-height: 1.2;
    }

    #db-maintenance-dialog .dialog-body {
        padding: 12px !important;
        max-height: calc(90dvh - 126px);
        overflow-y: auto;
    }

    #db-maintenance-dialog #maintenance-loading {
        padding: 8px !important;
    }

    #db-maintenance-dialog #maint-loading-stage {
        font-size: 0.86rem !important;
    }

    #db-maintenance-dialog #maint-loading-hint {
        font-size: 0.8rem !important;
        line-height: 1.32;
    }

    #db-maintenance-dialog #maint-recommendation {
        margin-bottom: 12px !important;
        font-size: 0.9rem;
        line-height: 1.35;
    }

    #db-maintenance-dialog .dialog-footer {
        display: grid !important;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px !important;
        padding: 10px 12px;
    }

    #db-maintenance-dialog .dialog-footer button {
        min-width: 0;
        min-height: 40px;
        padding: 8px 10px !important;
        font-size: 0.88rem;
    }

    .db-row-detail-dialog {
        width: 96vw;
    }

    .db-row-detail-body {
        max-height: 75vh;
        padding: 12px;
    }

    .db-detail-item {
        padding: 9px;
    }
}

/* Log viewer — mobile header layout so every control/button stays on screen.
   On phones the single-row flex header overflows and pushes the JS-injected
   Download / DB-health buttons off the right edge; stack the header and lay the
   controls out as a grid (level + search full-width, then a row of buttons). */
@media (max-width: 768px) {
    #log-viewer-overlay .log-viewer-modal {
        width: 96vw;
        height: 92vh;
        max-width: none;
    }

    #log-viewer-overlay .log-header {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        padding: 12px;
    }

    #log-viewer-overlay .log-header h2 {
        margin: 0;
        font-size: 1.15rem;
        line-height: 1.2;
    }

    #log-viewer-overlay .log-controls {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 8px;
        align-items: center;
    }

    /* Level select and search box each take their own full-width row. */
    #log-viewer-overlay .log-controls select,
    #log-viewer-overlay .log-controls input {
        grid-column: 1 / -1;
        width: 100%;
        min-width: 0;
    }

    /* Refresh / DB-health / Download / Close share the final row, evenly sized.
       margin override defeats the inline marginLeft set on injected buttons. */
    #log-viewer-overlay .log-controls .icon-btn,
    #log-viewer-overlay .log-controls .icon-btn-small {
        margin: 0 !important;
        min-height: 40px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}

/* Column Resizer */
.log-table th {
    position: sticky; /* Keep sticky behavior */
}

.resizer {
    position: absolute;
    top: 0;
    right: 0;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    user-select: none;
    z-index: 20;
    background: transparent;
}

.resizer:hover,
.resizing {
    background: var(--primary-color);
    opacity: 0.5;
}

/* Loading Toast */
.loading-toast {
    position: absolute;
    top: 25%;
    left: 50%;
    transform: translateX(-50%);
    background-color: var(--overlay-chrome-bg);
    color: white;
    padding: 12px 24px;
    border-radius: 20px;
    font-size: 1rem;
    font-weight: 500;
    z-index: 3000;
    box-shadow: 0 4px 15px color-mix(in srgb, var(--mix-dark) 20%, transparent);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.loading-toast.hidden {
    display: none !important;
}

.blinking-dots {
    animation: blink-animation 1s step-start infinite;
    display: inline-block;
    margin-left: 2px;
}

@keyframes blink-animation {
    50% { opacity: 0; }
}
