/* ============================================================
   Octacer Design System — canonical bridge layer (single source of truth)
   Origin: octa-id (id.octacer.info). Copy this file verbatim into
   each satellite's wwwroot/css/ so every Octacer app looks identical.

   CASCADE CONTRACT (Tailwind v4): this file declares the same layer order Tailwind uses,
   puts element defaults in @layer base and every .oc-* / .btn / .field-* rule in
   @layer components. Tailwind utilities live in @layer utilities, so a utility on an
   element (hidden, w-40, p-0, rounded-none ...) ALWAYS beats the component default,
   exactly like Tailwind's own component classes. Only the design tokens (:root / .dark
   custom properties) are unlayered. Never add unlayered selectors to this file.
   Deep indigo / slate brand. Light + dark both supported.
   ============================================================ */
@layer theme, base, components, utilities;

:root {
    color-scheme: light;

    /* Brand — deep indigo */
    --brand-50:  #eef2ff;
    --brand-100: #e0e7ff;
    --brand-500: #6366f1;
    --brand-600: #4f46e5;
    --brand-700: #4338ca;
    --brand-800: #3730a3;

    /* Public brand tokens. Apps may override these once in their own theme layer. */
    --primary: var(--brand-600);
    --primary-active: var(--brand-700);
    --primary-foreground: #ffffff;

    /* Ink / slate neutrals */
    --ink-900: #0f172a;
    --ink-700: #334155;
    --ink-600: #475569;
    --ink-500: #64748b;
    --ink-400: #94a3b8;
    --line:    #e2e8f0;
    --line-2:  #f1f5f9;
    --line-strong: #dbe1ea;   /* slightly darker hairline — card hover / active borders */
    --surface: #ffffff;
    --popover: #ffffff;              /* elevated surface (menus/popovers) — a distinct rung in dark */
    --bg:      #f8fafc;
    --surface-muted: #f8fafc;
    --input:   var(--line);          /* field border; lighter than --line in dark so inputs read editable */
    --overlay: rgb(15 23 42 / 0.5);  /* modal / drawer / sidebar scrim */

    /* State — solid (fill), foreground (text on solid), subtle (tinted bg) + subtle-foreground.
       Solids/foregrounds are mode-invariant (coloured chips/buttons); subtles flip in .dark. */
    --success: #059669;  --success-foreground: #ffffff;
    --warning: #d97706;  --warning-foreground: #ffffff;
    --danger:  #dc2626;  --danger-foreground:  #ffffff;
    --info:    #2563eb;  --info-foreground:    #ffffff;
    --success-subtle: #ecfdf5;  --success-subtle-foreground: #065f46;
    --warning-subtle: #fffbeb;  --warning-subtle-foreground: #92400e;
    --danger-subtle:  #fef2f2;  --danger-subtle-foreground:  #991b1b;
    --info-subtle:    #eff6ff;  --info-subtle-foreground:    #1e40af;

    /* Chart palette — distinct, accessible hues (surfaced to Tailwind as --color-chart-N,
       consumed by octacer-charts.js / _ChartCard). Lightened in .dark for dark canvases. */
    --chart-1: var(--brand-600);
    --chart-2: #22c55e;
    --chart-3: #f59e0b;
    --chart-4: #ec4899;
    --chart-5: #06b6d4;

    /* Typography: use semantic classes for values/code so content remains intentional. */
    --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --tracking-normal: -0.006em;   /* body default; base of the Tailwind tracking-* scale */

    /* Brand/mono gradients. Apps can replace these variables without changing components. */
    --gradient-brand: linear-gradient(135deg, var(--brand-800) 0%, var(--brand-600) 52%, var(--brand-500) 100%);
    --gradient-mono: linear-gradient(135deg, #0f172a 0%, #334155 52%, #64748b 100%);
    --gradient-surface: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);

    --radius:   0.5rem;    /* 8px — Tailwind rounded-lg */
    --radius-sm: calc(var(--radius) - 2px);   /* 6px  — Tailwind rounded-sm */
    --radius-md: calc(var(--radius) - 1px);   /* 7px  — Tailwind rounded-md */
    --radius-lg: .625rem;  /* 10px — .oc-card / .oc-modal-panel (≈ Tailwind rounded-xl) */
    --radius-xl: calc(var(--radius) + 4px);   /* 12px — Tailwind rounded-xl */
    --radius-2xl: calc(var(--radius) + 8px);  /* 16px — sheets */
    /* Focus ring: opaque 2px brand ring separated by a surface gap — ≥3:1 on every surface. */
    --ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand-500);
    --ring-inset: inset 0 0 0 2px var(--brand-500);

    /* Accent ink/tint — text/fill for "selected" states. Mode-aware (brand-700 fails AA on dark). */
    --primary-ink: var(--brand-700);
    --primary-tint: var(--brand-50);
    --primary-tint-border: var(--brand-100);

    /* Z-index scale — the ONLY stacking values components may use (var(--z-*)). */
    --z-sticky: 20;          /* sticky table heads, sticky tabs */
    --z-header: 30;          /* app bar / page header */
    --z-tabbar: 40;          /* bottom tab bar */
    --z-fab: 41;             /* floating action button, back-to-top */
    --z-sidebar-scrim: 44;   /* mobile drawer scrim (drawer opt-out mode) */
    --z-sidebar: 45;         /* mobile drawer (drawer opt-out mode) */
    --z-drawer: 50;          /* _Drawer */
    --z-sheet: 60;           /* _BottomSheet, nav "More" sheet */
    --z-modal: 60;           /* _ConfirmModal, _TypedConfirmModal */
    --z-modal-nested: 70;    /* a modal raised from a modal/sheet */
    --z-command: 80;         /* _CommandPalette */
    --z-popover: 90;         /* _Popover, pickers, menus teleported to <body> */
    --z-tooltip: 95;
    --z-toast: 200;
    --z-progress: 210;       /* htmx top progress bar */

    /* Mobile app-shell chrome. --oc-bottom-chrome is the height of whatever is fixed at the
       bottom (tab bar + home indicator); every bottom-anchored element (toast, FAB, back-to-top,
       sheets' scroll padding) offsets by it so nothing ever overlaps the tab bar. */
    --oc-appbar-h: 3.25rem;
    --oc-tabbar-h: 3.75rem;
    --oc-safe-top: env(safe-area-inset-top, 0px);
    --oc-safe-bottom: env(safe-area-inset-bottom, 0px);
    --oc-safe-left: env(safe-area-inset-left, 0px);
    --oc-safe-right: env(safe-area-inset-right, 0px);
    --shadow-sm: 0 1px 2px 0 rgba(15, 23, 42, .04), 0 1px 3px 0 rgba(15, 23, 42, .06);
    --shadow-md: 0 4px 6px -1px rgba(15, 23, 42, .07), 0 2px 4px -2px rgba(15, 23, 42, .05);
    --shadow-lg: 0 12px 30px -8px rgba(15, 23, 42, .18);

    /* Motion — durations + easing curves for consistent transitions. */
    --duration-fast: 120ms;
    --duration-base: 200ms;
    --duration-slow: 320ms;
    --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
}

/* Dark mode: shared class applied to <html> by octacer-theme-init.js. */
.dark {
    color-scheme: dark;
    /* AA-contrast primary: indigo-600 as text on near-black fails; use a lighter fill + dark text. */
    --primary: #818cf8;
    --primary-active: #6366f1;
    --primary-foreground: #1e1b4b;
    --ink-900: #f8fafc;
    --ink-700: #cbd5e1;
    --ink-600: #94a3b8;
    --ink-500: #94a3b8;
    --ink-400: #64748b;
    --line: #334155;
    --line-2: #1e293b;
    --line-strong: #475569;
    --surface: #0f172a;
    --popover: #172338;              /* elevated rung above --surface for menus/popovers */
    --surface-muted: #1e293b;
    --bg: #020617;
    --input: #475569;               /* lighter than --line so inputs read as editable on dark cards */
    --overlay: rgb(0 0 0 / 0.7);
    --primary-ink: #a5b4fc;                    /* indigo-300 on slate-900 ≈ 9:1 */
    --primary-tint: rgb(99 102 241 / .16);
    --primary-tint-border: rgb(129 140 248 / .35);
    /* Status subtle fills inverted for dark canvases (solids/foregrounds stay mode-invariant). */
    --success-subtle: #0c2417;  --success-subtle-foreground: #86efac;
    --warning-subtle: #2b1d05;  --warning-subtle-foreground: #fcd34d;
    --danger-subtle:  #2a1215;  --danger-subtle-foreground:  #fca5a5;
    --info-subtle:    #0b2434;  --info-subtle-foreground:    #7dd3fc;
    /* Lighter chart hues for dark canvases. */
    --chart-1: var(--brand-500);
    --chart-2: #10b981;
    --chart-3: #fbbf24;
    --chart-4: #f472b6;
    --chart-5: #22d3ee;
    --gradient-brand: linear-gradient(135deg, #312e81 0%, #4338ca 52%, #6366f1 100%);
    --gradient-mono: linear-gradient(135deg, #020617 0%, #1e293b 52%, #475569 100%);
    --gradient-surface: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
}

/* High-contrast preference: stronger hairlines (unlayered, like the tokens it overrides). */
@media (prefers-contrast: more) {
    :root { --line: #94a3b8; --line-strong: #64748b; }
    .dark { --line: #64748b; --line-strong: #94a3b8; }
}

@layer base {
    /* Default lives in a LAYER (not the unlayered token block) so the layered html:has(.oc-tabbar) rules can
       override it: unlayered declarations always beat layered ones regardless of specificity. */
    :root { --oc-bottom-chrome: 0px; }

    html { -webkit-text-size-adjust: 100%; }
    body { overflow-x: clip; }
    body {
        font-family: var(--font-sans);
        font-size: .875rem; line-height: 1.5;
        color: var(--ink-900);
        -webkit-font-smoothing: antialiased;
        text-rendering: optimizeLegibility;
        letter-spacing: var(--tracking-normal);
    }

    /* Display/UI face: Inter. Use .oc-mono or .oc-number for technical content. */
    h1, h2, h3, h4, .oc-card-title, .oc-section-title {
        font-family: var(--font-sans);
        letter-spacing: calc(var(--tracking-normal) - 0.005em);
        text-wrap: balance;
    }
    .oc-mono, .oc-number, .oc-code, code, kbd, pre, samp, .font-mono {
        font-family: var(--font-mono);
        font-variant-numeric: tabular-nums;
        letter-spacing: -0.02em;
    }
    .oc-number { font-weight: 600; }
    .oc-code { font-size: .875em; }

    /* Native-app touch feel: no grey tap flash, no double-tap-zoom delay on controls, scroll-padding
       so focused/anchored content never hides under the sticky app bar or the bottom tab bar. */
    html { -webkit-tap-highlight-color: transparent; scroll-padding-top: calc(var(--oc-appbar-h) + var(--oc-safe-top) + .5rem); scroll-padding-bottom: calc(var(--oc-bottom-chrome) + 1rem); }
    :where(a, button, [role="button"], [role="tab"], label, summary, input, select, textarea) { touch-action: manipulation; }
    @media (display-mode: standalone) { html, body { overscroll-behavior-y: none; } }
}

@layer components {

    /* Decorative widget backgrounds for the partial library (branded stat tile, CTA card, profile cover).
       Default to neutral brand gradients — NO external image request (keeps the zero-external-calls policy).
       Apps may override any of these once with a first-party image, e.g. .oc-profile-cover{background-image:url(/img/cover.jpg)}. */
    .channel-stats-bg { background-image: linear-gradient(135deg, var(--brand-50), transparent 60%); }
    .entry-callout-bg { background-image: radial-gradient(120% 120% at 100% 0%, var(--brand-100), transparent 55%); }
    .oc-profile-cover { background-image: linear-gradient(120deg, var(--brand-600), var(--brand-800)); }
    .dark .channel-stats-bg { background-image: linear-gradient(135deg, rgba(99,102,241,.15), transparent 60%); }
    .dark .entry-callout-bg { background-image: radial-gradient(120% 120% at 100% 0%, rgba(99,102,241,.18), transparent 55%); }

    /* Decorative keyframes (migrated out of the old inline <style> in _ThemeHead — CSP: no inline styles). */
    @keyframes oc-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-18px); } }
    .oc-float { animation: oc-float 7s ease-in-out infinite; }
    @keyframes oc-drift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
    .oc-mesh { background-size: 200% 200%; animation: oc-drift 14s ease infinite; }


    /* Theme-level mono-tone gradient utilities. */
    .oc-gradient-brand { background-image: var(--gradient-brand); color: #fff; }
    .oc-gradient-mono { background-image: var(--gradient-mono); color: #fff; }
    .oc-gradient-surface { background-image: var(--gradient-surface); }

    /* Keyboard focus is always visible and never relies on color alone. */
    :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
        outline: 3px solid color-mix(in srgb, var(--brand-500) 72%, white);
        outline-offset: 2px;
    }

    /* Premium page backdrop */
    .oc-app-bg {
        background-color: var(--bg);
        background-image:
            radial-gradient(60rem 60rem at 110% -10%, rgba(79, 70, 229, .06), transparent 60%),
            radial-gradient(40rem 40rem at -10% 10%, rgba(99, 102, 241, .05), transparent 55%);
    }

    /* ---------- Cards ---------- */
    .oc-card {
        background: var(--surface);
        border: 1px solid var(--line);
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow-sm);
        transition: box-shadow .2s ease, border-color .2s ease, transform .2s ease;
    }
    @media (hover: hover) { .oc-card-hover:hover { box-shadow: var(--shadow-md); border-color: var(--line-strong); transform: translateY(-1px); } }
    .oc-card-hover:active { transform: translateY(0); }
    /* Cards stacked in a column get a consistent gap without per-card utilities.
       (In grid/flex card layouts, reset this in the app layer — the container gap owns spacing.) */
    /* Spacing belongs to the parent (gap/space-y), never to the card itself. A sibling margin
       here makes grids and flex rows unexpectedly grow and is the source of many layout drift bugs. */
    .oc-card-head {
        display: flex; align-items: center; justify-content: space-between;
        gap: .75rem; padding: .625rem 1rem; min-height: 3rem;
        border-bottom: 1px solid var(--line-2);
    }
    /* Canonical card content region: owns its own padding + vertical rhythm so views never
       hand-roll per-card padding/margins. Wrap card contents in .oc-card-body; stacked children
       are auto-spaced, so drop the ad-hoc .oc-form padding and .oc-mb margins inside it. */
    .oc-card-body { padding: 1rem; }
    .oc-card-body > * + * { margin-top: .875rem; }
    .oc-card-title { font-size: .875rem; font-weight: 600; color: var(--ink-900); display: flex; align-items: center; gap: .5rem; line-height: 1.3; }
    .oc-card-sub { font-size: .8125rem; font-weight: 400; color: var(--ink-500); margin-top: .125rem; }

    /* Small tinted icon tile used in section headers */
    .oc-icon-box { width: 2rem; height: 2rem; border-radius: .5rem; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }

    /* ---------- Buttons ---------- */
    .btn {
        display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
        font-size: .8125rem; font-weight: 500; line-height: 1.25rem;
        padding: .3125rem .75rem; border-radius: var(--radius-sm); min-height: 2rem;
        border: 1px solid transparent; cursor: pointer;
        transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, transform .05s ease, color .15s ease;
        white-space: nowrap; user-select: none;
    }
    .btn:focus-visible { outline: none; box-shadow: var(--ring); }
    .btn { --oc-spin-color: var(--primary-foreground); }
    .btn-outline, .btn-ghost, .btn-white { --oc-spin-color: var(--primary); }
    .btn-danger { --oc-spin-color: var(--danger-foreground); }
    .btn-success { --oc-spin-color: var(--success-foreground); }
    .btn:active { transform: translateY(.5px) scale(.995); }
    .btn:disabled, .btn[disabled], .btn[aria-disabled="true"] { opacity: .6; pointer-events: none; }
    .btn-sm { padding: .1875rem .5rem; font-size: .75rem; line-height: 1.25rem; min-height: 1.75rem; border-radius: var(--radius-sm); gap: .375rem; }
    .btn-lg { padding: .5rem 1rem; font-size: .875rem; min-height: 2.5rem; }
    .btn-block { width: 100%; }

    /* Built on the public --primary tokens so an app override (or dark mode) re-brands every
       primary surface consistently — .btn-primary and bg-primary are the same colour. */
    .btn-primary {
        color: var(--primary-foreground);
        background: linear-gradient(180deg, color-mix(in oklab, var(--primary) 86%, white), var(--primary));
        box-shadow: 0 1px 2px rgba(15,23,42,.12), inset 0 1px 0 rgba(255,255,255,.12);
    }
    @media (hover: hover) { .btn-primary:hover { background: linear-gradient(180deg, var(--primary), var(--primary-active)); } }
    .btn-primary:active { background: var(--primary-active); }

    .btn-outline {
        color: var(--ink-700); background: var(--surface); border-color: var(--line);
        box-shadow: var(--shadow-sm);
    }
    @media (hover: hover) { .btn-outline:hover { background: var(--surface-muted); border-color: var(--line-strong); color: var(--ink-900); } }

    .btn-ghost { color: var(--ink-600); background: transparent; }
    @media (hover: hover) { .btn-ghost:hover { background: var(--surface-muted); color: var(--ink-900); } }

    .btn-danger { color: var(--danger-foreground); background: var(--danger); }
    @media (hover: hover) { .btn-danger:hover { background: color-mix(in oklab, var(--danger), black 12%); } }

    .btn-white { color: var(--brand-700); background: #fff; }
    @media (hover: hover) { .btn-white:hover { background: #eef2ff; } }

    /* Button loading state — set aria-busy="true" (or .is-loading) to reveal spinner */
    .btn[aria-busy="true"], .btn.is-loading { pointer-events: none; position: relative; color: transparent !important; }
    .btn[aria-busy="true"] > *, .btn.is-loading > * { visibility: hidden; }
    .btn[aria-busy="true"]::after, .btn.is-loading::after {
        content: ""; position: absolute; width: 1.05em; height: 1.05em;
        border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
        color: var(--oc-spin-color); animation: oc-spin .6s linear infinite; visibility: visible;
    }

    /* ---------- Form fields ---------- */
    .field-label { display: block; font-size: .8125rem; font-weight: 500; color: var(--ink-700); margin-bottom: .3125rem; }
    .field-hint  { font-size: .72rem; color: var(--ink-500); margin-top: .35rem; }
    .field-error { display: block; font-size: .72rem; color: var(--danger); margin-top: .35rem; }

    .field-input, .field-select, .field-textarea {
        width: 100%; font-size: .875rem; color: var(--ink-900);
        background: var(--surface); border: 1px solid var(--input);
        border-radius: var(--radius-sm); padding: .4375rem .625rem; line-height: 1.25rem;
        transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
        -webkit-appearance: none; appearance: none;
    }
    .field-textarea { line-height: 1.5; }
    .field-input::placeholder, .field-textarea::placeholder, .field-group > input::placeholder { color: var(--ink-500); opacity: 1; }
    .field-input:focus, .field-select:focus, .field-textarea:focus {
        outline: none; border-color: var(--brand-500); box-shadow: var(--ring); background: var(--surface);
    }
    .field-input:disabled, .field-select:disabled, .field-textarea:disabled { background: var(--surface-muted); color: var(--ink-400); cursor: not-allowed; }
    .field-input[aria-invalid="true"], .field-select[aria-invalid="true"], .field-textarea[aria-invalid="true"] { border-color: var(--danger); }
    .field-select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .75rem center; padding-right: 2.25rem; }

    /* Input group: leading icon + input */
    .field-group { display: flex; align-items: center; gap: .5rem; width: 100%; background: var(--surface); border: 1px solid var(--input); border-radius: var(--radius-sm); padding: 0 .625rem; transition: border-color .15s ease, box-shadow .15s ease; }
    .field-group:focus-within { border-color: var(--brand-500); box-shadow: var(--ring); }
    /* width:0 + basis 0: the input fills the group but contributes no intrinsic width, so a field never
       forces a narrow grid column / drawer wider than its container (an <input> is ~20ch wide by default). */
    .field-group > input, .field-group > .grow { flex: 1 1 0%; width: 0; min-width: 0; border: none; background: transparent; font-size: .875rem; color: var(--ink-900); padding: .4375rem 0; line-height: 1.25rem; }
    .field-group > input:focus { outline: none; }
    .field-group.is-error { border-color: var(--danger); }
    .field-group.is-success { border-color: var(--success); }

    /* Searchable selects preserve the native select for forms while exposing an accessible combobox UI. */
    .oc-searchable { min-width: 0; }
    .oc-searchable > select.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
    .oc-searchable-trigger { min-height: 2.125rem; }
    .oc-searchable-menu { animation: oc-menu-in .12s ease-out; }
    .oc-searchable-option[aria-selected="true"] { color: var(--primary-ink); background: var(--primary-tint); font-weight: 600; }
    @keyframes oc-menu-in { from { opacity: 0; transform: translateY(-.25rem); } to { opacity: 1; transform: translateY(0); } }

    /* Validation states from ASP.NET / jquery-validation */
    .field-input.input-validation-error, .field-select.input-validation-error, .field-textarea.input-validation-error { border-color: var(--danger); }
    .field-validation-error { color: var(--danger); font-size: .72rem; margin-top: .35rem; display: block; }

    /* ---------- Badges ---------- */
    .badge { display: inline-flex; align-items: center; gap: .3rem; font-size: .68rem; font-weight: 600; padding: .18rem .5rem; border-radius: 999px; line-height: 1.2; }
    .badge-brand   { color: var(--primary-ink); background: var(--primary-tint); }
    .badge-slate   { color: var(--ink-600);  background: var(--line-2); }
    .badge-success { color: var(--success-subtle-foreground); background: var(--success-subtle); }
    .badge-warning { color: var(--warning-subtle-foreground); background: var(--warning-subtle); }
    .badge-danger  { color: var(--danger-subtle-foreground);  background: var(--danger-subtle); }
    .badge-info    { color: var(--info-subtle-foreground);    background: var(--info-subtle); }
    .oc-dot { width: .45rem; height: .45rem; border-radius: 9999px; background: currentColor; flex: 0 0 auto; }

    /* ---------- Alerts ---------- */
    .oc-alert { display: flex; gap: .75rem; align-items: flex-start; padding: .875rem 1rem; border-radius: var(--radius); border: 1px solid; font-size: .85rem; }
    .oc-alert > span { min-width: 0; flex: 1 1 auto; }
    .oc-alert .btn { display: flex; width: max-content; }
    .oc-alert-success { background: var(--success-subtle); border-color: color-mix(in srgb, var(--success-subtle-foreground) 30%, transparent); color: var(--success-subtle-foreground); }
    .oc-alert-warning { background: var(--warning-subtle); border-color: color-mix(in srgb, var(--warning-subtle-foreground) 30%, transparent); color: var(--warning-subtle-foreground); }
    .oc-alert-danger  { background: var(--danger-subtle);  border-color: color-mix(in srgb, var(--danger-subtle-foreground) 30%, transparent);  color: var(--danger-subtle-foreground); }
    .oc-alert-info    { background: var(--info-subtle);    border-color: color-mix(in srgb, var(--info-subtle-foreground) 30%, transparent);    color: var(--info-subtle-foreground); }

    /* ---------- Toggle switch ---------- */
    .oc-toggle { position: relative; display: inline-block; width: 2.5rem; height: 1.4rem; flex-shrink: 0; }
    .oc-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
    .oc-toggle-track { position: absolute; inset: 0; background: var(--ink-400); border-radius: 999px; transition: background .2s ease; }
    .oc-toggle-track::before { content: ""; position: absolute; height: 1.05rem; width: 1.05rem; left: .18rem; top: .175rem; background: #fff; border-radius: 50%; transition: transform .2s ease; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
    .oc-toggle input:checked + .oc-toggle-track { background: var(--primary); }
    .oc-toggle input:checked + .oc-toggle-track::before { transform: translateX(1.1rem); }
    .oc-toggle input:focus-visible + .oc-toggle-track { box-shadow: var(--ring); }
    .oc-toggle input:disabled + .oc-toggle-track { opacity: .5; }
    .oc-toggle-success input:checked + .oc-toggle-track { background: var(--success); }

    /* ---------- Checkbox ---------- */
    .oc-check { width: 1.05rem; height: 1.05rem; border-radius: .3rem; border: 1.5px solid var(--input); accent-color: var(--primary); cursor: pointer; }
    .oc-check-success { accent-color: var(--success); }

    /* ---------- Spinner / skeleton ---------- */
    @keyframes oc-spin { to { transform: rotate(360deg); } }
    .oc-spinner { display: inline-block; width: 1.25rem; height: 1.25rem; border: 2.5px solid var(--primary-tint); border-right-color: var(--primary); border-radius: 50%; animation: oc-spin .6s linear infinite; }
    .oc-spinner-sm { width: 1rem; height: 1rem; border-width: 2px; }

    @keyframes oc-shimmer { 100% { transform: translateX(100%); } }
    .oc-skeleton { position: relative; overflow: hidden; background: color-mix(in srgb, var(--ink-400) 18%, var(--surface)); border-radius: .5rem; }
    .oc-skeleton::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--surface) 55%, transparent), transparent); animation: oc-shimmer 1.4s infinite; }

    /* ---------- Divider with label ---------- */
    .oc-divider { display: flex; align-items: center; gap: .75rem; color: var(--ink-500); font-size: .72rem; font-weight: 500; }
    .oc-divider::before, .oc-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }

    /* ---------- Tables ---------- */
    .oc-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: .85rem; }
    .oc-table thead th { text-align: left; font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-500); padding: .5rem .75rem; border-bottom: 1px solid var(--line); background: var(--surface-muted); }
    .oc-table tbody td { padding: .5rem .75rem; border-bottom: 1px solid var(--line-2); color: var(--ink-700); vertical-align: middle; }
    .oc-table tbody tr { transition: background .12s ease; }
    @media (hover: hover) { .oc-table tbody tr:hover { background: var(--surface-muted); } }
    .oc-table tbody tr:last-child td { border-bottom: none; }

    /* ---------- Shared table/list primitives ---------- */
    .oc-table-shell { min-width: 0; overflow: hidden; }
    .oc-table-scroll { position: relative; width: 100%; overflow-x: auto; overscroll-behavior-x: contain; }   /* relative: contains sr-only children so they cannot widen the page */
    .oc-table-scroll > .oc-table { min-width: 42rem; }
    .oc-table thead th:first-child, .oc-table tbody td:first-child { padding-left: 1rem; }
    .oc-table thead th:last-child, .oc-table tbody td:last-child { padding-right: 1rem; }
    .oc-table tbody tr:focus-within { background: var(--primary-tint); }
    .oc-list { display: flex; flex-direction: column; gap: .75rem; container: oc-list / inline-size; }   /* rows adapt to the LIST's width */
    .oc-list-item {
        display: flex; align-items: center; gap: .75rem; min-width: 0;
        padding: .625rem 1rem; background: var(--surface); border: 1px solid var(--line);
        border-radius: var(--radius); box-shadow: var(--shadow-sm);
        transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
    }
    @media (hover: hover) { .oc-list-item:hover { border-color: var(--line-strong); box-shadow: var(--shadow-md); } }
    .oc-list-item:focus-within { border-color: var(--brand-500); box-shadow: var(--ring); }
    .oc-list-item:active { background: var(--surface-muted); }
    .oc-list-item-main { min-width: 0; flex: 1 1 auto; }
    .oc-list-item-title { color: var(--ink-900); font-size: .875rem; font-weight: 600; }
    .oc-list-item-meta { color: var(--ink-500); font-size: .8125rem; margin-top: .2rem; }
    .oc-list-item-actions { display: inline-flex; align-items: center; gap: .5rem; flex: 0 0 auto; }
    .oc-row-actions-inline { display: inline-flex; align-items: center; justify-content: flex-end; gap: .25rem; }
    .oc-row-actions-menu { min-width: 12rem; }
    .oc-view-toggle { display: inline-flex; align-items: center; gap: .125rem; padding: .125rem; background: var(--surface-muted); border: 1px solid var(--line); border-radius: var(--radius-sm); }
    .oc-view-toggle-button { display: inline-flex; align-items: center; justify-content: center; gap: .375rem; min-width: 1.75rem; min-height: 1.625rem; padding: 0 .5rem; border: 0; border-radius: calc(var(--radius-sm) - 2px); font-size: .8125rem; color: var(--ink-500); background: transparent; cursor: pointer; }
    @media (hover: hover) { .oc-view-toggle-button:hover { color: var(--ink-900); } }
    .oc-view-toggle-button:active { transform: scale(.97); }
    .oc-view-toggle-button.is-active { color: var(--primary-ink); background: var(--surface); box-shadow: var(--shadow-sm); }
    .oc-view-toggle-button:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-modal-panel { overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); box-shadow: var(--shadow-lg); }
    .oc-drawer-panel { min-width: 0; max-width: 100%; }
    .oc-drawer-header, .oc-drawer-footer { flex: 0 0 auto; border-color: var(--line); }
    .oc-drawer-header { border-bottom: 1px solid var(--line); }
    .oc-drawer-footer { border-top: 1px solid var(--line); }
    .oc-drawer-body { min-height: 0; overflow-y: auto; }
    .oc-drawer-body > * + * { margin-top: 1rem; }

    /* Three layout contracts: content-only, app shell, and app shell with page rail. */
    .oc-layout { min-height: 100dvh; background: var(--bg); color: var(--ink-900); }
    .oc-layout-header { position: sticky; top: 0; z-index: var(--z-header); padding-top: var(--oc-safe-top); padding-left: var(--oc-safe-left); padding-right: var(--oc-safe-right); border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(12px); }
    .oc-layout-with-sidebar { display: grid; grid-template-columns: 15rem minmax(0, 1fr); min-height: 100dvh; }
    .oc-layout-with-inner-sidebar { display: grid; grid-template-columns: 15rem minmax(0, 1fr) 15rem; min-height: 100dvh; }
    .oc-layout-with-inner-sidebar-content { display: block; }
    @media (min-width: 1280px) { .oc-layout-with-inner-sidebar-content { display: grid; grid-template-columns: minmax(0, 1fr) 15rem; min-height: 100%; } }
    .oc-layout-main { min-width: 0; }
    .oc-layout-inner-sidebar { min-width: 0; border-left: 1px solid var(--line); background: var(--surface-muted); }

    /* Accordion and collapsible content. */
    .oc-accordion-trigger { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 0; color: var(--ink-900); font-size: .875rem; font-weight: 600; text-align: left; }
    .oc-accordion-trigger:hover { color: var(--primary-ink); }
    .oc-accordion-trigger:focus-visible { border-radius: .5rem; }
    .oc-accordion-panel { padding: 0 2rem 1rem 0; color: var(--ink-600); font-size: .875rem; line-height: 1.6; }
    .oc-accordion-trigger[aria-expanded="true"] i { transform: rotate(45deg); }
    .oc-accordion-trigger i { transition: transform .15s ease; color: var(--ink-500); }

    /* Tooltips: add data-oc-tooltip to any icon-only or ambiguous control. */
    [data-oc-tooltip] { position: relative; }
    [data-oc-tooltip]::after { content: attr(data-oc-tooltip); position: absolute; z-index: var(--z-tooltip); left: 50%; bottom: calc(100% + .5rem); width: max-content; max-width: 16rem; transform: translate(-50%, .25rem); padding: .35rem .5rem; border-radius: .375rem; background: var(--ink-900); color: var(--surface); font: 500 .7rem/1.2 var(--font-sans); opacity: 0; pointer-events: none; transition: opacity .12s ease, transform .12s ease; }
    [data-oc-tooltip]:focus-visible::after { opacity: 1; transform: translate(-50%, 0); }
    @media (hover: hover) { [data-oc-tooltip]:hover::after { opacity: 1; transform: translate(-50%, 0); } }

    /* Avatar sizes, status indicator, and consistent image cropping. */
    .oc-avatar { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; overflow: visible; border-radius: 999px; background: var(--primary-tint); color: var(--primary-ink); font-weight: 700; }
    .oc-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
    .oc-avatar-sm { width: 2rem; height: 2rem; font-size: .7rem; }
    .oc-avatar-md { width: 2.5rem; height: 2.5rem; font-size: .8rem; }
    .oc-avatar-lg { width: 3.5rem; height: 3.5rem; font-size: 1rem; }
    .oc-avatar-status { position: absolute; right: -.05rem; bottom: -.05rem; width: .7rem; height: .7rem; border: 2px solid var(--surface); border-radius: 999px; background: var(--ink-400); }
    .oc-avatar-status-online, .oc-avatar-status-active { background: var(--success); }
    .oc-avatar-status-busy { background: var(--danger); }
    .oc-avatar-status-away { background: var(--warning); }

    /* Stats and compact list families. */
    /* Columns follow the grid's REAL width (not the viewport): as many ≥8.5rem tracks as fit, so a desktop page
       with the sidebar open, a tablet and a phone all get a sane count (4 / 4–3 / 2). A column CAP
       (_StatsGrid Stats.Columns → .oc-stats-max-2|3|4) raises the minimum track to 1/max of the width, so
       the cap never forces 3 squeezed tiles into a narrow card the way a viewport lg:grid-cols-3 did. */
    .oc-stats-grid { --oc-stats-gap: 1rem; display: grid; grid-template-columns: repeat(auto-fit, minmax(max(min(100%, 8.5rem), calc((100% - (var(--oc-stats-max, 12) - 1) * var(--oc-stats-gap)) / var(--oc-stats-max, 12))), 1fr)); gap: var(--oc-stats-gap); }
    .oc-stats-grid.oc-stats-max-2 { --oc-stats-max: 2; }
    .oc-stats-grid.oc-stats-max-3 { --oc-stats-max: 3; }
    .oc-stats-grid.oc-stats-max-4 { --oc-stats-max: 4; }
    .oc-stats-grid > * { min-width: 0; }
    .oc-stat-value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
    .oc-code-editor { min-height: 12rem; resize: vertical; border-radius: .625rem; background: #0f172a; color: #e2e8f0; font: .8125rem/1.6 var(--font-mono); tab-size: 2; }
    .oc-richtext { min-height: 10rem; line-height: 1.65; }
    .oc-toast { pointer-events: auto; width: min(24rem, calc(100vw - 2rem)); }

    @media (max-width: 1023px) {
        .oc-layout-with-sidebar, .oc-layout-with-inner-sidebar, .oc-layout-with-inner-sidebar-content { display: block; }
        .oc-layout-inner-sidebar { border-top: 1px solid var(--line); border-left: 0; }
    }
    .oc-profile-header img { display: block; width: 100%; height: 100%; object-fit: cover; }

    /* ---------- Empty state ---------- */
    .oc-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 3rem 1.5rem; color: var(--ink-500); }
    .oc-empty-icon { width: 3rem; height: 3rem; border-radius: .875rem; background: var(--line-2); color: var(--ink-400); display: inline-flex; align-items: center; justify-content: center; margin-bottom: .875rem; }
    .oc-empty-title { font-size: .95rem; font-weight: 600; color: var(--ink-700); }
    .oc-empty-text { font-size: .85rem; color: var(--ink-500); margin-top: .2rem; }

    /* ---------- Success button (state action) ---------- */
    .btn-success { color: var(--success-foreground); background: var(--success); }
    @media (hover: hover) { .btn-success:hover { background: color-mix(in oklab, var(--success), black 12%); } }

    /* ---------- Icon-only button (table row actions) ---------- */
    .oc-icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; border-radius: .5rem; color: var(--ink-500); background: transparent; border: none; cursor: pointer; transition: background .15s, color .15s; }
    @media (hover: hover) { .oc-icon-btn:hover { background: var(--surface-muted); color: var(--ink-900); } }
    .oc-icon-btn:active { transform: scale(.96); }
    @media (hover: hover) { .oc-icon-btn.danger:hover { background: color-mix(in srgb, var(--danger) 10%, var(--surface)); color: var(--danger); } }

    /* ---------- Responsive and high-contrast affordances ---------- */
    .oc-card-head, .oc-page-actions { flex-wrap: wrap; }
    .oc-page-actions { display: flex; align-items: center; gap: .5rem; }
    .oc-table-scroll { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
    .oc-table-scroll:focus-visible { outline: 3px solid color-mix(in srgb, var(--brand-500) 72%, white); outline-offset: -3px; }

    @media (max-width: 640px) {
        .oc-stats-grid { --oc-stats-gap: .625rem; }
        .oc-page-header > .flex.items-start.justify-between { flex-direction: column; align-items: stretch; }
        .oc-page-header .oc-page-actions { width: 100%; flex-wrap: wrap; }
        .oc-page-header .oc-page-actions > .btn,
        .oc-page-header .oc-page-actions > a.btn { flex: 1 1 auto; }
        .oc-filter-bar .oc-filter-search { width: 100%; max-width: none; }
        .oc-filter-bar > .flex.items-center.justify-between { align-items: stretch; flex-direction: column; }
        .oc-filter-bar > .flex.items-center.justify-between > .btn { width: 100%; }
        .oc-card-head { align-items: flex-start; padding: .75rem 1rem; }
        .oc-card-body { padding: 1rem; }
        .oc-view-toggle-button { min-width: 2.5rem; min-height: 2.5rem; }
        .btn { min-height: 2.5rem; }
        .btn-sm { min-height: 2.25rem; }
        .oc-modal-panel { width: calc(100vw - 2rem); max-height: calc(100dvh - 2rem); overflow-y: auto; }
        .oc-drawer-panel { width: 100% !important; max-width: 100%; }
        .oc-drawer-header, .oc-drawer-body, .oc-drawer-footer { padding-left: 1rem; padding-right: 1rem; }
        .oc-drawer-footer { align-items: stretch; flex-direction: column-reverse; }
        .oc-drawer-footer .btn { width: 100%; }
    }

    @media (pointer: coarse) {
        .btn, .oc-icon-btn, .oc-check, .oc-view-toggle-button { min-height: 2.75rem; }
        .oc-icon-btn { min-width: 2.75rem; width: 2.75rem; }
    }

    @media (prefers-contrast: more) {
        .btn, .field-input, .field-select, .field-textarea, .oc-list-item, .oc-card { border-width: 2px; }
        .badge { border: 1px solid currentColor; }
    }

    /* ---------- Stat card (dashboards) ---------- */
    .oc-stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 1.25rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; transition: box-shadow .2s, transform .2s, border-color .2s; }
    @media (hover: hover) { .oc-stat-hover:hover, a.oc-stat:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); border-color: var(--line-strong); } }
    /* Responsive by the CARD's own width, never the viewport:
       - wrap-reverse: when text + icon no longer fit side by side, the icon wraps onto a line ABOVE the text
         (left-aligned) instead of squeezing the text column to a sliver;
       - container-type: the value scales with the card (cqi), so big numbers shrink instead of breaking;
       - words/numbers never break mid-glyph ("Revenu/e", "12/8"): labels wrap only at spaces, values stay on
         one line (ellipsis + title as the last resort for absurdly long values). */
    .oc-stat { container-type: inline-size; flex-wrap: wrap-reverse; align-content: flex-start; row-gap: .5rem; padding: .75rem 1rem; }
    /* min-content = the (nowrap) value or the longest single word, so the icon wraps above ONLY when the value
       itself can't sit beside it; labels and trend lines just wrap at spaces. */
    .oc-stat > div { flex: 1 1 0; min-width: min-content; max-width: 100%; }
    .oc-stat-label { font-size: .75rem; font-weight: 500; color: var(--ink-500); overflow-wrap: normal; word-break: normal; hyphens: none; }
    .oc-stat-value { margin-top: .15rem; font-size: clamp(1.125rem, 10cqi, 1.375rem); line-height: 1.2; font-weight: 600; color: var(--ink-900); letter-spacing: -.02em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .oc-stat-icon { width: 2rem; height: 2rem; border-radius: .5rem; font-size: .8125rem; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
    @container (max-width: 13rem) {
        .oc-stat-icon { width: 2.25rem; height: 2.25rem; border-radius: .625rem; font-size: .875rem; }
    }
    /* Narrow tiles ALWAYS put the icon on top (tiles in one grid row share a width, so the whole row switches
       together; a per-content decision made rows ragged: "Revenue $42.8k" stacked while "Open 128" didn't). */
    @container (max-width: 9.5rem) {   /* content box: ≈ tiles under ~190px */
        /* Narrow tiles drop the decorative icon instead of stacking it on top (which doubled their height);
           the label + value carry the meaning. */
        .oc-stat-icon { display: none; }
    }

    /* ---------- Widget KPI tiles + stat list (partials/widgets/_StatTile, _StatTileBranded, _StatListWithIcons) ----------
       Same contract as .oc-stat: layout follows the WIDGET's own width (container queries), never the viewport, so a
       tile in a 4-col dashboard beside the desktop sidebar (~150px) and one on a phone both look right. Values stay on
       one line and scale with the tile (cqi); ellipsis + title only as the last resort for absurdly long values.
       Labels wrap at spaces only. container-type also stops a long nowrap value from widening the parent grid track. */
    .oc-stat-tile { container: oc-stat-tile / inline-size; }
    .oc-stat-tile-body { padding: 1rem; }
    @container oc-stat-tile (max-width: 12.5rem) { .oc-stat-tile-body { padding: 1rem .875rem; } }
    @container oc-stat-tile (min-width: 22rem) { .oc-stat-tile-body { padding: 1.5rem 1.75rem; } }
    .oc-stat-tile-label { min-width: 0; overflow-wrap: normal; word-break: normal; hyphens: none; }
    /* Size = the tile's inner width ÷ the value's length bucket (--oc-chars, set by .oc-len-* from Razor), so
       "128" stays big and "$1,284,903.27" shrinks to fit the same tile instead of ellipsizing. */
    .oc-stat-tile-value { --oc-chars: 6; display: block; min-width: 0; max-width: 100%; font-size: clamp(1rem, calc((100cqi - 2rem) / (var(--oc-chars) * .62)), 1.5rem); line-height: 1.2; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .oc-stat-tile-value.oc-len-8 { --oc-chars: 8; }
    .oc-stat-tile-value.oc-len-10 { --oc-chars: 10; }
    .oc-stat-tile-value.oc-len-12 { --oc-chars: 12; }
    .oc-stat-tile-value.oc-len-15 { --oc-chars: 15; }
    .oc-stat-tile-trend { flex: 0 0 auto; white-space: nowrap; }
    .oc-stat-list { container: oc-stat-list / inline-size; }
    .oc-stat-list-body { padding: 1rem; }
    @container oc-stat-list (min-width: 26rem) { .oc-stat-list-body { padding: 1.5rem 1.75rem; } }
    /* Row: label (wraps at spaces) + figures (never wrap) on one line; in a card narrower than 20rem EVERY row
       stacks (figures under the label, right-aligned) so rows stay consistent and the label is never a sliver.
       flex-wrap is the safety net for a single extreme row. */
    .oc-stat-list-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; column-gap: 1rem; row-gap: .125rem; }
    .oc-stat-list-label { display: flex; align-items: center; gap: .375rem; flex: 1 1 6rem; min-width: min-content; max-width: 100%; overflow-wrap: normal; word-break: normal; }
    .oc-stat-list-label > svg, .oc-stat-list-label > i { align-self: flex-start; margin-top: .1875rem; }
    @container oc-stat-list (max-width: 20rem) { .oc-stat-list-label { flex-basis: 100%; } }
    .oc-stat-list-figures { display: flex; align-items: center; justify-content: flex-end; gap: 1rem; flex: 0 0 auto; margin-inline-start: auto; white-space: nowrap; font-variant-numeric: tabular-nums; }

    /* ---------- Tabs ---------- */
    .oc-tabs { display: flex; flex-wrap: wrap; gap: .25rem; border-bottom: 1px solid var(--line); }
    .oc-tabbed-view > .oc-tabs, .oc-tabs.oc-tabs-scroll { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
    .oc-tab { position: relative; padding: .5rem .75rem; font-size: .875rem; font-weight: 500; color: var(--ink-500); border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; transition: color .15s, border-color .15s; cursor: pointer; background: none; }
    @media (hover: hover) { .oc-tab:hover { color: var(--ink-700); } }
    .oc-tab.is-active, .oc-tab[aria-selected="true"] { color: var(--primary-ink); border-bottom-color: var(--primary); }
    .oc-tabbed-view { min-width: 0; }
    .oc-tab-panel { min-width: 0; }
    /* Tab overflow ("priority+", octacer-nav.js 5b, mouse/trackpad screens): the strip is wrapped so a
       "More ▾" button can sit after the tablist; the wrapper owns the baseline border. */
    .oc-tabs-wrap { display: flex; align-items: stretch; min-width: 0; border-bottom: 1px solid var(--line); }
    .oc-tabs-wrap > .oc-tabs { flex: 0 1 auto; min-width: 0; border-bottom: 0; }   /* More sits right after the last visible tab */
    .oc-tabs-more { display: flex; flex: 0 0 auto; }
    .oc-tabs-more[hidden] { display: none; }
    .oc-tabs-more-trigger { display: inline-flex; align-items: center; gap: .4rem; margin-bottom: -1px; padding: .5rem .75rem; border: 0; border-bottom: 2px solid transparent; background: none; color: var(--ink-500); font-size: .875rem; font-weight: 500; white-space: nowrap; cursor: pointer; }
    .oc-tabs-more-trigger > i { font-size: .7rem; }
    @media (hover: hover) { .oc-tabs-more-trigger:hover { color: var(--ink-700); } }
    .oc-tabs-more-trigger[aria-expanded="true"] { color: var(--ink-900); }
    .oc-tabs-more-trigger:focus-visible { outline: none; box-shadow: var(--ring-inset); border-radius: .375rem; }

    /* Sidebar: desktop persistent rail, mobile off-canvas drawer, optional collapsed rail. */
    /* Width lives HERE (not a w-72 utility on the markup): utilities beat this layer, so a utility width would
       keep the collapsed rail 15rem wide, covering the content. */
    .oc-sidebar { width: 15rem; transition: transform .2s ease, width .2s ease; }
    .oc-sidebar-nav { display: flex; flex-direction: column; gap: 1px; }
    .oc-sidebar-nav a, .oc-sidebar-nav button { display: flex; width: 100%; align-items: center; gap: .625rem; border: 1px solid transparent; border-radius: var(--radius-sm); padding: .3125rem .625rem; min-height: 2rem; color: var(--ink-600); font-size: .875rem; line-height: 1.25rem; text-align: left; transition: background .15s ease, color .15s ease, border-color .15s ease; }
    @media (hover: hover) { .oc-sidebar-nav a:hover, .oc-sidebar-nav button:hover { color: var(--ink-900); background: var(--surface-muted); } }
    .oc-sidebar-nav a[aria-current="page"], .oc-sidebar-nav button[aria-expanded="true"] { color: var(--primary-ink); background: var(--primary-tint); font-weight: 600; }
    /* Drawer opt-out mode only (ViewData["Shell.MobileNav"]="drawer"): the hamburger lives INSIDE the app
       bar (never position:fixed), so it can't float over the drawer/scrims or offset headers. */
    .oc-sidebar-mobile-button { display: none; flex: 0 0 auto; }
    .oc-sidebar.is-open { transform: translateX(0); visibility: visible; }
    .oc-sidebar-lock { overflow: hidden; }
    /* Collapsed rail is a DESKTOP-only state (never applies to the mobile drawer). html.oc-sidebar-collapsed
       is set before paint by octacer-theme-init.js so the rail never flashes wide on load. */
    @media (min-width: 1024px) {
        .oc-shell-content { padding-left: 15rem; transition: padding-left .2s ease; }
        html.oc-sidebar-collapsed .oc-shell-content { padding-left: 3.75rem; }
        html.oc-sidebar-collapsed .oc-sidebar { width: 3.75rem; }
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-nav span, html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-collapse span, html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-brand-text { display: none; }
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-nav a, html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-nav button { justify-content: center; position: relative; }
        /* Badges survive the icon rail as a dot on the icon (their text is in the link's aria-label). */
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-nav [data-oc-nav-badge] { display: block; position: absolute; top: .25rem; right: .625rem; width: .5rem; min-width: 0; height: .5rem; padding: 0; overflow: hidden; font-size: 0; border: 0; border-radius: 999px; background: var(--danger); }
    }
    @media (max-width: 1023px) {
        .oc-shell-drawer .oc-sidebar-mobile-button { display: inline-flex; }
        .oc-sidebar { transform: translateX(-100%); visibility: hidden; z-index: var(--z-sidebar); }
        .oc-sidebar.is-open { transform: translateX(0); visibility: visible; }
        .oc-sidebar-overlay { z-index: var(--z-sidebar-scrim); }
    }
    @media (max-width: 639px) {
        .oc-layout-header > div { gap: .5rem; padding-right: .75rem; }
        .oc-layout-header .oc-page-actions { gap: .35rem; }
    }
    @media (min-width: 1024px) {
        .oc-sidebar { transform: translateX(0); visibility: visible; }
    }

    /* ---------- Hero banner (dashboards) ---------- */
    .oc-hero { background: linear-gradient(120deg, var(--brand-800) 0%, var(--brand-700) 55%, var(--brand-600) 120%); color: #fff; border-radius: var(--radius-lg); box-shadow: 0 18px 40px -22px rgba(79,70,229,.6); }

    /* Submit button spinner while its form is mid-htmx-request */
    form.htmx-request button[type="submit"].btn { color: transparent !important; pointer-events: none; position: relative; }
    form.htmx-request button[type="submit"].btn > * { visibility: hidden; }
    form.htmx-request button[type="submit"].btn::after {
        content: ""; position: absolute; width: 1.05em; height: 1.05em; visibility: visible;
        border: 2px solid var(--oc-spin-color, #fff); border-right-color: transparent; border-radius: 50%;
        animation: oc-spin .6s linear infinite;
    }

    /* ---------- htmx global top progress bar ---------- */
    #oc-progress { position: fixed; top: 0; left: 0; height: 3px; width: 0; z-index: var(--z-progress); background: linear-gradient(90deg, var(--brand-500), var(--brand-700)); box-shadow: 0 0 10px rgba(79,70,229,.5); opacity: 0; transition: width .2s ease, opacity .3s ease; }
    #oc-progress.active { opacity: 1; }

    /* Alpine cloak — hide un-initialized components (global rule so [x-cloak] always works) */
    [x-cloak] { display: none !important; }

    /* Respect reduced motion */
    @media (prefers-reduced-motion: reduce) {
        *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
    }

    /* ============================================================
       Wave-1 primitives (companions to theme/partials/primitives/*.cshtml + their JS).
       Most primitives are styled purely with Tailwind token utilities; the rules below
       are the few things utilities can't express. Colours use theme vars for auto dark.
       ============================================================ */

    /* ---------- OTP / one-time-code boxes (_OtpInput.cshtml) ---------- */
    .oc-otp-box {
        width: 2.75rem;
        padding-left: 0;
        padding-right: 0;
        text-align: center;
        font-family: var(--font-mono);
        font-variant-numeric: tabular-nums;
        font-size: 1.125rem;
        font-weight: 600;
        letter-spacing: 0;
        caret-color: var(--brand-500);
    }
    @media (max-width: 640px) {
        .oc-otp-box { width: 2.5rem; min-height: 2.75rem; }
    }

    /* ---------- Command palette (_CommandPalette.cshtml / octacer-command.js) ---------- */
    .oc-command-kbd {
        display: inline-flex; align-items: center; justify-content: center;
        min-width: 1.5rem; height: 1.5rem; padding: 0 .375rem;
        font-family: var(--font-mono); font-size: .6875rem; line-height: 1; font-weight: 600;
        color: var(--ink-700); background: var(--surface);
        border: 1px solid var(--line); border-bottom-width: 2px; border-radius: var(--radius-sm);
    }

    /* ============================================================
       Mobile-native foundation — bottom sheet + bottom tab bar
       (companions: primitives/_BottomSheet.cshtml, primitives/_BottomTabBar.cshtml,
        js/octacer-bottomsheet.js). Phone-first primitives; the tab bar hides at lg+
        (desktop uses the sidebar). All colours via theme vars for auto dark mode.
       ============================================================ */

    /* ---------- Bottom sheet ---------- */
    .oc-sheet {
        height: 100dvh;
        -webkit-tap-highlight-color: transparent;
        touch-action: manipulation;
    }
    .oc-sheet-scrim {
        background: var(--overlay);
        opacity: 0;
        transition: opacity var(--duration-base) var(--ease-out);
    }
    .oc-sheet.is-open .oc-sheet-scrim { opacity: 1; }
    .oc-sheet.is-closing .oc-sheet-scrim { opacity: 0; }
    .oc-sheet-panel {
        background: var(--popover);
        max-height: 90dvh;
        padding-bottom: env(safe-area-inset-bottom, 0px);
        box-shadow: var(--shadow-lg);
        transform: translateY(100%);
        transition: transform var(--duration-slow) var(--ease-out);
        will-change: transform;
    }
    .oc-sheet.is-open .oc-sheet-panel { transform: translateY(0); }
    .oc-sheet.is-closing .oc-sheet-panel { transform: translateY(100%); }
    /* DesktopPlacement="side" (lg+): a full-height panel that slides in from the right instead of up from the bottom. */
    @media (min-width: 1024px) {
        .oc-sheet[data-oc-sheet-desktop="side"] .oc-sheet-panel { transform: translateX(100%); }
        .oc-sheet[data-oc-sheet-desktop="side"].is-open .oc-sheet-panel { transform: translateX(0); }
        .oc-sheet[data-oc-sheet-desktop="side"].is-closing .oc-sheet-panel { transform: translateX(100%); }
        .oc-sheet[data-oc-sheet-desktop="side"] .oc-sheet-handle { display: none; }
    }
    .oc-sheet-panel.is-dragging { transition: none; }
    .oc-sheet-handle {
        display: flex; align-items: center; justify-content: center;
        width: 100%; padding: .75rem 0 .25rem; border: 0; background: transparent;
        cursor: grab; touch-action: none; -webkit-tap-highlight-color: transparent;
    }
    .oc-sheet-handle:active { cursor: grabbing; }
    .oc-sheet-handle-bar {
        width: 2.25rem; height: .3rem; border-radius: 999px;
        background: var(--line-strong); transition: background .15s ease;
    }
    @media (hover: hover) { .oc-sheet-handle:hover .oc-sheet-handle-bar { background: var(--ink-400); } }
    .oc-sheet-handle:focus-visible { outline: none; }
    .oc-sheet-handle:focus-visible .oc-sheet-handle-bar { box-shadow: var(--ring); }
    .oc-sheet-header { touch-action: none; }
    .oc-sheet-footer { border-top: 1px solid var(--line); }
    .oc-sheet-body {
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
    }
    .oc-sheet-body > * + * { margin-top: 1rem; }

    /* ---------- Bottom tab bar ----------
       Fixed height (--oc-tabbar-h) so every bottom-anchored element can offset by it exactly.
       Material-3 / iOS feel: icon in a pill that fills when active, short label below. The whole
       cell is the touch target (≥ 60px tall, ≥ 64px wide at 5 items on a 320px phone). */
    .oc-tabbar {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-tabbar);
        background: color-mix(in srgb, var(--surface) 92%, transparent);
        -webkit-backdrop-filter: saturate(1.4) blur(14px);
        backdrop-filter: saturate(1.4) blur(14px);
        border-top: 1px solid var(--line);
        padding: 0 var(--oc-safe-right) var(--oc-safe-bottom) var(--oc-safe-left);
        -webkit-tap-highlight-color: transparent;
        touch-action: manipulation;
        user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
        transition: transform var(--duration-base) var(--ease-out);
    }
    .oc-tabbar.is-hidden { transform: translateY(calc(100% + 1px)); }
    html.oc-kb-open .oc-tabbar { transform: translateY(calc(100% + 1px)); visibility: hidden; }
    .oc-tabbar-list {
        display: flex; align-items: stretch; justify-content: space-around;
        max-width: 40rem; margin: 0 auto; padding: 0; list-style: none;
    }
    .oc-tabbar-item { flex: 1 1 0; min-width: 0; display: flex; }
    .oc-tabbar-link {
        position: relative;
        display: flex; flex-direction: column; align-items: center; justify-content: center;
        gap: .2rem; width: 100%; height: var(--oc-tabbar-h);
        padding: 0 .125rem;
        color: var(--ink-500); background: transparent; border: 0;
        font: 600 .6875rem/1.1 var(--font-sans); letter-spacing: 0;
        text-decoration: none; cursor: pointer;
        transition: color .15s ease;
    }
    @media (hover: hover) { .oc-tabbar-link:hover { color: var(--ink-900); } }
    .oc-tabbar-link:active .oc-tabbar-icon { transform: scale(.92); }
    .oc-tabbar-link:focus-visible { outline: none; }
    .oc-tabbar-link:focus-visible .oc-tabbar-icon { box-shadow: var(--ring); }
    .oc-tabbar-link[aria-current="page"], .oc-tabbar-link[aria-expanded="true"] { color: var(--primary-ink); font-weight: 700; }
    .oc-tabbar-icon {
        position: relative;
        display: inline-flex; align-items: center; justify-content: center;
        width: 3.5rem; height: 1.875rem; border-radius: 999px;
        font-size: 1.125rem;
        transition: background var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
    }
    .oc-tabbar-link[aria-current="page"] .oc-tabbar-icon { background: var(--primary-tint); }
    .oc-tabbar-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .oc-tabbar-badge {
        position: absolute; top: -.2rem; left: 58%;
        min-width: 1.125rem; height: 1.125rem; padding: 0 .3rem;
        display: inline-flex; align-items: center; justify-content: center;
        font: 700 .625rem/1 var(--font-mono);
        color: var(--danger-foreground); background: var(--danger);
        border-radius: 999px; border: 2px solid var(--surface);
    }
    .oc-tabbar-badge-dot { min-width: .625rem; width: .625rem; height: .625rem; padding: 0; top: .1rem; left: 62%; }
    .oc-has-bottom-tabbar { padding-bottom: calc(var(--oc-tabbar-h) + var(--oc-safe-bottom) + 1rem); }
    @media (max-width: 1023px) {
        /* Any page that renders a tab bar publishes its height so bottom-anchored UI can clear it. */
        html:has(.oc-tabbar) { --oc-bottom-chrome: calc(var(--oc-tabbar-h) + var(--oc-safe-bottom)); }
        html.oc-kb-open { --oc-bottom-chrome: 0px; }
    }
    @media (min-width: 1024px) {
        .oc-tabbar:not(.oc-tabbar-always) { display: none; }
        .oc-has-bottom-tabbar { padding-bottom: 0; }
    }
    @media (prefers-reduced-motion: reduce) {
        .oc-sheet-scrim,
        .oc-sheet-panel { transition: none !important; }
        .oc-sheet.is-open .oc-sheet-panel { transform: translateY(0); }
        .oc-sheet.is-closing .oc-sheet-panel { transform: translateY(100%); }
    }

    /* ============================================================
       Wave-2 primitives (companions to theme/partials/primitives/*.cshtml + their JS).
       All colours via theme vars for auto dark mode.
       ============================================================ */

    /* ---------- Calendar (date + range pickers) — _DatePicker / _DateRangePicker / octacer-datefields.js ---------- */
    .oc-cal-weekday { display: flex; align-items: center; justify-content: center; height: 2rem; font-size: .6875rem; font-weight: 600; text-decoration: none; color: var(--ink-500); cursor: default; }
    .oc-cal-day { display: inline-flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 1 / 1; min-height: 2.25rem; font-size: .8125rem; color: var(--ink-900); background: transparent; border: 0; border-radius: var(--radius-sm, .5rem); cursor: pointer; transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out); }
    @media (hover: hover) { .oc-cal-day:hover { background: var(--surface-muted); } }
    .oc-cal-day:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-500); }
    .oc-cal-day--muted { color: var(--ink-400); }
    .oc-cal-day--today { font-weight: 700; box-shadow: inset 0 0 0 1px var(--brand-500); }
    .oc-cal-day--inrange { background: color-mix(in srgb, var(--primary) 14%, transparent); border-radius: 0; }
    .oc-cal-day--selected { background: var(--primary); color: var(--primary-foreground); font-weight: 600; }
    .oc-cal-day--selected:hover { background: var(--primary-active); }
    .oc-cal-day:disabled, .oc-cal-day[aria-disabled="true"] { color: var(--ink-400); opacity: .45; cursor: not-allowed; text-decoration: line-through; background: transparent; }
    .oc-daterange-preset.is-active { background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--primary); font-weight: 600; }

    /* ---------- Slider — _Slider / octacer-inputs.js ---------- */
    .oc-slider-thumb { cursor: grab; touch-action: none; transition: scale var(--duration-fast) var(--ease-out); }
    .oc-slider-thumb:active { cursor: grabbing; scale: 1.1; }
    .oc-slider-bubble { position: absolute; bottom: calc(100% + .5rem); left: 50%; transform: translateX(-50%); padding: .125rem .375rem; border-radius: var(--radius-sm, .375rem); font-family: var(--font-mono); font-size: .6875rem; font-weight: 600; line-height: 1; white-space: nowrap; color: var(--primary-foreground); background: var(--primary); box-shadow: var(--shadow-sm); opacity: 0; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-slider-thumb:hover .oc-slider-bubble, .oc-slider-thumb:focus-visible .oc-slider-bubble, .oc-slider-thumb:active .oc-slider-bubble { opacity: 1; }

    /* ---------- Rating — _Rating / octacer-inputs.js ---------- */
    .oc-rating-star { color: var(--ink-400); transition: color var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out); }
    .oc-rating-star.is-filled { color: var(--warning); }
    .oc-rating:focus-visible { outline: none; border-radius: var(--radius-sm, .5rem); box-shadow: 0 0 0 2px var(--brand-500); }
    .oc-rating[role="slider"] .oc-rating-star:hover { transform: scale(1.08); }

    /* ---------- Rich-text / Markdown editors — _RichTextEditor / _MarkdownEditor / octacer-editor.js ---------- */
    .oc-richtext-input[data-empty="true"]::before { content: attr(data-placeholder); color: var(--ink-400); pointer-events: none; }
    .oc-richtext-input:focus { outline: none; }
    .oc-richtext h1, .oc-richtext h2, .oc-richtext h3 { font-weight: 600; line-height: 1.3; margin: .6em 0 .3em; }
    .oc-richtext h1 { font-size: 1.35rem; } .oc-richtext h2 { font-size: 1.15rem; } .oc-richtext h3 { font-size: 1rem; }
    .oc-richtext p { margin: .4em 0; }
    .oc-richtext ul, .oc-richtext ol { margin: .4em 0; padding-left: 1.4em; }
    .oc-richtext ul { list-style: disc; } .oc-richtext ol { list-style: decimal; }
    .oc-richtext a { color: var(--primary); text-decoration: underline; text-underline-offset: 2px; }
    .oc-richtext blockquote { margin: .5em 0; padding: .2em 0 .2em .9em; border-left: 3px solid var(--line-strong); color: var(--ink-600); }
    .oc-richtext pre, .oc-richtext code { font-family: var(--font-mono); font-size: .8125rem; }
    .oc-richtext pre { background: var(--surface-muted); border-radius: .5rem; padding: .75rem .9rem; overflow-x: auto; }
    .oc-richtext :where(code):not(pre code) { background: var(--surface-muted); border-radius: .3rem; padding: .1em .35em; }
    @media (prefers-reduced-motion: reduce) { .oc-dropzone, .oc-dropzone-progress-bar { transition: none !important; } }

    /* ---------- DataTable / TreeTable — _DataTable / _TreeTable / octacer-table.js ---------- */
    .oc-datatable-scroll { position: relative; overflow: auto; max-height: 70vh; }
    .oc-datatable-scroll > .oc-datatable thead th { position: sticky; top: 0; z-index: var(--z-sticky); background: var(--line-2); }
    .dark .oc-datatable-scroll > .oc-datatable thead th { background: var(--surface-muted); }
    .oc-datatable-scroll.oc-scrolled > .oc-datatable thead::after { content: ""; position: sticky; top: 0; display: block; height: 0; box-shadow: 0 6px 8px -6px rgba(15, 23, 42, .25); }
    /* Horizontal scroll-edge shadows: pure-CSS "scrolling shadows" (local covers + scroll shadows),
       so they work at any height without pseudo-element sizing. */
    .oc-datatable-scroll {
        background:
            linear-gradient(to right, var(--surface) 30%, transparent) left center / 2rem 100% no-repeat local,
            linear-gradient(to left, var(--surface) 30%, transparent) right center / 2rem 100% no-repeat local,
            radial-gradient(farthest-side at 0 50%, rgb(15 23 42 / .16), transparent) left center / .75rem 100% no-repeat scroll,
            radial-gradient(farthest-side at 100% 50%, rgb(15 23 42 / .16), transparent) right center / .75rem 100% no-repeat scroll;
    }
    .oc-datatable th.oc-col-pin-start, .oc-datatable td.oc-col-pin-start { position: sticky; left: 0; z-index: calc(var(--z-sticky) - 2); background: var(--surface); }
    .oc-datatable th.oc-col-pin-start { z-index: calc(var(--z-sticky) + 1); background: var(--line-2); }
    .oc-datatable th.oc-col-pin-end, .oc-datatable td.oc-col-pin-end { position: sticky; right: 0; z-index: calc(var(--z-sticky) - 2); background: var(--surface); }
    .oc-datatable th.oc-col-pin-end { z-index: calc(var(--z-sticky) + 1); background: var(--line-2); }
    .dark .oc-datatable th.oc-col-pin-start, .dark .oc-datatable th.oc-col-pin-end { background: var(--surface-muted); }
    /* Pinned header cells must stay above the other sticky headers that scroll underneath them (the generic
       sticky-thead rule above is more specific, so restate the pin z-index at equal-or-higher specificity). */
    .oc-datatable-scroll > .oc-datatable thead th.oc-col-pin-start,
    .oc-datatable-scroll > .oc-datatable thead th.oc-col-pin-end { z-index: calc(var(--z-sticky) + 1); }
    @media (hover: hover) { .oc-datatable tbody tr:hover td.oc-col-pin-start, .oc-datatable tbody tr:hover td.oc-col-pin-end { background: var(--surface-muted); } }
    .oc-th-sort { background: transparent; border: 0; padding: 0; margin: 0; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; }
    @media (hover: hover) { .oc-th-sort:hover .oc-th-sort-icon { color: var(--ink-700); } }
    .oc-density-compact .oc-table thead th { padding-top: .3125rem; padding-bottom: .3125rem; }
    .oc-density-compact .oc-table tbody td { padding-top: .3125rem; padding-bottom: .3125rem; font-size: .8125rem; }
    /* Row-level icon buttons never set the row height (mouse screens): 28px hit area, pulled into the cell padding. */
    @media (pointer: fine) {
        .oc-table tbody td .oc-icon-btn { width: 1.75rem; height: 1.75rem; margin-block: -.25rem; }
        .oc-table thead .oc-th-sort { margin-block: -.375rem; }
    }
    @media (pointer: coarse) { .oc-density-compact .oc-table tbody td .oc-icon-btn { min-width: 2.75rem; min-height: 2.75rem; } }
    .oc-row-chevron, .oc-tree-row-chevron { transition: transform var(--duration-fast) var(--ease-out); }
    .oc-row-chevron.is-open, .oc-tree-row-chevron.is-open { transform: rotate(90deg); }
    tr[data-oc-row-detail] > td { background: var(--surface-muted); }
    .oc-tree-indent { --oc-tree-step: 1.25rem; }
    .oc-tree-indent[data-oc-level="1"] { padding-left: 0; }
    .oc-tree-indent[data-oc-level="2"] { padding-left: calc(var(--oc-tree-step) * 1); }
    .oc-tree-indent[data-oc-level="3"] { padding-left: calc(var(--oc-tree-step) * 2); }
    .oc-tree-indent[data-oc-level="4"] { padding-left: calc(var(--oc-tree-step) * 3); }
    .oc-tree-indent[data-oc-level="5"] { padding-left: calc(var(--oc-tree-step) * 4); }
    .oc-tree-indent[data-oc-level="6"] { padding-left: calc(var(--oc-tree-step) * 5); }
    .oc-tree-leaf-spacer { display: inline-block; width: 2rem; }
    .oc-treetable tbody tr:focus-within { outline: none; }
    @media (prefers-reduced-motion: reduce) { .oc-row-chevron, .oc-tree-row-chevron { transition: none !important; } }

    /* ---------- Overlays — _Popover / _TypedConfirmModal / octacer-popover.js / octacer-typedconfirm.js / octacer-toast.js ---------- */
    /* The ONE scroll lock: set by window.OctacerLayers while any locking layer is open (modal, drawer, sheet,
       command palette, phone-docked picker). The gutter stays reserved so classic scrollbars don't make the
       page jump sideways when it locks. */
    html.oc-scroll-lock { overflow: hidden; scrollbar-gutter: stable; }
    .oc-popover-panel { will-change: transform, opacity; }
    .oc-popover-panel.flex { animation: oc-popover-in var(--duration-fast, 120ms) var(--ease-out, ease) both; }
    @keyframes oc-popover-in { from { opacity: 0; transform: scale(.98); } to { opacity: 1; transform: none; } }
    @media (prefers-reduced-motion: reduce) { .oc-popover-panel.flex { animation: none; } }
    .oc-toast-progress { width: 100%; border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; }

    /* ---------- Navigation — _Breadcrumbs / _MegaMenu / _ScrollSpyNav / _BackToTop / _WorkspaceSwitcher / octacer-nav.js ---------- */
    .oc-breadcrumb-ellipsis::-webkit-details-marker { display: none; }
    .oc-breadcrumb-collapse > summary::-webkit-details-marker { display: none; }

    /* ============================================================
       Wave-3 primitives (companions to theme/partials/primitives/*.cshtml + their JS).
       All colours via theme vars for auto dark mode.
       ============================================================ */

    /* ---------- Kanban board — _KanbanBoard.cshtml + octacer-kanban.js ---------- */
    .oc-kanban { min-width: 0; }
    /* Column width follows the BOARD's width (not the viewport): 17rem, but never more than 85% of the board so
       the next column always peeks. position:relative keeps absolutely-positioned descendants (sr-only text)
       inside the scroller — otherwise they escape the clip and widen the page. */
    .oc-kanban-scroll { position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(min(17rem, 85%), 1fr); gap: 1rem; overflow-x: auto; overscroll-behavior-x: contain; padding-bottom: .5rem; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; scroll-snap-type: x proximity; }
    .oc-kanban-scroll:focus-visible { outline: 3px solid color-mix(in srgb, var(--brand-500) 72%, white); outline-offset: -3px; }
    @media (pointer: coarse) { .oc-kanban-scroll { scroll-snap-type: x mandatory; } }
    .oc-kanban-col { position: relative; display: flex; flex-direction: column; min-width: 0; max-height: 100%; background: var(--surface-muted); border: 1px solid var(--line); border-radius: var(--radius-lg); scroll-snap-align: start; }
    .oc-kanban-col-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .75rem .875rem; border-bottom: 1px solid var(--line); }
    .oc-kanban-wip-warn { display: flex; align-items: center; gap: .4rem; margin: 0; padding: .4rem .875rem; font-size: .72rem; font-weight: 600; color: var(--danger-subtle-foreground); background: var(--danger-subtle); }
    .oc-kanban-col-body { display: flex; flex-direction: column; gap: .625rem; padding: .75rem; overflow-y: auto; min-height: 5rem; max-height: max(18rem, calc(100dvh - 12rem)); overscroll-behavior-y: contain; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
    .oc-kanban-col-body.is-drop-target { background: color-mix(in srgb, var(--primary) 8%, transparent); box-shadow: inset 0 0 0 2px var(--brand-500); border-radius: var(--radius); }
    .oc-kanban-card { position: relative; display: flex; gap: .5rem; padding: .75rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-sm); cursor: grab; transition: box-shadow .15s ease, border-color .15s ease, transform .1s ease, opacity .15s ease; }
    @media (hover: hover) { .oc-kanban-card:hover { border-color: var(--line-strong); box-shadow: var(--shadow-md); } }
    .oc-kanban-card:focus-visible { outline: none; border-color: var(--brand-500); box-shadow: var(--ring); }
    .oc-kanban-card:active { cursor: grabbing; }
    .oc-kanban-card.is-dragging { opacity: .5; box-shadow: var(--shadow-lg); }
    .oc-kanban-card-main { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: .4rem; }
    .oc-kanban-card-labels { display: flex; flex-wrap: wrap; gap: .3rem; }
    .oc-kanban-card-title { font-size: .8125rem; font-weight: 600; color: var(--ink-900); line-height: 1.35; }
    .oc-kanban-card-link { color: inherit; }
    .oc-kanban-card-link:hover { color: var(--primary-ink); text-decoration: underline; text-underline-offset: 2px; }
    .oc-kanban-card-foot { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-top: .1rem; }
    .oc-kanban-card-meta { font-size: .7rem; color: var(--ink-500); min-width: 0; }
    .oc-kanban-card-move { flex: 0 0 auto; }
    .oc-kanban-move-btn { width: 1.75rem; height: 1.75rem; }
    @media (pointer: coarse) { .oc-kanban-move-btn { min-width: 2.75rem; min-height: 2.75rem; } }
    .oc-kanban-move-menu { position: absolute; right: .5rem; top: 2.25rem; z-index: 30; width: 15rem; max-height: 18rem; overflow-y: auto; padding: .25rem; background: var(--popover); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-lg); }
    .oc-kanban-move-group + .oc-kanban-move-group { border-top: 1px solid var(--line-2); margin-top: .25rem; padding-top: .25rem; }
    .oc-kanban-move-heading { margin: .25rem .5rem; font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-500); }
    .oc-kanban-move-item { display: block; width: 100%; text-align: left; padding: .5rem .625rem; min-height: 2.25rem; font-size: .8125rem; color: var(--ink-700); background: transparent; border: 0; border-radius: .45rem; cursor: pointer; }
    @media (hover: hover) { .oc-kanban-move-item:hover { background: var(--surface-muted); color: var(--ink-900); } }
    .oc-kanban-move-item:focus-visible { outline: none; box-shadow: var(--ring); }
    @media (pointer: coarse) { .oc-kanban-move-item { min-height: 2.75rem; } }
    .oc-kanban-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .3rem; padding: 1.25rem .75rem; text-align: center; font-size: .78rem; color: var(--ink-500); border: 1px dashed var(--line-strong); border-radius: var(--radius); }
    .oc-kanban-empty-hint { font-size: .68rem; color: var(--ink-400); }
    @media (prefers-reduced-motion: reduce) { .oc-kanban-card, .oc-kanban-col-body { transition: none !important; } }

    /* ---------- Calendar — _Calendar.cshtml + octacer-calendar.js ---------- */
    .oc-cal-toolbar { justify-content: space-between; }
    .oc-calendar .oc-cal-shell { padding: 0; }
    .oc-cal-body { min-height: 20rem; }
    .oc-cal-chip--primary, .oc-cal-block--primary { --oc-cal-accent: var(--primary); --oc-cal-tint: color-mix(in srgb, var(--primary) 14%, transparent); --oc-cal-ink: var(--primary); }
    .oc-cal-chip--success, .oc-cal-block--success { --oc-cal-accent: var(--success); --oc-cal-tint: var(--success-subtle); --oc-cal-ink: var(--success-subtle-foreground); }
    .oc-cal-chip--warning, .oc-cal-block--warning { --oc-cal-accent: var(--warning); --oc-cal-tint: var(--warning-subtle); --oc-cal-ink: var(--warning-subtle-foreground); }
    .oc-cal-chip--danger, .oc-cal-block--danger { --oc-cal-accent: var(--danger); --oc-cal-tint: var(--danger-subtle); --oc-cal-ink: var(--danger-subtle-foreground); }
    .oc-cal-chip--info, .oc-cal-block--info { --oc-cal-accent: var(--info); --oc-cal-tint: var(--info-subtle); --oc-cal-ink: var(--info-subtle-foreground); }
    .oc-cal-chip--neutral, .oc-cal-block--neutral { --oc-cal-accent: var(--ink-500); --oc-cal-tint: var(--surface-muted); --oc-cal-ink: var(--ink-700); }
    .oc-cal-marker--primary { background: var(--primary); } .oc-cal-marker--success { background: var(--success); } .oc-cal-marker--warning { background: var(--warning); } .oc-cal-marker--danger { background: var(--danger); } .oc-cal-marker--info { background: var(--info); } .oc-cal-marker--neutral { background: var(--ink-500); }
    .oc-cal-month-head { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border-bottom: 1px solid var(--line); }
    .oc-cal-month-head .oc-cal-weekday { height: 2.25rem; }
    .oc-cal-month-grid { display: grid; grid-auto-rows: minmax(6.5rem, 1fr); }
    .oc-cal-week-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
    .oc-cal-cell { display: flex; flex-direction: column; gap: .25rem; min-height: 6.5rem; padding: .375rem; border-right: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2); cursor: pointer; transition: background var(--duration-fast, .15s) var(--ease-out, ease); }
    .oc-cal-cell:nth-child(7n) { border-right: 0; }
    @media (hover: hover) { .oc-cal-cell:hover { background: var(--surface-muted); } }
    .oc-cal-cell:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--brand-500); }
    .oc-cal-cell--muted { background: color-mix(in srgb, var(--surface-muted) 55%, transparent); }
    .oc-cal-cell--muted .oc-cal-daynum { color: var(--ink-400); }
    .oc-cal-daynum { align-self: flex-start; display: inline-flex; align-items: center; justify-content: center; min-width: 1.5rem; height: 1.5rem; padding: 0 .375rem; font-size: .75rem; font-weight: 600; color: var(--ink-700); border-radius: 999px; }
    .oc-cal-daynum--today { background: var(--primary); color: var(--primary-foreground); }
    .oc-cal-chips { display: flex; flex-direction: column; gap: .1875rem; min-width: 0; }
    .oc-cal-chip { display: flex; align-items: center; gap: .3125rem; width: 100%; min-height: 1.375rem; padding: .1875rem .375rem; font-size: .6875rem; line-height: 1.1; text-align: left; text-decoration: none; color: var(--oc-cal-ink); background: var(--oc-cal-tint); border: 0; border-left: 3px solid var(--oc-cal-accent); border-radius: var(--radius-sm, .375rem); cursor: pointer; transition: filter var(--duration-fast, .15s) var(--ease-out, ease); }
    @media (hover: hover) { .oc-cal-chip:hover { filter: brightness(0.97) saturate(1.05); } }
    .oc-cal-chip:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-500); }
    .oc-cal-chip-dot { width: .375rem; height: .375rem; border-radius: 999px; background: var(--oc-cal-accent); flex: 0 0 auto; }
    .oc-cal-chip-time { font-size: .625rem; opacity: .85; flex: 0 0 auto; }
    .oc-cal-chip-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; font-weight: 500; }
    .oc-cal-chip--allday { font-weight: 600; }
    .oc-cal-more { align-self: flex-start; padding: .0625rem .25rem; font-size: .6875rem; font-weight: 600; color: var(--ink-500); background: transparent; border: 0; border-radius: var(--radius-sm, .375rem); cursor: pointer; }
    @media (hover: hover) { .oc-cal-more:hover { color: var(--primary-ink); background: var(--surface-muted); } }
    .oc-cal-more:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-500); }
    .oc-cal-timegrid { display: flex; flex-direction: column; }
    .oc-cal-tg-head { display: grid; grid-template-columns: 3.5rem repeat(var(--oc-cal-cols, 7), minmax(0, 1fr)); border-bottom: 1px solid var(--line); }
    .oc-cal-tg-daybtn { display: flex; flex-direction: column; align-items: center; gap: .125rem; padding: .5rem 0; background: transparent; border: 0; border-left: 1px solid var(--line-2); cursor: pointer; }
    @media (hover: hover) { .oc-cal-tg-daybtn:hover { background: var(--surface-muted); } }
    .oc-cal-tg-daybtn:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--brand-500); }
    .oc-cal-tg-dow { font-size: .6875rem; font-weight: 600; color: var(--ink-500); text-transform: uppercase; letter-spacing: .03em; }
    .oc-cal-tg-dom { font-size: 1rem; font-weight: 600; color: var(--ink-900); }
    .oc-cal-tg-dom--today { display: inline-flex; align-items: center; justify-content: center; width: 1.75rem; height: 1.75rem; background: var(--primary); color: var(--primary-foreground); border-radius: 999px; }
    .oc-cal-tg-allday { display: grid; grid-template-columns: 3.5rem repeat(var(--oc-cal-cols, 7), minmax(0, 1fr)); border-bottom: 1px solid var(--line); background: var(--surface-muted); }
    .oc-cal-tg-allday-label { display: flex; align-items: center; justify-content: flex-end; padding-right: .5rem; font-size: .625rem; font-weight: 600; text-transform: uppercase; color: var(--ink-500); }
    .oc-cal-tg-allday-cell { display: flex; flex-direction: column; gap: .1875rem; padding: .25rem; border-left: 1px solid var(--line-2); min-width: 0; }
    .oc-cal-tg-scroll { max-height: 32rem; overflow-y: auto; }
    .oc-cal-tg-body { display: flex; }
    .oc-cal-tg-gutter { flex: 0 0 3.5rem; width: 3.5rem; }
    .oc-cal-tg-hour { position: relative; border-bottom: 1px solid var(--line-2); }
    .oc-cal-tg-hourlabel { position: absolute; top: -.5rem; right: .375rem; font-size: .625rem; color: var(--ink-400); }
    .oc-cal-tg-cols { display: grid; grid-template-columns: repeat(var(--oc-cal-cols, 7), minmax(0, 1fr)); flex: 1 1 auto; }
    .oc-cal-tg-col { position: relative; border-left: 1px solid var(--line-2); }
    .oc-cal-tg-slot { border-bottom: 1px solid var(--line-2); }
    .oc-cal-block { position: absolute; display: flex; flex-direction: column; gap: .0625rem; overflow: hidden; padding: .1875rem .375rem; font-size: .6875rem; text-align: left; text-decoration: none; color: var(--oc-cal-ink); background: var(--oc-cal-tint); border-left: 3px solid var(--oc-cal-accent); border-radius: var(--radius-sm, .375rem); cursor: pointer; z-index: 1; }
    @media (hover: hover) { .oc-cal-block:hover { filter: brightness(0.97) saturate(1.05); z-index: 2; } }
    .oc-cal-block:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-500); z-index: 3; }
    .oc-cal-block-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .oc-cal-block-time { font-size: .625rem; opacity: .85; }
    .oc-cal-now { position: absolute; left: 0; right: 0; height: 0; border-top: 2px solid var(--danger); z-index: 4; pointer-events: none; }
    .oc-cal-now-dot { position: absolute; left: -.25rem; top: -.3125rem; width: .625rem; height: .625rem; background: var(--danger); border-radius: 999px; }
    .oc-cal-agenda { display: flex; flex-direction: column; }
    .oc-cal-agenda-group { display: flex; gap: .875rem; padding: .75rem 1rem; border-bottom: 1px solid var(--line-2); }
    .oc-cal-agenda-date { position: relative; display: flex; flex-direction: column; align-items: center; flex: 0 0 3.25rem; padding: .375rem 0; background: transparent; border: 0; border-radius: var(--radius-sm, .5rem); cursor: pointer; }
    @media (hover: hover) { .oc-cal-agenda-date:hover { background: var(--surface-muted); } }
    .oc-cal-agenda-date:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-500); }
    .oc-cal-agenda-dow { font-size: .625rem; font-weight: 600; text-transform: uppercase; color: var(--ink-500); }
    .oc-cal-agenda-dom { font-size: 1.25rem; font-weight: 700; color: var(--ink-900); line-height: 1.1; }
    .oc-cal-agenda-mon { font-size: .625rem; font-weight: 600; text-transform: uppercase; color: var(--ink-500); }
    .oc-cal-agenda-date.is-today .oc-cal-agenda-dom { color: var(--primary); }
    .oc-cal-agenda-todaytag { margin-top: .125rem; padding: 0 .375rem; font-size: .5625rem; font-weight: 700; text-transform: uppercase; color: var(--primary-foreground); background: var(--primary); border-radius: 999px; }
    .oc-cal-agenda-items { display: flex; flex-direction: column; gap: .25rem; flex: 1 1 auto; min-width: 0; }
    .oc-cal-agenda-item { display: flex; align-items: center; gap: .625rem; padding: .5rem .625rem; text-decoration: none; color: var(--ink-900); background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm, .5rem); cursor: pointer; min-height: 2.75rem; }
    @media (hover: hover) { .oc-cal-agenda-item:hover { background: var(--surface-muted); border-color: var(--line); } }
    .oc-cal-agenda-item:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--brand-500); }
    .oc-cal-agenda-marker { flex: 0 0 auto; width: .5rem; height: .5rem; border-radius: 999px; }
    .oc-cal-agenda-when { flex: 0 0 auto; width: 6.5rem; font-size: .75rem; color: var(--ink-500); }
    .oc-cal-agenda-title { flex: 1 1 auto; min-width: 0; font-size: .8125rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .oc-cal-skeleton { padding: .75rem; }
    .oc-cal-skel-head { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .375rem; margin-bottom: .375rem; }
    .oc-cal-skel-weekday { height: 1.25rem; border-radius: var(--radius-sm, .375rem); background: var(--surface-muted); }
    .oc-cal-skel-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .375rem; }
    .oc-cal-skel-cell { height: 5rem; border-radius: var(--radius-sm, .5rem); background: linear-gradient(90deg, var(--surface-muted) 25%, var(--line-2) 37%, var(--surface-muted) 63%); background-size: 400% 100%; animation: oc-cal-shimmer 1.4s ease infinite; }
    @keyframes oc-cal-shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
    /* Layout follows the calendar's OWN width (JS sets data-oc-cal-size / data-oc-cal-compact from a ResizeObserver). */
    .oc-cal-cell, .oc-cal-chip { min-width: 0; }
    .oc-cal-chip { overflow: hidden; }
    .oc-cal-more { white-space: nowrap; }
    .oc-cal-weekday abbr { text-decoration: none; }
    .oc-cal-wd-narrow { display: none; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-wd-short { display: none; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-wd-narrow { display: inline; }
    .oc-calendar[data-oc-cal-size="medium"] .oc-cal-month-grid .oc-cal-chip-time { display: none; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-view-opt[data-oc-cal-view-opt="week"] { display: none; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-view-label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
    @media (prefers-reduced-motion: reduce) { .oc-cal-cell, .oc-cal-chip, .oc-cal-block, .oc-cal-tg-daybtn { transition: none; } .oc-cal-skel-cell { animation: none; } }

    /* ---------- Picker primitives — _Combobox / _ColorPicker / octacer-pickers.js ---------- */
    .oc-combobox-menu { animation: oc-menu-in .12s ease-out; }
    .oc-combobox-option.is-active { background: var(--primary-tint); color: var(--primary-ink); }
    .oc-combobox-option[aria-selected="true"] { font-weight: 600; }
    .oc-color-well { -webkit-appearance: none; appearance: none; }
    .oc-color-well::-webkit-color-swatch-wrapper { padding: 0; }
    .oc-color-well::-webkit-color-swatch { border: none; border-radius: .375rem; }
    .oc-color-well::-moz-color-swatch { border: none; border-radius: .375rem; }
    .oc-color-swatch { cursor: pointer; }
    .oc-color-swatch.is-selected { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--brand-500); }
    .oc-color-hex.is-invalid { border-color: var(--danger); }

    /* ---------- Editable data grid — _DataGrid.cshtml + octacer-datagrid.js ---------- */
    .oc-datagrid { --oc-dg-editing: color-mix(in srgb, var(--primary) 8%, var(--surface)); --oc-dg-dirty: var(--warning); --oc-dg-invalid: var(--danger); --oc-dg-saving: var(--info); --oc-dg-saved: var(--success); }
    .oc-datagrid tbody td.oc-datagrid-cell { position: relative; cursor: cell; padding-top: .375rem; padding-bottom: .375rem; }
    .oc-datagrid tbody td.oc-datagrid-cell[data-oc-readonly] { cursor: default; color: var(--ink-500); background: color-mix(in srgb, var(--line-2) 60%, transparent); }
    .oc-datagrid-cell:focus-visible, .oc-datagrid-cell[tabindex="0"]:focus { outline: none; box-shadow: inset 0 0 0 2px var(--brand-500); border-radius: .25rem; }
    .oc-datagrid-cell[aria-selected="true"] { background: color-mix(in srgb, var(--primary) 6%, transparent); }
    .oc-datagrid-cell-display { display: inline-block; min-height: 1.25rem; min-width: 1ch; }
    .oc-datagrid-cell-empty::after { content: "—"; color: var(--ink-400); }
    .oc-datagrid-cell.is-editing { padding: .125rem .25rem; background: var(--oc-dg-editing); box-shadow: inset 0 0 0 2px var(--brand-500); }
    .oc-datagrid-input { width: 100%; min-width: 0; height: 2rem; margin: 0; border-radius: .375rem; font-size: .85rem; }
    .oc-datagrid-input:focus { box-shadow: none; }
    .oc-datagrid-cell.is-dirty::before { content: ""; position: absolute; top: 0; left: 0; border-width: .4rem; border-style: solid; border-color: var(--oc-dg-dirty) transparent transparent var(--oc-dg-dirty); }
    .oc-datagrid tbody tr.is-dirty > td:first-child { box-shadow: inset .1875rem 0 0 var(--oc-dg-dirty); }
    .oc-datagrid-cell.is-invalid, .oc-datagrid-cell[aria-invalid="true"] { background: var(--danger-subtle); box-shadow: inset 0 0 0 2px var(--oc-dg-invalid); }
    .oc-datagrid-cell.is-saving { background: color-mix(in srgb, var(--oc-dg-saving) 10%, transparent); }
    .oc-datagrid-cell.is-saving .oc-datagrid-cell-display { opacity: .6; }
    .oc-datagrid-cell.is-saved { animation: oc-dg-saved-pulse var(--duration-slow) var(--ease-out); }
    .oc-datagrid-cell.is-error { background: var(--danger-subtle); box-shadow: inset 0 0 0 2px var(--oc-dg-invalid); }
    @keyframes oc-dg-saved-pulse { from { background: color-mix(in srgb, var(--oc-dg-saved) 22%, transparent); } to { background: transparent; } }
    .oc-datagrid-check-mark { display: inline-block; width: 1.05rem; height: 1.05rem; border-radius: .3rem; border: 1.5px solid var(--input); background: var(--surface); vertical-align: middle; position: relative; }
    .oc-datagrid-check-mark.is-on { background: var(--primary); border-color: var(--primary); }
    .oc-datagrid-check-mark.is-on::after { content: ""; position: absolute; left: .32rem; top: .12rem; width: .3rem; height: .55rem; border: solid var(--primary-foreground); border-width: 0 2px 2px 0; transform: rotate(45deg); }
    @media (pointer: coarse) { .oc-datagrid tbody td.oc-datagrid-cell { min-height: 2.75rem; } }
    @media (prefers-reduced-motion: reduce) { .oc-datagrid-cell.is-saved { animation: none !important; } }

    /* ============================================================
       App-shell & mobile-native foundation (2026-10). Below lg every Octacer app behaves like an
       installed phone app: compact safe-area app bar, bottom tab bar (+ "More" sheet), overlays as
       bottom sheets, tables as cards, FAB, pull-to-refresh, swipe rows. Contract: theme/COMPONENTS.md.
       ============================================================ */

    /* ---------- Skip link ---------- */
    .oc-skip-link { position: fixed; left: calc(.75rem + var(--oc-safe-left)); top: calc(.75rem + var(--oc-safe-top)); z-index: var(--z-progress); transform: translateY(-200%); padding: .5rem .875rem; border-radius: .625rem; background: var(--primary); color: var(--primary-foreground); font-size: .875rem; font-weight: 600; box-shadow: var(--shadow-lg); }
    .oc-skip-link:focus, .oc-skip-link:focus-visible { transform: none; outline: none; box-shadow: var(--ring); }

    /* ---------- Compact app bar (_AppHeader below lg; whole header in _LayoutMobile) ---------- */
    .oc-appbar { display: flex; align-items: center; gap: .25rem; min-height: var(--oc-appbar-h); padding: .25rem .5rem; }
    .oc-appbar-lead, .oc-appbar-trail { display: flex; align-items: center; gap: .125rem; flex: 0 0 auto; min-width: 2.75rem; }
    .oc-appbar-trail { justify-content: flex-end; }
    .oc-appbar-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1.0625rem; font-weight: 700; color: var(--ink-900); line-height: 1.2; }
    .oc-appbar-title.is-centered { text-align: center; }
    .oc-appbar-sub { display: block; font-size: .72rem; font-weight: 500; color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; }
    .oc-layout-header.is-condensed { box-shadow: var(--shadow-sm); }
    /* Large title, ALL widths: when the page has a _PageHeader heading, the app-bar title stays hidden until that
       heading scrolls under the bar — so the title is never shown twice (app bar + page heading). */
    .oc-layout-header [data-oc-appbar-compact-title] { opacity: 0; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-layout-header.is-condensed [data-oc-appbar-compact-title] { opacity: 1; }
    @media (max-width: 1023px) {
        /* In the phone app shell, back + tabs replace breadcrumbs (they cost a row and repeat the title). */
        html:has(.oc-tabbar) .oc-page-header .oc-breadcrumbs { display: none; }
        /* A FAB floats over the end of the page: leave room so the last content can scroll clear of it. */
        /* Not keyed to .is-hidden: the FAB auto-hides on scroll-down, and the space must not vanish (page jump). */
        html:has(.oc-fab) .oc-has-bottom-tabbar { padding-bottom: calc(var(--oc-tabbar-h) + var(--oc-safe-bottom) + 5.5rem); }
    }
    @media (min-width: 1024px) {
        /* Desktop: breadcrumbs already lead "up", so the app-bar back arrow is redundant next to them. */
        html:has(.oc-page-header .oc-breadcrumbs) .oc-appbar-lead [data-oc-back] { display: none; }
    }
    .oc-layout-header, .oc-sidebar-nav, .oc-sheet-handle { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

    /* ---------- Large title (iOS) — _PageHeader LargeTitle=true; collapses into the app bar ---------- */
    .oc-large-title { font-size: 1.875rem; font-weight: 800; line-height: 1.15; letter-spacing: -.02em; color: var(--ink-900); }
    @media (min-width: 1024px) { .oc-large-title { font-size: 1.5rem; font-weight: 700; } }

    /* ---------- Sticky tabs / segmented control under the app bar ---------- */
    /* Solid page background (not a translucent blur), so the strip is invisible until it actually sticks —
       a translucent fill read as a stray grey band on desktop. */
    .oc-tabs-sticky { position: sticky; top: calc(var(--oc-appbar-h) + var(--oc-safe-top)); z-index: var(--z-sticky); background: var(--bg); }
    .oc-tabs-scroll, .oc-tabbed-view > .oc-tabs { scrollbar-width: none; }
    .oc-tabs-scroll::-webkit-scrollbar, .oc-tabbed-view > .oc-tabs::-webkit-scrollbar { display: none; }

    /* ---------- "More" nav sheet (bottom tab bar overflow) ---------- */
    .oc-more-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr)); gap: .5rem; }
    .oc-more-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .375rem; min-height: 5rem; padding: .625rem .25rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--ink-700); font-size: .75rem; font-weight: 600; text-align: center; text-decoration: none; }
    .oc-more-tile > .oc-more-tile-icon { display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; border-radius: .75rem; background: var(--surface-muted); color: var(--ink-600); font-size: 1.05rem; }
    .oc-more-tile[aria-current="page"] { color: var(--primary-ink); border-color: var(--primary-tint-border); background: var(--primary-tint); }
    .oc-more-tile[aria-current="page"] > .oc-more-tile-icon { background: var(--primary); color: var(--primary-foreground); }
    .oc-more-tile:active { transform: scale(.97); }
    .oc-more-tile:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-more-group-title { margin: 0 0 .5rem; font-size: .6875rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-500); }

    /* ---------- Floating action button (_Fab) — phones/tablets only by default ---------- */
    .oc-fab {
        position: fixed; z-index: var(--z-fab);
        right: calc(1rem + var(--oc-safe-right));
        bottom: calc(var(--oc-bottom-chrome) + 1rem);
        display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
        width: 3.5rem; height: 3.5rem; border: 0; border-radius: 1.125rem;
        color: var(--primary-foreground); background: var(--primary);
        box-shadow: 0 10px 24px -8px color-mix(in srgb, var(--primary) 70%, transparent), var(--shadow-md);
        font-size: 1.25rem; font-weight: 700; cursor: pointer; text-decoration: none;
        -webkit-tap-highlight-color: transparent;
        transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out), bottom var(--duration-base) var(--ease-out);
    }
    .oc-fab:active { transform: scale(.94); }
    .oc-fab:focus-visible { outline: none; box-shadow: var(--ring), var(--shadow-md); }
    .oc-fab-extended { width: auto; padding: 0 1.25rem 0 1rem; font-size: .9375rem; }
    .oc-fab-extended > .oc-fab-label { font-size: .875rem; }
    /* Hidden = shrink + fade in place (sliding down would land it on the tab bar). */
    .oc-fab.is-hidden, html.oc-kb-open .oc-fab { transform: translateY(1rem) scale(.6); opacity: 0; pointer-events: none; }
    .oc-fab { transition: transform var(--duration-base) var(--ease-out), opacity var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out); }
    @media (min-width: 1024px) { .oc-fab:not(.oc-fab-always) { display: none; } }

    /* ---------- Back to top (_BackToTop) — always clears the tab bar and a FAB ---------- */
    .oc-back-to-top { position: fixed; z-index: var(--z-fab); right: calc(1rem + var(--oc-safe-right)); bottom: calc(var(--oc-bottom-chrome) + 1rem); transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out); }
    .oc-back-to-top.is-hidden { opacity: 0; transform: translateY(.5rem); pointer-events: none; visibility: hidden; }
    @media (max-width: 1023px) { html:has(.oc-fab:not(.is-hidden)) .oc-back-to-top { bottom: calc(var(--oc-bottom-chrome) + 5.25rem); } }

    /* ---------- Toast region — top-right on desktop, above the tab bar on phones ---------- */
    .oc-toast-region { position: fixed; z-index: var(--z-toast); display: flex; flex-direction: column; gap: .5rem; pointer-events: none;
        top: calc(1rem + var(--oc-safe-top)); right: calc(1rem + var(--oc-safe-right)); width: min(24rem, calc(100vw - 2rem - var(--oc-safe-left) - var(--oc-safe-right))); }
    .oc-toast-region > * { pointer-events: auto; }
    @media (max-width: 639px) {
        .oc-toast-region { top: auto; left: calc(.75rem + var(--oc-safe-left)); right: calc(.75rem + var(--oc-safe-right)); width: auto; bottom: calc(var(--oc-bottom-chrome) + .75rem); flex-direction: column-reverse; }
    }

    /* ---------- Overlay contract: _ConfirmModal / _TypedConfirmModal / _Drawer ----------
       Root: .oc-modal (centered dialog) or .oc-drawer (side panel); JS toggles hidden/flex.
       Panel: .oc-modal-panel / .oc-drawer-panel. Do NOT put items-, justify-, p- or rounded- utilities
       on these roots/panels — utilities would win and break the phone bottom-sheet conversion.
       Opt out per overlay with data-oc-mobile-sheet="false". */
    .oc-modal { position: fixed; inset: 0; z-index: var(--z-modal); align-items: center; justify-content: center; padding: 1rem; }
    .oc-modal[data-oc-nested="true"] { z-index: var(--z-modal-nested); }
    .oc-modal-backdrop, .oc-drawer-backdrop { position: absolute; inset: 0; background: var(--overlay); }
    .oc-modal > .oc-modal-panel { position: relative; width: 100%; max-height: calc(100dvh - 2rem); overflow-y: auto; overscroll-behavior: contain; animation: oc-modal-in var(--duration-base) var(--ease-out); }
    .oc-drawer { position: fixed; inset: 0; z-index: var(--z-drawer); justify-content: flex-end; }
    .oc-drawer > .oc-drawer-panel { position: relative; display: flex; flex-direction: column; height: 100%; width: 100%; background: var(--surface); box-shadow: var(--shadow-lg); padding-top: var(--oc-safe-top); padding-bottom: var(--oc-safe-bottom); animation: oc-drawer-in var(--duration-slow) var(--ease-out); }
    @keyframes oc-modal-in { from { opacity: 0; transform: translateY(.5rem) scale(.98); } to { opacity: 1; transform: none; } }
    @keyframes oc-drawer-in { from { transform: translateX(100%); } to { transform: none; } }
    @keyframes oc-sheet-up { from { transform: translateY(100%); } to { transform: none; } }
    @media (max-width: 639px) {
        .oc-modal:not([data-oc-mobile-sheet="false"]) { align-items: flex-end; padding: 0; }
        .oc-modal:not([data-oc-mobile-sheet="false"]) > .oc-modal-panel { max-width: none; max-height: 92dvh; border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; border-bottom: 0; padding-bottom: var(--oc-safe-bottom); animation: oc-sheet-up var(--duration-slow) var(--ease-out); }
        .oc-modal:not([data-oc-mobile-sheet="false"]) > .oc-modal-panel::before,
        .oc-drawer:not([data-oc-mobile-sheet="false"]) > .oc-drawer-panel::before { content: ""; display: block; flex: 0 0 auto; width: 2.25rem; height: .3rem; margin: .625rem auto .125rem; border-radius: 999px; background: var(--line-strong); }
        .oc-drawer:not([data-oc-mobile-sheet="false"]) { align-items: flex-end; }
        .oc-drawer:not([data-oc-mobile-sheet="false"]) > .oc-drawer-panel { height: auto; max-height: 94dvh; max-width: none !important; width: 100% !important; padding-top: 0; border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; animation: oc-sheet-up var(--duration-slow) var(--ease-out); }
        /* Action rows in sheets: full-width, primary on top, thumb-reachable. */
        .oc-modal:not([data-oc-mobile-sheet="false"]) .oc-modal-actions { flex-direction: column-reverse; align-items: stretch; }
        .oc-modal:not([data-oc-mobile-sheet="false"]) .oc-modal-actions > .btn { width: 100%; min-height: 2.875rem; }
    }

    /* ---------- Anchored popups as sheets on phones (pickers, combobox, menus) ----------
       JS adds .is-sheet to a popup panel when matchMedia('(max-width: 639px)') matches (see
       OctacerSheetDock in octacer-bottomsheet.js); the scrim is a sibling .oc-dock-scrim. */
    .oc-dock-scrim { position: fixed; inset: 0; z-index: calc(var(--z-popover) - 1); background: var(--overlay); animation: oc-fade-in var(--duration-base) var(--ease-out); }
    .is-sheet.is-sheet { position: fixed !important; inset: auto 0 0 0 !important; z-index: var(--z-popover) !important; width: auto !important; max-width: none !important; max-height: min(85dvh, calc(var(--oc-vvh, 100dvh) - 3rem)) !important; overflow-y: auto; transform: none !important; margin: 0 !important;
        border-radius: var(--radius-2xl) var(--radius-2xl) 0 0 !important; padding-bottom: calc(var(--oc-safe-bottom) + .5rem) !important; background: var(--popover); box-shadow: var(--shadow-lg); animation: oc-sheet-up var(--duration-slow) var(--ease-out); }
    @keyframes oc-fade-in { from { opacity: 0; } to { opacity: 1; } }

    /* ---------- Tables → cards in narrow space (_Table / _DataTable MobileLayout="cards", the default) ----------
       Cells carry data-label="Column". Mark the title cell data-oc-cell="title", the actions cell
       data-oc-cell="actions", the checkbox cell data-oc-cell="select"; low-value columns
       data-oc-priority="low" are hidden in card mode.
       Driven by the space the TABLE has, not the viewport: a table in a 360px card, a drawer or a half-width
       column on desktop becomes cards; a table across a wide tablet stays a table. The containers are the
       scroll region (works for hand-written .oc-table-scroll > table) and the swap region [data-oc-table]
       (so the scroll region's own overrides can query too). Never the shell card: it holds the phone-fixed
       bulk bar, and a size container must not risk becoming its containing block. */
    .oc-table-scroll, .oc-table-shell [data-oc-table] { container: oc-table / inline-size; }
    @container oc-table (width < 40rem) {
        .oc-table-cards { min-width: 0 !important; border-spacing: 0; }
        .oc-table-cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
        .oc-table-cards tbody, .oc-table-cards tr, .oc-table-cards td { display: block; }
        .oc-table-cards tbody { display: flex; flex-direction: column; gap: .5rem; padding: .625rem; }
        .oc-table-cards tbody tr { position: relative; padding: .625rem .875rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-sm); }
        .oc-table-cards tbody tr:focus-within { box-shadow: var(--ring); }
        .oc-table-cards tbody td, .oc-table-cards tbody td:first-child, .oc-table-cards tbody td:last-child { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; padding: .1875rem 0; border: 0; text-align: right; min-width: 0; overflow-wrap: break-word; }
        .oc-table-cards tbody td::before { content: attr(data-label); flex: 0 0 auto; max-width: 45%; text-align: left; font: 600 .72rem/1.3 var(--font-sans); letter-spacing: normal; color: var(--ink-500); }
        .oc-table-cards tbody td:not([data-label])::before, .oc-table-cards tbody td[data-label=""]::before { content: none; }
        .oc-table-cards tbody td[data-oc-cell="title"] { display: block; padding: 0 2.5rem .25rem 0; text-align: left; font-size: .875rem; font-weight: 600; color: var(--ink-900); }
        .oc-table-cards tbody td[data-oc-cell="title"]::before { content: none; }
        .oc-table-cards tbody td[data-oc-cell="select"] { position: absolute; top: .625rem; right: .625rem; padding: 0; }
        .oc-table-cards tbody td[data-oc-cell="select"]::before { content: none; }
        .oc-table-cards tbody td[data-oc-cell="actions"] { justify-content: flex-end; margin-top: .25rem; padding-top: .25rem; border-top: 1px solid var(--line-2); }
        .oc-table-cards tbody td[data-oc-cell="actions"]::before { content: none; }
        .oc-table-cards tbody td[data-oc-priority="low"] { display: none; }
        /* Pinned-column rules (sticky + solid bg) don't apply inside a card. */
        .oc-table-cards tbody td.oc-col-pin-start, .oc-table-cards tbody td.oc-col-pin-end { left: auto; background: transparent; box-shadow: none; z-index: auto; }
        .oc-table-cards tbody td[data-oc-cell="select"] { width: auto; left: auto; z-index: 1; }
        .oc-table-cards tbody td[data-oc-cell="actions"] { position: static; right: auto; }
        .oc-table-cards tbody tr.oc-table-state-row, .oc-table-cards tbody tr.oc-table-state-row td { display: block; border: 0; box-shadow: none; padding: 0; background: transparent; text-align: center; }
        .oc-table-cards tbody tr.oc-table-state-row td::before { content: none; }
        .oc-table-scroll:has(> .oc-table-cards) { overflow-x: visible; }
        .oc-datatable-scroll:has(> .oc-table-cards) { max-height: none; background: none; }
    }

    /* ---------- Pull to refresh ([data-oc-ptr], octacer-appshell.js) ---------- */
    .oc-ptr-indicator { position: fixed; left: 50%; top: calc(var(--oc-appbar-h) + var(--oc-safe-top) + .5rem); z-index: var(--z-header); display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; margin-left: -1.25rem; border-radius: 999px; background: var(--popover); color: var(--primary); box-shadow: var(--shadow-md); opacity: 0; transform: translateY(calc(var(--oc-ptr-pull, 0px) - 3rem)) rotate(calc(var(--oc-ptr-pull, 0px) * 3)); pointer-events: none; }
    .oc-ptr-indicator.is-pulling { opacity: 1; }
    .oc-ptr-indicator.is-armed { color: var(--primary-foreground); background: var(--primary); }
    .oc-ptr-indicator.is-refreshing { opacity: 1; transform: translateY(0); }
    .oc-ptr-indicator.is-refreshing > * { animation: oc-spin .7s linear infinite; }

    /* ---------- Swipe actions on list rows ([data-oc-swipe], octacer-appshell.js) ----------
       Never swipe-only: the same actions stay reachable via the row's visible menu/buttons. */
    .oc-swipe { position: relative; overflow: hidden; touch-action: pan-y; }
    .oc-swipe-content { position: relative; z-index: 1; background: var(--surface); transform: translateX(var(--oc-swipe-x, 0px)); transition: transform var(--duration-base) var(--ease-out); }
    .oc-swipe.is-dragging .oc-swipe-content { transition: none; }
    .oc-swipe-actions { position: absolute; inset: 0 0 0 auto; display: flex; align-items: stretch; }
    /* At rest the action layer must not peek around the row's rounded border. */
    .oc-swipe:not(.is-dragging):not(.is-open) .oc-swipe-actions { visibility: hidden; }
    .oc-swipe-action { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: .25rem; min-width: 4.5rem; padding: 0 .75rem; border: 0; color: var(--primary-foreground); background: var(--primary); font-size: .72rem; font-weight: 600; cursor: pointer; }
    .oc-swipe-action.is-danger { color: var(--danger-foreground); background: var(--danger); }
    .oc-swipe-action.is-neutral { color: var(--ink-900); background: var(--surface-muted); }

    /* ---------- Load more (_Pagination MobileMode) ---------- */
    .oc-load-more { display: flex; justify-content: center; padding: 1rem 0; }
    .oc-load-more-sentinel { height: 1px; }

    /* ---------- Touch & form ergonomics ---------- */
    @media (pointer: coarse) {
        /* iOS Safari zooms the page when a focused field is < 16px. Important so a text-sm utility on a
           field can't re-introduce the zoom (component-layer !important outranks utilities). */
        .field-input, .field-select, .field-textarea, .field-group > input, .oc-code-editor, .oc-datagrid-input,
        .oc-searchable input, .oc-combobox input, input.oc-command-input, [data-oc-command] input[type="text"],
        [data-oc-command] input[type="search"], .oc-tags-input input { font-size: 16px !important; }
        [data-oc-tooltip]::after { display: none; }
    }
    @media (max-width: 639px) {
        .field-input, .field-select, .field-textarea, .field-group > input, .oc-code-editor { font-size: 16px; }
    }

    /* ---------- Forced colors (Windows High Contrast) ---------- */
    @media (forced-colors: active) {
        .btn, .oc-icon-btn, .oc-tabbar-link, .oc-fab, .oc-more-tile { border: 1px solid ButtonText; }
        :focus-visible { outline: 2px solid Highlight !important; outline-offset: 2px; }
        .oc-tabbar-link[aria-current="page"], .oc-sidebar-nav a[aria-current="page"] { outline: 2px solid Highlight; }
    }

    /* ---------- Print ---------- */
    @media print {
        .oc-sidebar, .oc-sidebar-overlay, .oc-tabbar, .oc-fab, .oc-back-to-top, .oc-toast-region, #oc-progress, .oc-skip-link, .oc-sheet, .oc-ptr-indicator, [data-oc-print="hide"] { display: none !important; }
        .oc-layout-header { position: static; backdrop-filter: none; box-shadow: none; }
        .oc-shell-content { padding-left: 0 !important; }
        .oc-has-bottom-tabbar { padding-bottom: 0 !important; }
        .oc-card, .oc-stat, .oc-list-item { box-shadow: none; break-inside: avoid; }
        body, .oc-layout, .oc-app-bg { background: #fff !important; color: #000; }
    }

    /* ============================================================
       App shell & navigation (layouts, _AppHeader, _Sidebar, _BottomTabBar, _NavMoreSheet, _ThemeToggle)
       ============================================================ */
    /* ============================================================
       Agent A — app shell: sidebar / app bar / tab bar / More sheet / layouts.
       ============================================================ */

    /* Skip-link target: focusing <main> programmatically must not paint a ring around the whole page. */
    #oc-main:focus, #oc-main:focus-visible { outline: none; box-shadow: none; }

    /* ---------- Sidebar ---------- */
    .oc-sidebar { z-index: var(--z-sidebar); }
    .oc-sidebar-group-title { margin: 1rem 0 .25rem; padding: 0 .625rem; font-size: .6875rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-500); }
    .oc-sidebar-nav > .oc-sidebar-group-title:first-child { margin-top: .25rem; }
    .oc-sidebar-nav .badge { flex: 0 0 auto; }
    .oc-sidebar-chevron { transition: transform var(--duration-fast) var(--ease-out); }
    .oc-sidebar-nav [data-oc-sidebar-submenu][aria-expanded="true"] .oc-sidebar-chevron { transform: rotate(180deg); }
    /* An expanded submenu is not "current" — only the trail to the current page is highlighted. */
    .oc-sidebar-nav [data-oc-sidebar-submenu][aria-expanded="true"]:not(.is-trail) { color: var(--ink-900); background: transparent; border-color: transparent; box-shadow: none; font-weight: 600; }
    .oc-sidebar-nav [data-oc-sidebar-submenu].is-trail[aria-expanded="false"] { color: var(--primary-ink); font-weight: 700; }
    .oc-sidebar-sub { margin-top: .125rem; }
    @media (hover: hover) { .oc-sidebar-collapse:hover { background: var(--surface-muted); color: var(--ink-900); } }
    .oc-sidebar-collapse { min-height: 2rem; }
    @media (min-width: 1024px) {
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-group-title,
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-chevron,
        html.oc-sidebar-collapsed .oc-sidebar .oc-theme-toggle-label,
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-sub { display: none; }
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-footer { align-items: center; overflow: hidden; padding-left: .5rem; padding-right: .5rem; }
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-footer .oc-theme-toggle { width: auto; justify-content: center; }
        html.oc-sidebar-collapsed .oc-sidebar .oc-sidebar-collapse { margin-left: .5rem; margin-right: .5rem; }
        html.oc-sidebar-collapsed .oc-sidebar > div:first-child { justify-content: center; padding-left: .5rem; padding-right: .5rem; }
    }
    /* Drawer (opt-out mode, < lg): slide out before becoming hidden; shadow only while open. */
    @media (max-width: 1023px) {
        .oc-sidebar { transition: transform var(--duration-base) var(--ease-out), visibility 0s linear var(--duration-base); padding-top: var(--oc-safe-top); padding-bottom: var(--oc-safe-bottom); padding-left: var(--oc-safe-left); max-width: calc(100vw - 3rem); }
        .oc-sidebar.is-open { transition: transform var(--duration-base) var(--ease-out), visibility 0s; box-shadow: var(--shadow-lg); }
    }
    @media (prefers-reduced-motion: reduce) { .oc-sidebar { transition: none !important; } }

    /* ---------- App bar ---------- */
    .oc-appbar-trail:empty { visibility: hidden; }
    /* ⋯ "More actions" wrapper built by octacer-appshell.js when actions squeeze the title (§12 there). */
    .oc-appbar-overflow { display: inline-flex; flex: 0 0 auto; }

    /* _PageHeader "More" actions trigger: a labelled outline button on desktop; below lg it is moved into the
       app bar (data-oc-appbar-teleport) and reads as a plain ⋯ icon button (the native action-sheet trigger). */
    .oc-page-more-trigger { display: inline-flex; align-items: center; justify-content: center; gap: .5rem; min-height: 2rem; padding: .3125rem .75rem; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink-700); font-size: .8125rem; font-weight: 500; line-height: 1.25rem; white-space: nowrap; cursor: pointer; box-shadow: var(--shadow-sm); }
    @media (hover: hover) { .oc-page-more-trigger:hover { background: var(--surface-muted); border-color: var(--line-strong); color: var(--ink-900); } }
    .oc-page-more-trigger:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-page-more-trigger[aria-expanded="true"] { background: var(--surface-muted); }
    @media (max-width: 1023px) {
        .oc-page-more-trigger { width: 2.75rem; height: 2.75rem; min-height: 0; padding: 0; border: 0; border-radius: .625rem; background: transparent; box-shadow: none; color: var(--ink-700); font-size: 1.125rem; }
        .oc-page-more-label { display: none; }
        /* Not yet teleported (no JS / no app bar): keep it at the end of the title row. */
        .oc-page-header .oc-page-more { margin-left: auto; }
    }
    @media (min-width: 1024px) {
        .oc-appbar-title { font-size: 1.125rem; }
        .oc-appbar-trail { min-width: 0; }
    }

    /* ---------- Bottom tab bar ---------- */
    /* Shell.TabBarAlways (_LayoutMobile): keep the bar AND its space reservation on large screens. */
    @media (min-width: 1024px) {
        html:has(.oc-tabbar.oc-tabbar-always) { --oc-bottom-chrome: calc(var(--oc-tabbar-h) + var(--oc-safe-bottom)); }
        html:has(.oc-tabbar.oc-tabbar-always) .oc-has-bottom-tabbar { padding-bottom: calc(var(--oc-tabbar-h) + var(--oc-safe-bottom) + 1rem); }
        html.oc-kb-open:has(.oc-tabbar.oc-tabbar-always) { --oc-bottom-chrome: 0px; }
    }
    @media (prefers-reduced-motion: reduce) { .oc-tabbar { transition: none; } }

    /* ---------- "More" sheet ---------- */
    .oc-more-tile-icon { position: relative; }
    /* Tile label: up to 2 lines, wrapping at spaces ("Reports and / analytics") instead of "Reports an…". */
    .oc-more-tile-label { max-width: 100%; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; line-height: 1.25; overflow-wrap: normal; word-break: normal; }
    .oc-more-tile-icon > .oc-tabbar-badge { top: -.35rem; left: auto; right: -.5rem; }
    .oc-more-tile-icon > .oc-tabbar-badge-dot { top: -.1rem; right: -.1rem; }
    @media (hover: hover) { .oc-more-tile:hover { border-color: var(--line-strong); color: var(--ink-900); } }
    .oc-more-footer:empty { display: none; }

    /* ---------- Theme toggle ---------- */
    .oc-theme-toggle [data-oc-theme-icon] { display: inline-flex; align-items: center; justify-content: center; }
    .oc-theme-toggle[aria-pressed] { font-weight: 600; }

    /* ---------- _LayoutShell (in-page scaffold — never a second full-height shell) ---------- */
    .oc-layout-shell .oc-layout-with-sidebar,
    .oc-layout-shell .oc-layout-with-inner-sidebar,
    .oc-layout-shell .oc-layout-with-inner-sidebar-content { min-height: 0; }
    .oc-layout-shell .oc-layout-inner-sidebar { border-radius: var(--radius); }
    /* Columns follow the SCAFFOLD's own width (it lives inside the content column, beside the desktop sidebar),
       never the viewport: stacked below 48rem, side column from 48rem, page rail beside main from 64rem. */
    .oc-layout-shell { container: oc-layout-shell / inline-size; }
    .oc-layout-shell .oc-layout-with-sidebar,
    .oc-layout-shell .oc-layout-with-inner-sidebar,
    .oc-layout-shell .oc-layout-with-inner-sidebar-content { display: block; }
    .oc-layout-shell .oc-layout-inner-sidebar { margin-top: 1rem; }
    @container oc-layout-shell (min-width: 48rem) {
        .oc-layout-shell .oc-layout-with-sidebar { display: grid; grid-template-columns: 14rem minmax(0, 1fr); }
        .oc-layout-shell .oc-layout-with-inner-sidebar { display: grid; grid-template-columns: 14rem minmax(0, 1fr); }
        .oc-layout-shell .oc-layout-with-inner-sidebar > .oc-layout-inner-sidebar { grid-column: 1 / -1; }
    }
    @container oc-layout-shell (min-width: 64rem) {
        .oc-layout-shell .oc-layout-with-inner-sidebar { grid-template-columns: 14rem minmax(0, 1fr) 14rem; column-gap: 1.5rem; }
        .oc-layout-shell .oc-layout-with-inner-sidebar > .oc-layout-inner-sidebar { grid-column: auto; margin-top: 0; }
        .oc-layout-shell .oc-layout-with-inner-sidebar-content { display: grid; grid-template-columns: minmax(0, 1fr) 14rem; column-gap: 1.5rem; }
        .oc-layout-shell .oc-layout-with-inner-sidebar-content > .oc-layout-inner-sidebar { margin-top: 0; }
    }

    /* ---------- Page rail (_LayoutInnerSidebar) ---------- */
    @media (min-width: 1280px) { .oc-layout-with-inner-sidebar-content > .oc-layout-inner-sidebar { min-height: calc(100dvh - var(--oc-appbar-h)); } }


    /* ============================================================
       Overlays, feedback & navigation primitives (modal/drawer/sheet/popover/toast/fab/command/breadcrumbs/tabs)
       ============================================================ */
    /* ---------- Agent B: overlays, toasts, nav, buttons (appended at the end of @layer components) ---------- */

    /* _Button LoadingLabel: when busy, show "spinner + label" instead of a blank button. */
    .btn[aria-busy="true"][data-oc-loading-label], .btn.is-loading[data-oc-loading-label] { color: inherit !important; }
    .btn[aria-busy="true"][data-oc-loading-label] > *, .btn.is-loading[data-oc-loading-label] > * { display: none; }
    .btn[aria-busy="true"][data-oc-loading-label]::before, .btn.is-loading[data-oc-loading-label]::before { content: attr(data-oc-loading-label); order: 2; }
    .btn[aria-busy="true"][data-oc-loading-label]::after, .btn.is-loading[data-oc-loading-label]::after { position: static; flex: 0 0 auto; order: 1; }
    a.btn[aria-disabled="true"] { cursor: not-allowed; }

    /* Toasts: fill the region (no overflow at 320px), long words wrap, ≥44px dismiss on touch. */
    .oc-toast-region > .oc-toast { width: auto; max-width: 100%; }
    .oc-toast-message { overflow-wrap: anywhere; }
    .oc-toast .oc-toast-action { color: inherit; }
    @media (pointer: coarse) {
        .oc-toast .oc-toast-close { width: 2.75rem; height: 2.75rem; margin: -.625rem -.625rem -.625rem 0; }
        .oc-toast .oc-toast-action { min-height: 2.75rem; margin: -.5rem 0; }
    }

    /* Overlays: the header × of modals/drawers/sheets is a ≥44px target on touch. */
    @media (pointer: coarse) {
        .oc-modal-panel .oc-icon-btn, .oc-drawer-panel .oc-icon-btn, .oc-sheet-panel .oc-icon-btn, .oc-command-panel .oc-icon-btn { width: 2.75rem; height: 2.75rem; }
    }
    .oc-drawer > .oc-drawer-panel { border-left: 1px solid var(--line); }
    @media (max-width: 639px) {
        .oc-drawer:not([data-oc-mobile-sheet="false"]) > .oc-drawer-panel { border-left: 0; border-top: 1px solid var(--line); }
    }

    /* _BottomSheet: never taller than the visible viewport (keyboard open), safe-area padding from the shell vars. */
    .oc-sheet-panel { max-height: min(90dvh, calc(var(--oc-vvh, 100dvh) - 1rem)); padding-bottom: var(--oc-safe-bottom, env(safe-area-inset-bottom, 0px)); }
    html.oc-kb-open .oc-sheet { height: var(--oc-vvh, 100dvh); }
    @media (prefers-reduced-motion: reduce) { .oc-sheet-scrim, .oc-sheet-panel { transition: none !important; } }

    /* _Popover: the body scrolls when the panel is height-capped; docked (phone sheet) panels drop the arrow. */
    .oc-popover-panel { max-width: calc(100vw - 1rem); }
    .oc-popover-panel > .oc-popover-body { flex: 1 1 auto; }
    .oc-popover-panel.is-sheet { display: flex; flex-direction: column; }
    .is-sheet > .oc-popover-arrow { display: none; }
    .oc-popover-panel.is-sheet > .oc-popover-body { padding: 1rem; }
    .oc-popover-panel.is-sheet::before { content: ""; display: block; flex: 0 0 auto; width: 2.25rem; height: .3rem; margin: .625rem auto 0; border-radius: 999px; background: var(--line-strong); }

    /* _CommandPalette: keyboard hint strip only where there is a keyboard-ish pointer. */
    @media (hover: none), (pointer: coarse) { .oc-command-hints { display: none !important; } }

    /* Scrollable tab strips (_PageHeader / _TabbedView): no visible scrollbar on any width. */
    .oc-tabs.oc-tabs-scroll { scrollbar-width: none; }
    .oc-tabs.oc-tabs-scroll::-webkit-scrollbar { display: none; }
    .oc-tab[role="tab"]:focus-visible { outline: none; box-shadow: var(--ring-inset, var(--ring)); border-radius: .375rem .375rem 0 0; }
    .oc-tab { min-height: 2.25rem; }
    .oc-tab-panel:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius-sm); }

    /* _Fab: the icon never shrinks in the extended pill. */
    .oc-fab > i { flex: 0 0 auto; }


    /* ============================================================
       Tables, lists, trees & data display
       ============================================================ */
/* ===================== Agent C — tables, lists, trees, data-display ===================== */

/* ---------- Popup menus ([data-oc-popmenu]: _RowActions overflow, _DataTable columns) ----------
   octacer-table.js moves the open panel to <body> and fixed-positions it under its trigger (never clipped
   by .oc-table-scroll / card overflow); on phones it gets .is-sheet via OctacerSheetDock. */
.oc-popmenu { position: fixed; z-index: var(--z-popover); min-width: 12rem; max-width: calc(100vw - 1rem); max-height: min(24rem, calc(100dvh - 2rem)); overflow-y: auto; overscroll-behavior: contain; padding: .25rem; color: var(--ink-700); background: var(--popover); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-lg); animation: oc-menu-in var(--duration-fast) var(--ease-out); }
.oc-popmenu:focus { outline: none; }
.oc-popmenu-heading { margin: 0; padding: .375rem .625rem .25rem; font-size: .7rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-500); }
.oc-popmenu-item { display: flex; align-items: center; gap: .5rem; width: 100%; min-height: 2rem; padding: .3125rem .5rem; border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--ink-700); font: inherit; font-size: .875rem; line-height: 1.25; text-align: left; text-decoration: none; cursor: pointer; }
.oc-popmenu-item:focus-visible { outline: none; background: var(--surface-muted); color: var(--ink-900); box-shadow: var(--ring-inset); }
.oc-popmenu-item.is-danger { color: var(--danger); }
.oc-popmenu-item.is-danger:focus-visible { background: color-mix(in srgb, var(--danger) 10%, var(--popover)); color: var(--danger); }
.oc-popmenu-item[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.oc-popmenu-sep { height: 1px; margin: .25rem .375rem; background: var(--line); }
.oc-popmenu-label { padding: .5rem .625rem .25rem; font-size: .6875rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-500); }

/* ---------- Account menu (_UserMenu) — avatar at the far right of the app bar ---------- */
.oc-user-menu { display: inline-flex; flex: 0 0 auto; }
.oc-user-trigger { display: inline-flex; align-items: center; gap: .5rem; min-height: 2.25rem; max-width: 16rem; padding: .25rem .375rem; border: 0; border-radius: 999px; background: transparent; color: var(--ink-700); font: inherit; font-size: .875rem; font-weight: 600; cursor: pointer; }
@media (hover: hover) { .oc-user-trigger:hover { background: var(--surface-muted); } }
.oc-user-trigger[aria-expanded="true"] { background: var(--surface-muted); }
.oc-user-trigger:focus-visible { outline: none; box-shadow: var(--ring); }
.oc-user-avatar { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 2rem; height: 2rem; overflow: hidden; border-radius: 999px; background: var(--primary-tint); color: var(--primary-ink); font-size: .75rem; font-weight: 700; letter-spacing: 0; }
.oc-user-avatar > img { width: 100%; height: 100%; object-fit: cover; }
.oc-user-avatar-lg { width: 2.75rem; height: 2.75rem; font-size: .9375rem; }
.oc-user-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-user-caret { display: inline-flex; color: var(--ink-500); flex: 0 0 auto; }
/* Phones/tablets: avatar only (the name lives in the menu header). */
@media (max-width: 1023px) {
    .oc-user-trigger { padding: .375rem; }
    .oc-user-name, .oc-user-caret { display: none; }
}
.oc-user-panel { min-width: 16rem; max-height: min(40rem, calc(100dvh - 5rem)); }   /* tall enough that Sign out never scrolls out of view */
.oc-user-head { display: flex; align-items: center; gap: .75rem; padding: .625rem .625rem .5rem; }
.oc-user-head-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .9375rem; font-weight: 700; color: var(--ink-900); }
.oc-user-head-sub { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .8125rem; color: var(--ink-500); }
.oc-user-theme[aria-checked="true"] { color: var(--primary-ink); background: var(--primary-tint); font-weight: 600; }
.oc-user-theme[aria-checked="true"]::after { content: "\2713"; margin-left: auto; font-weight: 700; }
@media (hover: hover) {
    .oc-popmenu-item:hover { background: var(--surface-muted); color: var(--ink-900); }
    .oc-popmenu-item.is-danger:hover { background: color-mix(in srgb, var(--danger) 10%, var(--popover)); color: var(--danger); }
}
@media (pointer: coarse) { .oc-popmenu-item { min-height: 2.75rem; } }
.oc-popmenu.is-sheet { padding-top: .25rem; padding-left: .5rem; padding-right: .5rem; }
.oc-popmenu.is-sheet::before { content: ""; display: block; width: 2.25rem; height: .3rem; margin: .375rem auto .5rem; border-radius: 999px; background: var(--line-strong); }
.oc-popmenu.is-sheet .oc-popmenu-item { min-height: 3rem; padding-left: 1rem; padding-right: 1rem; font-size: 1rem; }
[data-oc-popmenu-trigger][aria-expanded="true"] { background: var(--surface-muted); color: var(--ink-900); }
@media (prefers-reduced-motion: reduce) { .oc-popmenu { animation: none; } }

/* ---------- Tables: sort headers, selection, state rows, region busy ---------- */
.oc-th-sort { border-radius: .25rem; }
.oc-th-sort:focus-visible { outline: none; box-shadow: var(--ring); }
.oc-table thead th[aria-sort="ascending"], .oc-table thead th[aria-sort="descending"] { color: var(--ink-900); }
.oc-table thead th[aria-sort="ascending"] .oc-th-sort-icon, .oc-table thead th[aria-sort="descending"] .oc-th-sort-icon { color: var(--primary-ink); }
/* Layer the (possibly translucent) tint over an opaque surface so pinned cells stay opaque when scrolled. */
.oc-table tbody tr.is-selected, .oc-table tbody tr.is-selected > td { background: linear-gradient(var(--primary-tint), var(--primary-tint)), var(--surface); }
.oc-table tbody tr.oc-table-state-row > td { padding: 0; border-bottom: 0; }
@media (hover: hover) { .oc-table tbody tr.oc-table-state-row:hover { background: transparent; } }
.oc-table tbody tr.oc-table-state-row:focus-within { background: transparent; }
[data-oc-table].htmx-request .oc-table-scroll, [data-oc-table].htmx-request .oc-empty-state { opacity: .55; pointer-events: none; transition: opacity var(--duration-base) var(--ease-out); }

/* ---------- Table toolbar — wraps by its OWN content, never the viewport ----------
   Title keeps the line; the search/tools group sits beside it while both fit and drops onto its own
   full-width line when they don't (a 360px card, a drawer, a phone). */
.oc-table-toolbar { row-gap: .625rem; }
.oc-table-toolbar > .oc-card-title { flex: 999 1 auto; min-width: 0; }
.oc-table-toolbar > .field-group { flex: 1 1 16rem; min-width: 0; }
.oc-table-toolbar > .oc-table-tools { flex: 1 1 auto; min-width: 0; }
.oc-table-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: .5rem; }
.oc-table-tools > .field-group { flex: 1 1 auto; width: 14rem; min-width: 0; }
/* MobileLayout="scroll" in narrow space: a slimmer minimum so fewer columns hide off-screen. */
@container oc-table (width < 40rem) { .oc-table-scroll > .oc-table:not(.oc-table-cards, .oc-treetable) { min-width: 36rem; } }
/* Tree tables have few columns — size to their content instead of the generic 42rem scroll width. */
.oc-table-scroll > .oc-table.oc-treetable { min-width: 0; }
/* The name column takes the leftover width and truncates (full text in title=) instead of pushing Status/
   Count off-screen; it never gets narrower than 11rem — below that the region scrolls sideways. */
.oc-treetable > * > tr > [data-oc-col="name"] { width: 100%; max-width: 0; min-width: 11rem; }
@media (pointer: coarse) { .oc-tree-leaf-spacer { width: 2.75rem; } }

/* ---------- Bulk-action bar ---------- */
.oc-bulk-action-bar { background: linear-gradient(var(--primary-tint), var(--primary-tint)), var(--surface); border: 1px solid var(--primary-tint-border); }
[data-oc-bulkbar-slot]:has(> [data-oc-bulkbar][hidden]) { display: none; }
@media (max-width: 639px) {
    /* Phones: a fixed, thumb-reachable action bar above the tab bar / home indicator. */
    .oc-bulk-action-bar:not([hidden]) { position: fixed; z-index: var(--z-fab); left: calc(.75rem + var(--oc-safe-left)); right: calc(.75rem + var(--oc-safe-right)); bottom: calc(max(var(--oc-bottom-chrome), var(--oc-safe-bottom)) + .75rem); background: linear-gradient(var(--primary-tint), var(--primary-tint)), var(--popover); box-shadow: var(--shadow-lg); animation: oc-sheet-up var(--duration-base) var(--ease-out); }
    [data-oc-bulkbar-slot]:has(> .oc-bulk-action-bar:not([hidden])) { padding: 0; }
    .oc-table-shell:has(.oc-bulk-action-bar:not([hidden])) { padding-bottom: 7rem; }
    html:has(.oc-bulk-action-bar:not([hidden])) .oc-fab,
    html:has(.oc-bulk-action-bar:not([hidden])) .oc-back-to-top { opacity: 0; pointer-events: none; }
}
@media (max-width: 639px) and (prefers-reduced-motion: reduce) { .oc-bulk-action-bar:not([hidden]) { animation: none; } }

/* ---------- Load more (_Pagination MobileMode) ---------- */
.oc-load-more-busy { display: none; }
.htmx-request > .oc-load-more-busy { display: inline-flex; }
.htmx-request > .oc-load-more-idle { display: none; }

/* ---------- Filter chips (_FilterBar) — the × keeps a ≥44px hit area ---------- */
.oc-filter-chip { min-height: 1.75rem; padding-right: .25rem; }
.oc-filter-chip-remove { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; margin: -.25rem 0; border-radius: 999px; color: var(--ink-500); }
.oc-filter-chip-remove::after { content: ""; position: absolute; inset: -.625rem; }
.oc-filter-chip-remove:focus-visible { outline: none; box-shadow: var(--ring); }
/* "+N more" chip (Filter.MaxChips) — opens the panel that lists every applied filter. */
.oc-filter-chip-more { border: 0; cursor: pointer; }
.oc-filter-chip-more:focus-visible { outline: none; box-shadow: var(--ring); }
/* Filter panel fields: any number of filters lays out as an intrinsic grid (1 column on phones, 2–3 in the
   desktop panel); the panel body scrolls while the Apply / Clear footer stays pinned. */
.oc-filter-fields { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)); gap: 1rem 1.25rem; align-items: start; }
.oc-filter-fields > .oc-filter-field-full, .oc-filter-fields > fieldset { grid-column: 1 / -1; }
@media (hover: hover) { .oc-filter-chip-remove:hover { background: var(--line); color: var(--ink-900); } }
.oc-sheet .oc-filter-chip { min-height: 2.5rem; padding-left: .75rem; font-size: .875rem; }

/* ---------- Lists (_List) — narrow LIST (phone, drawer, half column): actions drop under the text ---------- */
@container oc-list (width < 32rem) {
    .oc-list-item { align-items: flex-start; flex-wrap: wrap; padding: .875rem 1rem; }
    .oc-list-item-actions { width: 100%; padding-left: 3rem; }
    /* Basis 0: icon + text + badge share the first line (title truncates) instead of the badge wrapping alone. */
    .oc-list-item-main { flex-basis: 0; flex-grow: 1; }
    /* A lone ⋯ menu stays on the row instead of wrapping onto its own line. */
    .oc-list-item:has(> .oc-list-item-actions > .oc-row-actions:only-child) { flex-wrap: nowrap; align-items: center; }
    .oc-list-item-actions:has(> .oc-row-actions:only-child) { width: auto; padding-left: 0; }
}

/* ---------- Tree view (_TreeView) ---------- */
.oc-tree-row { min-height: 2rem; }
.oc-tree-row.is-selected { background: var(--primary-tint); }
.oc-tree-row.is-selected .oc-tree-label { color: var(--primary-ink); font-weight: 600; }
.oc-tree-toggle, .oc-tree-toggle-spacer { width: 1.5rem; height: 1.5rem; flex: 0 0 auto; }
.oc-tree-toggle { padding: 0; border: 0; background: transparent; cursor: pointer; }
.oc-tree-chevron { transition: transform var(--duration-fast) var(--ease-out); }
.oc-tree-chevron.is-open { transform: rotate(90deg); }
@media (hover: hover) {
    .oc-tree-row:not(.is-selected):hover { background: var(--surface-muted); }
    .oc-tree-toggle:hover { color: var(--ink-900); background: var(--line-2); }
}
@media (pointer: coarse) {
    .oc-tree-row, .oc-tree-label { min-height: 2.75rem; }
    .oc-tree-toggle, .oc-tree-toggle-spacer { width: 2.75rem; height: 2.75rem; }
}
@media (prefers-reduced-motion: reduce) { .oc-tree-chevron { transition: none; } }

/* ---------- Timeline (_Timeline) — tap the time to see the absolute timestamp ---------- */
.oc-timeline-time { position: relative; padding: 0; border: 0; border-radius: .25rem; background: transparent; cursor: pointer; }
.oc-timeline-time::after { content: ""; position: absolute; inset: -.75rem -.5rem; }
.oc-timeline-time:focus-visible { outline: none; box-shadow: var(--ring); }
@media (hover: hover) { .oc-timeline-time:hover { color: var(--ink-900); } }

/* ---------- Stepper (_Stepper Orientation="horizontal") ---------- */
.oc-stepper[tabindex]:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius); }


    /* ============================================================
       Calendar, kanban, data grid, media grid & lightbox
       ============================================================ */
    /* ================= Agent D — Calendar / Kanban / DataGrid / MediaGrid / Lightbox ================= */

    /* ---------- Calendar — toolbar (root is the outer section; wraps on phones) ---------- */
    .oc-cal-toolbar { flex-wrap: wrap; row-gap: .5rem; }
    .oc-cal-toolbar-main { display: flex; align-items: center; gap: .75rem; min-width: 0; flex: 1 1 auto; }
    .oc-cal-title { min-width: 0; }
    .oc-cal-viewswitch { flex: 0 0 auto; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar { align-items: center; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar-main { flex: 1 1 100%; flex-wrap: wrap; row-gap: .25rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-title { flex: 1 1 100%; order: 3; }

    /* ---------- Calendar — time grid geometry via custom properties (set by the JS through the CSSOM) ---------- */
    .oc-cal-tg-hour, .oc-cal-tg-slot { height: var(--oc-cal-hour-h, 3rem); }
    .oc-cal-tg-col { height: var(--oc-cal-grid-h, auto); }
    .oc-cal-tg-scroll { max-height: min(32rem, 65dvh); overscroll-behavior: contain; }
    /* Time-grid blocks: title first and never squeezed to 0 height; both lines ellipsize (no mid-number wraps). */
    .oc-cal-block > * { flex-shrink: 0; min-width: 0; }
    .oc-cal-block-time { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .oc-cal-tg-allday-label { text-align: end; line-height: 1.15; }
    .oc-cal-agenda-item { width: 100%; text-align: start; }
    .oc-cal-agenda-text { display: flex; align-items: center; gap: .625rem; flex: 1 1 auto; min-width: 0; }
    .oc-cal-agenda-when { white-space: nowrap; }
    /* Narrow calendar: title first (wraps at spaces, max 2 lines), time range underneath on one line. */
    .oc-calendar[data-oc-cal-compact] .oc-cal-agenda-text { flex-direction: column; align-items: flex-start; gap: .125rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-agenda-title { order: -1; width: 100%; white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-agenda-when { width: auto; font-size: .75rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-tg-gutter { flex-basis: 3rem; width: 3rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-tg-head, .oc-calendar[data-oc-cal-compact] .oc-cal-tg-allday { grid-template-columns: 3rem repeat(var(--oc-cal-cols, 1), minmax(0, 1fr)); }
    .oc-calendar[data-oc-cal-compact] .oc-cal-block { font-size: .75rem; padding: .3125rem .5rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-agenda-group { gap: .625rem; padding: .625rem .75rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-agenda-date { flex-basis: 3rem; min-height: 2.75rem; }
    @media (pointer: coarse) {
        .oc-cal-tg-allday .oc-cal-chip, .oc-cal-more { min-height: 2.75rem; }
        .oc-cal-tg-daybtn { min-height: 2.75rem; }
    }

    /* ---------- Calendar — compact (phone) month: whole cell is the target, readable colour dots ---------- */
    .oc-cal-month-grid.is-compact { grid-auto-rows: minmax(3.5rem, auto); }
    .oc-cal-month-grid.is-compact .oc-cal-cell { min-height: 3.5rem; padding: .25rem .125rem; align-items: center; gap: .3125rem; }
    .oc-cal-month-grid.is-compact .oc-cal-daynum { align-self: center; min-width: 1.75rem; height: 1.75rem; font-size: .8125rem; }
    .oc-cal-dots { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .1875rem; min-height: .5rem; }
    .oc-cal-dot { flex: 0 0 auto; width: .5rem; height: .5rem; border-radius: 999px; }
    .oc-cal-dot-more { font-size: .625rem; font-weight: 600; line-height: .5rem; color: var(--ink-500); }
    .oc-cal-cell[aria-current="date"] { box-shadow: inset 0 0 0 1px var(--primary-tint-border); }
    @media (hover: none) { .oc-cal-cell:hover:not(.oc-cal-cell--muted) { background: transparent; } }

    /* ---------- Kanban — floated / docked Move menu (lives in <body> while open, never clipped) ---------- */
    .oc-kanban-move-menu { position: fixed; z-index: var(--z-popover); right: auto; top: auto; width: min(16rem, calc(100vw - 1rem)); max-height: min(20rem, calc(100dvh - 2rem)); overscroll-behavior: contain; }
    .oc-kanban-move-menu.is-sheet { padding: .5rem .5rem calc(var(--oc-safe-bottom) + .5rem); }
    .oc-kanban-move-menu.is-sheet .oc-kanban-move-item { min-height: 2.75rem; font-size: .9375rem; }

    /* ---------- Kanban — touch long-press drag ---------- */
    .oc-kanban-card { -webkit-touch-callout: none; }
    /* Touch: a linked card's whole surface opens the link (a short title like "1:1" is otherwise a 16px target);
       the Move button stays above it. */
    @media (pointer: coarse) {
        .oc-kanban-card-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
        .oc-kanban-card-move { position: relative; z-index: 1; }
    }
    @media (pointer: coarse) { .oc-kanban-card { -webkit-user-select: none; user-select: none; } }
    .oc-kanban-card.is-pressing { transform: scale(.98); box-shadow: var(--shadow-md); }
    .oc-kanban.is-touch-dragging .oc-kanban-scroll { scroll-snap-type: none; }
    .oc-kanban.is-touch-dragging { -webkit-user-select: none; user-select: none; }
    .oc-kanban-ghost { position: fixed; left: 0; top: 0; z-index: var(--z-popover); margin: 0; pointer-events: none; cursor: grabbing; opacity: .95; box-shadow: var(--shadow-lg); border-color: var(--primary-tint-border); will-change: transform; }
    .oc-kanban-col-body.is-drop-target { box-shadow: inset 0 0 0 2px var(--primary); }
    @media (prefers-reduced-motion: reduce) { .oc-kanban-card.is-pressing { transform: none; } }

    /* ---------- DataGrid — root is the card; toolbar, undo bar, sticky first column ---------- */
    .oc-datagrid-toolbar { flex-wrap: wrap; row-gap: .5rem; }
    @media (max-width: 639px) { .oc-datagrid-toolbar { flex-direction: row; align-items: center; } }
    .oc-datagrid-undo { align-items: center; gap: .625rem; margin: .75rem 1rem 0; padding: .5rem .5rem .5rem .875rem; background: var(--surface-muted); border: 1px solid var(--line); border-radius: var(--radius); }
    .oc-datagrid tbody td.oc-datagrid-cell.oc-col-pin-start { position: sticky; left: 0; }
    /* Fixed layout honours the declared column widths; --oc-dg-min-w (sum of them, set by the JS) stops the table
       squeezing in a narrow card — it scrolls inside the card instead of breaking values mid-number. */
    .oc-datagrid { table-layout: fixed; width: 100%; min-width: var(--oc-dg-min-w, 100%); }
    .oc-datagrid-cell[data-oc-type="number"], .oc-datagrid-cell[data-oc-type="date"], .oc-datagrid-cell[data-oc-type="select"] { white-space: nowrap; }
    .oc-datagrid-cell-display { max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: middle; }
    /* The pinned header cell must sit above the other sticky header cells it slides over. */
    .oc-datagrid-scroll > .oc-datagrid thead th.oc-col-pin-start { z-index: calc(var(--z-sticky) + 1); }
    /* The pinned cell needs an opaque background (it slides over its neighbours); keep its state tints. */
    .oc-datagrid tbody td.oc-col-pin-start[data-oc-readonly] { background: color-mix(in srgb, var(--line-2) 60%, var(--surface)); }
    .oc-datagrid tbody td.oc-col-pin-start.is-editing { background: var(--oc-dg-editing); }
    .oc-datagrid tbody td.oc-col-pin-start.is-saving { background: color-mix(in srgb, var(--oc-dg-saving) 10%, var(--surface)); }
    .oc-datagrid tbody td.oc-col-pin-start.is-invalid, .oc-datagrid tbody td.oc-col-pin-start[aria-invalid="true"], .oc-datagrid tbody td.oc-col-pin-start.is-error { background: var(--danger-subtle); }
    .oc-datagrid-row-delete { color: var(--ink-500); }
    @media (hover: hover) { .oc-datagrid-row-delete:hover { color: var(--danger); background: var(--danger-subtle); } }
    .oc-datagrid-row-delete:focus-visible { outline: none; box-shadow: var(--ring); }
    @media (pointer: coarse) {
        .oc-datagrid tbody td.oc-datagrid-cell { height: 2.75rem; }
        .oc-datagrid-input { height: 2.5rem; }
    }

    /* ---------- MediaGrid — tile thumb, always-reachable selection checkbox ---------- */
    /* Default MediaGrid columns: as many ≥ 7rem tiles as the grid's OWN width fits — 2 on a 320px phone or in a 360px
       card, 6–7 full width (auto-fill keeps tile size when there are only a few items). Replaces viewport sm:/lg:
       counts that squeezed tiles in narrow columns. */
    .oc-media-cols { grid-template-columns: repeat(auto-fill, minmax(min(100%, 7rem), 1fr)); }
    .oc-media-thumb { position: relative; display: block; width: 100%; aspect-ratio: 1 / 1; padding: 0; overflow: hidden; border: 0; border-radius: var(--radius-lg); background: var(--surface-muted); color: inherit; cursor: pointer; }
    div.oc-media-thumb { cursor: default; }
    .oc-media-thumb:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-media-tile[data-oc-selected="true"] .oc-media-thumb { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--primary); }
    .oc-media-select { position: absolute; left: 0; top: 0; display: flex; align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem; cursor: pointer; opacity: 0; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-media-select .oc-check { width: 1.25rem; height: 1.25rem; min-height: 0; margin: 0; background: var(--surface); box-shadow: var(--shadow-sm); }
    .oc-media-tile:focus-within .oc-media-select,
    .oc-media-select[data-oc-shown="true"],
    [data-oc-has-selection="true"] .oc-media-select { opacity: 1; }
    @media (hover: hover) and (pointer: fine) { .oc-media-tile:hover .oc-media-select { opacity: 1; } }
    @media (hover: none), (pointer: coarse) { .oc-media-select { opacity: 1; } }
    @media (prefers-reduced-motion: reduce) { .oc-media-select { transition: none; } }

    /* ---------- Lightbox — safe areas + swipe surface ---------- */
    .oc-lightbox { background: rgb(2 6 23 / .92); }
    /* Phones: prev/next float over the stage edges (swipe is the primary gesture) so the media gets the full width. */
    @media (max-width: 639px) {
        .oc-lightbox-stage > [data-oc-lightbox-prev], .oc-lightbox-stage > [data-oc-lightbox-next] { position: absolute; top: calc(50% - 1.375rem); z-index: 1; }
        .oc-lightbox-stage > [data-oc-lightbox-prev] { left: .5rem; }
        .oc-lightbox-stage > [data-oc-lightbox-next] { right: .5rem; }
    }
    .oc-lightbox { margin: 0; padding: var(--oc-safe-top) var(--oc-safe-right) var(--oc-safe-bottom) var(--oc-safe-left); overscroll-behavior: contain; }
    .oc-lightbox-stage { touch-action: pinch-zoom; }
    .oc-lightbox-media { transition: transform var(--duration-fast) var(--ease-out), opacity var(--duration-fast) var(--ease-out); }
    .oc-lightbox-media.is-swiping { transition: none; }
    @media (prefers-reduced-motion: reduce) { .oc-lightbox-media { transition: none; } }


    /* ============================================================
       Form controls & pickers
       ============================================================ */
/* ============================================================
   Agent E — form primitives (pickers, date fields, inputs, editors, uploads).
   Sizes live here (not as utilities on the element) so the touch rules below can grow them.
   ============================================================ */

/* ---------- Small icon buttons inside a .field-group (clear date / clear rating / clear colour) ---------- */
.oc-field-icon-btn { width: 1.75rem; min-width: 1.75rem; height: 1.75rem; min-height: 1.75rem; margin-inline-end: -.375rem; flex: 0 0 auto; }
@media (pointer: coarse) {
    .oc-field-icon-btn { width: 2.75rem; min-width: 2.75rem; height: 2.75rem; min-height: 2.75rem; margin-block: -.25rem; }
}

/* ---------- Combobox (_Combobox.cshtml) ---------- */
.oc-combobox-list { max-height: 16rem; overflow-y: auto; overscroll-behavior: contain; }
.oc-combobox-option { min-height: 2.25rem; }
.oc-combobox-option.is-active { background: var(--surface-muted); }
.oc-combobox-option[aria-selected="true"] { color: var(--primary-ink); background: var(--primary-tint); font-weight: 600; }
.oc-combobox-option[aria-selected="true"].is-active { background: color-mix(in srgb, var(--primary-tint) 70%, var(--surface-muted)); }
@media (hover: hover) { .oc-combobox-option:hover { background: var(--surface-muted); } }
.oc-combobox-sheet-head { display: none; }
.is-sheet .oc-combobox-sheet-head { display: flex; align-items: center; gap: .5rem; position: sticky; top: 0; z-index: 1; padding: .25rem .25rem .5rem; background: var(--popover); }
.is-sheet .oc-combobox-list { max-height: none; overflow: visible; }
.is-sheet .oc-combobox-option { min-height: 2.75rem; }

/* ---------- Searchable select (octacer-searchable.js) ---------- */
.oc-searchable-list { max-height: 16rem; overflow-y: auto; overscroll-behavior: contain; padding: .25rem; }
.oc-searchable-option { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: .5rem; min-height: 2.25rem; padding: .5rem .75rem; border: 0; border-radius: .5rem; background: transparent; color: var(--ink-700); font-size: .875rem; text-align: start; cursor: pointer; }
.oc-searchable-option.is-active { background: var(--surface-muted); color: var(--ink-900); }
@media (hover: hover) { .oc-searchable-option:not([aria-disabled="true"]):hover { background: var(--surface-muted); color: var(--ink-900); } }
.oc-searchable-option[aria-disabled="true"] { color: var(--ink-400); cursor: not-allowed; }
.oc-searchable-search { border-width: 0 0 1px 0; border-radius: 0; box-shadow: none; }
.oc-searchable-search:focus { box-shadow: none; border-color: var(--line); }
.oc-searchable-trigger:disabled { background: var(--surface-muted); color: var(--ink-400); cursor: not-allowed; }
.is-sheet .oc-searchable-search { position: sticky; top: 0; z-index: 1; background: var(--popover); }
.is-sheet .oc-searchable-list { max-height: none; overflow: visible; }
.is-sheet .oc-searchable-option { min-height: 2.75rem; }

/* ---------- Colour picker swatches (_ColorPicker.cshtml) ---------- */
.oc-color-swatch { width: 1.75rem; height: 1.75rem; flex: 0 0 auto; }
.oc-color-well { width: 3rem; height: 2.625rem; }
@media (pointer: coarse) {
    .oc-color-swatch { width: 2.75rem; height: 2.75rem; }
    .oc-color-well { height: 2.75rem; }
}

/* ---------- Date fields (_DatePicker / _DateRangePicker) ---------- */
/* Grid with a minmax(0,1fr) track: the trigger keeps its natural (max-content) width in toolbars, but its
   min-content is ~0, so a long "Tuesday, September 1, 2026 – …" never forces a narrow column/drawer wider;
   the text ellipsizes instead of breaking. */
.oc-datefield-trigger { min-height: 2.5rem; display: grid; grid-template-columns: minmax(0, 1fr); align-items: center; }
.oc-datefield-trigger > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (pointer: coarse) {
    .oc-datefield-trigger { min-height: 2.75rem; }
    .oc-daterange-preset { min-height: 2.75rem; }
}
.oc-daterange-preset.is-active { color: var(--primary-ink); background: var(--primary-tint); }
.is-sheet[data-oc-dp-panel], .is-sheet[data-oc-dr-panel] { padding-left: 1rem; padding-right: 1rem; }
.is-sheet .oc-cal-day { min-height: 2.75rem; font-size: .9375rem; }
.oc-daterange-presets { flex-wrap: wrap; }
.is-sheet .oc-daterange-presets { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: .25rem; }
.is-sheet .oc-daterange-presets::-webkit-scrollbar { display: none; }
.is-sheet .oc-daterange-preset { flex: 0 0 auto; white-space: nowrap; border: 1px solid var(--line); }

/* ---------- Slider (_Slider.cshtml) — 20px visual thumb, 44px hit area ---------- */
.oc-slider-track { touch-action: pan-y; cursor: pointer; }
.oc-slider-track::before { content: ""; position: absolute; inset: -1rem 0; }
.oc-slider-thumb { width: 1.25rem; height: 1.25rem; }
.oc-slider-thumb::before { content: ""; position: absolute; inset: -.75rem; border-radius: 999px; }
.oc-slider-thumb:disabled, [data-oc-slider-disabled="true"] .oc-slider-track { cursor: not-allowed; }
@media (pointer: coarse) {
    .oc-slider-thumb { width: 1.5rem; height: 1.5rem; }
    .oc-slider-thumb::before { inset: -.625rem; }
}

/* ---------- Rating (_Rating.cshtml) ---------- */
.oc-rating { flex-wrap: wrap; max-width: 100%; }   /* many stars (Max=10) wrap instead of overflowing */
.oc-rating-star { flex-shrink: 0; width: 2.25rem; height: 2.25rem; font-size: 1.375rem; }
.oc-rating-star--sm { width: 1.5rem; height: 1.5rem; font-size: .9375rem; }
.oc-rating-star--lg { width: 2.75rem; height: 2.75rem; font-size: 1.875rem; }
@media (pointer: coarse) {
    .oc-rating[role="slider"] .oc-rating-star { width: 2.75rem; height: 2.75rem; }
}

/* ---------- OTP boxes (_OtpInput.cshtml) — shrink to fit 360px with up to 8 boxes ---------- */
/* Sized by the space the row has (not the viewport): the row ignores its content width (contain) and the boxes
   shrink from 2.75rem towards 1.75rem, so 6–8 boxes fit a 320px phone, a drawer or a half-width card. */
.oc-otp-row { display: flex; align-items: center; gap: .375rem; flex-wrap: nowrap; max-width: 100%; contain: inline-size; }
.oc-otp-row .oc-otp-box { width: 2.75rem; min-width: 1.5rem; flex: 0 1 2.75rem; }

/* ---------- Tags input chips (_TagsInput.cshtml) ---------- */
.oc-tag-remove { position: relative; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; width: 1.25rem; height: 1.25rem; border: 0; border-radius: 999px; background: transparent; color: inherit; opacity: .75; cursor: pointer; }
.oc-tag-remove:focus-visible { outline: none; opacity: 1; box-shadow: var(--ring); }
@media (hover: hover) { .oc-tag-remove:hover { opacity: 1; background: color-mix(in srgb, currentColor 15%, transparent); } }
.oc-tag-remove::after { content: ""; position: absolute; inset: -.375rem; }
.oc-tag-remove:disabled { cursor: not-allowed; opacity: .4; }
@media (pointer: coarse) {
    .oc-tag-remove { width: 1.5rem; height: 1.5rem; }
    .oc-tag-remove::after { inset: -.625rem; }
    .oc-tags-input [data-oc-tags-shell] { row-gap: .5rem; }
}

/* ---------- Segmented control (_SegmentedControl.cshtml) — scroll instead of overflowing at 360px ---------- */
.oc-segmented-scroll { max-width: 100%; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.oc-segmented-scroll::-webkit-scrollbar { display: none; }
.oc-segmented-scroll > .oc-view-toggle { min-width: max-content; }
.oc-segmented-scroll > .oc-view-toggle.oc-segmented-full { width: max-content; min-width: 100%; }
/* Full: block-level + full width, so it may ignore its content width — never widens a grid column/drawer. */
.oc-segmented-scroll-full { contain: inline-size; }
.oc-view-toggle-button:disabled { cursor: not-allowed; opacity: .55; }

/* ---------- Dropzone (_Dropzone.cshtml) — touch copy swap ---------- */
.oc-dropzone-hint-touch { display: none; }
@media (pointer: coarse) {
    .oc-dropzone-hint-mouse { display: none; }
    .oc-dropzone-hint-touch { display: inline; }
    .oc-dropzone-browse { min-height: 2.75rem; display: inline-flex; align-items: center; }
}

/* ---------- Rich text / Markdown editors ---------- */
.oc-richtext-linkbar .field-input { font-family: var(--font-sans, inherit); }
/* contenteditable zooms on iOS like an input when < 16px (the markup carries text-sm; !important beats it). */
@media (pointer: coarse) { .oc-richtext-input { font-size: 16px !important; } }
.oc-markdown-panel[hidden] { display: none; }

/* ---------- Client-side required guard (octacer-forms.js) ---------- */
[data-oc-required-root].is-invalid .oc-slider-track { box-shadow: 0 0 0 1px var(--danger); }
[data-oc-required-root].is-invalid .oc-view-toggle { border-color: var(--danger); }
[data-oc-required-root].is-invalid .oc-richtext-shell, [data-oc-required-root].is-invalid .oc-dropzone { border-color: var(--danger); }
[data-oc-required-root].is-invalid .oc-rating { border-radius: var(--radius-sm, .5rem); box-shadow: 0 0 0 1px var(--danger); }

/* ---------- Colour picker: "no colour chosen" preview dot ---------- */
.oc-color-preview-empty { background: repeating-linear-gradient(45deg, var(--surface-muted) 0 3px, var(--surface) 3px 6px); border-style: dashed; }


    /* ============================================================
       Widgets & charts
       ============================================================ */
/* ---------- Agent F: widgets (_ChartCard) ---------- */
/* Chart mount never forces horizontal overflow; ApexCharts redraws to the container width. */
.oc-chart-mount { width: 100%; min-width: 0; }
.oc-chart-mount .apexcharts-canvas, .oc-chart-mount svg { max-width: 100%; }
/* Period change in flight (hx-indicator = the card): dim the plot, keep the header usable. */
.oc-chart-card .oc-chart-body { transition: opacity var(--duration-fast) var(--ease-out); }
.oc-chart-card.htmx-request .oc-chart-body { opacity: .55; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
    .oc-chart-card .oc-chart-body { transition: none; }
}


    /* ============================================================
       Shell integration (page-header FAB auto mode, code editor tokens)
       ============================================================ */
    /* ---------- Lead: _PageHeader PrimaryMobile="auto" (default) ----------
       Header primary button + FAB are both rendered; CSS shows the FAB only on phones/tablets when the page
       renders the bottom tab bar (the app shell), otherwise the header button stays. */
    .oc-fab.oc-fab-auto { display: none; }
    @media (max-width: 1023px) {
        html:has(.oc-tabbar) .oc-fab.oc-fab-auto { display: inline-flex; }
        html:has(.oc-tabbar) .btn.oc-primary-auto { display: none; }
    }

    /* ---------- Lead: code editor on tokens (dark slab in both modes, readable) ---------- */
    .oc-code-editor { background: color-mix(in srgb, var(--ink-900) 92%, var(--primary)); color: var(--surface); }
    .dark .oc-code-editor { background: var(--bg); color: var(--ink-700); border-color: var(--line); }

    /* ============================================================
       _Wizard (octacer-wizard.js) — step-based multi-step flow
       ------------------------------------------------------------
       Layout follows the wizard's OWN width (container oc-wizard on the <form>): ≥ 48rem a vertical step rail
       beside the panel; narrower a horizontal scrolling strip above it. Phone/tablet FOCUS mode (viewport
       < 1024px, page-level wizard only — never inside a drawer/modal/sheet): compact sticky header under the
       app bar + sticky bottom action bar; the tab bar and FAB hide. State is attribute-driven; html[data-oc-theme]
       (set by octacer-theme-init.js) means JS runs — without it every step is shown stacked with one Submit.
       ============================================================ */
    .oc-wizard { display: block; min-width: 0; --oc-wizard-top: 0px; --oc-wizard-bleed: 0px; }
    .oc-wizard-form { container: oc-wizard / inline-size; display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
    .oc-wizard-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; align-items: start; }
    .oc-wizard-main { display: flex; flex-direction: column; gap: 1.25rem; min-width: 0; }

    /* Step rail — default: horizontal strip that scrolls inside itself (current step kept in view by JS). */
    .oc-wizard-nav { min-width: 0; }
    .oc-wizard-steps { display: flex; align-items: center; margin: 0; padding: .125rem; list-style: none; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
    .oc-wizard-steps::-webkit-scrollbar { display: none; }
    /* Edge fades while steps are scrolled out of view (classes kept by octacer-wizard.js). */
    .oc-wizard-steps.is-clipped-end { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent); }
    .oc-wizard-steps.is-clipped-start { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent); }
    .oc-wizard-steps.is-clipped-start.is-clipped-end { -webkit-mask-image: linear-gradient(to right, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent); mask-image: linear-gradient(to right, transparent, #000 2.5rem, #000 calc(100% - 2.5rem), transparent); }
    .oc-wizard-step { position: relative; display: flex; align-items: center; flex: 0 0 auto; min-width: 0; }
    .oc-wizard-step + .oc-wizard-step::before { content: ""; flex: 0 0 auto; width: 1rem; height: 2px; margin: 0 .125rem; border-radius: 999px; background: var(--line-strong); }
    .oc-wizard-step:is([data-state="complete"], [data-state="current"])::before { background: var(--primary); }
    .oc-wizard-step-link { display: inline-flex; align-items: center; gap: .5rem; min-height: 2.75rem; max-width: 13rem; padding: .25rem .5rem; border-radius: var(--radius-md); color: var(--ink-500); font-size: .875rem; line-height: 1.25; text-decoration: none; }
    .oc-wizard-step-link[href] { cursor: pointer; }
    .oc-wizard-step-link[aria-disabled="true"] { cursor: default; }
    @media (hover: hover) { .oc-wizard-step-link[href]:hover { background: var(--surface-muted); color: var(--ink-900); } }
    .oc-wizard-step-link:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-wizard-marker {
        display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
        width: 2rem; height: 2rem; border-radius: 999px; border: 2px solid var(--line-strong);
        background: var(--surface); color: var(--ink-500); font: 600 .8125rem/1 var(--font-mono);
        transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out);
    }
    .oc-wizard-ico-done, .oc-wizard-ico-err { display: none; align-items: center; justify-content: center; font-size: .8125rem; }
    .oc-wizard-step-text { display: flex; flex-direction: column; min-width: 0; }
    .oc-wizard-step-title { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
    .oc-wizard-step-desc { display: none; }
    .oc-wizard-step[data-state="complete"] .oc-wizard-marker { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); }
    .oc-wizard-step[data-state="complete"] .oc-wizard-step-link { color: var(--ink-700); }
    .oc-wizard-step[data-state="current"] .oc-wizard-marker { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent); }
    .oc-wizard-step[data-state="current"] .oc-wizard-step-link { color: var(--ink-900); font-weight: 600; }
    .oc-wizard-step[data-state="error"] .oc-wizard-marker { background: var(--danger); border-color: var(--danger); color: var(--danger-foreground); }
    .oc-wizard-step[data-state="error"] .oc-wizard-step-link { color: var(--danger); font-weight: 600; }
    .oc-wizard-step[data-state="error"][aria-current="step"] .oc-wizard-marker { box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 22%, transparent); }
    .oc-wizard-step[data-state="complete"] .oc-wizard-num, .oc-wizard-step[data-state="error"] .oc-wizard-num { display: none; }
    .oc-wizard-step[data-state="complete"] .oc-wizard-ico-done, .oc-wizard-step[data-state="error"] .oc-wizard-ico-err { display: inline-flex; }

    /* Step panel */
    .oc-wizard-panel { display: flex; flex-direction: column; gap: 1.25rem; min-width: 0; scroll-margin-top: calc(var(--oc-wizard-top) + 1rem); }
    .oc-wizard-panel-head { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
    .oc-wizard-panel-kicker { margin: 0; font-size: .75rem; font-weight: 600; letter-spacing: .02em; color: var(--primary-ink); }
    /* The heading is a programmatic focus target (tabindex=-1) on step change, not a control: no ring. */
    .oc-wizard-panel-title { margin: 0; font-size: 1.125rem; font-weight: 700; line-height: 1.3; color: var(--ink-900); }
    .oc-wizard-panel-title:focus { outline: none; }
    .oc-wizard-panel-desc { margin: 0; font-size: .875rem; color: var(--ink-500); }
    .oc-wizard-panel-body { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
    .oc-wizard-panel-pending { margin: 0; font-size: .875rem; color: var(--ink-500); }

    /* Footer actions: Cancel left; Save draft, Back, Next / Submit right. */
    .oc-wizard-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .75rem; padding-top: 1rem; border-top: 1px solid var(--line); }
    .oc-wizard-footer-start, .oc-wizard-footer-end { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; min-width: 0; }
    .oc-wizard-footer-end { margin-left: auto; justify-content: flex-end; }

    /* JS state (attribute-driven, matches the server-rendered first paint) */
    html[data-oc-theme] .oc-wizard-panel:not(.is-current) { display: none; }
    html[data-oc-theme] .oc-wizard-form[data-oc-wizard-at="first"] .oc-wizard-back { display: none; }
    html[data-oc-theme] .oc-wizard-form:not([data-oc-wizard-at="last"]) .oc-wizard-submit { display: none; }
    html[data-oc-theme] .oc-wizard-form[data-oc-wizard-at="last"] .oc-wizard-next { display: none; }
    html:not([data-oc-theme]) .oc-wizard :is(.oc-wizard-next, .oc-wizard-back, [data-oc-wizard-js]) { display: none; }
    html:not([data-oc-theme]) .oc-wizard-panel + .oc-wizard-panel { padding-top: 1.5rem; border-top: 1px solid var(--line); }

    /* Compact progress header — phones/tablets in focus mode only (see the media block below). */
    .oc-wizard-mhead { display: none; }
    .oc-wizard-mhead-row { display: flex; align-items: center; gap: .25rem; min-height: 2.75rem; }
    .oc-wizard-mhead-cancel { margin-left: -.5rem; }
    .oc-wizard-mhead-text { display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; }
    .oc-wizard-mhead-count { font-size: .75rem; font-weight: 600; color: var(--ink-500); white-space: nowrap; }
    .oc-wizard-mhead-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1rem; font-weight: 700; color: var(--ink-900); }
    .oc-wizard-mhead-draft { flex: 0 0 auto; }
    .oc-wizard-progress { display: block; width: 100%; height: .25rem; margin-top: .375rem; border: 0; border-radius: 999px; background: var(--line); color: var(--primary); -webkit-appearance: none; appearance: none; overflow: hidden; }
    .oc-wizard-progress::-webkit-progress-bar { background: var(--line); border-radius: 999px; }
    .oc-wizard-progress::-webkit-progress-value { background: var(--primary); border-radius: 999px; transition: width var(--duration-base) var(--ease-out); }
    .oc-wizard-progress::-moz-progress-bar { background: var(--primary); border-radius: 999px; }

    /* Review step */
    .oc-wizard-review-group { min-width: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
    .oc-wizard-review-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; padding: .375rem .375rem .375rem 1rem; border-bottom: 1px solid var(--line); background: var(--surface-muted); }
    .oc-wizard-review-title { min-width: 0; margin: 0; font-size: .875rem; font-weight: 700; color: var(--ink-900); }
    .oc-wizard-review-list { display: grid; grid-template-columns: minmax(0, 1fr); margin: 0; padding: .25rem 1rem; }
    .oc-wizard-review-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: .125rem; padding: .625rem 0; border-top: 1px solid var(--line-2); }
    .oc-wizard-review-row:first-child, .oc-wizard-review-sub + .oc-wizard-review-row { border-top: 0; }
    .oc-wizard-review-row dt { font-size: .75rem; font-weight: 600; color: var(--ink-500); }
    .oc-wizard-review-row dd { margin: 0; min-width: 0; font-size: .875rem; color: var(--ink-900); overflow-wrap: break-word; }
    .oc-wizard-review-row dd.is-multiline { white-space: pre-line; }
    .oc-wizard-review-row dd.is-empty { color: var(--ink-400); font-style: italic; }
    .oc-wizard-review-sub { padding: .875rem 0 .125rem; font-size: .6875rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-500); }
    .oc-wizard-review-none { margin: 0; padding: .75rem 1rem; font-size: .875rem; color: var(--ink-500); }
    .oc-wizard-review .oc-wizard-panel-body { gap: .875rem; }

    /* Final success panel (Wizard.Success) */
    .oc-wizard-success { display: flex; align-items: flex-start; gap: 1rem; padding: 1.5rem; border: 1px solid var(--line); border-radius: var(--radius-xl); background: var(--surface); }
    .oc-wizard-success:focus { outline: none; }
    .oc-wizard-success:focus-visible { box-shadow: var(--ring); }
    .oc-wizard-success-icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 3rem; height: 3rem; border-radius: 999px; background: var(--success-subtle); color: var(--success-subtle-foreground); }

    @container oc-wizard (min-width: 36rem) {
        .oc-wizard-review-row { grid-template-columns: minmax(7rem, 2fr) minmax(0, 3fr); gap: 1rem; align-items: baseline; }
    }
    /* Wide wizard: vertical rail on the left (sticky), the panel on its own surface on the right. */
    @container oc-wizard (min-width: 48rem) {
        .oc-wizard-layout { grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr); gap: 2rem; }
        .oc-wizard-nav { position: sticky; top: calc(var(--oc-appbar-h) + var(--oc-safe-top) + 1rem); }
        .oc-wizard-steps { flex-direction: column; align-items: stretch; gap: .25rem; padding: 0; overflow: visible; }
        .oc-wizard-step { display: block; }
        .oc-wizard-step + .oc-wizard-step::before { content: none; }
        .oc-wizard-step:not(:last-child)::after { content: ""; position: absolute; left: calc(1.5rem - 1px); top: 2.75rem; bottom: -.25rem; width: 2px; border-radius: 999px; background: var(--line-strong); }
        .oc-wizard-step[data-state="complete"]:not(:last-child)::after { background: var(--primary); }
        .oc-wizard-step-link { display: flex; align-items: flex-start; gap: .75rem; width: 100%; max-width: none; padding: .5rem; }
        .oc-wizard-step[aria-current="step"] .oc-wizard-step-link { background: var(--primary-tint); }
        .oc-wizard-step-text { padding-top: .3125rem; }
        .oc-wizard-step-title { white-space: normal; overflow: visible; }
        .oc-wizard-step-desc { display: block; margin-top: .125rem; font-size: .75rem; font-weight: 400; color: var(--ink-500); }
        .oc-wizard-main { padding: 1.5rem; border: 1px solid var(--line); border-radius: var(--radius-xl); background: var(--surface); box-shadow: var(--shadow-sm); }
        .oc-wizard-panel-title { font-size: 1.25rem; }
    }

    /* Overlay wizards (drawer / modal / sheet) on phones: the footer sticks to the bottom of the sheet. */
    @media (max-width: 639px) {
        :is(.oc-drawer, .oc-modal, .oc-sheet) .oc-wizard-footer { position: sticky; bottom: 0; z-index: 1; padding-bottom: .75rem; background: var(--surface); }
    }

    /* Phone / tablet FOCUS mode (page-level wizards only). */
    @media (max-width: 1023px) {
        .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) { --oc-wizard-top: calc(var(--oc-appbar-h) + var(--oc-safe-top)); }
        .oc-layout-main > .oc-wizard[data-oc-wizard-focus="true"] { --oc-wizard-bleed: 1rem; }
        @media (min-width: 640px) { .oc-layout-main > .oc-wizard[data-oc-wizard-focus="true"] { --oc-wizard-bleed: 1.5rem; } }
        /* The wizard's action bar replaces the tab bar as the bottom chrome (toasts/back-to-top clear it). */
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) {
            --oc-bottom-chrome: calc(4.3125rem + var(--oc-safe-bottom));
            scroll-padding-top: calc(var(--oc-appbar-h) + var(--oc-safe-top) + 5.5rem);
            scroll-padding-bottom: calc(5rem + var(--oc-safe-bottom));
        }
        html.oc-kb-open:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) { --oc-bottom-chrome: 0px; }
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) :is(.oc-tabbar, .oc-fab) { display: none; }
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) .oc-has-bottom-tabbar { padding-bottom: 0; }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-mhead {
            display: block; position: sticky; top: var(--oc-wizard-top); z-index: var(--z-sticky);
            margin: 0 calc(-1 * var(--oc-wizard-bleed)); padding: .375rem var(--oc-wizard-bleed) .625rem;
            border-bottom: 1px solid var(--line); background: var(--bg);
        }
        /* Spacer so the fixed action bar never covers the last field. */
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-form { padding-bottom: calc(4.75rem + var(--oc-safe-bottom)); }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) :is(.oc-wizard-nav, .oc-wizard-panel-kicker, .oc-wizard-footer-start, .oc-wizard-draft) { display: none; }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-panel { scroll-margin-top: calc(var(--oc-wizard-top) + 5.5rem); }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-footer {
            position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky); flex-wrap: nowrap;
            padding: .75rem calc(1rem + var(--oc-safe-right)) calc(.75rem + var(--oc-safe-bottom)) calc(1rem + var(--oc-safe-left));
            background: var(--surface); box-shadow: 0 -4px 12px -8px color-mix(in srgb, var(--ink-900) 25%, transparent);
        }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-footer-end { flex: 1 1 auto; flex-wrap: nowrap; margin-left: 0; }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) :is(.oc-wizard-next, .oc-wizard-submit) { flex: 1 1 auto; }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-back { flex: 0 0 auto; width: 2.75rem; min-width: 2.75rem; padding-left: 0; padding-right: 0; }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-back > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; }
        html.oc-kb-open[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-footer { display: none; }
    }
    @media (prefers-reduced-motion: reduce) {
        .oc-wizard-marker, .oc-wizard-progress::-webkit-progress-value { transition: none; }
    }

    /* ============================================================
       Review checklist (_ReviewChecklist.cshtml / octacer-review.js)
       Layout follows the component's OWN width: @container oc-review — split ≥ 48rem, list ⇄ item below.
       The modal lives outside .oc-review-frame (container-type would contain the fixed overlay).
       ============================================================ */
    .oc-review { display: block; min-width: 0; }
    .oc-review [hidden] { display: none !important; }
    .oc-review-frame { container: oc-review / inline-size; min-width: 0; --oc-review-top: 0px; }
    html:has(.oc-layout-header) .oc-review-frame { --oc-review-top: calc(var(--oc-appbar-h) + var(--oc-safe-top)); }
    @media (min-width: 1024px) { html:has(.oc-layout-header) .oc-review-frame { --oc-review-top: 4rem; } }

    /* Status tones (decision variants + pending) — every surface reads these four tokens. */
    .oc-review [data-tone] { --oc-rv-solid: var(--primary); --oc-rv-on: var(--primary-foreground); --oc-rv-subtle: var(--primary-tint); --oc-rv-ink: var(--primary-ink); }
    .oc-review [data-tone="success"] { --oc-rv-solid: var(--success); --oc-rv-on: var(--success-foreground); --oc-rv-subtle: var(--success-subtle); --oc-rv-ink: var(--success-subtle-foreground); }
    .oc-review [data-tone="danger"] { --oc-rv-solid: var(--danger); --oc-rv-on: var(--danger-foreground); --oc-rv-subtle: var(--danger-subtle); --oc-rv-ink: var(--danger-subtle-foreground); }
    .oc-review [data-tone="warning"] { --oc-rv-solid: var(--warning); --oc-rv-on: var(--warning-foreground); --oc-rv-subtle: var(--warning-subtle); --oc-rv-ink: var(--warning-subtle-foreground); }
    .oc-review [data-tone="info"] { --oc-rv-solid: var(--info); --oc-rv-on: var(--info-foreground); --oc-rv-subtle: var(--info-subtle); --oc-rv-ink: var(--info-subtle-foreground); }
    .oc-review [data-tone="pending"] { --oc-rv-solid: var(--ink-400); --oc-rv-on: var(--surface); --oc-rv-subtle: var(--line-2); --oc-rv-ink: var(--ink-600); }

    /* Head: title, keyboard disclosure, submit */
    .oc-review-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: .75rem 1rem; padding: 1rem 1.25rem .75rem; }
    .oc-review-titles { min-width: 0; flex: 1 1 14rem; }
    .oc-review-title { font-size: 1rem; font-weight: 600; line-height: 1.3; color: var(--ink-900); }
    .oc-review-subtitle { margin-top: .125rem; font-size: .8125rem; color: var(--ink-500); }
    .oc-review-head-actions { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: flex-end; gap: .5rem; }
    .oc-review-submit-wrap { display: flex; flex-direction: column; align-items: flex-end; gap: .25rem; }
    .oc-review-submit-hint { font-size: .75rem; color: var(--ink-500); text-align: end; }
    .oc-review-submit-hint:empty { display: none; }
    /* Blocked submit stays clickable: the click explains why (toast) and jumps to the Pending filter. */
    .oc-review .btn[data-oc-review-submit][aria-disabled="true"] { opacity: .6; cursor: not-allowed; pointer-events: auto; }
    .oc-review-keys { position: relative; }
    .oc-review-keys > summary { list-style: none; cursor: pointer; }
    .oc-review-keys > summary::-webkit-details-marker { display: none; }
    .oc-review-keys-panel { position: absolute; right: 0; top: calc(100% + .375rem); z-index: var(--z-popover); width: max-content; max-width: 18rem; padding: .75rem .875rem; background: var(--popover); border: 1px solid var(--line); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); }
    .oc-review-keys-list { display: grid; gap: .375rem; margin: 0; }
    .oc-review-keys-list > div { display: flex; align-items: center; justify-content: space-between; gap: 1rem; font-size: .8125rem; color: var(--ink-700); }
    .oc-review-keys-list dt { display: inline-flex; gap: .25rem; }
    .oc-review-keys-list dd { margin: 0; }
    .oc-review-keys-note { margin-top: .5rem; font-size: .75rem; color: var(--ink-500); }

    /* Banners, progress, all-reviewed callout, filters */
    .oc-review-banner { margin: 0 1.25rem .75rem; }
    .oc-review-progress { display: grid; gap: .375rem; padding: 0 1.25rem .75rem; }
    .oc-review-progress-text { font-size: .8125rem; font-weight: 600; color: var(--ink-700); font-variant-numeric: tabular-nums; }
    .oc-review-bar { display: flex; gap: 2px; height: .5rem; overflow: hidden; border-radius: 999px; background: var(--line-2); }
    .oc-review-bar-seg { flex: 0 1 0%; min-width: 0; background: var(--oc-rv-solid); transition: flex-grow var(--duration-base) var(--ease-out); }
    .oc-review-bar-seg[data-tone="pending"] { background: var(--line); }
    .oc-review-done { margin: 0 1.25rem .75rem; flex-wrap: wrap; align-items: center; }
    .oc-review-done-text { display: flex; flex-direction: column; gap: .125rem; flex: 1 1 12rem; min-width: 0; }
    .oc-review-filters { min-width: 0; padding: 0 1.25rem .75rem; }
    .oc-review-filters .oc-view-toggle-button { gap: .375rem; }
    .oc-review-dot { width: .5rem; height: .5rem; flex-shrink: 0; border-radius: 999px; background: var(--oc-rv-solid); }
    .oc-review-count { min-width: 1.25rem; padding: .05rem .375rem; border-radius: 999px; font-size: .6875rem; font-weight: 600; line-height: 1.3; text-align: center; font-variant-numeric: tabular-nums; color: var(--ink-600); background: var(--line-2); }
    .oc-review-filters .is-active .oc-review-count { color: var(--primary-ink); background: var(--primary-tint); }

    /* Item list */
    .oc-review-body { min-width: 0; border-top: 1px solid var(--line); }
    .oc-review-listpane { min-width: 0; }
    .oc-review-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2px; margin: 0; padding: .375rem; list-style: none; }
    .oc-review-row { position: relative; border-radius: var(--radius-md); }
    .oc-review-row-btn { display: flex; align-items: center; gap: .75rem; width: 100%; min-height: 3.25rem; padding: .625rem .75rem; border: 0; border-radius: var(--radius-md); text-align: start; color: var(--ink-900); background: var(--surface); cursor: pointer; }
    @media (hover: hover) { .oc-review-row-btn:hover { background: var(--surface-muted); } }
    .oc-review-row-btn:focus-visible { outline: none; box-shadow: var(--ring-inset); }
    .oc-review-row-btn[aria-current="true"] { background: linear-gradient(var(--primary-tint), var(--primary-tint)), var(--surface); box-shadow: inset 3px 0 0 var(--primary); }
    .oc-review-row-btn[aria-current="true"]:focus-visible { box-shadow: var(--ring-inset); }
    .oc-review-row-icon { display: inline-flex; align-items: center; justify-content: center; width: 1.75rem; height: 1.75rem; flex-shrink: 0; border-radius: 999px; color: var(--oc-rv-ink); background: var(--oc-rv-subtle); }
    .oc-review-row-main { display: flex; flex: 1 1 auto; flex-direction: column; min-width: 0; }
    /* Up to 2 lines (long document names are the norm in reviews), then an ellipsis; full text in title=. */
    .oc-review-row-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; font-size: .875rem; font-weight: 600; line-height: 1.3; overflow-wrap: break-word; }
    .oc-review-row-sub { overflow: hidden; font-size: .75rem; color: var(--ink-500); text-overflow: ellipsis; white-space: nowrap; }
    .oc-review-row-status, .oc-review-row-chevron { flex-shrink: 0; }
    .oc-review-row-chevron { color: var(--ink-400); }
    .oc-review-chip { white-space: nowrap; color: var(--oc-rv-ink); background: var(--oc-rv-subtle); }
    .oc-review-row.is-saving .oc-review-row-icon { animation: oc-review-pulse 1s ease-in-out infinite; }
    @keyframes oc-review-pulse { 50% { opacity: .35; } }
    .oc-review-swipe-action[data-tone] { color: var(--oc-rv-on); background: var(--oc-rv-solid); }
    .oc-review-filter-empty { padding: .5rem; }
    .oc-review-skel-row { display: flex; align-items: center; gap: .75rem; padding: .75rem; }

    /* Item detail */
    .oc-review-detailpane { display: none; flex-direction: column; min-width: 0; }
    .oc-review-skel-detail { gap: .75rem; padding: 1.25rem 1.5rem; }
    .oc-review-itembar { display: flex; align-items: center; gap: .25rem; padding: .375rem .5rem; border-bottom: 1px solid var(--line); background: var(--surface); }
    .oc-review-pos { flex: 1 1 auto; min-width: 0; padding-inline: .5rem; font-size: .8125rem; font-weight: 600; white-space: nowrap; color: var(--ink-700); font-variant-numeric: tabular-nums; }
    .oc-review-steps { display: flex; gap: .25rem; }
    .oc-review-back, .oc-review-step-h { display: none; }
    .oc-review-detail-scroll { min-width: 0; padding: 1rem 1.25rem; touch-action: pan-y; }
    .oc-review-item { transform: translateX(var(--oc-review-swipe-x, 0px)); transition: transform var(--duration-base) var(--ease-out); }
    .oc-review-detail-scroll.is-swiping .oc-review-item { transition: none; }
    .oc-review-item-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: .5rem .75rem; margin-bottom: 1rem; }
    .oc-review-item-head > :first-child { flex: 1 1 14rem; }
    .oc-review-item-title { font-size: 1.0625rem; font-weight: 600; color: var(--ink-900); outline: none; }
    .oc-review-item-title:focus-visible { border-radius: var(--radius-sm); box-shadow: var(--ring); }
    .oc-review-item-sub { margin-top: .125rem; font-size: .8125rem; color: var(--ink-500); }
    .oc-review-evidence { min-width: 0; }
    .oc-review-evidence img { max-width: 100%; height: auto; }
    .oc-review-item-comment { margin-top: 1rem; padding: .75rem .875rem; border: 1px solid var(--line); border-radius: var(--radius-md); background: var(--surface-muted); }
    .oc-review-item-comment-label { display: flex; align-items: center; gap: .375rem; font-size: .75rem; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--ink-500); }
    .oc-review-item-comment-text { margin-top: .25rem; font-size: .875rem; white-space: pre-line; overflow-wrap: break-word; color: var(--ink-900); }

    /* Decision bar */
    .oc-review-decide { display: grid; gap: .5rem; padding: .75rem 1rem; border-top: 1px solid var(--line); background: var(--surface); }
    .oc-review-decide-row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
    .oc-review-decision { flex: 1 1 auto; min-height: 2.75rem; }
    .oc-review-decision[data-tone] { color: var(--oc-rv-ink); background: var(--surface); border-color: color-mix(in srgb, var(--oc-rv-solid) 45%, var(--line)); }
    @media (hover: hover) { .oc-review-decision[data-tone]:hover { background: var(--oc-rv-subtle); } }
    .oc-review-decision[data-tone][aria-pressed="true"] { color: var(--oc-rv-on); background: var(--oc-rv-solid); border-color: var(--oc-rv-solid); }
    .oc-review-comment { display: grid; gap: .375rem; }
    .oc-review-comment-input { min-height: 4.5rem; resize: vertical; }
    .oc-review-confirm-row { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .5rem; }
    .oc-review-confirm-row .btn { flex: 1 1 8rem; }
    .oc-review-status { font-size: .75rem; color: var(--ink-500); }
    .oc-review-status:empty { display: none; }
    .oc-review-status[data-state="error"] { font-weight: 600; color: var(--danger-subtle-foreground); }
    .oc-review-status[data-state="saved"] { color: var(--success-subtle-foreground); }
    @media (prefers-reduced-motion: reduce) {
        .oc-review-item, .oc-review-bar-seg { transition: none; }
        .oc-review-row.is-saving .oc-review-row-icon { animation: none; opacity: .5; }
    }

    /* Wide container: master–detail split, both panes scroll inside a viewport-sized body. */
    @container oc-review (min-width: 48rem) {
        .oc-review-body { display: grid; grid-template-columns: minmax(15rem, 20rem) minmax(0, 1fr); height: clamp(24rem, calc(100dvh - 9rem), 48rem); }
        .oc-review-listpane { min-height: 0; overflow-y: auto; overscroll-behavior: contain; border-right: 1px solid var(--line); }
        .oc-review-detailpane { display: flex; min-height: 0; }
        .oc-review-detail-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 1.25rem 1.5rem; }
        .oc-review-row-chevron { display: none; }
        /* Sticky to the viewport bottom while the pane runs below the fold, so decisions are always reachable. */
        .oc-review-decide { position: sticky; bottom: 0; z-index: var(--z-sticky); padding: .75rem 1.5rem; border-bottom-right-radius: var(--radius-lg); }
        .oc-review-comment-toggle { margin-right: auto; }
        .oc-review-decision { flex: 0 1 auto; }
    }

    /* Narrow container (phone / 360px card): the list is the main view; the item view swaps in. */
    @container oc-review (max-width: 47.999rem) {
        .oc-review-head { padding: .875rem 1rem .625rem; }
        .oc-review-progress, .oc-review-filters { padding-inline: 1rem; }
        .oc-review-banner, .oc-review-done { margin-inline: 1rem; }
        .oc-review-keys { display: none; }
        .oc-review-head-actions { width: 100%; justify-content: flex-start; }
        .oc-review-submit-wrap { flex-direction: row; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; width: 100%; }
        .oc-review-submit-hint { text-align: start; }
        .oc-review-row-btn { min-height: 3.5rem; }
        .oc-review-back { display: inline-flex; }
        .oc-review-pos-word, .oc-review-step-v { display: none; }
        .oc-review-step-h { display: inline-block; }
        [data-oc-review-view="item"] .oc-review-head,
        [data-oc-review-view="item"] .oc-review-banner,
        [data-oc-review-view="item"] .oc-review-progress,
        [data-oc-review-view="item"] .oc-review-done,
        [data-oc-review-view="item"] .oc-review-filters,
        [data-oc-review-view="item"] .oc-review-listpane { display: none; }
        [data-oc-review-view="item"] .oc-review-body { border-top: 0; }
        [data-oc-review-view="item"] .oc-review-detailpane { display: flex; }
        /* Phones/tablets: the item view fills the screen under the app bar, so the decision bar sits at the
           bottom edge (thumb zone) even for short evidence, and toasts stack above it. */
        @media (max-width: 1023px) {
            [data-oc-review-view="item"] .oc-review-detailpane { min-height: calc(100dvh - var(--oc-review-top)); }
            [data-oc-review-view="item"] .oc-review-detail-scroll { flex: 1 0 auto; }
        }
        .oc-review-itembar { position: sticky; top: var(--oc-review-top); z-index: var(--z-sticky); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
        .oc-review-detail-scroll { padding: 1rem; }
        .oc-review-decide { position: sticky; bottom: 0; z-index: var(--z-sticky); padding: .75rem 1rem calc(.75rem + var(--oc-safe-bottom)); border-radius: 0 0 var(--radius-lg) var(--radius-lg); box-shadow: 0 -10px 20px -16px color-mix(in srgb, var(--ink-900) 45%, transparent); }
        .oc-review-decision { flex: 1 1 0; min-width: max-content; min-height: 3rem; }
        .oc-review-comment-toggle { min-width: 3rem; min-height: 3rem; }
        .oc-review-confirm-row .btn { min-height: 3rem; }
    }
    /* Very narrow: icon over label so three decisions fit one thumb row at 320px. */
    @container oc-review (max-width: 25.999rem) {
        .oc-review-decision { flex-direction: column; gap: .125rem; min-width: 0; padding-inline: .25rem; font-size: .75rem; }
        .oc-review-row-icon { display: none; }
    }

    /* Item view open on a phone: hide the tab bar / FAB / back-to-top; toasts clear the decision bar instead. */
    html.oc-review-focus .oc-tabbar,
    html.oc-review-focus .oc-fab,
    html.oc-review-focus .oc-back-to-top { visibility: hidden; pointer-events: none; }
    html.oc-review-focus .oc-tabbar { transform: translateY(calc(100% + 1px)); }
    html.oc-review-focus,
    html.oc-review-focus:has(.oc-tabbar) { --oc-bottom-chrome: var(--oc-review-bar-h, 0px); }

    /* Density: the theme is compact (32px controls, Notion/Linear class) on mouse screens; touch screens get
       44px targets back. Kept LAST in the layer so it wins over every component min-height above. */
    @media (pointer: coarse) {
        .btn, .oc-tab, .oc-popmenu-item, .oc-user-trigger, .oc-page-more-trigger, .oc-sidebar-nav a, .oc-sidebar-nav button,
        .field-input, .field-select, .field-group, .oc-searchable-trigger { min-height: 2.75rem; }
        .btn-sm, .oc-filter-chip { min-height: 2.25rem; }
    }
}

/* Cross-document view transitions (MPA navigations + hx-boost with transition:true). Motion only when allowed. */
@media (prefers-reduced-motion: no-preference) {
    @view-transition { navigation: auto; }
    ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 180ms; }
}
