/* ============================================================
   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;

/* First paint (M9/L1): a local system face with Inter's metrics, used until the Inter webfont arrives
   (font-display: swap) — the swap then changes glyph shapes only, not line boxes (no layout shift). */
@font-face {
    font-family: "Inter Fallback";
    src: local("Segoe UI"), local("SegoeUI"), local("Arial"), local("ArialMT"), local("Helvetica Neue"), local("Helvetica");
    size-adjust: 107%;
    ascent-override: 90%;
    descent-override: 22.4%;
    line-gap-override: 0%;
}

: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: #5b6b82;   /* muted text: ≥4.9:1 on --line-2/#f1f5f9 headers + chips, 5.4:1 on white (WCAG 1.4.3) */
    --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;
    /* Form fields (shadcn/Linear-class): a light hairline + a 1px drop shadow at rest; the brand border + a soft
       3px halo on focus; danger border + danger halo when invalid. See THEME.md "Form fields" for the contrast
       rationale (the resting text-field border is deliberately light; small controls keep a 3:1 boundary). */
    --input:   #d4dae3;              /* text-like field border at rest (input/select/textarea/field-group) */
    --input-hover: #b4bfcc;          /* field border on hover — one step darker */
    --input-strong: #8491a5;         /* SMALL control boundary (checkbox, radio, toggle-off): 3.2:1 on white (WCAG 1.4.11) */
    --input-bg: var(--surface);      /* field fill */
    --input-bg-muted: #f6f8fa;       /* read-only / disabled field fill */
    --input-placeholder: var(--ink-400);
    --input-shadow: 0 1px 2px rgb(15 23 42 / .05);
    --input-ring: 0 0 0 3px color-mix(in srgb, var(--brand-500) 22%, transparent);
    --input-ring-danger: 0 0 0 3px color-mix(in srgb, var(--danger) 16%, transparent);
    --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;
    --danger-ink: #dc2626;  /* destructive TEXT (4.8:1 on white); lightened in .dark */
    --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. */
    /* "Inter Fallback" = a metric-matched local face (see @font-face below) so the swap to Inter doesn't reflow. */
    --font-sans: "Inter", "Inter Fallback", 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);
    /* Global :focus-visible outline colour. Light: brand-600 (6.3:1 on white, 6.0:1 on #f8fafc, ≥5:1 on the
       brand-50 active tint). Dark overrides below with a lightened brand (≥6:1 on the dark surfaces). */
    --focus-outline: var(--brand-600);

    /* 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);

    /* Loading — skeleton bone fill + its shimmer highlight (ONE shimmer, see .oc-skeleton). */
    --oc-skel-base: #eceef2;
    --oc-skel-hi:   #f8f9fb;
}
/* Landscape phones (short viewport): a compact 44px tab bar — icon and label sit in a row (see .oc-tabbar-link
   in the max-height: 30rem block). Unlayered like the token above, so every --oc-bottom-chrome consumer follows. */
@media (max-height: 30rem) { :root { --oc-tabbar-h: 2.75rem; } }

/* Dark mode: shared class applied to <html> by octacer-theme-init.js. */
.dark {
    color-scheme: dark;
    --focus-outline: color-mix(in srgb, var(--brand-500) 72%, white);
    /* 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: #334155;               /* field border at rest (on the lifted field fill below) */
    --input-hover: #475569;
    --input-strong: #6b7a90;        /* small-control boundary ≥3:1 — 4.1:1 on --surface, 3.35:1 on --surface-muted */
    --input-bg: color-mix(in srgb, var(--surface-muted) 50%, var(--surface));   /* a slightly lifted field fill */
    --input-bg-muted: color-mix(in srgb, var(--surface-muted) 85%, var(--surface));
    --input-placeholder: #6b7a90;
    --input-shadow: 0 1px 2px rgb(0 0 0 / .25);
    --input-ring: 0 0 0 3px color-mix(in srgb, var(--brand-500) 32%, transparent);
    --input-ring-danger: 0 0 0 3px color-mix(in srgb, var(--danger) 28%, transparent);
    --danger-ink: #f87171;          /* destructive TEXT on dark canvases (6.5:1); the solid --danger fill is unchanged */
    --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%);
    /* Skeleton: the highlight is LIGHTER than the bone on dark canvases (a darker band reads as a hole). */
    --oc-skel-base: #1e283c;
    --oc-skel-hi:   #2c384d;
}

/* High-contrast preference: stronger hairlines (unlayered, like the tokens it overrides). */
@media (prefers-contrast: more) {
    /* …and the 3:1 field boundary + AA placeholder back (the default resting field border is a light hairline). */
    :root { --line: #94a3b8; --line-strong: #64748b; --input: #8491a5; --input-hover: #64748b; --input-placeholder: var(--ink-500); }
    .dark { --line: #64748b; --line-strong: #94a3b8; --input: #6b7a90; --input-hover: #94a3b8; --input-placeholder: var(--ink-500); }
}

@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;
    }
    /* Mono is ONLY for identifiers/codes (.oc-mono / .oc-code / code). Times, money and counts are sans
       with tabular figures (.oc-number / tabular-nums) so they align without eating horizontal space. */
    .oc-mono, .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-family: var(--font-sans); font-variant-numeric: tabular-nums; 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; } }
}

/* Mode-aware destructive TEXT (WCAG 1.4.3): Tailwind's text-destructive resolves to the solid --danger fill
   (#dc2626 = 3.7:1 on the dark surface). In dark mode text uses --danger-ink (#f87171) instead; bg-destructive /
   .btn-danger fills are untouched. (0,2,0) beats the generated (0,1,0) utility within the utilities layer. */
@layer utilities {
    .dark .text-destructive, .dark .text-danger { color: var(--danger-ink); }
}

@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)); }
    /* _ProfileHeader with no CoverClass: a soft brand mesh (reads as intentional, not a missing image). */
    .oc-profile-cover-default {
        background-color: var(--primary-tint);
        background-image:
            radial-gradient(90% 140% at 0% 0%, color-mix(in srgb, var(--brand-500) 28%, transparent), transparent 60%),
            radial-gradient(70% 120% at 100% 100%, color-mix(in srgb, var(--brand-700) 22%, transparent), transparent 65%),
            radial-gradient(50% 90% at 70% 10%, color-mix(in srgb, var(--chart-5) 16%, transparent), transparent 70%);
    }
    .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 var(--focus-outline);
        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; min-width: 0; overflow-wrap: anywhere; }
    .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; } }

    /* Busy contract (C3) — ONE CSS path keyed on aria-busy="true" (.is-loading is a legacy alias). It is set by
       octacer-loading.js on EVERY request path (hx-* buttons, forms' submitter, confirms, wizard, FAB, row/bulk
       actions, hx-disabled-elt) 150 ms after the click and held ≥ 400 ms; server-rendered Loading=true sets it
       directly. data-oc-busy is the IMMEDIATE click lock (aria-disabled + no pointer) that precedes it, so a
       fast request never flashes a spinner and a second click never sends a second request. */
    :is(.btn, .oc-icon-btn, .oc-fab)[data-oc-busy] { pointer-events: none; cursor: progress; }
    :is(.btn, .oc-icon-btn, .oc-fab)[data-oc-busy]:is(:disabled, [aria-disabled="true"]) { opacity: 1; }
    :is(.btn, .oc-icon-btn):is([aria-busy="true"], .is-loading) { position: relative; }
    :is(.btn, .oc-icon-btn, .oc-fab):is([aria-busy="true"], .is-loading) { pointer-events: none; color: transparent !important; }
    /* opacity (not visibility:hidden) so the label stays in the accessibility tree — a busy button keeps its name */
    :is(.btn, .oc-icon-btn, .oc-fab):is([aria-busy="true"], .is-loading) > * { opacity: 0; }
    :is(.btn, .oc-icon-btn, .oc-fab):is([aria-busy="true"], .is-loading)::after {
        content: ""; position: absolute; inset: 0; margin: auto; width: 1.05em; height: 1.05em;
        border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
        color: var(--oc-spin-color, var(--ink-500)); animation: oc-spin .6s linear infinite; visibility: visible;
    }
    .oc-fab { --oc-spin-color: var(--primary-foreground); }
    /* Ink of the busy label ("Saving…") — the variant's own text colour (the busy rule hides the label with transparent). */
    .btn { --oc-busy-ink: var(--primary-foreground); }
    .btn-outline, .btn-ghost { --oc-busy-ink: var(--ink-700); }
    .btn-white { --oc-busy-ink: var(--brand-700); }
    .btn-danger { --oc-busy-ink: var(--danger-foreground); }
    .btn-success { --oc-busy-ink: var(--success-foreground); }

    /* ---------- Form fields ---------- */
    .field-label { display: block; font-size: .8125rem; font-weight: 500; line-height: 1.25rem; color: var(--ink-700); margin-bottom: .3125rem; }
    /* Helper + error text: ONE size (12px) for every field; plain wrapping so a message uses the full width. */
    .field-hint  { font-size: .75rem; color: var(--ink-500); margin-top: .35rem; text-wrap: wrap; }
    .field-error { display: block; width: 100%; font-size: .75rem; color: var(--danger-ink); margin-top: .35rem; text-wrap: wrap; }
    .field-error > span { flex: 1 1 auto; min-width: 0; }

    /* ONE look for every text-like control (.field-input / .field-select / .field-textarea / .field-group — and so the
       searchable, combobox, date, colour, tags and user-picker triggers built on them): a light hairline + 1px drop
       shadow at rest, one step darker on hover, the brand border + a soft 3px halo on focus, danger border + danger
       halo when invalid, a muted fill when read-only/disabled. Tokens: --input* (see :root / .dark). */
    .field-input, .field-select, .field-textarea {
        width: 100%; font-size: .875rem; color: var(--ink-900);
        background-color: var(--input-bg); border: 1px solid var(--input); box-shadow: var(--input-shadow);
        border-radius: var(--radius-sm); padding: .3125rem .625rem; line-height: 1.25rem;
        transition: border-color var(--duration-fast) ease, box-shadow var(--duration-fast) ease, background-color var(--duration-fast) ease;
        -webkit-appearance: none; appearance: none;
    }
    /* Long values / placeholders end in an ellipsis instead of a hard mid-word cut (not while typing — the caret scrolls). */
    .field-input, .field-group > input { text-overflow: ellipsis; }
    /* 32px on mouse: 5px + 20px line + 5px + 2×1px border (field-input / field-select / field-group alike).
       Textareas share the input's padding and line box so the first line sits exactly where an input's would. */
    .field-textarea { line-height: 1.25rem; padding-block: .375rem; resize: vertical; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
    /* Autosize (_FormField AutoSize, default): grows with its content between --oc-rows-min (3) and --oc-rows-max (12)
       lines, then scrolls. field-sizing where supported; octacer-forms.js sizes it elsewhere ([data-oc-autosize]). */
    .field-textarea[data-oc-autosize] {
        field-sizing: content;
        min-height: calc(var(--oc-rows-min, 3) * 1.25rem + .75rem + 2px);
        max-height: calc(var(--oc-rows-max, 12) * 1.25rem + .75rem + 2px);
    }
    .field-textarea::-webkit-scrollbar { width: .5rem; height: .5rem; }
    .field-textarea::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
    .field-textarea::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
    .field-textarea::-webkit-scrollbar-track, .field-textarea::-webkit-scrollbar-corner { background: transparent; }
    .field-input::placeholder, .field-textarea::placeholder, .field-group > input::placeholder { color: var(--input-placeholder); opacity: 1; }
    @media (hover: hover) {
        .field-input:hover:not(:focus, :disabled, [readonly], [aria-invalid="true"]), .field-select:hover:not(:focus, :disabled, [aria-invalid="true"]),
        .field-textarea:hover:not(:focus, :disabled, [readonly], [aria-invalid="true"]),
        .field-group:hover:not(:focus-within, .is-error, .is-readonly, :has(> input[readonly], > input:disabled, [aria-invalid="true"])) { border-color: var(--input-hover); }
    }
    /* Focus: the brand border (4.5:1 on white — the ≥3:1 indicator) + a soft brand halo. Fields only; buttons keep --ring. */
    .field-input:focus, .field-select:focus, .field-textarea:focus {
        outline: none; border-color: var(--brand-500); box-shadow: var(--input-shadow), var(--input-ring);
    }
    .field-input:disabled, .field-select:disabled, .field-textarea:disabled { background-color: var(--input-bg-muted); color: var(--ink-400); box-shadow: none; cursor: not-allowed; }
    .field-input[readonly], .field-textarea[readonly] { background-color: var(--input-bg-muted); box-shadow: none; }
    .field-input[aria-invalid="true"], .field-select[aria-invalid="true"], .field-textarea[aria-invalid="true"] { border-color: var(--danger); box-shadow: var(--input-shadow), var(--input-ring-danger); }
    .field-input[aria-invalid="true"]:focus, .field-select[aria-invalid="true"]:focus, .field-textarea[aria-invalid="true"]:focus { border-color: var(--danger); box-shadow: var(--input-shadow), 0 0 0 3px color-mix(in srgb, var(--danger) 26%, transparent); }
    .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='m7 10 5 5 5-5'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right .5rem center; background-size: 1rem 1rem; padding-right: 2rem; text-overflow: ellipsis; }
    .dark .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='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E"); }
    .field-select[multiple], .field-select[size]:not([size="1"]) { background-image: none; padding-right: .625rem; }
    .field-select option { background-color: var(--popover); color: var(--ink-900); }

    /* Native date/time pickers (apps that still use <input type=date|time|…>): a muted 14px picker icon, no inner
       padding, and a min-width per type so "09:00 AM" / "12/31/2026" never truncate. Prefer _DatePicker / _TimePicker. */
    :is(.field-input, .field-group > input):is([type="date"], [type="time"], [type="datetime-local"], [type="month"], [type="week"]) { font-variant-numeric: tabular-nums; }
    .field-input[type="time"] { min-width: 7.5rem; }
    .field-input:is([type="date"], [type="month"]) { min-width: 9.5rem; }
    .field-input[type="week"] { min-width: 10.5rem; }
    .field-input[type="datetime-local"] { min-width: 14rem; }
    :is(.field-input, .field-group > input)::-webkit-calendar-picker-indicator {
        width: .875rem; height: .875rem; margin: 0 0 0 .375rem; padding: .125rem; opacity: .5; cursor: pointer; border-radius: .25rem; transition: opacity var(--duration-fast) ease;
    }
    :is(.field-input, .field-group > input)::-webkit-calendar-picker-indicator:hover { opacity: .9; }
    :is(.field-input, .field-group > input)::-webkit-datetime-edit, :is(.field-input, .field-group > input)::-webkit-datetime-edit-fields-wrapper { padding: 0; }
    :is(.field-input, .field-group > input)::-webkit-date-and-time-value { text-align: start; min-height: 1.25rem; }
    :is(.field-input, .field-group > input):is([type="date"], [type="time"], [type="datetime-local"], [type="month"], [type="week"]):disabled::-webkit-calendar-picker-indicator { opacity: .25; cursor: not-allowed; }
    /* Number inputs: no spin buttons (use _NumberStepper for − / + steppers). */
    :is(.field-input, .field-group > input)[type="number"] { -moz-appearance: textfield; appearance: textfield; }
    :is(.field-input, .field-group > input)[type="number"]::-webkit-inner-spin-button,
    :is(.field-input, .field-group > input)[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
    :is(.field-input, .field-group > input)[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }

    /* Input group: leading icon / prefix / suffix + input (also the searchable / combobox / date / colour triggers). */
    .field-group { display: flex; align-items: center; gap: .5rem; width: 100%; background-color: var(--input-bg); border: 1px solid var(--input); box-shadow: var(--input-shadow); border-radius: var(--radius-sm); padding: 0 .625rem; transition: border-color var(--duration-fast) ease, box-shadow var(--duration-fast) ease, background-color var(--duration-fast) ease; }
    .field-group:focus-within { border-color: var(--brand-500); box-shadow: var(--input-shadow), var(--input-ring); }
    .field-group:is(.is-readonly, :has(> input[readonly])) { background-color: var(--input-bg-muted); box-shadow: none; }
    .field-group:has(> input:disabled) { background-color: var(--input-bg-muted); box-shadow: none; cursor: not-allowed; }
    .field-group:has(> input:disabled) > input { color: var(--ink-400); cursor: not-allowed; }
    /* 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: .3125rem 0; line-height: 1.25rem; }
    .field-group > input:focus { outline: none; }
    .field-group:is(.is-error, .input-validation-error, :has([aria-invalid="true"])) { border-color: var(--danger); box-shadow: var(--input-shadow), var(--input-ring-danger); }
    .field-group:is(.is-error, .input-validation-error, :has([aria-invalid="true"])):focus-within { box-shadow: var(--input-shadow), 0 0 0 3px color-mix(in srgb, var(--danger) 26%, transparent); }
    .field-group.is-success { border-color: var(--success); }
    /* Inline adornments (_FormField Prefix / Suffix / PrefixIcon / SuffixIcon): muted, never wrap, click focuses the input. */
    .field-affix { flex: 0 0 auto; display: inline-flex; align-items: center; gap: .25rem; max-width: 45%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: .875rem; line-height: 1.25rem; color: var(--ink-500); user-select: none; cursor: text; }
    .field-affix-icon { color: var(--ink-400); }
    .field-affix-icon svg, .field-affix-icon i { width: .875rem; height: .875rem; }
    .field-group > .field-affix + input { padding-inline-start: 0; }
    /* A prefix that reads AS PART OF the value ("/blogs/", "https://") sits flush against the input. */
    .field-group:has(> .field-affix-flush) { gap: 0; }
    .field-group:has(> .field-affix-flush) > .field-affix:not(.field-affix-flush) { margin-inline-start: .5rem; }
    .field-group[data-oc-field-focus] { cursor: text; }

    /* Label row: label (+ subtle required "*") on the left; an inline hint / label action on the right. */
    /* Same 20px line box as a bare .field-label, so a field with an inline hint / action lines up with its neighbours. */
    .field-label-row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; min-width: 0; min-height: 1.25rem; margin-bottom: .3125rem; }
    .field-label-row > .field-label { margin-bottom: 0; min-width: 0; line-height: 1.25rem; }
    .field-label-row > div { align-items: center; line-height: 1.25rem; }
    .field-label-row .field-hint { margin: 0; flex: 0 1 auto; min-width: 0; text-align: end; line-height: 1.25rem; }
    .field-label :is(.text-destructive, .field-required)[aria-hidden="true"] { color: color-mix(in srgb, var(--danger-ink) 70%, var(--ink-500)); font-weight: 400; }
    .field-label-action { flex: 0 0 auto; display: inline-flex; align-items: center; gap: .3125rem; margin: -.125rem -.25rem -.125rem 0; padding: .125rem .25rem; border: 0; border-radius: .25rem; background: none; font: inherit; font-size: .75rem; font-weight: 500; line-height: 1rem; color: var(--primary-ink); text-decoration: none; cursor: pointer; }
    @media (hover: hover) { .field-label-action:hover { text-decoration: underline; text-underline-offset: 2px; } }
    .field-label-action:focus-visible { outline: none; box-shadow: var(--ring); }
    .field-label-action:disabled { color: var(--ink-400); cursor: not-allowed; text-decoration: none; }
    @media (pointer: coarse) { .field-label-action { min-height: 2.75rem; margin-block: -.875rem; padding-inline: .5rem; } }

    /* Footer row under a field: hint / error on the left, the character counter on the right. */
    .field-foot { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; min-width: 0; margin-top: .35rem; }
    .field-foot > :is(.field-hint, .field-error) { margin-top: 0; flex: 1 1 auto; min-width: 0; }
    .field-counter { flex: 0 0 auto; margin: 0 0 0 auto; font-size: .75rem; line-height: 1rem; color: var(--ink-500); font-variant-numeric: tabular-nums; white-space: nowrap; }
    .field-counter.is-good { color: var(--success-subtle-foreground); }
    .field-counter.is-warn { color: var(--warning-subtle-foreground); }
    .field-counter.is-over { color: var(--danger-ink); font-weight: 500; }
    .field-counter-state { font-weight: 500; }

    /* ReadOnly="display": the value as static text with a lock, a copy affordance and the "why" hint. */
    .field-static { display: flex; align-items: center; gap: .5rem; min-width: 0; min-height: 2rem; padding: .3125rem .3125rem .3125rem .625rem; border: 1px dashed var(--input); border-radius: var(--radius-sm); background-color: var(--input-bg-muted); font-size: .875rem; line-height: 1.25rem; color: var(--ink-700); }
    .field-static-icon { flex: 0 0 auto; color: var(--ink-400); }
    .field-static-value { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-family: var(--font-mono); font-size: .8125rem; }
    .field-static-value.is-empty { font-family: inherit; color: var(--ink-500); }
    .field-static > .btn { flex: 0 0 auto; }
    @media (pointer: coarse) { .field-static { min-height: 2.75rem; } }

    /* Raw native controls inside an .oc-form (apps that haven't moved to the primitives yet): text-like inputs,
       selects and textareas get the field look; un-classed checkboxes / radios get the themed box. :where() keeps the
       specificity at zero so any utility / component class still wins. */
    :where(.oc-form) :where(input:is(:not([type]), [type="text"], [type="email"], [type="url"], [type="tel"], [type="password"], [type="search"], [type="number"], [type="date"], [type="time"], [type="datetime-local"], [type="month"], [type="week"]), select, textarea):where(:not([class])) {
        width: 100%; min-height: 2rem; font: inherit; font-size: .875rem; line-height: 1.25rem; color: var(--ink-900);
        background-color: var(--input-bg); border: 1px solid var(--input); box-shadow: var(--input-shadow);
        border-radius: var(--radius-sm); padding: .3125rem .625rem;
    }
    :where(.oc-form) :where(input, select, textarea):where(:not([class], [type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="hidden"])):focus { outline: none; border-color: var(--brand-500); box-shadow: var(--input-shadow), var(--input-ring); }
    :where(.oc-form) :where(select):where(:not([class], [multiple])) {
        -webkit-appearance: none; appearance: none; padding-right: 2rem; background-repeat: no-repeat; background-position: right .5rem center; background-size: 1rem 1rem;
        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='m7 10 5 5 5-5'/%3E%3C/svg%3E");
    }
    :where(.dark .oc-form) :where(select):where(:not([class], [multiple])) { 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='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E"); }
    :where(.oc-form) :where(input[type="number"]):where(:not([class])) { -moz-appearance: textfield; appearance: textfield; }
    :where(.oc-form) :where(input[type="number"]):where(:not([class]))::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
    :where(.oc-form) :where(textarea):where(:not([class])) { min-height: calc(3 * 1.25rem + .75rem + 2px); resize: vertical; field-sizing: content; max-height: calc(12 * 1.25rem + .75rem + 2px); scrollbar-width: thin; }
    :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class], [role="switch"])),
    .oc-radio {
        -webkit-appearance: none; appearance: none; display: inline-grid; place-content: center; flex: 0 0 auto; margin: 0;
        width: 1.05rem; height: 1.05rem; border-radius: .3rem; border: 1.5px solid var(--input-strong); background: var(--input-bg);
        box-shadow: var(--input-shadow); cursor: pointer; vertical-align: middle;
        transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
    }
    :where(.oc-form, .field-check) input[type="radio"]:where(:not([class])), .oc-radio { border-radius: 999px; }
    :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class], [role="switch"]))::before, .oc-radio::before {
        content: ""; width: .625rem; height: .625rem; background: var(--primary-foreground); transform: scale(0); transition: transform var(--duration-fast) var(--ease-out);
        -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5'/%3E%3C/svg%3E") center / contain no-repeat;
        mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5'/%3E%3C/svg%3E") center / contain no-repeat; }
    :where(.oc-form, .field-check) input[type="radio"]:where(:not([class]))::before, .oc-radio::before { width: .4375rem; height: .4375rem; border-radius: 999px; -webkit-mask: none; mask: none; }
    :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class], [role="switch"])):checked, .oc-radio:checked { background: var(--primary); border-color: var(--primary); }
    :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class], [role="switch"])):checked::before, .oc-radio:checked::before { transform: scale(1); }
    :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class], [role="switch"])):focus-visible, .oc-radio:focus-visible { outline: none; box-shadow: var(--ring); }
    :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class], [role="switch"])):disabled, .oc-radio:disabled { opacity: .5; cursor: not-allowed; }
    @media (forced-colors: active) {
        :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class])), .oc-radio { -webkit-appearance: auto; appearance: auto; }
        :where(.oc-form, .field-check) input:is([type="checkbox"], [type="radio"]):where(:not([class]))::before, .oc-radio::before { content: none; }
    }

    /* 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: 2rem; }
    .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); box-shadow: var(--input-shadow), var(--input-ring-danger); }
    .field-validation-error { color: var(--danger-ink); font-size: .75rem; margin-top: .35rem; display: block; }

    /* ---------- Badges ---------- */
    .badge { display: inline-flex; align-items: center; gap: .3rem; font-size: .75rem; font-weight: 600; padding: .125rem .5rem; border-radius: 999px; line-height: 1rem; }
    .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: .8125rem; }
    .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; }
    /* Off: a muted fill + a ≥3:1 --input ring so "off" reads as an enabled control (distinct from disabled). */
    .oc-toggle-track { position: absolute; inset: 0; background: var(--line); box-shadow: inset 0 0 0 1px var(--input-strong); border-radius: 999px; transition: background .2s ease, box-shadow .2s ease; }
    .oc-toggle input:checked + .oc-toggle-track { box-shadow: none; }
    .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: .45; cursor: not-allowed; }
    .oc-toggle input:disabled + .oc-toggle-track::before { box-shadow: none; }
    .oc-toggle-success input:checked + .oc-toggle-track { background: var(--success); }

    /* ---------- Checkbox ---------- */
    /* Themed checkbox (both themes): a drawn box instead of the UA control, so the border/background follow the
       tokens in dark mode too (the native box ignored the border and rendered its own grey). */
    .oc-check { -webkit-appearance: none; appearance: none; display: inline-grid; place-content: center; flex: 0 0 auto; margin: 0; width: 1.05rem; height: 1.05rem; border-radius: .3rem; border: 1.5px solid var(--input-strong); background: var(--input-bg); box-shadow: var(--input-shadow); accent-color: var(--primary); cursor: pointer; vertical-align: middle; transition: background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out); }
    .oc-check::before { content: ""; width: .625rem; height: .625rem; background: var(--primary-foreground); transform: scale(0); transition: transform var(--duration-fast) var(--ease-out);
        -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5'/%3E%3C/svg%3E") center / contain no-repeat;
        mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.2l2.3 2.3 4.7-5'/%3E%3C/svg%3E") center / contain no-repeat; }
    .oc-check:indeterminate::before {
        -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M3 6h6'/%3E%3C/svg%3E") center / contain no-repeat;
        mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M3 6h6'/%3E%3C/svg%3E") center / contain no-repeat; }
    .oc-check:is(:checked, :indeterminate) { background: var(--primary); border-color: var(--primary); }
    .oc-check:is(:checked, :indeterminate)::before { transform: scale(1); }
    @media (hover: hover) { .oc-check:not(:disabled, :checked, :indeterminate):hover { border-color: color-mix(in srgb, var(--input-strong) 65%, var(--ink-900)); } }
    .oc-check:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-check:disabled { opacity: .5; cursor: not-allowed; }
    .oc-check-success:is(:checked, :indeterminate) { background: var(--success); border-color: var(--success); }
    @media (forced-colors: active) { .oc-check { -webkit-appearance: auto; appearance: auto; } .oc-check::before { content: none; } }
    @media (prefers-reduced-motion: reduce) { .oc-check, .oc-check::before { transition: none; } }
    /* Native radios / un-classed checkboxes: themed via accent-color (+ color-scheme from the theme tokens). */
    input[type="radio"], input[type="checkbox"]:not(.oc-check, [role="switch"]) { accent-color: var(--primary); }

    /* ---------- Spinner / skeleton (unified loading system — see the LOADING block near the end of this layer) ---------- */
    @keyframes oc-spin { to { transform: rotate(360deg); } }
    @keyframes oc-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
    /* ONE spinner (C5): @Html.Spinner("sm"|"md"|"lg"). currentColor ring + arc, so it inherits the context colour. */
    .oc-spinner { display: inline-block; flex: 0 0 auto; width: 1.25rem; height: 1.25rem; vertical-align: -.25em; color: var(--primary); border: 2px solid color-mix(in srgb, currentColor 22%, transparent); border-top-color: currentColor; border-radius: 50%; animation: oc-spin .7s linear infinite; }
    .oc-spinner-sm { width: 1rem; height: 1rem; }
    .oc-spinner-lg { width: 2rem; height: 2rem; border-width: 3px; }

    /* ONE shimmer (C1): every bone paints the same viewport-anchored gradient (background-attachment: fixed), so a
       single highlight band sweeps the whole skeleton in sync — no per-bone phase drift, no ::after band. */
    @keyframes oc-shimmer { from { background-position: -80vw 0; } to { background-position: 60vw 0; } }
    .oc-skeleton {
        position: relative; overflow: hidden; border-radius: .375rem;
        background-color: var(--oc-skel-base);
        background-image: linear-gradient(100deg, transparent 35%, var(--oc-skel-hi) 50%, transparent 65%);
        background-size: 120vw 100%; background-repeat: no-repeat; background-attachment: fixed;
        animation: oc-shimmer 1.6s linear infinite;
    }

    /* ---------- Divider with label ---------- */
    .oc-divider { display: flex; align-items: center; gap: .75rem; color: var(--ink-500); font-size: .75rem; 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: .8125rem; }
    .oc-table thead th { text-align: left; font-size: .6875rem; 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 .75rem/1.25 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: .6875rem; }
    /* Compact workspace switcher trigger (default): a 20px avatar keeps the trigger a single 32px line. */
    .oc-workspace-trigger.is-compact .oc-avatar { width: 1.25rem; height: 1.25rem; font-size: .5625rem; border-radius: .3125rem; }
    .oc-avatar-md { width: 2.5rem; height: 2.5rem; font-size: .8125rem; }
    .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; }
    /* Two-column grids (phones, narrow cards, Stats.Columns=2): an odd last tile spans both columns instead of
       leaving a hole. Two columns ⇔ grid narrower than three 8.5rem tracks + gaps. */
    .oc-stats-grid { container: oc-stats / inline-size; }
    @container oc-stats (width >= 18rem) { .oc-stats-grid.oc-stats-max-2 > :last-child:nth-child(odd):not(:first-child) { grid-column: span 2; } }
    @container oc-stats (18rem <= width < 26.75rem) { .oc-stats-grid > :last-child:nth-child(odd):not(:first-child) { grid-column: span 2; } }
    .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); }
    /* THE empty/error-state icon tile — one shape everywhere (rounded square, 44px tile, 20px glyph). Used by
       _EmptyState, _EmptyStateCard, _Timeline/_TreeView/_Calendar empties and the widgets' empty/error states. */
    .oc-empty-icon { flex: 0 0 auto; width: 2.75rem; height: 2.75rem; border-radius: var(--radius-lg); background: var(--surface-muted); box-shadow: inset 0 0 0 1px var(--line); color: var(--ink-500); display: inline-flex; align-items: center; justify-content: center; margin-bottom: .75rem; font-size: 1.25rem; }
    .oc-empty-icon > :is(i, svg) { width: 1.25rem; height: 1.25rem; font-size: 1.25rem; }
    .oc-empty-icon-danger { color: var(--danger-ink); background: var(--danger-subtle); box-shadow: none; }
    .oc-empty-title { font-size: .875rem; font-weight: 600; color: var(--ink-900); }
    .oc-empty-text { font-size: .8125rem; color: var(--ink-500); margin-top: .25rem; }

    /* ---------- 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; }
    /* A Font Awesome <i> sized with w-5/h-5 is a 20px box whose 14px glyph sat at the TOP (line-height 14px):
       centre the glyph inside its box so ☰ / ‹ / × sit dead-centre in the button. */
    .oc-icon-btn > i[class*="fa-"] { --fa-display: inline-flex; align-items: center; justify-content: center; } /* FA's display reads --fa-display */
    @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); } }
    /* Pager page buttons: square at 1–2 digits, grow for "128"; the current page is a filled primary chip. */
    /* _Pagination default (Page.Bordered unset): the top divider only when the pager is a card footer. */
    .oc-card .oc-pagination-auto-border { border-top: 1px solid var(--line); }
    .oc-pagination .oc-icon-btn { width: auto; min-width: 2rem; padding-inline: .375rem; font-variant-numeric: tabular-nums; }
    .oc-pagination .oc-icon-btn.oc-page-current { color: var(--primary-foreground); background: var(--primary); font-weight: 600; box-shadow: var(--shadow-sm); cursor: default; }
    @media (hover: hover) { .oc-pagination .oc-icon-btn.oc-page-current:hover { color: var(--primary-foreground); background: var(--primary); } }
    @media (pointer: coarse) { .oc-pagination .oc-icon-btn { min-width: 2.75rem; } }

    /* ---------- 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 var(--focus-outline); 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: center; 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-view-toggle-button { min-height: 2.75rem; }
        .oc-icon-btn { min-width: 2.75rem; width: 2.75rem; }
        /* Checkboxes keep their visual size (a 44px-tall .oc-check made touch rows 66px); the selection CELL is
           the hit area instead (octacer-table.js forwards a tap on the cell to its checkbox), and in card mode
           the absolutely-placed cell grows an invisible 44px ::after target. */
        .oc-table :is(td, th)[data-oc-cell="select"] { cursor: pointer; }
        .oc-table-cards tbody td[data-oc-cell="select"]::after { content: ""; position: absolute; inset: 50% auto auto 50%; width: 2.75rem; height: 2.75rem; transform: translate(-50%, -50%); }
    }

    @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) ---------- */
    /* ONE tile design for hand-written .oc-stat markup AND widgets/_StatTile (which renders this same markup):
         row 1  label (≤2 lines, clamped)                      icon (top-right, optional)
         row 2  value — sans, tabular-nums, one line, full tile width; shrinks with the tile (cqi) and by the
                .oc-len-* length bucket, ellipsis + title only as the last resort — never overflows the tile
         row 3+ delta pill (.oc-stat-delta — @Html.StatDelta) / error / segments, left-aligned
       Content is TOP-aligned (tiles in one grid row share a height; the spare space falls at the bottom). The text
       wrapper <div> is display:contents, so the icon may come before or after it in the markup — same layout. */
    .oc-stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); transition: box-shadow .2s, transform .2s, border-color .2s;
        container-type: inline-size; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; align-content: start; column-gap: .75rem; row-gap: .375rem; padding: .875rem 1rem; min-width: 0; }
    @media (hover: hover) { .oc-stat-hover:hover, a.oc-stat:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); border-color: var(--line-strong); } }
    .oc-stat > div:not([class]) { display: contents; }   /* the hand-written text wrapper only */
    /* :where() keeps this default at (0,1,0) so the label / icon placement rules below always win (the
       label used to span under the icon when it sat inside the hand-written text wrapper). */
    :where(.oc-stat > :not(.oc-stat-icon), .oc-stat > div:not([class]) > *) { grid-column: 1 / -1; min-width: 0; }
    .oc-stat .oc-stat-label { grid-column: 1; grid-row: 1; align-self: center; font-size: .75rem; font-weight: 500; line-height: 1.35; color: var(--ink-500);
        display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
    .oc-stat .oc-stat-icon { grid-column: 2; grid-row: 1; }
    .oc-stat-value { --oc-chars: 6; margin: 0; font-family: var(--font-sans); font-variant-numeric: tabular-nums; font-size: clamp(1rem, calc(100cqi / (var(--oc-chars) * .6)), 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-value.oc-len-8 { --oc-chars: 8; }
    .oc-stat-value.oc-len-10 { --oc-chars: 10; }
    .oc-stat-value.oc-len-12 { --oc-chars: 12; }
    .oc-stat-value.oc-len-15 { --oc-chars: 15; }
    .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; color: var(--primary-ink); background: var(--primary-tint); }
    /* Very narrow tiles drop the decorative icon (label + value carry the meaning). */
    @container (max-width: 7rem) { .oc-stat-icon { display: none; } }
    /* Delta pill — tone up (success) / down (danger) / neutral (slate). Rendered by @Html.StatDelta, which
       auto-detects the tone from a leading +/−/"flat"/0 (overridable). */
    .oc-stat-delta { display: inline-flex; align-items: center; gap: .25rem; justify-self: start; max-width: 100%; padding: .125rem .4375rem; border-radius: 999px; font-size: .6875rem; font-weight: 600; line-height: 1.3; white-space: nowrap; font-variant-numeric: tabular-nums; }
    .oc-stat-delta-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
    .oc-stat-delta-icon { flex: 0 0 auto; font-size: .625rem; }
    .oc-stat-delta-up { color: var(--success-subtle-foreground); background: var(--success-subtle); }
    .oc-stat-delta-down { color: var(--danger-subtle-foreground); background: var(--danger-subtle); }
    .oc-stat-delta-neutral { color: var(--ink-600); background: var(--line-2); }

    /* ---------- 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: 1rem 1.125rem; } }
    .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: 1rem 1.125rem; } }
    /* 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(6rem, 100%); max-width: 100%; overflow-wrap: break-word; word-break: normal; }
    .oc-stat-list-label > :not(svg, i) { min-width: 0; overflow-wrap: break-word; }
    .oc-stat-list-trend { display: inline-flex; align-items: center; justify-content: flex-end; gap: .25rem; min-width: 4.25rem; }
    .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: .75rem; 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: .75rem; }
    @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); }

    /* (The old `form.htmx-request button[type=submit]` spinner path is retired: octacer-loading.js marks the form's
       submitter aria-busy, so htmx forms get the same delay/min-time/LoadingLabel/SlowLabel as every button.)
       The top progress bar (#oc-progress) lives in the LOADING block near the end of this layer. */

    /* 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);
    }
    /* The search field's clear ×: a quiet muted glyph (not the UA's blue bold one); hidden on phones, where the
       palette's own close × sits right beside it (two ×s side by side read as one ambiguous control). */
    .oc-command-input::-webkit-search-cancel-button {
        -webkit-appearance: none; appearance: none; width: 1rem; height: 1rem; margin-inline-start: .5rem; cursor: pointer;
        background-color: var(--ink-400);
        -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / .75rem no-repeat;
        mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / .75rem no-repeat;
    }
    @media (hover: hover) { .oc-command-input::-webkit-search-cancel-button:hover { background-color: var(--ink-700); } }
    @media (max-width: 639px) { .oc-command-input::-webkit-search-cancel-button { display: none; } }

    /* ============================================================
       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 .6875rem/1 var(--font-sans); font-variant-numeric: tabular-nums;
        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.oc-has-tabbar is emitted by the layouts on the server (true from the first paint, no CLS); :has()
           covers hand-built shells and the JS-built legacy bar. Same specificity as the old html:has(.oc-tabbar). */
        html:is(.oc-has-tabbar, :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-500); } /* out-of-month but selectable: ≥4.5:1 */
    .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); }
    /* Range edges meet the in-range band (range rows have no column gap — octacer-datefields.js ROW_OPEN_BAND). */
    .oc-cal-day--range-start { border-start-end-radius: 0; border-end-end-radius: 0; }
    .oc-cal-day--range-end { border-start-start-radius: 0; border-end-start-radius: 0; }
    .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.25rem; } .oc-richtext h2 { font-size: 1.125rem; } .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); } }
    /* Pinned-column edge: while data is hidden under a pinned column (octacer-table.js toggles .oc-scroll-start /
       .oc-scroll-end on the region), draw an inset hairline + soft shadow on the pinned column's inner edge so the
       content visibly slides UNDER it. No edge once scrolled fully to that side. */
    /* (Card mode never shows it: the region doesn't overflow there, so both edge classes are set.) */
    [data-oc-datatable-scroll]:not(.oc-scroll-end) > .oc-datatable :is(th, td).oc-col-pin-end { box-shadow: inset 1px 0 0 var(--line), -8px 0 8px -8px rgb(15 23 42 / .28); }
    [data-oc-datatable-scroll]:not(.oc-scroll-start) > .oc-datatable :is(th, td).oc-col-pin-start { box-shadow: inset -1px 0 0 var(--line), 8px 0 8px -8px rgb(15 23 42 / .28); }
    .dark [data-oc-datatable-scroll]:not(.oc-scroll-end) > .oc-datatable :is(th, td).oc-col-pin-end { box-shadow: inset 1px 0 0 var(--line), -8px 0 10px -8px rgb(0 0 0 / .7); }
    .dark [data-oc-datatable-scroll]:not(.oc-scroll-start) > .oc-datatable :is(th, td).oc-col-pin-start { box-shadow: inset -1px 0 0 var(--line), 8px 0 10px -8px rgb(0 0 0 / .7); }
    .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); }
    /* 24px per level + a subtle guide line per ancestor level, centred under the ancestor's chevron (drawn on the
       name cell so it runs through the cell padding and connects row to row). */
    .oc-treetable, .oc-tree-indent { --oc-tree-step: 1.5rem; --oc-tree-toggle: 1.75rem; }
    @media (pointer: coarse) { .oc-treetable, .oc-tree-indent { --oc-tree-toggle: 2.75rem; } }
    .oc-treetable tbody td[data-oc-col="name"] { background-image: repeating-linear-gradient(to right, var(--line) 0 1px, transparent 1px var(--oc-tree-step)); background-repeat: no-repeat; background-position: calc(1rem + var(--oc-tree-toggle) / 2) 0; background-size: calc(var(--oc-tree-step) * var(--oc-tree-depth, 0)) 100%; }
    .oc-treetable tbody td[data-oc-col="name"]:has(> [data-oc-level="2"]) { --oc-tree-depth: 1; }
    .oc-treetable tbody td[data-oc-col="name"]:has(> [data-oc-level="3"]) { --oc-tree-depth: 2; }
    .oc-treetable tbody td[data-oc-col="name"]:has(> [data-oc-level="4"]) { --oc-tree-depth: 3; }
    .oc-treetable tbody td[data-oc-col="name"]:has(> [data-oc-level="5"]) { --oc-tree-depth: 4; }
    .oc-treetable tbody td[data-oc-col="name"]:has(> [data-oc-level="6"]) { --oc-tree-depth: 5; }
    .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: var(--oc-tree-toggle, 1.75rem); }
    .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. */
    /* .oc-scroll-gutter is added by OctacerLayers only when the page had a vertical scrollbar before locking, so
       hiding it doesn't reflow long pages AND short pages (no scrollbar) don't gain a phantom 15px gutter. */
    html.oc-scroll-lock { overflow: hidden; }
    html.oc-scroll-lock.oc-scroll-gutter { 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 var(--focus-outline); 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: .75rem; 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: .75rem; color: var(--ink-500); min-width: 0; }
    /* Move handle: a quiet grip OVERLAID on the card's top-right corner — no reserved column, so the title and
       footer use the full card width. Shown on hover / keyboard focus / while its menu is open; always visible
       (and given a little room) where there is no hover. The keyboard Move menu stays one Tab away. */
    .oc-kanban-card-move { position: absolute; top: .3125rem; right: .3125rem; z-index: 1; opacity: 0; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-kanban-card:hover .oc-kanban-card-move, .oc-kanban-card:focus-within .oc-kanban-card-move,
    .oc-kanban-card-move:has([aria-expanded="true"]) { opacity: 1; }
    .oc-kanban-move-btn { width: 1.5rem; height: 1.5rem; color: var(--ink-500); background: var(--surface); border-radius: var(--radius-sm); }
    @media (hover: none) {
        .oc-kanban-card-move { opacity: 1; }
        .oc-kanban-card-main { padding-inline-end: 1rem; }
    }
    @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: .6875rem; 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: .8125rem; color: var(--ink-500); border: 1px dashed var(--line-strong); border-radius: var(--radius); }
    .oc-kanban-empty-hint { font-size: .75rem; color: var(--ink-500); }
    @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-ink); }
    .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-template-rows: auto; grid-auto-rows: minmax(6.5rem, 1fr); } /* row 1 = weekday header (inside the grid) */
    .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-500); font-weight: 500; }
    .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: .75rem; 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 { flex: 0 0 auto; font-weight: 500; font-variant-numeric: tabular-nums; } /* same size/ink as the title: ≥4.5:1 */
    .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; display: inline-flex; align-items: center; min-height: 1.5rem; padding: .0625rem .375rem; 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: .6875rem; 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: .6875rem; color: var(--ink-500); font-variant-numeric: tabular-nums; }
    .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: .75rem; 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-variant-numeric: tabular-nums; }
    .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: .6875rem; 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: .6875rem; 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: .6875rem; 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; }
    /* flex-start + a first-line-centred marker: the dot sits on the title's FIRST line when it wraps. */
    .oc-cal-agenda-item { display: flex; align-items: flex-start; gap: .625rem; padding: .75rem .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; margin-top: .375rem; border-radius: 999px; }
    .oc-cal-agenda-when { flex: 0 0 auto; width: 6.5rem; font-size: .75rem; line-height: 1.25rem; color: var(--ink-500); font-variant-numeric: tabular-nums; }
    .oc-cal-agenda-title { flex: 1 1 auto; min-width: 0; font-size: .8125rem; line-height: 1.25rem; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    /* Calendar loading = primitives/_Skeleton shape "calendar": the REAL .oc-cal-month-grid with bones (the old
       .oc-cal-skel-* grid and its own oc-cal-shimmer are retired — ONE shimmer, see .oc-skeleton). */
    /* 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; }
    /* Narrow: the switcher keeps its words (clearer than three bare icons) and drops the icons instead. */
    .oc-calendar[data-oc-cal-compact] .oc-cal-view-opt { --fa-display: none; padding-inline: .5rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-view-opt > :is(i, svg) { display: none; }
    .oc-cal-title { font-size: 1rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-title { font-size: .875rem; }
    @media (prefers-reduced-motion: reduce) { .oc-cal-cell, .oc-cal-chip, .oc-cal-block, .oc-cal-tg-daybtn { transition: 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: .8125rem; }
    .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-strong); 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 ---------- */
    /* Parked far above the viewport (top: -10rem), not translateY(-200%): on notched iPhones --oc-safe-top ≈ 47px,
       so a relative offset left the pill peeking out inside the status bar. Restored only while focused. */
    .oc-skip-link { position: fixed; left: calc(.75rem + var(--oc-safe-left)); top: -10rem; z-index: var(--z-progress); padding: .5rem .875rem; border-radius: .625rem; background: var(--primary); color: var(--primary-foreground); font-size: .875rem; font-weight: 600; box-shadow: none; }
    /* Shadow only while shown — the off-screen link's shadow used to bleed into the top-left corner. */
    .oc-skip-link:focus, .oc-skip-link:focus-visible { top: calc(.75rem + var(--oc-safe-top)); outline: none; box-shadow: var(--ring), var(--shadow-lg); }

    /* ---------- 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: 1rem; font-weight: 700; color: var(--ink-900); line-height: 1.2; }
    /* Phone root pages: the app name holds the left of the bar until the page H1 scrolls under it. */
    .oc-appbar-appname { flex: 1 1 auto; min-width: 0; padding-inline-start: .5rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 1rem; font-weight: 700; color: var(--ink-900); line-height: 1.2; }
    @media (max-width: 1023px) {
        .oc-layout-header:not(.is-condensed) .oc-appbar-appname + .oc-appbar-title { flex: 0 0 0; }
        .oc-layout-header.is-condensed .oc-appbar-appname { display: none; }
    }
    .oc-appbar-title.is-centered { text-align: center; }
    .oc-appbar-sub { display: block; font-size: .75rem; 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:is(.oc-has-tabbar, :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); }
    /* Children (sub-destinations) inside a group: parent label + an indented list with a guide line — visibly a
       level BELOW the uppercase group heading, never a second heading of the same style. */
    .oc-more-nested:not(:first-child) { margin-top: .75rem; }
    .oc-more-nested-parent { display: flex; align-items: center; gap: .5rem; min-height: 2.75rem; margin: 0; padding: 0 .5rem; border-radius: var(--radius-sm); color: var(--ink-900); font-size: .875rem; font-weight: 600; text-decoration: none; }
    .oc-more-nested-parent > i { color: var(--ink-500); }
    .oc-more-sublist { margin: 0 0 0 1rem; padding: 0 0 0 .75rem; list-style: none; border-inline-start: 1px solid var(--line); }
    .oc-more-subitem { display: flex; align-items: center; gap: .5rem; width: 100%; min-height: 2.75rem; padding: 0 .5rem; border: 0; border-radius: var(--radius-sm); background: none; color: var(--ink-700); font-size: .875rem; text-align: start; text-decoration: none; }
    .oc-more-subitem[aria-current="page"], .oc-more-nested-parent[aria-current="page"] { color: var(--primary-ink); background: var(--primary-tint); font-weight: 600; }
    .oc-more-subitem:focus-visible, .oc-more-nested-parent:focus-visible { outline: none; box-shadow: var(--ring); }
    @media (hover: hover) { .oc-more-subitem:hover, a.oc-more-nested-parent:hover { background: var(--surface-muted); } }
    .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: .875rem; }
    .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; } }
    /* A visible FAB covers the bottom-right of the viewport: keep focused/scrolled-to content clear of it (2.4.11). */
    @media (max-width: 1023px) { html:has(.oc-fab:not(.is-hidden)) { scroll-padding-bottom: calc(var(--oc-bottom-chrome) + 5rem); } }
    /* Very short viewports (≈400% zoom, landscape phones): sticky/fixed chrome would cover the focused element
       (WCAG 2.4.11 / 1.4.10). The extended FAB collapses to an icon-only button (its label stays as the
       accessible name, visually hidden) and the header + tab strips scroll with the page instead of sticking. */
    @media (max-height: 30rem) {
        .oc-fab-extended { width: 2.75rem; height: 2.75rem; padding: 0; border-radius: .875rem; }
        .oc-fab-extended > .oc-fab-label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
        .oc-fab:not(.oc-fab-extended) { width: 2.75rem; height: 2.75rem; }
        .oc-layout-header { position: relative; }
        .oc-tabs-sticky { position: static; }
        html { scroll-padding-top: .5rem; }
        /* Landscape tab bar: 44px tall (--oc-tabbar-h, set with the tokens), icon + label in one row. */
        .oc-tabbar-link { flex-direction: row; gap: .375rem; }
        .oc-tabbar-icon { width: 2.25rem; height: 1.75rem; font-size: 1rem; flex: 0 0 auto; }
        .oc-tabbar-label { font-size: .75rem; }
    }

    /* ---------- 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 — bottom-right on desktop/tablet (above any bottom chrome), full-width above the tab
       bar on phones. Newest toast sits nearest the edge. While a side drawer is open (≥640px) the region moves to
       the bottom-LEFT so it never covers the drawer's header/footer actions. ---------- */
    .oc-toast-region { position: fixed; z-index: var(--z-toast); display: flex; flex-direction: column; gap: .5rem; pointer-events: none;
        bottom: calc(var(--oc-bottom-chrome, 0px) + 1rem); 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 (min-width: 640px) {
        html:has(.oc-drawer.flex) .oc-toast-region { right: auto; left: calc(1rem + var(--oc-safe-left)); }
    }
    @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); }
    }

    /* ---------- 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 .75rem/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; }
        /* No footer row for actions (it wasted ~25% of every card):
           - ONE non-destructive action (the usual Open ›): the whole card is its tap target (stretched ::before),
             a small chevron sits vertically centred on the right edge; the cell itself takes no space.
           - 2 inline actions or the ⋯ menu: inline on the TITLE row, right-aligned, left of the checkbox. */
        .oc-table-cards tbody tr { --oc-card-trail: 0rem; }
        .oc-table-cards tbody tr:has(> td[data-oc-cell="select"]) { --oc-card-trail: 1.75rem; }
        .oc-table-cards tbody td[data-oc-cell="title"] { padding-right: calc(var(--oc-card-trail) + .25rem); overflow-wrap: anywhere; }
        .oc-table-cards tbody td[data-oc-cell="select"] { top: 1.25rem; transform: translateY(-50%); }
        .oc-table-cards tbody td :is(a[href], button, input, select, label, summary) { position: relative; z-index: 1; }
        .oc-table-cards tbody td[data-oc-cell="actions"]:is(:has(> :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger])), :has(> .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger))) { display: contents; }
        .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger])),
        .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger)) { padding-right: 2.25rem; cursor: pointer; }
        .oc-table-cards tbody td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger]),
        .oc-table-cards tbody td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger) {
            position: static; z-index: auto; display: block; width: 0; min-width: 0; height: 0; min-height: 0; padding: 0; margin: 0; overflow: visible; background: none; }
        .oc-table-cards tbody td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger])::before,
        .oc-table-cards tbody td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger)::before { content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit; }
        .oc-table-cards tbody td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger]) > *,
        .oc-table-cards tbody td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger) > * { position: absolute; right: .75rem; top: 50%; transform: translateY(-50%); width: .875rem; height: .875rem; color: var(--ink-400); }
        .oc-table-cards tbody td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:focus-visible { box-shadow: none; }
        .oc-table-cards tbody td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger])::after,
        .oc-table-cards tbody td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger)::after { content: none; }
        @media (hover: hover) { .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger])):hover { border-color: var(--line-strong); } }
        /* Several actions / the ⋯ menu: on the title row, right-aligned (left of the checkbox when selectable). */
        .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] :is(.oc-row-actions, .oc-row-actions-inline > * + *)) { --oc-card-trail: calc(var(--oc-card-actions-w, 2rem) + .25rem); }
        .oc-table-cards tbody tr:has(> td[data-oc-cell="select"]):has(> td[data-oc-cell="actions"] :is(.oc-row-actions, .oc-row-actions-inline > * + *)) { --oc-card-trail: calc(var(--oc-card-actions-w, 2rem) + 2rem); }
        .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] .oc-row-actions-inline > * + *) { --oc-card-actions-w: 3.75rem; }
        .oc-table-cards tbody td[data-oc-cell="actions"]:has(:is(.oc-row-actions, .oc-row-actions-inline > * + *)) { position: absolute; top: 1.25rem; right: .375rem; transform: translateY(-50%); margin: 0; padding: 0; border: 0; z-index: 1; }
        .oc-table-cards tbody tr:has(> td[data-oc-cell="select"]) > td[data-oc-cell="actions"]:has(:is(.oc-row-actions, .oc-row-actions-inline > * + *)) { right: 2.125rem; }
        .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; }
        /* The thead is hidden in card mode, so its "select all" lives in this visible card toolbar instead. */
        .oc-table-cardbar.oc-table-cardbar { display: flex; }
        /* Inside a bordered .oc-card (every _Table/_DataTable shell) the rows are FLUSH — dividers only, no card-
           in-card double borders. A hand-written card table outside a card keeps the bordered row cards. */
        .oc-card .oc-table-cards tbody { gap: 0; padding: 0; }
        .oc-card .oc-table-cards tbody tr { padding: .75rem 1rem; border: 0; border-bottom: 1px solid var(--line-2); border-radius: 0; box-shadow: none; }
        .oc-card .oc-table-cards tbody tr:last-child { border-bottom: 0; }
        .oc-card .oc-table-cards tbody tr:focus-within { box-shadow: var(--ring-inset); }
        .oc-card .oc-table-cards tbody td[data-oc-cell="select"] { right: 1rem; top: 1.375rem; }
        .oc-card .oc-table-cards tbody td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger]) > *,
        .oc-card .oc-table-cards tbody td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger) > * { right: 1rem; }
        .oc-card .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] > :is(a, button).oc-icon-btn:only-child:not(.danger, [data-oc-popmenu-trigger])),
        .oc-card .oc-table-cards tbody tr:has(> td[data-oc-cell="actions"] > .oc-row-actions-inline:only-child > :is(a, button):only-child:not(.danger)) { padding-right: 2.5rem; }
        .oc-card .oc-table-cards tbody td[data-oc-cell="actions"]:has(:is(.oc-row-actions, .oc-row-actions-inline > * + *)) { top: 1.375rem; right: .625rem; }
        .oc-card .oc-table-cards tbody tr:has(> td[data-oc-cell="select"]) > td[data-oc-cell="actions"]:has(:is(.oc-row-actions, .oc-row-actions-inline > * + *)) { right: 2.375rem; }
        .oc-card .oc-table-cardbar { padding-right: 1rem; padding-bottom: .375rem; border-bottom: 1px solid var(--line-2); }
        .oc-card [data-oc-table-skeleton] .oc-table-cards tbody td[data-oc-cell="actions"] { right: 1rem; }
        /* Skeleton cards mirror the real ones: label/value lines, square checkbox top-right, chevron right-centre. */
        .oc-table-cards .oc-skel-label { display: block; flex: 0 0 auto; }
        .oc-table-cards tbody td > .oc-skel-label + .oc-skeleton { flex: 0 1 auto; margin-block: .125rem; }
        [data-oc-table-skeleton] .oc-table-cards tbody tr { padding-right: 2.25rem; }
        [data-oc-table-skeleton] .oc-table-cards tbody td[data-oc-cell="actions"] { position: absolute; right: .75rem; top: max(50%, 2.5rem); transform: translateY(-50%); margin: 0; padding: 0; border: 0; }
        [data-oc-table-skeleton] .oc-table-cards tbody td[data-oc-cell="actions"] > .oc-skeleton { margin: 0; }
        .oc-table-cardbar:has(input:disabled) { display: none; }
    }
    /* Right-aligned so its checkbox lines up with the cards' top-right checkboxes. */
    .oc-skel-label { display: none; }
    .oc-table-cardbar { display: none; align-items: center; justify-content: flex-end; gap: .5rem; padding: .625rem calc(1.25rem + 1px) 0 1rem; font-size: .8125rem; color: var(--ink-600); }
    .oc-table-cardbar label { display: inline-flex; align-items: center; gap: .5rem; cursor: pointer; min-height: 1.75rem; }

    /* ---------- 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: .75rem; 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 { width: 100%; }   /* infinite scroll: a visible bone row (primitives/_Skeleton "list") */

    /* ---------- 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; }
        /* Detail pages print as a document: no app chrome, no actions, ALL tab panels expanded and titled. */
        .oc-layout-header, .oc-page-actions, .oc-page-more, .oc-tabs, [role="tablist"], [data-oc-copy], [data-oc-copy-target],
        .oc-bulk-action-bar, .oc-wizard-footer, .oc-pagination, [data-oc-load-more], .oc-table-toolbar, .oc-error-actions,
        .oc-icon-btn[data-oc-back], .oc-modal, .oc-drawer, .oc-command { display: none !important; }
        .oc-shell-content, [data-oc-shell-content], .oc-layout-main { margin: 0 !important; padding: 0 !important; max-width: none !important; }
        .oc-tab-panel, [role="tabpanel"] { display: block !important; padding-top: 0; margin-top: 1rem; }
        [role="tabpanel"][hidden] { display: block !important; }
        [role="tabpanel"][data-oc-print-label]::before { content: attr(data-oc-print-label); display: block; font-weight: 600; font-size: 1rem; margin: 0 0 .5rem; padding-bottom: .25rem; border-bottom: 1px solid #ccc; }
        tr, .oc-description-list > div, dl > div, .oc-timeline-item, .oc-alert { break-inside: avoid; }
        h1, h2, h3 { break-after: avoid; }
        a[href]::after { content: none; }
        .oc-card { border-color: #ccc; }
    }

    /* ---------- Flow primitives (octacer-flow.js / octacer-dirty.js / octacer-session.js) ---------- */
    .oc-overlay-icon-info { color: var(--primary-ink); background: var(--primary-tint); }
    .oc-error-summary { scroll-margin-top: calc(var(--oc-appbar-h, 3.5rem) + 1rem); }
    .oc-error-summary:focus-visible, .oc-error-summary:focus { outline: 2px solid var(--danger-subtle-foreground); outline-offset: 2px; }
    .oc-error-summary a { color: inherit; }
    .oc-wizard-mhead-status { flex: 0 0 auto; font-size: .75rem; color: var(--muted-foreground); white-space: nowrap; }
    .oc-wizard-draft-status { font-size: .75rem; color: var(--muted-foreground); white-space: nowrap; align-self: center; }
    .oc-wizard-resume { margin-bottom: 1rem; }
    /* Optimistic bulk action: rows already left the view; [hidden] is enough, this guards display overrides. */
    [data-oc-optimistic="removed"] { display: none !important; }
    /* Bulk bar visible → the FAB is out of the way AND out of the tab order (visibility removes focusability). */
    html:has(.oc-bulk-action-bar:not([hidden])) .oc-fab { visibility: hidden; transition: visibility 0s linear var(--duration-base), opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out); }

    /* ============================================================
       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 (and, after 5 s, SlowLabel — data-oc-busy-slow, set by octacer-loading.js): when busy,
       show "spinner + label" instead of a blank button. Works for EVERY busy path (htmx forms included). */
    .btn:is([aria-busy="true"], .is-loading):is([data-oc-loading-label], [data-oc-busy-slow]) { color: var(--oc-busy-ink, currentColor) !important; position: relative; }
    /* The original label stays in the accessibility tree (visually hidden) so the button keeps its name; the
       visible "Saving…" pseudo-label is marked decorative with the content alt-text syntax so it isn't read twice. */
    .btn:is([aria-busy="true"], .is-loading):is([data-oc-loading-label], [data-oc-busy-slow]) > * { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
    .btn:is([aria-busy="true"], .is-loading)[data-oc-loading-label]::before { content: attr(data-oc-loading-label); content: attr(data-oc-loading-label) / ""; order: 2; }
    .btn:is([aria-busy="true"], .is-loading)[data-oc-busy-slow]::before { content: attr(data-oc-busy-slow); content: attr(data-oc-busy-slow) / ""; order: 2; }
    .btn:is([aria-busy="true"], .is-loading):is([data-oc-loading-label], [data-oc-busy-slow])::after { position: static; inset: auto; margin: 0; 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-ref { font-size: .75rem; font-variant-numeric: tabular-nums; opacity: .7; white-space: nowrap; }
    .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; } }

    /* ---------- One overlay vocabulary: _Drawer / _BottomSheet / _ConfirmModal / _TypedConfirmModal ----------
       Title: one size everywhere (16px/600). Danger tile: a rounded-square destructive glyph beside the title
       of every destructive confirm (neutral header — no tinted band). Footer: Cancel then primary, right-aligned
       on wider screens; stacked full-width (primary on top, thumb-reachable) on phones; always clear of the
       home indicator. */
    /* Scroll-edge fades (octacer-nav.js toggles the classes only while content is hidden past that edge). */
    :is(.oc-tabs-scroll, .oc-tabbed-view > .oc-tabs, .oc-segmented-scroll, .oc-richtext-toolbar, .oc-kanban-scroll, [data-oc-scroll-fade]) { --oc-fade: 1.5rem; --oc-fade-dir: to right; }
    :is(.oc-tabs-scroll, .oc-tabbed-view > .oc-tabs, .oc-segmented-scroll, .oc-richtext-toolbar, .oc-kanban-scroll, [data-oc-scroll-fade]):dir(rtl) { --oc-fade-dir: to left; }
    .is-scroll-end { -webkit-mask-image: linear-gradient(var(--oc-fade-dir, to right), #000 calc(100% - var(--oc-fade, 1.5rem)), transparent); mask-image: linear-gradient(var(--oc-fade-dir, to right), #000 calc(100% - var(--oc-fade, 1.5rem)), transparent); }
    .is-scroll-start { -webkit-mask-image: linear-gradient(var(--oc-fade-dir, to right), transparent, #000 var(--oc-fade, 1.5rem)); mask-image: linear-gradient(var(--oc-fade-dir, to right), transparent, #000 var(--oc-fade, 1.5rem)); }
    .is-scroll-start.is-scroll-end { -webkit-mask-image: linear-gradient(var(--oc-fade-dir, to right), transparent, #000 var(--oc-fade, 1.5rem), #000 calc(100% - var(--oc-fade, 1.5rem)), transparent); mask-image: linear-gradient(var(--oc-fade-dir, to right), transparent, #000 var(--oc-fade, 1.5rem), #000 calc(100% - var(--oc-fade, 1.5rem)), transparent); }
    .oc-kanban-scroll { --oc-fade: 2.5rem; }
    .oc-richtext-toolbar, .oc-markdown-toolbar { scrollbar-width: none; }
    .oc-richtext-toolbar::-webkit-scrollbar, .oc-markdown-toolbar::-webkit-scrollbar { display: none; }
    .oc-richtext-toolbar > *, .oc-markdown-toolbar > * { flex-shrink: 0; }

    .oc-overlay-title { margin: 0; font-size: 1rem; line-height: 1.375rem; font-weight: 600; color: var(--ink-900); letter-spacing: -0.011em; }
    .oc-overlay-icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 2.25rem; height: 2.25rem; border-radius: var(--radius); }
    .oc-overlay-icon-danger { color: var(--danger-ink); background: var(--danger-subtle); }
    .oc-modal-actions, .oc-drawer-footer, .oc-sheet-footer { display: flex; align-items: center; justify-content: flex-end; gap: .625rem; }
    .oc-sheet-footer { padding-bottom: max(.75rem, var(--oc-safe-bottom)); }
    .oc-sheet-panel:has(> .oc-sheet-footer) { padding-bottom: 0; }
    @media (max-width: 639px) {
        .oc-modal:not([data-oc-mobile-sheet="false"]) .oc-modal-actions,
        .oc-drawer:not([data-oc-mobile-sheet="false"]) .oc-drawer-footer,
        .oc-sheet-footer { flex-direction: column-reverse; align-items: stretch; }
        .oc-modal:not([data-oc-mobile-sheet="false"]) .oc-modal-actions > .btn,
        .oc-drawer:not([data-oc-mobile-sheet="false"]) .oc-drawer-footer > .btn,
        .oc-sheet-footer > .btn { width: 100%; }
    }

    /* _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: .6875rem; 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: .875rem; }
.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: .875rem; 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; }
/* Action sheet extras (octacer-table.js decorateSheet): the record/page name as a title, a closing Cancel row. */
.oc-popmenu-sheet-title { margin: 0 0 .25rem; padding: 0 1rem .5rem; border-bottom: 1px solid var(--line); text-align: center; font-size: .8125rem; font-weight: 600; color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-popmenu.is-sheet .oc-popmenu-cancel { justify-content: center; font-weight: 600; color: var(--ink-900); }
[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; }
/* Table region busy (search / sort / page / filter) = the unified region-dim (C4, [data-oc-busy-state]) — no
   per-call hx-indicator needed; see the LOADING block. */

/* ---------- 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: 18rem; min-width: 0; }
/* One control height per toolbar row (mouse screens): search field, Filters / Columns buttons, view toggle all
   32px (--oc-toolbar-h). Touch screens keep the 44px targets from the coarse-pointer block. */
:is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) { --oc-toolbar-h: 2rem; }
@media (pointer: fine) {
    :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) :is(.btn, .btn-sm) { min-height: var(--oc-toolbar-h); }
    :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) .field-group { min-height: var(--oc-toolbar-h); }
    :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) .field-group > input { padding-block: .3125rem; }
    :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) :is(.field-input, .field-select) { min-height: var(--oc-toolbar-h); padding-block: .3125rem; }
    :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) .oc-view-toggle { min-height: var(--oc-toolbar-h); align-items: stretch; }
}
/* Narrow table toolbar (its OWN width): title + Columns share the first row (Columns icon-only), search takes
   the full second row — the Columns button never wraps onto a row of its own. */
.oc-table-toolbar { container: oc-toolbar / inline-size; align-items: center; }
/* Title visually hidden (it repeats the page H1): tools sit at the trailing edge, never alone on the left. */
.oc-table-toolbar:has(> .sr-only:first-child) { justify-content: flex-end; }
@container oc-toolbar (width < 34rem) {
    .oc-table-toolbar > .oc-table-tools { display: contents; }
    .oc-table-toolbar > .oc-card-title { flex: 1 1 0; order: 0; overflow-wrap: anywhere; }
    .oc-table-tools > :not(.field-group) { order: 1; flex: 0 0 auto; }
    .oc-table-tools > .field-group, .oc-table-toolbar > .field-group { order: 2; flex: 1 1 100%; width: auto; }
    .oc-table-columns-btn .oc-tool-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .oc-table-columns-btn { min-width: 2rem; padding-inline: .5rem; }
}
@media (pointer: coarse) { .oc-table-columns-btn { min-width: 2.75rem; } }
/* 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; }

/* ---------- 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) ---------- */
/* "Load more" busy = the button busy contract (spinner + LoadingLabel "Loading…"); the old idle/busy span pair
   (whose Tailwind inline-flex beat these layer rules and showed BOTH labels) is retired. */

/* ---------- 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); } }
/* Applied chips inside the filters sheet/drawer use the SAME .oc-filter-chip size as the desktop row (the
   remove × keeps its 44px ::after hit area), no larger sheet-only variant. */

/* ---------- 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; }
}
/* Description-list copy button: centred on the value's first line and pulled into the row padding, so a row
   with a copy button is no taller than one without (32px button on a 20px line ⇒ −6px top/bottom). */
.oc-dl-copy.oc-dl-copy { margin-block: -.375rem; }
@media (pointer: coarse) { .oc-dl-copy.oc-dl-copy { margin-block: -.75rem; } }
/* Meta "Lahore · ORD-1042": each segment stays whole; lines break between segments. */
.oc-list-item-meta-seg { white-space: nowrap; }
/* Phone-narrow list (< 25rem): the badge moves UNDER the title so the name gets the full width (no "James Mill…"
   beside a fixed badge column); icon and actions span both lines. */
@container oc-list (width < 25rem) {
    .oc-list-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "main act" "badge act"; align-items: center; column-gap: .75rem; row-gap: .25rem; }
    .oc-list-item:has(> .oc-list-item-icon) { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "icon main act" "icon badge act"; }
    .oc-list-item > .oc-list-item-icon { grid-area: icon; }
    .oc-list-item > .oc-list-item-main { grid-area: main; }
    .oc-list-item > .badge { grid-area: badge; justify-self: start; }
    .oc-list-item > .oc-list-item-actions { grid-area: act; width: auto; padding-left: 0; }
    .oc-list-item:not(:has(> .badge)) { grid-template-areas: "main act"; }
    .oc-list-item:has(> .oc-list-item-icon):not(:has(> .badge)) { grid-template-areas: "icon main act"; }
}
/* Inside a card (the _List shell, any .oc-card): rows are flush, separated by dividers only — no bordered row
   cards inside a bordered card. */
.oc-card .oc-list { gap: 0; }
.oc-card .oc-list-item { border: 0; border-radius: 0; box-shadow: none; border-bottom: 1px solid var(--line-2); padding: .625rem 1rem; }
.oc-card .oc-list > :last-child .oc-list-item, .oc-card .oc-list > .oc-list-item:last-child { border-bottom: 0; }
.oc-card .oc-list-item:focus-within { box-shadow: var(--ring-inset); }
@media (hover: hover) { .oc-card .oc-list-item:hover { box-shadow: none; background: var(--surface-muted); } }
/* ---------- 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; }
    /* Narrow calendar: TWO rows max. Row 1 = card title | view switcher (labels, no icons); row 2 = range title |
       prev/Today/next. Without a card title: row 1 = range | nav, row 2 = view switcher. */
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: .5rem .5rem; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar-main { display: contents; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar-main > .oc-card-title { grid-area: 1 / 1; min-width: 0; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-viewswitch { grid-area: 1 / 2; justify-self: end; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-title { grid-area: 2 / 1; min-width: 0; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-nav { grid-area: 2 / 2; justify-self: end; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar:not(:has(.oc-card-title)) .oc-cal-title { grid-area: 1 / 1; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar:not(:has(.oc-card-title)) .oc-cal-nav { grid-area: 1 / 2; }
    .oc-calendar[data-oc-cal-compact] .oc-cal-toolbar:not(:has(.oc-card-title)) .oc-cal-viewswitch { grid-area: 2 / 1 / 3 / 3; justify-self: start; }

    /* ---------- 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: .6875rem; font-weight: 600; line-height: .5rem; color: var(--ink-500); }
    /* Today: a soft brand wash + the filled day number — no inset box (it sat 1px off the shared grid lines). */
    .oc-cal-cell[aria-current="date"] { background: color-mix(in srgb, var(--primary) 6%, transparent); }
    @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: .875rem; }

    /* ---------- 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 { top: 0; right: 0; z-index: 1; } /* 44px target tucked into the corner */
        .oc-kanban-card-move .oc-kanban-move-btn { background: transparent; }
    }
    @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; }
/* Phone-sheet header for docked pickers (_Combobox / _DatePicker / _DateRangePicker): the same handle + title +
   close as _BottomSheet. Hidden while the popup is an anchored desktop panel. */
.oc-picker-sheet-head { display: none; }
/* Fixed height (grip 1.175rem + bar 2.75rem) so the search row below can stick right under it. */
.is-sheet { --oc-picker-head-h: 3.925rem; }
.is-sheet > .oc-picker-sheet-head { display: block; position: sticky; top: 0; z-index: 2; height: var(--oc-picker-head-h); background: var(--popover); }
.is-sheet.oc-combobox-menu > .oc-picker-sheet-head { margin: -.25rem -.25rem .25rem; }
.is-sheet[data-oc-dp-panel] > .oc-picker-sheet-head, .is-sheet[data-oc-dr-panel] > .oc-picker-sheet-head { margin: -.75rem -1rem .5rem; padding-inline: .25rem; }
.oc-picker-sheet-grip { display: block; width: 2.25rem; height: .3rem; margin: .625rem auto .25rem; border-radius: 999px; background: var(--line-strong); }
.oc-picker-sheet-bar { display: flex; align-items: center; gap: .5rem; height: 2.75rem; padding: 0 .25rem 0 .75rem; }
.is-sheet .oc-combobox-sheet-head { top: calc(var(--oc-picker-head-h) - .25rem); }
.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: var(--oc-picker-head-h, 0px); 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: 2rem; } /* = the hex field beside it (32px mouse / 44px touch) */
/* One even row: tracks grow from 1.5rem up to the swatch size and shrink together when narrow (no orphan). */
.oc-color-swatches { --oc-swatch: 1.75rem; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(1.5rem, var(--oc-swatch)); gap: .375rem; justify-content: start; align-items: center; min-width: 0; padding: .25rem; margin: -.25rem; }
.oc-color-swatches:has(> :nth-child(9)) { grid-auto-flow: row; grid-template-columns: repeat(auto-fill, minmax(1.75rem, 1fr)); }
.oc-color-swatches > .oc-color-swatch { width: 100%; height: auto; aspect-ratio: 1; }
@media (pointer: coarse) {
    .oc-color-swatch { width: 2.75rem; height: 2.75rem; }
    .oc-color-swatches { --oc-swatch: 2.75rem; }
    .oc-color-swatches:has(> :nth-child(9)) { grid-template-columns: repeat(auto-fill, minmax(2.25rem, 1fr)); }
    .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. */
/* Inside a .field-group (1px border each side): 30px trigger → 32px field on mouse; 42px → 44px on touch. */
.oc-datefield-trigger { min-height: 1.875rem; 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.625rem; }
    .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: .875rem; }
.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) ---------- */
/* Stars never wrap: with 6+ stars (Max=10) the field becomes a container and each star shrinks to fit ONE row
   (leaving ~6.75rem for the "7 / 10" readout + the 44px clear button), never below 1.5rem (24px, WCAG 2.5.8). */
.oc-rating { flex-wrap: nowrap; max-width: 100%; --oc-rating-n: 5; }
.oc-rating:has(> :nth-child(6)) { --oc-rating-n: 6; }
.oc-rating:has(> :nth-child(7)) { --oc-rating-n: 7; }
.oc-rating:has(> :nth-child(8)) { --oc-rating-n: 8; }
.oc-rating:has(> :nth-child(9)) { --oc-rating-n: 9; }
.oc-rating:has(> :nth-child(10)) { --oc-rating-n: 10; }
[data-oc-rating]:has(.oc-rating > :nth-child(6)) { container-type: inline-size; }
.oc-rating-star { --oc-rating-base: 2.25rem; --oc-star: var(--oc-rating-base); flex-shrink: 0; width: var(--oc-star); height: var(--oc-star); font-size: calc(var(--oc-star) * .62); }
[data-oc-rating]:has(.oc-rating > :nth-child(6)) .oc-rating-star { --oc-star: min(var(--oc-rating-base), max(1.5rem, calc((100cqi - var(--oc-rating-reserve, 6.75rem)) / var(--oc-rating-n)))); }
/* Phone-narrow field with many stars: the decorative "7 / 10" readout (aria-hidden; the value is in
   aria-valuetext) yields its room so the stars stay ≥24px on one row next to the clear button. */
@container (max-width: 26rem) {
    [data-oc-rating]:has(.oc-rating > :nth-child(6)) [data-oc-rating-readout] { display: none; }
    [data-oc-rating]:has(.oc-rating > :nth-child(6)) .oc-rating-star { --oc-rating-reserve: 3.5rem; }
}
.oc-rating-star--sm { --oc-rating-base: 1.5rem; }
.oc-rating-star--lg { --oc-rating-base: 2.75rem; }
@media (pointer: coarse) {
    .oc-rating[role="slider"] .oc-rating-star { --oc-rating-base: 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; min-height: 2rem; align-items: stretch; } /* = field height */
@media (pointer: coarse) {
    .oc-segmented-scroll > .oc-view-toggle { min-height: 2.75rem; }
    .oc-segmented-scroll > .oc-view-toggle > .oc-view-toggle-button { min-height: 0; }
}
.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; }
/* Development-only partial misuse warning (@Html.DevGuard) — loud on purpose; never rendered in Production. */
.oc-dev-guard { display: block; margin: .25rem 0; padding: .375rem .625rem; border: 2px dashed #dc2626; border-radius: .375rem; background: #fef2f2; color: #991b1b; font: 600 .75rem/1.4 var(--font-mono, ui-monospace, monospace); text-align: left; white-space: normal; }
/* The zone shows where keyboard focus is (browse button or a focused queue control inside it). */
.oc-dropzone:focus-within { border-color: var(--brand-500); box-shadow: var(--ring); }
@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; font-size: .875rem; }
}

/* ---------- 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:is(.oc-has-tabbar, :has(.oc-tabbar)) .oc-fab.oc-fab-auto { display: inline-flex; }
        html:is(.oc-has-tabbar, :has(.oc-tabbar)) .btn.oc-primary-auto { display: none; }
    }
    /* First run: a first-use empty state that carries its own create CTA owns the ONE "New …" action — the
       _PageHeader primary button and its FAB step aside (no two identical CTAs on an empty page). */
    html:has(.oc-empty-state[data-oc-empty-kind="first-use"] :is(a, button).btn) :is(.btn.oc-page-primary, .oc-fab.oc-page-primary-fab) { display: none !important; }

    /* ---------- 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); }
    /* _MarkdownEditor writes prose, not code: its source pane follows the surface tokens (light in light mode,
       the card surface in dark) inside the bordered shell; only the monospace face is kept. */
    .oc-markdown-shell .oc-code-editor.oc-markdown-source { background: var(--surface); color: var(--ink-900); border-radius: 0; caret-color: var(--primary); }
    .oc-markdown-shell .oc-code-editor.oc-markdown-source::placeholder { color: var(--ink-500); opacity: 1; }

    /* ============================================================
       _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); }
    /* Connectors give way first (1rem → .75rem) before the strip overflows, so a near-fit (e.g. 1024px) doesn't
       turn into a masked/faded scroller over a couple of pixels; the step links themselves never shrink. */
    .oc-wizard-step { position: relative; display: flex; align-items: center; flex: 0 1 auto; }
    .oc-wizard-step > .oc-wizard-step-link { flex: 0 0 auto; }
    .oc-wizard-step + .oc-wizard-step::before { content: ""; flex: 0 1 1rem; min-width: .75rem; 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-sans); font-variant-numeric: tabular-nums;
        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. */
    /* 16px/600 — one step BELOW the page H1 (18px), same tier as overlay titles. */
    .oc-wizard-panel-title { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.375; 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; }
        /* The sticky phone header already names the step — the panel h2 stays (focus target, AT heading) but is
           visually hidden so the step name is shown once. */
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-panel-title { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
        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; }
        /* ONE top bar in focus mode: the app bar loses its back / actions / avatar and scrolls away with the page;
           the wizard bar (× Cancel · step · Save draft) becomes THE sticky top bar, safe-area aware. The page
           header's description is hidden too (the step title already says where you are). */
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) .oc-layout-header { position: relative; }
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) .oc-layout-header :is(.oc-appbar-lead, .oc-appbar-trail) { visibility: hidden; }
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) .oc-page-header :is(.oc-page-header-desc, .oc-breadcrumbs) { display: none; }
        html:has(.oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *)) { scroll-padding-top: calc(var(--oc-safe-top) + 5.5rem); }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) { --oc-wizard-top: 0px; }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-mhead { padding-top: calc(var(--oc-safe-top) + .375rem); }
        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-safe-top) + 5.5rem); }
        html[data-oc-theme] .oc-wizard[data-oc-wizard-focus="true"]:not(:is(.oc-drawer, .oc-modal, .oc-sheet) *) .oc-wizard-mhead :is(.btn, .oc-icon-btn) { min-height: 2.75rem; min-width: 2.75rem; }
    }
    @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); }
    /* Pending = amber, the same as StatusTone.For("pending") / .badge-warning everywhere else. */
    .oc-review [data-tone="pending"] { --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-row.is-saving .oc-review-chip { animation: oc-review-pulse 1s ease-in-out infinite; }
    @media (prefers-reduced-motion: reduce) { .oc-review-row.is-saving .oc-review-chip { animation: none; opacity: .5; } }

    /* 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: .875rem; font-weight: 600; line-height: 1.3; color: var(--ink-900); } /* = .oc-card-title */
    .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: 1rem; 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); }
    /* Pressed fills that carry white text need ≥4.5:1 — the stock success/warning/pending solids don't. */
    .oc-review-decision[data-tone="success"][aria-pressed="true"] { --oc-rv-solid: #047857; } /* 5.5:1 */
    .oc-review-decision[data-tone="warning"][aria-pressed="true"] { --oc-rv-solid: #b45309; } /* 5.0:1 */
    .oc-review-decision[data-tone="pending"][aria-pressed="true"] { --oc-rv-solid: #475569; --oc-rv-on: #ffffff; } /* 7.6:1 */
    .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); }

    /* ============================================================
       LOADING — the unified loading system (theme/COMPONENTS.md → "Loading states"; behaviour:
       partials/js/octacer-loading.js). ONE shimmer (.oc-skeleton, top of this layer) · ONE skeleton partial
       (primitives/_Skeleton) · ONE busy contract (aria-busy, top of this layer) · ONE region dim · ONE spinner ·
       ONE page progress bar · ONE content-enter animation. Timing: delay 150 · min 400 · slow 5000 · stuck 15000 ·
       timeout 30000 ms.
       ============================================================ */

    /* ---- Skeleton shapes (primitives/_Skeleton). role=status root; the sr-only "Loading {noun}…" is a sibling of
       .oc-skel-body (never a grid/flex child of the bones), and the bones are aria-hidden. ---- */
    .oc-skel { position: relative; min-width: 0; }
    .oc-skel-body { display: flex; flex-direction: column; min-width: 0; pointer-events: none; }   /* no hover states on bones */
    .oc-skel-line { display: flex; align-items: center; min-width: 0; height: 1.25rem; }
    .oc-skel-line > .oc-skeleton { display: block; height: .75rem; width: 92%; }
    .oc-skel-text { display: flex; flex-direction: column; min-width: 0; }
    .oc-skel-text > .oc-skel-line:nth-child(4n+2) > .oc-skeleton { width: 76%; }
    .oc-skel-text > .oc-skel-line:nth-child(4n+3) > .oc-skeleton { width: 84%; }
    .oc-skel-text > .oc-skel-line:nth-child(4n+4) > .oc-skeleton { width: 60%; }
    .oc-skel-avatar { display: block; flex: 0 0 auto; width: 2rem; height: 2rem; border-radius: 999px; }
    .oc-skel-pill { display: inline-block; flex: 0 0 auto; height: 1.25rem; width: 3.5rem; border-radius: 999px; vertical-align: middle; }
    .oc-skel-btn { display: inline-block; flex: 0 0 auto; height: 2rem; width: 6rem; border-radius: var(--radius-sm); }
    .oc-skel-control { display: block; height: 2rem; width: 100%; border-radius: var(--radius-sm); }
    .oc-skel-inline { display: inline-block; vertical-align: middle; height: .75rem; }   /* a bone inside a REAL text line box */
    .oc-skel-cards { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr)); }
    /* list: the REAL .oc-list-item row (3.875rem): avatar 2.5rem · 2 lines · badge · kebab */
    .oc-skel--list .oc-skel-avatar { width: 2.5rem; height: 2.5rem; }
    .oc-skel--list .oc-list-item-meta { margin-top: .2rem; }
    .oc-skel-kebab { display: inline-flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; flex: 0 0 auto; }
    .oc-skel-kebab > .oc-skeleton { width: .25rem; height: 1rem; border-radius: 999px; }
    /* stat: label .75rem · value 1.25rem · delta pill · 2rem icon — inside the REAL .oc-stat grid (identical height) */
    .oc-stat .oc-skel-icon { display: block; width: 2rem; height: 2rem; border-radius: var(--radius); background-color: var(--oc-skel-base); color: transparent; }
    .oc-stat .oc-stat-delta.oc-skeleton { background-color: var(--oc-skel-base); color: transparent; }
    /* chart: header + 6 bars on a baseline */
    .oc-skel-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .75rem 1rem; border-bottom: 1px solid var(--line); }
    .oc-skel-chart-plot { display: flex; align-items: flex-end; justify-content: space-around; gap: 6%; height: 15rem; padding: .75rem 1rem 0 2.25rem; position: relative; }
    .oc-skel-chart-plot::after { content: ""; position: absolute; left: 1.5rem; right: 1rem; bottom: 0; height: 1px; background: var(--line); }
    .oc-skel-chart-plot > .oc-skeleton { flex: 1 1 0; max-width: 3rem; border-radius: .25rem .25rem 0 0; }
    .oc-skel-chart-plot > .oc-skeleton:nth-child(1) { height: 45%; } .oc-skel-chart-plot > .oc-skeleton:nth-child(2) { height: 70%; }
    .oc-skel-chart-plot > .oc-skeleton:nth-child(3) { height: 55%; } .oc-skel-chart-plot > .oc-skeleton:nth-child(4) { height: 85%; }
    .oc-skel-chart-plot > .oc-skeleton:nth-child(5) { height: 62%; } .oc-skel-chart-plot > .oc-skeleton:nth-child(6) { height: 78%; }
    /* form-field: label + a 2rem control (2.75rem on touch, like the real control) */
    .oc-skel-field { display: flex; flex-direction: column; gap: .3125rem; min-width: 0; }
    .oc-skel-field > .oc-skel-line { height: 1.25rem; }
    .oc-skel-field > .oc-skel-line > .oc-skeleton { width: 7rem; max-width: 60%; }
    .oc-skel-form { display: flex; flex-direction: column; gap: 1rem; }
    .oc-skel-actions { display: flex; justify-content: flex-end; gap: .625rem; padding-top: .25rem; }
    @media (pointer: coarse) { .oc-skel-control { height: 2.75rem; } .oc-skel-btn { height: 2.75rem; } }
    /* description-list: 2.25rem rows; two columns from 40rem (container) */
    .oc-skel-dl { container: oc-skel-dl / inline-size; }
    .oc-skel-dl-grid { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: 2rem; }
    .oc-skel-dl-row { display: flex; align-items: center; gap: 1rem; height: 2.25rem; border-bottom: 1px solid var(--line-2); min-width: 0; }
    .oc-skel-dl-row > .oc-skeleton:first-child { width: 28%; max-width: 8rem; height: .625rem; flex: 0 0 auto; }
    .oc-skel-dl-row > .oc-skeleton:last-child { width: 45%; height: .75rem; }
    .oc-skel-dl-row:nth-child(3n+2) > .oc-skeleton:last-child { width: 60%; }
    .oc-skel-dl-row:nth-child(3n+3) > .oc-skeleton:last-child { width: 35%; }
    @container oc-skel-dl (width >= 40rem) { .oc-skel-dl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
    /* timeline: dot + 2 lines */
    .oc-skel-tl { display: flex; flex-direction: column; gap: 1.25rem; }
    .oc-skel-tl-item { display: flex; gap: .75rem; min-width: 0; }
    .oc-skel-tl-item > .oc-skeleton:first-child { width: 1.5rem; height: 1.5rem; border-radius: 999px; flex: 0 0 auto; }
    .oc-skel-tl-item > .oc-skel-text { flex: 1 1 auto; padding-top: .125rem; }
    /* calendar: the REAL month grid (weekday row + 6 week rows of .oc-cal-cell) */
    .oc-skel-cal { container: oc-skel-cal / inline-size; }
    .oc-skel-cal-agenda { display: none; flex-direction: column; }
    @container oc-skel-cal (width < 40rem) { .oc-skel-cal > .oc-cal-month-grid { display: none; } .oc-skel-cal-agenda { display: flex; } }
    .oc-skel-cal .oc-cal-cell { cursor: default; }
    @media (hover: hover) { .oc-skel-cal .oc-cal-cell:hover { background: transparent; } }
    .oc-skel-cal .oc-cal-cell > .oc-skeleton:first-child { width: 1.25rem; height: .75rem; margin: .375rem .25rem .25rem; }
    .oc-skel-cal .oc-cal-cell > .oc-skeleton + .oc-skeleton { height: 1.125rem; width: 100%; border-radius: var(--radius-sm); }
    .oc-skel-cal .oc-cal-weekday > .oc-skeleton { width: 1.75rem; height: .625rem; }
    /* kanban: the REAL lane grid (lane ≈ 17.25rem) */
    .oc-skel-kanban .oc-kanban-card { cursor: default; flex-direction: column; gap: .5rem; }
    .oc-skel-kanban .oc-kanban-card-foot { display: flex; align-items: center; justify-content: space-between; }
    /* table extras (_TableSkeleton) — the MEASURED metrics of the loaded _DataTable/_Table (compact density):
       head row 37px · body rows 37px with .625rem bones · pager footer 65px; phone cards: title 25px + 26px
       label/value lines, the "Select all" bar, and the "N loaded · Load more" footer (133px). */
    [data-oc-table-skeleton] { container: oc-table / inline-size; }
    [data-oc-table-skeleton] .oc-table thead th .oc-skeleton { height: .625rem; }
    @container oc-table (width >= 40rem) {
        [data-oc-table-skeleton] .oc-table thead th { height: 2.3125rem; padding-block: 0; }
        [data-oc-table-skeleton] .oc-table tbody td { height: 2.3125rem; padding-block: 0; }
    }
    .oc-skel-table-foot { display: flex; align-items: center; justify-content: space-between; gap: 1rem; min-height: 4.0625rem; padding: 0 1.25rem; border-top: 1px solid var(--line); }
    .oc-skel-table-foot .oc-skel-pager { display: flex; gap: .375rem; }
    .oc-skel-table-foot .oc-skel-pager > .oc-skeleton { width: 2rem; height: 2rem; border-radius: var(--radius-sm); }
    .oc-skel-table-foot .oc-skel-more { display: none; }
    [data-oc-table-skeleton] .oc-table-cardbar.oc-skel-cardbar { display: none; }
    @container oc-table (width < 40rem) {
        .oc-skel-table-foot { flex-direction: column; justify-content: center; gap: .5rem; padding: 2rem 1rem; }
        .oc-skel-table-foot > .oc-skeleton:first-child { margin-block: .1875rem; }
        .oc-skel-table-foot .oc-skel-pager { display: none; }
        .oc-skel-table-foot .oc-skel-more { display: block; width: 100%; height: 2rem; border-radius: var(--radius-sm); }
        [data-oc-table-skeleton] .oc-table-cardbar.oc-skel-cardbar { display: flex; }
        [data-oc-table-skeleton] .oc-table-cards tbody td[data-oc-cell="title"] { display: flex; align-items: center; min-height: 1.5625rem; }
        [data-oc-table-skeleton] .oc-table-cards tbody td:not([data-oc-cell]) { min-height: 1.625rem; }
    }
    @media (pointer: coarse) { .oc-skel-table-foot .oc-skel-more { height: 2.75rem; } }

    /* ---- C4 · Region busy: [data-oc-busy-region] (and every [data-oc-table]) — octacer-loading.js resolves the
       request's target, dims the STALE content to .6 (it stays readable — never blanked), sets aria-busy, and shows
       an optional status pill ([data-oc-busy-pill]); a skeleton is swapped in only on FIRST load. ---- */
    [data-oc-busy-state] { position: relative; }
    [data-oc-busy-state="busy"] > :not(.oc-busy-pill, .oc-skel, [data-oc-table-skeleton], input[type="hidden"]) { opacity: .6; pointer-events: none; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-busy-pill {
        position: absolute; z-index: 3; top: .75rem; left: 50%; translate: -50% 0;
        display: inline-flex; align-items: center; gap: .5rem; max-width: calc(100% - 2rem);
        padding: .25rem .75rem .25rem .625rem; font-size: .75rem; font-weight: 500; line-height: 1.25rem; white-space: nowrap;
        color: var(--ink-700); background: var(--popover); border: 1px solid var(--line); border-radius: 999px; box-shadow: var(--shadow-md);
    }
    .oc-busy-pill .btn { min-height: 1.5rem; padding: 0 .5rem; margin-inline-end: -.375rem; }
    /* After a pagination/filter swap the region's caption/status receives focus (tabindex=-1): no ring flash. */
    [data-oc-region-focus]:focus { outline: none; }
    /* A confirm modal whose action is running: Cancel / × wait for it (CancelWhileBusy="disable", the default). */
    [data-oc-modal]:not([data-oc-cancel-while-busy="abort"]):has([data-oc-busy]) [data-oc-modal-close] { opacity: .6; pointer-events: none; }

    /* ---- C5 · Spinner reduced-motion: a calm PULSE of the full ring — never a frozen arc. (Busy buttons too.) ---- */
    @media (prefers-reduced-motion: reduce) {
        .oc-spinner { border-color: currentColor; animation: oc-pulse 1.4s ease-in-out infinite !important; }
        :is(.btn, .oc-icon-btn, .oc-fab):is([aria-busy="true"], .is-loading)::after { border-right-color: currentColor; animation: oc-pulse 1.4s ease-in-out infinite !important; }
        .oc-skeleton { animation: none !important; background-image: none; }
    }

    /* ---- C6 · Page progress bar: page-level navigation ONLY (boosted / hx-push-url outside a region / unload).
       transform: scaleX trickle (no width/layout work); never completes while a request is in flight — it
       settles into a slow, breathing state instead. ---- */
    #oc-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: var(--z-progress); pointer-events: none;
        background: linear-gradient(90deg, var(--brand-500), var(--brand-700)); box-shadow: 0 0 10px rgba(79,70,229,.45);
        transform-origin: 0 50%; transform: scaleX(0); opacity: 0; transition: opacity .2s ease; }
    #oc-progress.is-loading { opacity: 1; animation: oc-progress-trickle 8s cubic-bezier(.08, .7, .2, 1) forwards; }
    #oc-progress.is-slow { opacity: 1; transform: scaleX(.92); animation: oc-pulse 1.6s ease-in-out infinite; }
    #oc-progress.is-done { opacity: 0; transform: scaleX(1); animation: none; transition: transform .2s ease-out, opacity .25s ease .15s; }
    @keyframes oc-progress-trickle { 0% { transform: scaleX(0); } 10% { transform: scaleX(.25); } 40% { transform: scaleX(.6); } 100% { transform: scaleX(.9); } }
    @media (prefers-reduced-motion: reduce) { #oc-progress.is-slow { animation: none !important; } }

    /* ---- C7 · Content enter: swapped-in content fades + rises 4px (160ms); reduced motion = a 120ms fade only.
       Applied on htmx:load and removed on animationend; appended load-more rows stagger 20ms (max 8 steps). ---- */
    @keyframes oc-enter { from { opacity: 0; translate: 0 4px; } }
    @keyframes oc-enter-fade { from { opacity: 0; } }
    .oc-enter { animation: oc-enter 160ms var(--ease-out) both; animation-delay: var(--oc-enter-delay, 0ms); }
    .oc-enter-fade { animation: oc-enter-fade 160ms var(--ease-out) both; animation-delay: var(--oc-enter-delay, 0ms); }
    @media (prefers-reduced-motion: reduce) {
        .oc-enter, .oc-enter-fade { animation: oc-enter-fade 120ms ease-out both !important; animation-delay: 0ms !important; }
    }

    /* ---- C8 · Slow/stuck feedback: a polite live region (octacer-loading.js) + the SlowLabel on busy buttons. ---- */
    .oc-loading-live { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }

    /* Fixed column widths (DT.Columns width hints) — page swaps never make the columns jump. */
    .oc-table.oc-table-fixed { table-layout: fixed; }

    /* Optimistic toggles (_SettingsToggleGroup, data-oc-optimistic): Saving… / Saved status next to the switch. */
    .oc-optimistic-status { min-width: 3.75rem; font-size: .75rem; line-height: 1rem; text-align: end; color: var(--ink-500); white-space: nowrap; }
    .oc-optimistic-status[data-state="saved"] { color: var(--success-subtle-foreground); }
    .oc-optimistic-status:empty { min-width: 0; }

    /* ============================================================
       Agent B6 — collaboration & workspace components
       (_ActivityThread, _NotificationBell/_NotificationList, _ShortcutHelp, _SetupChecklist, _AuditLog,
        _DashboardGrid, _Lightbox file preview, _CopyButton link mode, truncation hints)
       ============================================================ */

    /* ---------- Keyboard key chip (shortcut help, composer hints) ---------- */
    .oc-kbd {
        display: inline-flex; align-items: center; justify-content: center; min-width: 1.25rem; height: 1.25rem; padding: 0 .3125rem;
        font-family: var(--font-sans); 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: .3125rem; white-space: nowrap;
    }

    /* ---------- _ActivityThread ---------- */
    .oc-thread { display: flex; flex-direction: column; gap: .75rem; min-width: 0; }
    .oc-thread-head { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; }
    .oc-thread-title { margin: 0; font-size: .9375rem; font-weight: 600; color: var(--ink-900); }
    .oc-thread-count { font-size: .75rem; color: var(--ink-500); font-variant-numeric: tabular-nums; }
    .oc-thread-empty { display: flex; flex-direction: column; align-items: center; gap: .375rem; padding: 1.5rem .5rem; text-align: center; border: 1px dashed var(--line); border-radius: var(--radius-lg); }
    .oc-thread-empty.hidden { display: none; }
    .oc-thread-list { position: relative; display: flex; flex-direction: column; gap: .875rem; margin: 0; padding: 0; list-style: none; }
    .oc-thread-list.hidden { display: none; }
    /* The rail: one line behind the avatars / dots. */
    .oc-thread-list::before { content: ""; position: absolute; top: .5rem; bottom: .5rem; left: .9375rem; width: 1px; background: var(--line); }
    .oc-thread-item { position: relative; display: flex; gap: .75rem; min-width: 0; }
    .oc-thread-avatar {
        position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 2rem; height: 2rem;
        overflow: hidden; border-radius: 999px; background: var(--surface-muted); color: var(--ink-700); font-size: .6875rem; font-weight: 600;
        box-shadow: 0 0 0 3px var(--bg);
    }
    .oc-thread-avatar img { width: 100%; height: 100%; object-fit: cover; }
    .oc-thread-avatar-sm { box-shadow: none; }
    .oc-thread-avatar-xs { width: 1.5rem; height: 1.5rem; font-size: .625rem; box-shadow: none; }
    .oc-card .oc-thread-avatar { box-shadow: 0 0 0 3px var(--surface); }
    .oc-thread-bubble { flex: 1 1 auto; min-width: 0; padding: .5rem .75rem .625rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-lg); }
    .oc-thread-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .5rem; margin-bottom: .125rem; }
    .oc-thread-actor { font-size: .8125rem; font-weight: 600; color: var(--ink-900); overflow-wrap: anywhere; }
    .oc-thread-you { padding: 0 .375rem; font-size: .6875rem; color: var(--primary-ink); background: var(--primary-tint); }
    .oc-thread-time, .oc-thread-meta .oc-time { font-size: .75rem; color: var(--ink-500); font-variant-numeric: tabular-nums; }
    .oc-thread-body { font-size: .875rem; line-height: 1.5; color: var(--ink-700); overflow-wrap: anywhere; }
    .oc-thread-body > * + * { margin-top: .5rem; }
    .oc-thread-body a { color: var(--primary-ink); text-decoration: underline; text-underline-offset: 2px; }
    .oc-thread-body .mention, .oc-thread-body [data-mention] { color: var(--primary-ink); background: var(--primary-tint); border-radius: .25rem; padding: 0 .125rem; font-weight: 500; }
    .oc-thread-text { white-space: pre-wrap; }
    .oc-thread-files { display: flex; flex-wrap: wrap; gap: .375rem; margin: .5rem 0 0; padding: 0; list-style: none; }
    .oc-thread-file { display: inline-flex; align-items: center; gap: .375rem; max-width: 16rem; min-height: 1.75rem; padding: .125rem .5rem; font-size: .75rem; color: var(--ink-700); background: var(--surface-muted); border: 1px solid var(--line); border-radius: .375rem; }
    @media (hover: hover) { .oc-thread-file:hover { border-color: var(--line-strong); color: var(--ink-900); } }
    .oc-thread-comment.is-pending .oc-thread-bubble { border-style: dashed; }
    .oc-thread-comment.is-pending .oc-thread-body { color: var(--ink-500); }
    .oc-thread-comment.is-failed .oc-thread-bubble { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); background: color-mix(in srgb, var(--danger-subtle) 45%, var(--surface)); }
    .oc-thread-status { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; margin-top: .375rem; font-size: .75rem; color: var(--ink-500); }
    .oc-thread-status-sending, .oc-thread-status-error { display: inline-flex; align-items: center; gap: .375rem; }
    .oc-thread-status-error { color: var(--danger-ink); font-weight: 500; }
    .oc-thread-status-actions { display: inline-flex; gap: .125rem; margin-inline-start: auto; }
    .oc-thread-status-actions .btn { min-height: 1.75rem; padding-inline: .5rem; }
    /* System events: a small _Timeline dot on the rail + one muted sentence. */
    .oc-thread-event { align-items: flex-start; }
    .oc-thread-dot { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 1.25rem; height: 1.25rem; margin: .125rem .375rem 0; border-radius: 999px; }
    .oc-thread-event-text { margin: 0; padding-top: .125rem; font-size: .8125rem; line-height: 1.25rem; color: var(--ink-500); overflow-wrap: anywhere; }
    .oc-thread-event-text .oc-time { color: var(--ink-500); }
    .oc-thread-composer { display: flex; gap: .75rem; align-items: flex-start; padding-top: .25rem; }
    .oc-thread-compose-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .375rem; }
    .oc-thread-input-wrap { position: relative; }
    .oc-thread-input { width: 100%; min-height: 4.5rem; resize: vertical; }
    .oc-thread-compose-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem; }
    .oc-thread-compose-foot .btn { margin-inline-start: auto; }
    @media (hover: none) and (pointer: coarse) { .oc-thread-compose-foot .field-hint { display: none; } }
    .oc-thread-readonly { display: flex; align-items: center; gap: .5rem; margin: 0; padding: .625rem .75rem; font-size: .8125rem; color: var(--ink-500); background: var(--surface-muted); border-radius: var(--radius); }
    .oc-mention-pop { position: absolute; z-index: var(--z-popover); left: 0; top: calc(100% + .25rem); width: min(20rem, 100%); padding: .25rem; background: var(--popover); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); }
    .oc-mention-pop[hidden] { display: none; }
    .oc-mention-list { margin: 0; padding: 0; list-style: none; max-height: 15rem; overflow-y: auto; overscroll-behavior: contain; }
    .oc-mention-list:empty { display: none; }
    .oc-mention-option { display: flex; align-items: center; gap: .5rem; min-height: 2.25rem; padding: .25rem .5rem; font-size: .8125rem; border-radius: .375rem; cursor: pointer; }
    .oc-mention-option.is-active { background: var(--surface-muted); box-shadow: inset 2px 0 0 var(--primary); }
    @media (hover: hover) { .oc-mention-option:hover { background: var(--surface-muted); } }
    .oc-mention-status { margin: 0; padding: .375rem .5rem; font-size: .75rem; color: var(--ink-500); }
    .oc-mention-status[hidden], .oc-mention-status:empty { display: none; }
    @media (max-width: 639px) {
        .oc-thread-composer > .oc-thread-avatar { display: none; }
        .oc-mention-pop { width: 100%; }
    }
    @media (pointer: coarse) {
        .oc-mention-option { min-height: 2.75rem; }
        .oc-thread-status-actions .btn { min-height: 2.75rem; }
        .oc-thread-file { min-height: 2.75rem; }
    }

    /* ---------- _NotificationBell ---------- */
    .oc-bell-wrap { display: inline-flex; position: relative; }
    .oc-bell { position: relative; }
    .oc-bell-badge {
        position: absolute; top: 0; left: calc(50% + .125rem); min-width: 1rem; height: 1rem; padding: 0 .25rem; display: inline-flex; align-items: center; justify-content: center;
        font-size: .625rem; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; color: #fff; background: var(--danger);
        border-radius: 999px; box-shadow: 0 0 0 2px var(--surface); pointer-events: none;
    }
    .oc-bell-badge[hidden] { display: none; }
    .oc-bell > i { font-size: 1.125rem; }
    @media (pointer: coarse) { .oc-bell-badge { top: .3125rem; } }
    .oc-notif-panel { display: flex; flex-direction: column; margin: -.75rem; min-height: 0; }
    .oc-notif-panel-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; min-height: 2.75rem; padding: .375rem .5rem .375rem .875rem; border-bottom: 1px solid var(--line); }
    .oc-notif-panel-title { margin: 0; font-size: .875rem; font-weight: 600; color: var(--ink-900); }
    .oc-notif-panel-body { max-height: min(26rem, 60vh); overflow-y: auto; overscroll-behavior: contain; transition: opacity var(--duration-fast) var(--ease-out); }
    .is-sheet .oc-notif-panel-body { max-height: none; }
    .oc-notif-panel-body[aria-busy="true"] { opacity: .6; }
    .oc-notif-panel-foot { padding: .375rem; border-top: 1px solid var(--line); }
    .oc-notif-skeleton { display: flex; flex-direction: column; padding: .25rem 0; }
    .oc-notif-skel-row { display: flex; align-items: center; gap: .75rem; padding: .625rem .875rem; }

    /* ---------- _NotificationList ---------- */
    .oc-notifs { display: flex; flex-direction: column; min-width: 0; }
    .oc-notifs-head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; padding-bottom: .75rem; }
    .oc-notifs-head .badge[hidden] { display: none; }
    .oc-notifs-title { margin: 0; font-size: .9375rem; font-weight: 600; color: var(--ink-900); }
    .oc-notifs-empty { display: flex; flex-direction: column; align-items: center; gap: .375rem; padding: 2rem 1rem; text-align: center; }
    .oc-notifs-empty.hidden, .oc-notifs-list.hidden { display: none; }
    .oc-notifs-list { margin: 0; padding: 0; list-style: none; }
    .oc-notifs:not(.is-compact) .oc-notifs-list { border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; background: var(--surface); }
    .oc-notif { position: relative; display: flex; align-items: flex-start; gap: .75rem; padding: .75rem .875rem; border-bottom: 1px solid var(--line); }
    .oc-notifs-list > .oc-notif:last-child { border-bottom: 0; }
    .oc-notif.is-unread { background: color-mix(in srgb, var(--primary-tint) 55%, transparent); }
    .oc-notif-icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 2rem; height: 2rem; overflow: hidden; border-radius: 999px; background: var(--surface-muted); color: var(--ink-700); font-size: .6875rem; font-weight: 600; }
    .oc-notif-icon img { width: 100%; height: 100%; object-fit: cover; }
    .oc-notif-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: .125rem; }
    .oc-notif-title { margin: 0; font-size: .8125rem; line-height: 1.25rem; color: var(--ink-700); overflow-wrap: anywhere; }
    .oc-notif.is-unread .oc-notif-title { font-weight: 600; color: var(--ink-900); }
    /* The whole row is the link's hit area; the per-row buttons sit above it. */
    .oc-notif-link { color: inherit; text-decoration: none; }
    .oc-notif-link::after { content: ""; position: absolute; inset: 0; }
    .oc-notif-link:focus-visible { outline: none; }
    .oc-notif-link:focus-visible::after { outline: 2px solid var(--ring); outline-offset: -2px; border-radius: .25rem; }
    @media (hover: hover) { .oc-notif:has(.oc-notif-link):hover { background: var(--surface-muted); } }
    .oc-notif-body { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--ink-500); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
    .oc-notif-missing { display: inline-flex; align-items: center; gap: .25rem; margin: 0; font-size: .75rem; color: var(--warning-subtle-foreground); }
    .oc-notif-time { font-size: .75rem; color: var(--ink-500); font-variant-numeric: tabular-nums; }
    .oc-notif-dot { flex: 0 0 auto; width: .5rem; height: .5rem; margin-top: .375rem; border-radius: 999px; background: var(--primary); }
    .oc-notif-read-btn { position: relative; z-index: 1; width: 1.75rem; height: 1.75rem; margin: -.125rem -.375rem 0 -.25rem; }
    .oc-notifs-more { padding: .375rem; }
    @media (pointer: coarse) {
        .oc-notif { min-height: 3.5rem; }
        .oc-notif-read-btn { width: 2.75rem; height: 2.75rem; margin-block: -.5rem; }
    }

    /* ---------- _ShortcutHelp ---------- */
    [data-oc-shortcut-help] .oc-overlay-icon { color: var(--ink-700); background: var(--surface-muted); }
    .oc-shortcuts-body { display: grid; gap: 1rem 2rem; padding: 1rem 1.25rem; max-height: min(60vh, 32rem); overflow-y: auto; overscroll-behavior: contain; }
    @media (min-width: 640px) { .oc-shortcuts-body:has(> .oc-shortcuts-group + .oc-shortcuts-group) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
    .oc-shortcuts-group-title { margin: 0 0 .375rem; font-size: .6875rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-500); }
    .oc-shortcuts-list { margin: 0; display: flex; flex-direction: column; }
    .oc-shortcuts-row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; min-height: 2rem; padding: .25rem 0; border-bottom: 1px solid var(--line-2, var(--line)); }
    .oc-shortcuts-row:last-child { border-bottom: 0; }
    .oc-shortcuts-row dt { font-size: .8125rem; color: var(--ink-700); min-width: 0; }
    .oc-shortcuts-row dd { margin: 0; flex: 0 0 auto; }
    .oc-shortcuts-keys { display: inline-flex; align-items: center; gap: .1875rem; }
    .oc-shortcut-then { margin: 0 .125rem; font-size: .6875rem; color: var(--ink-500); }
    .oc-shortcuts-empty { margin: 0; padding: 1rem 0; text-align: center; font-size: .8125rem; color: var(--ink-500); }
    .oc-shortcuts-foot { margin: 0; padding: .625rem 1.25rem .875rem; font-size: .75rem; color: var(--ink-500); border-top: 1px solid var(--line); }

    /* ---------- _SetupChecklist ---------- */
    .oc-checklist { padding: 1rem 1rem .75rem; }
    .oc-checklist-head { display: flex; align-items: flex-start; gap: .75rem; }
    .oc-checklist-icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 2rem; height: 2rem; border-radius: var(--radius); color: var(--primary-ink); background: var(--primary-tint); }
    .oc-checklist-icon.is-complete { color: var(--success-subtle-foreground); background: var(--success-subtle); }
    .oc-checklist-title { margin: 0; font-size: .9375rem; font-weight: 600; color: var(--ink-900); }
    .oc-checklist-desc { margin: .125rem 0 0; font-size: .8125rem; color: var(--ink-500); }
    .oc-checklist-progress { display: flex; flex-wrap: wrap; align-items: center; gap: .375rem .75rem; margin-top: .5rem; }
    .oc-checklist-bar { -webkit-appearance: none; appearance: none; flex: 1 1 8rem; max-width: 16rem; height: .375rem; border: 0; border-radius: 999px; overflow: hidden; background: var(--surface-muted); color: var(--primary); }
    .oc-checklist-bar::-webkit-progress-bar { background: var(--surface-muted); border-radius: 999px; }
    .oc-checklist-bar::-webkit-progress-value { background: var(--primary); border-radius: 999px; transition: width var(--duration-fast) var(--ease-out); }
    .oc-checklist-bar::-moz-progress-bar { background: var(--primary); border-radius: 999px; }
    .oc-checklist.is-complete .oc-checklist-bar::-webkit-progress-value { background: var(--success); }
    .oc-checklist.is-complete .oc-checklist-bar::-moz-progress-bar { background: var(--success); }
    .oc-checklist-count { font-size: .75rem; font-weight: 500; color: var(--ink-500); }
    .oc-checklist-actions { display: flex; gap: .125rem; margin: -.25rem -.375rem 0 0; }
    .oc-checklist-chevron { display: inline-flex; transition: transform var(--duration-fast) var(--ease-out); }
    .oc-checklist-chevron.is-open { transform: rotate(180deg); }
    .oc-checklist-steps { margin: .75rem 0 0; padding: 0; list-style: none; border-top: 1px solid var(--line); }
    .oc-checklist-step { display: flex; align-items: center; gap: .75rem; padding: .625rem 0; border-bottom: 1px solid var(--line-2, var(--line)); }
    .oc-checklist-step:last-child { border-bottom: 0; padding-bottom: .25rem; }
    .oc-checklist-mark { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 1.5rem; height: 1.5rem; border-radius: 999px; font-size: .6875rem; font-weight: 600; color: var(--ink-500); border: 1.5px solid var(--line-strong); }
    .oc-checklist-step.is-next .oc-checklist-mark { color: var(--primary-ink); border-color: var(--primary); }
    .oc-checklist-step.is-done .oc-checklist-mark { color: var(--success-foreground, #fff); background: var(--success); border-color: var(--success); }
    .oc-checklist-step-title { margin: 0; font-size: .8125rem; font-weight: 500; color: var(--ink-900); overflow-wrap: anywhere; }
    .oc-checklist-step.is-done .oc-checklist-step-title { font-weight: 400; color: var(--ink-500); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--ink-500) 60%, transparent); }
    .oc-checklist-step-desc { margin: .125rem 0 0; font-size: .75rem; color: var(--ink-500); }
    @media (max-width: 479px) {
        .oc-checklist-step { flex-wrap: wrap; }
        .oc-checklist-step > div { flex-basis: calc(100% - 2.25rem); }
        .oc-checklist-step > .btn { margin-inline-start: 2.25rem; }
    }
    @media (prefers-reduced-motion: reduce) { .oc-checklist-chevron, .oc-checklist-bar::-webkit-progress-value { transition: none; } }

    /* ---------- _AuditLog ---------- */
    .oc-audit { display: flex; flex-direction: column; gap: .75rem; min-width: 0; container-type: inline-size; }
    .oc-audit-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem 1rem; }
    .oc-audit-title { margin: 0; font-size: .9375rem; font-weight: 600; color: var(--ink-900); }
    .oc-audit-filters { display: flex; flex-wrap: wrap; gap: .5rem; }
    .oc-audit-filter .field-select { min-width: 10rem; }
    .oc-audit-results { display: flex; flex-direction: column; gap: .5rem; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-audit-results[aria-busy="true"] { opacity: .6; pointer-events: none; }
    .oc-audit-count { margin: 0; font-size: .75rem; color: var(--ink-500); }
    .oc-audit-noresults { display: flex; flex-direction: column; align-items: center; gap: .5rem; padding: 2rem 1rem; text-align: center; }
    .oc-audit-noresults.hidden { display: none; }
    .oc-audit-error { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .5rem .75rem; font-size: .8125rem; color: var(--danger-subtle-foreground); background: var(--danger-subtle); border-radius: var(--radius); }
    .oc-audit-error p { margin: 0; }
    .oc-audit-list { position: relative; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 1rem; }
    .oc-audit-list::before { content: ""; position: absolute; top: .5rem; bottom: .5rem; left: .75rem; width: 1px; background: var(--line); }
    .oc-audit-entry { position: relative; display: flex; gap: .75rem; min-width: 0; }
    .oc-audit-dot { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 1.5rem; height: 1.5rem; border-radius: 999px; }
    .oc-audit-head { margin: .125rem 0 0; font-size: .8125rem; line-height: 1.25rem; color: var(--ink-500); overflow-wrap: anywhere; }
    .oc-audit-head .oc-time { color: var(--ink-500); }
    .oc-audit-note { margin: .25rem 0 0; font-size: .8125rem; color: var(--ink-700); font-style: italic; }
    .oc-audit-diff { width: 100%; table-layout: fixed; margin-top: .5rem; border-collapse: separate; border-spacing: 0; font-size: .8125rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
    .oc-audit-diff th, .oc-audit-diff td { padding: .375rem .625rem; text-align: start; vertical-align: top; border-bottom: 1px solid var(--line-2, var(--line)); }
    .oc-audit-diff tbody tr:last-child > * { border-bottom: 0; }
    .oc-audit-field { width: 9rem; font-weight: 500; color: var(--ink-700); }
    .oc-audit-from .oc-audit-val { color: var(--danger-ink); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--danger-ink) 50%, transparent); }
    .oc-audit-to .oc-audit-val { color: var(--success-subtle-foreground); font-weight: 500; }
    .oc-audit-from, .oc-audit-to { overflow-wrap: anywhere; }
    .oc-audit-arrow { width: 1.5rem; padding-inline: 0 !important; text-align: center !important; color: var(--ink-500); }
    .oc-audit-empty-val { font-style: italic; color: var(--ink-500); }
    .oc-audit-more { margin-inline-start: .25rem; padding: 0; border: 0; background: none; font: inherit; font-size: .75rem; font-weight: 500; color: var(--primary-ink); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
    [data-oc-audit-full] { white-space: pre-wrap; }
    /* Narrow: each change row stacks — field label, then before → after. */
    @container (max-width: 34rem) {
        .oc-audit-diff, .oc-audit-diff tbody, .oc-audit-diff th, .oc-audit-diff td { display: block; width: auto; }
        .oc-audit-diff tr { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); padding: .375rem .625rem; border-bottom: 1px solid var(--line-2, var(--line)); }
        .oc-audit-diff tbody tr:last-child { border-bottom: 0; }
        .oc-audit-diff th, .oc-audit-diff td { padding: 0; border: 0; }
        .oc-audit-diff tr[hidden] { display: none; }
        .oc-audit-field { grid-column: 1 / -1; margin-bottom: .125rem; font-size: .75rem; color: var(--ink-500); }
        .oc-audit-arrow { padding: 0 .375rem !important; }
    }
    @media (max-width: 639px) { .oc-audit-filters { width: 100%; } .oc-audit-filter { flex: 1 1 100%; } .oc-audit-filter .field-select { width: 100%; min-width: 0; } }
    @media (pointer: coarse) { .oc-audit-more { min-height: 2.75rem; padding-inline: .25rem; } }

    /* ---------- _DashboardGrid (container queries on the grid's own width) ---------- */
    .oc-dash { container: oc-dash / inline-size; min-width: 0; }
    .oc-dash-grid { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); }
    @container oc-dash (min-width: 40rem) {
        .oc-dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
        .oc-dash-widget.oc-dash-wide { grid-column: 1 / -1; }
    }
    @container oc-dash (min-width: 64rem) {
        .oc-dash-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
        .oc-dash-span-1 { grid-column: span 1; } .oc-dash-span-2 { grid-column: span 2; } .oc-dash-span-3 { grid-column: span 3; }
        .oc-dash-span-4 { grid-column: span 4; } .oc-dash-span-5 { grid-column: span 5; } .oc-dash-span-6 { grid-column: span 6; }
        .oc-dash-widget.oc-dash-span-7 { grid-column: span 7; } .oc-dash-widget.oc-dash-span-8 { grid-column: span 8; } .oc-dash-widget.oc-dash-span-9 { grid-column: span 9; }
        .oc-dash-widget.oc-dash-span-10 { grid-column: span 10; } .oc-dash-widget.oc-dash-span-11 { grid-column: span 11; } .oc-dash-widget.oc-dash-span-12 { grid-column: span 12; }
    }
    .oc-dash-widget { display: flex; flex-direction: column; min-width: 0; padding: 0; }
    .oc-dash-head { display: flex; align-items: flex-start; gap: .5rem; padding: .75rem .75rem 0 1rem; }
    .oc-dash-title { margin: .25rem 0 0; font-size: .875rem; font-weight: 600; color: var(--ink-900); overflow-wrap: anywhere; }
    .oc-dash-desc { margin: .125rem 0 0; font-size: .75rem; color: var(--ink-500); }
    .oc-dash-updated { align-self: center; font-size: .6875rem; color: var(--ink-500); white-space: nowrap; font-variant-numeric: tabular-nums; }
    .oc-dash-updated:empty { display: none; }
    .oc-dash-actions { display: flex; gap: .25rem; }
    .oc-dash-body { flex: 1 1 auto; min-width: 0; padding: .75rem 1rem 1rem; transition: opacity var(--duration-fast) var(--ease-out); }
    .oc-dash-widget.is-refreshing .oc-dash-body { opacity: .6; pointer-events: none; }
    .oc-dash-widget.is-refreshing [data-oc-dash-refresh] > i { animation: oc-spin 1s linear infinite; }
    @media (prefers-reduced-motion: reduce) { .oc-dash-widget.is-refreshing [data-oc-dash-refresh] > i { animation: none; } }

    /* ---------- _Lightbox file preview (PDF / text) ---------- */
    .oc-lightbox-doc, .oc-lightbox-text { width: min(100%, 60rem); height: 100%; min-height: 0; }
    .oc-lightbox-doc:not(.hidden), .oc-lightbox-text:not(.hidden) { display: flex; flex-direction: column; }
    .oc-lightbox-pdf { flex: 1 1 auto; width: 100%; min-height: 0; border: 0; border-radius: var(--radius-lg); background: var(--surface); }
    .oc-lightbox-doc-fallback { display: flex; height: 100%; flex-direction: column; align-items: center; justify-content: center; gap: .75rem; padding: 2rem; text-align: center; background: var(--surface); border-radius: var(--radius-lg); }
    .oc-lightbox-text { gap: .5rem; padding: .75rem; background: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--shadow-md); }
    .oc-lightbox-text-head { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
    .oc-lightbox-text-status { margin: 0; min-width: 0; font-size: .75rem; color: var(--ink-500); }
    .oc-lightbox-text-status.is-error { color: var(--danger-ink); }
    .oc-lightbox-pre { flex: 1 1 auto; min-height: 0; margin: 0; padding: .75rem; overflow: auto; font-size: .75rem; line-height: 1.5; color: var(--ink-900); background: var(--surface-muted); border-radius: var(--radius); white-space: pre; tab-size: 4; }
    .oc-lightbox-pre:empty { display: none; }

    /* ---------- _CopyButton Kind="link" (share on touch) ---------- */
    .oc-copy-link-icon, .oc-share-icon { display: inline-flex; align-items: center; }
    .oc-copy-link .oc-share-icon, .oc-copy-link.is-share .oc-copy-link-icon { display: none; }
    .oc-copy-link.is-share .oc-share-icon { display: inline-flex; }

    /* ---------- end Agent B6 ---------- */

    /* ======================================================================================================
       FORM KIT (F2) — _WeekdayPicker · _TimePicker · _NumberStepper · _DurationInput · _SlugField · _TagsInput
       polish · _SettingsRow (behaviour: octacer-formkit.js / octacer-forms.js). Builds ON the shared field look
       (.field-group, .field-affix, .field-static, .field-label-action) — never restyles those base classes.
       Mouse = compact 32px; the 44px touch sizes are in this section's own (pointer: coarse) block at the end.
       ====================================================================================================== */

    /* ---------- _WeekdayPicker: 7 chips ≈ 15.5rem on mouse ---------- */
    .oc-weekday-row { display: flex; flex-wrap: wrap; align-items: center; gap: .375rem .75rem; min-width: 0; }
    .oc-weekday-chips { display: inline-flex; flex-wrap: wrap; gap: .25rem; min-width: 0; }
    .oc-weekday-chip { display: inline-flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; padding: 0; border: 1px solid var(--input); border-radius: var(--radius-sm); background: var(--surface); color: var(--ink-700); font: inherit; font-size: .75rem; font-weight: 600; line-height: 1; letter-spacing: .01em; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; transition: background-color .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease, transform .1s ease; }
    @media (hover: hover) {
        .oc-weekday-chip:not(:disabled):not([aria-disabled="true"]):hover { border-color: var(--input-hover); background: var(--surface-muted); color: var(--ink-900); }
        .oc-weekday-chip[aria-pressed="true"]:not(:disabled):not([aria-disabled="true"]):hover { background: color-mix(in srgb, var(--primary) 88%, var(--ink-900)); border-color: transparent; color: var(--primary-foreground); }
    }
    .oc-weekday-chip:focus-visible { outline: none; border-color: var(--brand-500); box-shadow: var(--ring); }
    .oc-weekday-chip[aria-pressed="true"] { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); }
    .oc-weekday-chip:active:not(:disabled):not([aria-disabled="true"]) { transform: scale(.94); }
    .oc-weekday-chip:disabled { cursor: not-allowed; opacity: .5; }
    .oc-weekday.is-readonly .oc-weekday-chip { cursor: default; background: var(--input-bg-muted); }
    .oc-weekday.is-readonly .oc-weekday-chip[aria-pressed="true"] { background: var(--primary-tint); border-color: transparent; color: var(--primary-ink); }
    :is(.oc-weekday-chips.is-error, .oc-weekday.is-invalid .oc-weekday-chips) .oc-weekday-chip[aria-pressed="false"] { border-color: var(--danger); }
    .oc-weekday-presets { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .125rem; margin-inline-start: -.375rem; }
    .oc-weekday-preset { display: inline-flex; align-items: center; min-height: 1.75rem; padding: .25rem .375rem; border: 0; border-radius: .375rem; background: none; font: inherit; font-size: .75rem; font-weight: 500; color: var(--primary-ink); cursor: pointer; white-space: nowrap; }
    @media (hover: hover) { .oc-weekday-preset:hover { background: var(--primary-tint); } }
    .oc-weekday-preset:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-weekday-summary { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--ink-500); }

    /* ---------- _TimePicker: fixed intrinsic width that always fits "12:45 PM" (+ zone, + clear) ---------- */
    .oc-timepicker-anchor { width: max-content; max-width: 100%; }
    .oc-timepicker-group { width: 9.75rem; max-width: 100%; }
    .oc-timepicker-group.has-zone { width: 12rem; }
    .oc-timepicker-group.no-clear { width: 8.5rem; }
    .oc-timepicker-group.has-zone.no-clear { width: 10.75rem; }
    .oc-timepicker.is-full :is(.oc-timepicker-anchor, .oc-timepicker-group) { width: 100%; }
    .oc-timepicker-group > .field-affix { font-size: .75rem; font-weight: 500; letter-spacing: .02em; }
    .oc-timepicker-menu { position: absolute; inset-inline-start: 0; top: 100%; z-index: var(--z-popover); width: max(100%, 10rem); max-width: calc(100vw - 2rem); margin-top: .25rem; padding: .25rem; border: 1px solid var(--line); border-radius: .75rem; background: var(--popover); box-shadow: var(--shadow-lg); animation: oc-menu-in .12s ease-out; }
    .oc-timepicker-menu.is-above { top: auto; bottom: 100%; margin-top: 0; margin-bottom: .25rem; }
    .oc-timepicker-list { position: relative; max-height: 15rem; overflow-y: auto; overscroll-behavior: contain; outline: none; scrollbar-width: thin; }
    .oc-timepicker-option { display: flex; align-items: center; min-height: 2rem; padding: .25rem .625rem; border-radius: .5rem; font-size: .875rem; line-height: 1.25rem; font-variant-numeric: tabular-nums; color: var(--ink-700); white-space: nowrap; cursor: pointer; }
    .oc-timepicker-option.is-active { background: var(--surface-muted); color: var(--ink-900); }
    @media (hover: hover) { .oc-timepicker-option:hover { background: var(--surface-muted); color: var(--ink-900); } }
    .oc-timepicker-option[aria-selected="true"] { background: var(--primary-tint); color: var(--primary-ink); font-weight: 600; }
    .oc-timepicker-option[aria-selected="true"].is-active { background: color-mix(in srgb, var(--primary-tint) 70%, var(--surface-muted)); }
    .oc-timepicker-list:focus-visible .oc-timepicker-option.is-active { box-shadow: inset 0 0 0 2px var(--brand-500); }
    .oc-timepicker-sheet-type { display: none; }
    .is-sheet.oc-timepicker-menu { animation: none; border-radius: 1rem 1rem 0 0; padding: .25rem .5rem calc(var(--oc-safe-bottom, 0px) + .5rem); }
    .is-sheet.oc-timepicker-menu > .oc-picker-sheet-head { margin: -.25rem -.5rem .25rem; }
    .is-sheet .oc-timepicker-sheet-type { display: block; position: sticky; top: var(--oc-picker-head-h); z-index: 1; padding: 0 .25rem .5rem; background: var(--popover); }
    .is-sheet .oc-timepicker-list { max-height: none; overflow: visible; }
    .is-sheet .oc-timepicker-option { min-height: 2.75rem; padding-inline: 1rem; font-size: 1rem; }

    /* ---------- _NumberStepper: [−][ 3 /day ][+] in one field ---------- */
    .oc-numstepper-group { width: 7rem; max-width: 100%; padding: 0; gap: 0; }
    .oc-numstepper-group.has-suffix { width: 7.75rem; }
    .oc-numstepper-group.is-wide { width: 10rem; }
    .oc-numstepper-group.is-full { width: 100%; }
    .oc-numstepper-btn { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 1.875rem; align-self: stretch; padding: 0; border: 0; background: transparent; color: var(--ink-500); cursor: pointer; -webkit-tap-highlight-color: transparent; user-select: none; touch-action: manipulation; transition: background-color .15s ease, color .15s ease; }
    .oc-numstepper-btn:first-child { border-start-start-radius: calc(var(--radius-sm) - 1px); border-end-start-radius: calc(var(--radius-sm) - 1px); }
    .oc-numstepper-btn:last-child { border-start-end-radius: calc(var(--radius-sm) - 1px); border-end-end-radius: calc(var(--radius-sm) - 1px); }
    @media (hover: hover) { .oc-numstepper-btn:not(:disabled):hover { background: var(--surface-muted); color: var(--ink-900); } }
    .oc-numstepper-btn:not(:disabled):active { background: var(--surface-muted); color: var(--primary-ink); }
    .oc-numstepper-btn:disabled { cursor: not-allowed; opacity: .35; }
    .oc-numstepper-group > .oc-numstepper-input { text-align: center; font-variant-numeric: tabular-nums; font-weight: 500; }
    .oc-numstepper-group.has-suffix > .oc-numstepper-input { flex: 0 1 auto; width: calc(var(--oc-ns-ch, 2) * 1ch + .25rem); margin-inline-start: auto; text-align: end; }
    .oc-numstepper-suffix { flex: 0 1 auto; min-width: 0; margin-inline: .1875rem auto; font-size: .8125rem; line-height: 1.25rem; color: var(--ink-500); white-space: nowrap; cursor: text; }
    .oc-numstepper.is-clamped .oc-numstepper-group { animation: oc-fk-nudge .3s ease; }

    /* ---------- _DurationInput: number + unit select in one field ---------- */
    .oc-duration-group { width: 10rem; max-width: 100%; }
    .oc-duration-group:has(> .oc-duration-unit) { padding-inline-end: 0; }
    .oc-duration-group > input { font-variant-numeric: tabular-nums; }
    .oc-duration-unit { flex: 0 0 auto; align-self: stretch; margin: 0; padding: 0 1.625rem 0 .5rem; border: 0; border-inline-start: 1px solid var(--line); border-radius: 0; border-start-end-radius: calc(var(--radius-sm) - 1px); border-end-end-radius: calc(var(--radius-sm) - 1px); background-color: transparent; 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 .4375rem center; background-size: .875rem; font: inherit; font-size: .8125rem; color: var(--ink-700); cursor: pointer; -webkit-appearance: none; appearance: none; }
    .oc-duration-unit:focus { outline: none; }
    .oc-duration-unit:focus-visible { background-color: var(--surface-muted); }
    @media (hover: hover) { .oc-duration-unit:not(:disabled):hover { background-color: var(--surface-muted); } }
    .oc-duration-unit:disabled { cursor: not-allowed; color: var(--ink-400); }
    .oc-duration-unit option { color: var(--ink-900); background: var(--popover); }
    .oc-duration-summary { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--ink-500); font-variant-numeric: tabular-nums; }
    .oc-duration-summary.is-empty { display: none; }

    /* ---------- _SlugField ---------- */
    .oc-slug-actions { display: inline-flex; align-items: center; gap: .5rem; }
    .oc-slug-input { font-variant-ligatures: none; }
    .oc-slug-linked { flex: 0 0 auto; display: inline-flex; align-items: center; margin-inline-start: .375rem; color: var(--ink-400); }
    .oc-slug-indicator { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 1rem; margin-inline-start: .375rem; font-size: .875rem; }
    .oc-slug-indicator:empty { display: none; }
    .oc-slug-indicator.is-available { color: var(--success); }
    .oc-slug-indicator.is-taken { color: var(--danger-ink); }
    .oc-slug-indicator.is-error { color: var(--warning); }
    .oc-slug-preview { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--ink-500); overflow-wrap: anywhere; }
    .oc-slug-preview-slug { color: var(--ink-900); font-weight: 500; }
    .oc-slug-preview-slug.is-placeholder { color: var(--ink-500); font-weight: 400; font-style: italic; }
    .oc-slug-status { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--ink-500); }
    .oc-slug-status:empty { display: none; }
    .oc-slug-status.is-available { color: var(--success-subtle-foreground); }
    .oc-slug-status.is-taken { color: var(--danger-ink); }
    .oc-slug-status.is-error { color: var(--warning-subtle-foreground); }
    .field-group.is-taken { border-color: var(--danger); }

    /* ---------- _TagsInput polish: chips wrap (never truncate mid-word), note, suggestions, duplicate shake ---------- */
    .oc-tag-chip { max-width: 100%; min-width: 0; gap: .25rem; padding-inline: .625rem .25rem; }
    .oc-tag-text { min-width: 0; white-space: normal; overflow-wrap: break-word; }
    .oc-tags-note { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--warning-subtle-foreground); }
    .oc-tags-suggest-menu .oc-combobox-list { max-height: 14rem; }
    .oc-tags-suggest-note { padding: .5rem .75rem; font-size: .8125rem; color: var(--ink-500); }
    .oc-tags-suggest-note.is-error { color: var(--danger-ink); }
    .oc-shake { animation: oc-fk-shake .42s ease; }
    .badge.oc-shake { box-shadow: 0 0 0 2px var(--warning); }
    @keyframes oc-fk-shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-3px); } 40% { transform: translateX(3px); } 60% { transform: translateX(-2px); } 80% { transform: translateX(2px); } }
    @keyframes oc-fk-nudge { 0%, 100% { box-shadow: var(--ring); } 50% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--warning) 35%, transparent); } }
    @media (prefers-reduced-motion: reduce) { .oc-shake, .oc-numstepper.is-clamped .oc-numstepper-group { animation: none; } }

    /* ---------- _SettingsRow: identity · controls · meta/action; lays out by its OWN width ---------- */
    .oc-setrows { margin: 0; padding: 0; list-style: none; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface); }
    .oc-setrows > li + li, .oc-setrows > .oc-setrow + .oc-setrow { border-top: 1px solid var(--line-2); }
    .oc-setrows > li:first-child > .oc-setrow, .oc-setrows > .oc-setrow:first-child { border-start-start-radius: var(--radius-lg); border-start-end-radius: var(--radius-lg); }
    .oc-setrows > li:last-child > .oc-setrow, .oc-setrows > .oc-setrow:last-child { border-end-start-radius: var(--radius-lg); border-end-end-radius: var(--radius-lg); }
    .oc-setrow { container-type: inline-size; min-width: 0; transition: background-color .15s ease; }
    .oc-setrow-inner { display: grid; grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr) auto; grid-template-areas: "main controls end"; align-items: center; gap: .625rem 1.25rem; padding: .75rem 1rem; }
    .oc-setrow-main { grid-area: main; display: flex; align-items: center; gap: .75rem; min-width: 0; }
    .oc-setrow-icon { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; border-radius: .5rem; background: var(--primary-tint); color: var(--primary-ink); }
    .oc-setrow-text { min-width: 0; }
    .oc-setrow-title { margin: 0; font-size: .875rem; line-height: 1.25rem; font-weight: 600; color: var(--ink-900); overflow-wrap: anywhere; }
    .oc-setrow-desc { margin: 0; font-size: .75rem; line-height: 1rem; color: var(--ink-500); overflow-wrap: anywhere; }
    .oc-setrow-controls { grid-area: controls; display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; min-width: 0; margin: 0; padding: 0; border: 0; }
    .oc-setrow-controls > * { min-width: 0; }
    .oc-setrow-end { grid-area: end; display: flex; align-items: center; justify-content: flex-end; gap: .75rem; min-width: 0; }
    .oc-setrow-meta { font-size: .75rem; line-height: 1rem; color: var(--ink-500); white-space: nowrap; font-variant-numeric: tabular-nums; }
    .oc-setrow-actions { display: inline-flex; align-items: center; gap: .5rem; }
    .oc-setrow.is-disabled :is(.oc-setrow-main, .oc-setrow-meta) { opacity: .6; }
    .oc-setrow[data-oc-dirty="true"] { background: color-mix(in srgb, var(--primary-tint) 45%, transparent); }
    .oc-setrow[data-oc-dirty="true"] .oc-setrow-save:not([aria-busy="true"]) { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); }
    @container (max-width: 60rem) {
        .oc-setrow-inner { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "main end" "controls controls"; }
    }
    @container (max-width: 40rem) {
        .oc-setrow-inner { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main" "controls" "end"; padding: .875rem 1rem; }
        .oc-setrow-end { justify-content: space-between; }
    }

    /* ---------- Form kit on touch: 44px targets ---------- */
    @media (pointer: coarse) {
        .oc-weekday-chip { width: 2.75rem; height: 2.75rem; font-size: .8125rem; }
        .oc-weekday-chips { gap: .1875rem; }
        .oc-weekday-preset { min-height: 2.75rem; padding-inline: .5rem; }
        .oc-timepicker-group { width: 11.25rem; }
        .oc-timepicker-group.has-zone { width: 13.5rem; }
        .oc-timepicker-group.no-clear { width: 9.25rem; }
        .oc-timepicker-group.has-zone.no-clear { width: 11.5rem; }
        .oc-timepicker-option { min-height: 2.75rem; }
        .oc-numstepper-btn { width: 2.75rem; }
        .oc-numstepper-group { width: 9.25rem; }
        .oc-numstepper-group.has-suffix { width: 10.5rem; }
        .oc-numstepper-suffix { font-size: .875rem; }
        .oc-duration-group { width: 11rem; }
        .oc-duration-unit { font-size: 16px; padding-inline-start: .75rem; }
        .oc-slug-indicator { width: 1.25rem; }
    }
    /* ====================================== end FORM KIT (F2) ====================================== */

    /* 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; }
        /* Toolbars: ONE 44px row height on touch — search, Filters/Columns (incl. .btn-sm), chips, selects and the
           view toggle (44px OUTER: its padding + border included, the segments stretch inside it). */
        :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) :is(.btn, .btn-sm, .field-group, .field-input, .field-select, .oc-searchable-trigger, .oc-icon-btn) { min-height: 2.75rem; }
        :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) .oc-view-toggle { min-height: 2.75rem; align-items: stretch; box-sizing: border-box; }
        :is(.oc-table-toolbar, .oc-filter-bar, .oc-toolbar) .oc-view-toggle-button { min-height: 0; min-width: 2.5rem; }
        /* Table rows: 44px icon buttons (row actions, tree toggles) overlap the cell's vertical padding instead of
           adding to it, so touch rows stay ~49px (not 61px) while every target keeps its full 44px. */
        .oc-table tbody td :is(.oc-icon-btn, .oc-tree-toggle-btn) { margin-block: -.375rem; }

        /* Phone touch targets that the rules above miss (≥ 44px, WCAG 2.5.8 + native feel). */
        [data-oc-calendar] [data-oc-cal-today], .oc-table-columns-btn, [data-oc-copy] { min-height: 2.75rem; min-width: 2.75rem; }
        .oc-cal-viewswitch { min-height: 2.75rem; align-items: stretch; box-sizing: border-box; }
        .oc-cal-viewswitch .oc-cal-view-opt { min-height: 0; min-width: 2.75rem; }
        .oc-color-swatches, .oc-color-swatches:has(> :nth-child(9)) { grid-auto-flow: row; grid-template-columns: repeat(auto-fill, 2.75rem); }
        .oc-color-swatches > .oc-color-swatch { width: 2.75rem; height: 2.75rem; }
        .oc-slider-thumb::before { inset: -.75rem; } /* 24px thumb → 48px hit area */
        .oc-kanban-card { position: relative; }
        .oc-kanban-card-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; } /* whole card opens it */
        .oc-kanban-card :is(input, select, .badge a[href]) { position: relative; z-index: 1; } /* Move button: z-index above (kanban touch block) */

        /* Native list feel: pressing a tappable row/tab gives instant feedback; long-press doesn't select text or
           open the iOS callout on list/card rows (links inside still work). */
        .oc-table-cards tbody tr:is([data-oc-row], [data-oc-row-href]):has(a[href]):active,
        .oc-list-item:has(a[href]):active,
        dl > div:has(> dd a[href]):active { background: var(--surface-muted); }
        .oc-tab:active { background: var(--surface-muted); }
        .oc-table-cards tbody tr, .oc-list-item, .oc-more-tile { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
    }
}

/* Cross-document view transitions (MPA navigations + hx-boost with transition:true). Motion only when allowed. */
/* The fixed chrome (tab bar, app bar, sidebar) is captured on its own and swapped with NO animation, so it never
   cross-fades through a blank frame; only the page content (#oc-main) moves — a 120ms fade + 4px rise. The names
   exist only while html.oc-vt is set (octacer-theme-init.js: pageswap/pagereveal; octacer-appshell.js: hx-boost
   transitions): a view-transition-name makes its element a stacking context, which must never trap the fixed
   modals/sheets that pages render inside #oc-main. */
@media (prefers-reduced-motion: no-preference) {
    @view-transition { navigation: auto; }
    html.oc-vt #oc-tabbar { view-transition-name: oc-tabbar; }
    html.oc-vt [data-oc-shell-content] > .oc-layout-header { view-transition-name: oc-appbar; }
    html.oc-vt body > .oc-sidebar { view-transition-name: oc-sidebar; }
    html.oc-vt #oc-main { view-transition-name: oc-main; }
    ::view-transition-old(root), ::view-transition-new(root),
    ::view-transition-group(oc-tabbar), ::view-transition-group(oc-appbar), ::view-transition-group(oc-sidebar),
    ::view-transition-new(oc-tabbar), ::view-transition-new(oc-appbar), ::view-transition-new(oc-sidebar),
    ::view-transition-group(oc-main) { animation: none; }
    ::view-transition-old(oc-tabbar), ::view-transition-old(oc-appbar), ::view-transition-old(oc-sidebar) { display: none; }
    ::view-transition-old(oc-main) { animation: oc-vt-out 90ms var(--ease-out) both; }
    ::view-transition-new(oc-main) { animation: oc-vt-in 120ms var(--ease-out) both; }
}
@keyframes oc-vt-out { to { opacity: 0; } }
@keyframes oc-vt-in { from { opacity: 0; transform: translateY(4px); } }

/* =====================================================================================================================
   Agent B5 — settings page + save bar, user picker, live time, saved views, jobs + .oc-progress, split view, inline edit.
   Its own @layer components block (same cascade layer as the rest; appended so it never fights the density block).
   ===================================================================================================================== */
@layer components {
    /* ---------- Generic progress bar (.oc-progress on a native <progress>) ----------
       Determinate: value/max (real numbers only, §61). Indeterminate: no value attribute → a moving band; static under
       reduced motion. Tones: .oc-progress-success / -warning / -danger, or set --oc-progress-fill. */
    .oc-progress { -webkit-appearance: none; appearance: none; display: block; width: 100%; height: .375rem; border: 0; border-radius: 999px; overflow: hidden;
        background-color: color-mix(in srgb, var(--ink-400) 24%, transparent); color: var(--oc-progress-fill, var(--primary)); vertical-align: middle; }
    .oc-progress::-webkit-progress-bar { background: transparent; border-radius: 999px; }
    .oc-progress::-webkit-progress-value { background: var(--oc-progress-fill, var(--primary)); border-radius: 999px; transition: width .35s var(--ease-out); }
    .oc-progress::-moz-progress-bar { background: var(--oc-progress-fill, var(--primary)); border-radius: 999px; }
    .oc-progress-success { --oc-progress-fill: var(--success); }
    .oc-progress-warning { --oc-progress-fill: var(--warning); }
    .oc-progress-danger  { --oc-progress-fill: var(--danger); }
    .oc-progress:indeterminate { background-image: linear-gradient(var(--oc-progress-fill, var(--primary)), var(--oc-progress-fill, var(--primary)));
        background-repeat: no-repeat; background-size: 35% 100%; background-position: -60% 0; animation: oc-progress-band 1.3s var(--ease-in-out) infinite; }
    .oc-progress:indeterminate::-webkit-progress-bar { background: transparent; }
    .oc-progress:indeterminate::-moz-progress-bar { background: transparent; }
    @keyframes oc-progress-band { from { background-position: -60% 0; } to { background-position: 160% 0; } }
    @media (prefers-reduced-motion: reduce) {
        .oc-progress:indeterminate { animation: none; background-size: 100% 100%; background-image: repeating-linear-gradient(-45deg,
            color-mix(in srgb, var(--oc-progress-fill, var(--primary)) 55%, transparent) 0 .375rem, transparent .375rem .75rem); }
        .oc-progress::-webkit-progress-value { transition: none; }
    }

    /* ---------- Live time (@Html.Time, octacer-time.js) — tap shows the absolute-time tooltip on touch ---------- */
    .oc-time { white-space: nowrap; }
    @media (hover: hover) { .oc-time[data-oc-tooltip] { cursor: default; text-decoration: underline dotted color-mix(in srgb, currentColor 35%, transparent); text-underline-offset: 3px; } }
    .oc-time.is-tip-open::after { display: block; opacity: 1; transform: translate(-50%, 0); }

    /* ---------- Settings page (_SettingsPage.cshtml, octacer-settings.js) ---------- */
    .oc-settings { min-width: 0; }
    .oc-settings-form { display: block; min-width: 0; }
    .oc-settings-layout { display: grid; gap: 1.5rem; min-width: 0; }
    .oc-settings-body { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
    .oc-settings-sections { display: flex; flex-direction: column; gap: 1rem; min-width: 0; margin: 0; padding: 0; border: 0; }
    .oc-settings-section { min-width: 0; scroll-margin-top: calc(var(--oc-appbar-h, 3.5rem) + 1rem); }
    .oc-settings-section:focus { outline: none; }
    .oc-settings-section:focus-visible { box-shadow: var(--ring); }
    .oc-settings-section-head { display: flex; flex-direction: column; align-items: flex-start; gap: .125rem; padding: 1rem 1.25rem .875rem; border-bottom: 1px solid var(--line-2); }
    .oc-settings-section-title { margin: 0; font-size: 1rem; line-height: 1.5rem; font-weight: 600; color: var(--ink-900); }
    .oc-settings-section-title:focus { outline: none; }
    .oc-settings-section-desc { margin: 0; font-size: .8125rem; line-height: 1.25rem; color: var(--ink-500); }
    .oc-settings-section-body { padding: 1rem 1.25rem 1.25rem; min-width: 0; }
    .oc-settings-back { display: none; margin: -.25rem 0 .375rem -.5rem; }
    .oc-settings-index { display: none; overflow: hidden; }
    .oc-settings-index ul { margin: 0; padding: 0; list-style: none; }
    .oc-settings-index li + li { border-top: 1px solid var(--line-2); }
    .oc-settings-index-link { display: flex; align-items: center; gap: .75rem; min-height: 3.25rem; padding: .625rem 1rem; color: var(--ink-700); text-decoration: none; }
    .oc-settings-index-link:focus-visible { outline: none; box-shadow: var(--ring-inset); }
    @media (hover: hover) { .oc-settings-index-link:hover { background: var(--surface-muted); } }
    .oc-settings-index-title { display: block; font-size: .9375rem; font-weight: 500; color: var(--ink-900); }
    .oc-settings-index-desc { display: block; margin-top: .125rem; font-size: .8125rem; color: var(--ink-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    @media (min-width: 1024px) {
        .oc-settings-layout { grid-template-columns: 13rem minmax(0, 1fr); align-items: start; }
        .oc-settings-nav { position: sticky; top: calc(var(--oc-appbar-h, 3.5rem) + 1rem); }
    }
    @media (max-width: 1023.98px) {
        .oc-settings-nav { display: none; }
        .oc-settings:not([data-oc-settings-mode]) .oc-settings-index { display: block; }   /* no JS: anchor list + stacked */
        .oc-settings[data-oc-settings-mode="push"][data-oc-settings-view="index"] .oc-settings-index { display: block; }
        .oc-settings[data-oc-settings-mode="push"][data-oc-settings-view="index"] .oc-settings-section { display: none; }
        .oc-settings[data-oc-settings-mode="push"][data-oc-settings-view="index"] .oc-savebar[data-oc-savebar-state="clean"] { display: none; }
        .oc-settings[data-oc-settings-mode="push"][data-oc-settings-view="section"] .oc-settings-section:not(.is-current) { display: none; }
        .oc-settings[data-oc-settings-mode="push"][data-oc-settings-view="section"] .oc-settings-back { display: inline-flex; }
    }

    /* ---------- Save bar (_SaveBar.cshtml) — sticky while dirty; the phone form footer ---------- */
    .oc-savebar { display: none; position: sticky; bottom: calc(var(--oc-bottom-chrome) + .75rem); z-index: var(--z-sticky); margin-top: .25rem; }
    .oc-savebar:not(.is-ready), .oc-savebar[data-oc-savebar-state="dirty"], .oc-savebar[data-oc-savebar-always="true"] { display: block; }
    .oc-savebar[data-oc-savebar-state="dirty"] { animation: oc-savebar-in var(--duration-base, .2s) var(--ease-out); }
    @keyframes oc-savebar-in { from { opacity: 0; transform: translateY(.5rem); } }
    .oc-savebar-inner { display: flex; align-items: center; justify-content: space-between; gap: .75rem; padding: .5rem .5rem .5rem 1rem;
        background: var(--popover); border: 1px solid var(--line); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
    .oc-savebar-msg { display: flex; align-items: center; gap: .5rem; min-width: 0; margin: 0; font-size: .875rem; font-weight: 500; color: var(--ink-900); }
    .oc-savebar-dot { flex: 0 0 auto; width: .5rem; height: .5rem; border-radius: 999px; background: var(--warning); }
    .oc-savebar[data-oc-savebar-state="clean"] .oc-savebar-dot { background: var(--ink-400); }
    .oc-savebar[data-oc-savebar-state="clean"] [data-oc-savebar-dirty-text],
    .oc-savebar:not([data-oc-savebar-state="clean"]) [data-oc-savebar-clean-text] { display: none; }
    .oc-savebar-actions { display: flex; align-items: center; gap: .5rem; flex: 0 0 auto; }
    .oc-savebar [aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
    @media (max-width: 639.98px) {
        .oc-savebar { display: block; bottom: var(--oc-bottom-chrome); margin-inline: -.25rem; }
        .oc-savebar-inner { padding: .5rem .5rem .5rem .875rem; border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding-bottom: calc(.5rem + var(--oc-safe-bottom, 0px)); }
        :root:has(.oc-tabbar) .oc-savebar-inner { padding-bottom: .5rem; }
        .oc-savebar-msg { font-size: .8125rem; }
    }
    @media (prefers-reduced-motion: reduce) { .oc-savebar[data-oc-savebar-state="dirty"] { animation: none; } }

    /* ---------- People picker (_UserPicker.cshtml) ---------- */
    .oc-avatar-xs { width: 1.5rem; height: 1.5rem; font-size: .625rem; }
    .oc-userpicker-field { flex-wrap: wrap; row-gap: .25rem; min-height: 2rem; padding-top: .1875rem; padding-bottom: .1875rem; cursor: text; }
    .oc-userpicker-field > input { min-height: 1.5rem; }
    .oc-userpicker-field.is-disabled { background: var(--surface-muted); cursor: not-allowed; }
    .oc-userpicker-field.is-disabled > input { color: var(--ink-600); cursor: not-allowed; }
    .oc-userpicker-lead { width: 1.375rem; height: 1.375rem; }
    .oc-userpicker-chips { display: flex; flex-wrap: wrap; gap: .25rem; margin: 0; padding: 0; list-style: none; min-width: 0; }
    .oc-userpicker-chips:empty { display: none; }
    .oc-userpicker-chip { display: inline-flex; align-items: center; gap: .3125rem; max-width: 14rem; min-height: 1.5rem; padding: .0625rem .125rem .0625rem .125rem;
        border: 1px solid var(--line); border-radius: 999px; background: var(--surface-muted); font-size: .8125rem; color: var(--ink-900); }
    .oc-userpicker-chip .oc-avatar-xs { width: 1.25rem; height: 1.25rem; font-size: .5625rem; }
    .oc-userpicker-chip-x { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 1.25rem; height: 1.25rem;
        border: 0; border-radius: 999px; background: transparent; color: var(--ink-500); cursor: pointer; }
    .oc-userpicker-chip-x::before { content: ""; position: absolute; inset: -.375rem; }   /* ≥ 32px hit area */
    @media (hover: hover) { .oc-userpicker-chip-x:hover { background: var(--line); color: var(--ink-900); } }
    .oc-userpicker-chip-x:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-userpicker-option { display: flex; align-items: center; justify-content: flex-start; gap: .625rem; padding: .375rem .625rem; border-radius: var(--radius-sm); font-size: .875rem; color: var(--ink-900); cursor: pointer; }
    .oc-userpicker-option-text { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; line-height: 1.25; }
    .oc-userpicker-option-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .oc-userpicker-option-email { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .75rem; font-weight: 400; color: var(--ink-500); }
    .oc-userpicker-option.is-error .oc-userpicker-option-name { color: var(--danger-ink); }
    .oc-userpicker-none { background: var(--surface-muted); color: var(--ink-500); }
    .oc-userpicker-err { background: var(--danger-subtle); color: var(--danger-ink); }
    .oc-userpicker-note { display: flex; align-items: center; justify-content: center; gap: .5rem; padding: .75rem; font-size: .8125rem; color: var(--ink-500); text-align: center; }
    .oc-userpicker-spin { width: .875rem; height: .875rem; border: 2px solid currentColor; border-right-color: transparent; border-radius: 999px; animation: oc-spin .7s linear infinite; }
    .is-sheet .oc-userpicker-option { min-height: 3rem; }
    @media (pointer: coarse) { .oc-userpicker-field { min-height: 2.75rem; } }
    @media (prefers-reduced-motion: reduce) { .oc-userpicker-spin { animation-duration: 2.4s; } }

    /* ---------- Saved views strip (_SavedViews.cshtml) ---------- */
    .oc-views { display: flex; align-items: flex-end; gap: .5rem; min-width: 0; padding: .25rem 1rem 0; border-bottom: 1px solid var(--line-2); }
    .oc-views-tabs { display: flex; align-items: stretch; gap: .125rem; flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
    .oc-views-tabs::-webkit-scrollbar { display: none; }
    .oc-views-tab { display: inline-flex; align-items: center; gap: .375rem; flex: 0 0 auto; max-width: 15rem; min-height: 2.25rem; padding: 0 .625rem; margin-bottom: -1px;
        border-bottom: 2px solid transparent; font-size: .8125rem; font-weight: 500; color: var(--ink-500); white-space: nowrap; text-decoration: none; }
    .oc-views-tab[hidden] { display: none; }
    @media (hover: hover) { a.oc-views-tab:hover { color: var(--ink-900); } }
    .oc-views-tab:focus-visible { outline: none; box-shadow: var(--ring-inset); border-radius: var(--radius-sm); }
    .oc-views-tab.is-active { color: var(--ink-900); border-bottom-color: var(--primary); }
    .oc-views-tab.is-unsaved { color: var(--ink-700); font-style: italic; border-bottom-style: dashed; }
    .oc-views-count { min-width: 1.25rem; padding: 0 .375rem; border-radius: 999px; background: var(--surface-muted); color: var(--ink-600); font-size: .6875rem; line-height: 1.125rem; text-align: center; }
    .oc-views-tab.is-active .oc-views-count { background: var(--primary-tint); color: var(--primary-ink); }
    .oc-views-picker { display: none; }
    .oc-views-save { flex: 0 0 auto; padding-bottom: .25rem; }
    .oc-views-save-panel { width: 20rem; }
    .oc-views-save-panel.is-sheet { width: auto; }
    @media (max-width: 639.98px) {
        .oc-views { align-items: center; padding: .5rem .75rem; }
        .oc-views-tabs { display: none; }
        .oc-views-picker { display: flex; flex: 1 1 auto; min-width: 0; }
        .oc-views-picker-btn { max-width: 100%; min-width: 0; }
        .oc-views-save { padding-bottom: 0; }
    }

    /* ---------- Long-running jobs (_JobProgress.cshtml inline + octacer-jobs.js toast) ---------- */
    .oc-job { display: flex; flex-direction: column; gap: .625rem; min-width: 0; padding: 1rem 1.25rem; }
    .oc-job-compact { padding: 0; }
    .oc-job-head { display: flex; align-items: flex-start; gap: .75rem; min-width: 0; }
    .oc-job-icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 2rem; height: 2rem; border-radius: 999px; }
    .oc-job-icon-info { background: var(--primary-tint); color: var(--primary-ink); }
    .oc-job-icon-success { background: var(--success-subtle); color: var(--success-subtle-foreground); }
    .oc-job-icon-warning { background: var(--warning-subtle); color: var(--warning-subtle-foreground); }
    .oc-job-icon-danger { background: var(--danger-subtle); color: var(--danger-subtle-foreground); }
    .oc-job-icon-muted { background: var(--surface-muted); color: var(--ink-500); }
    .oc-job-spin { display: inline-block; width: 1rem; height: 1rem; border: 2px solid currentColor; border-right-color: transparent; border-radius: 999px; animation: oc-spin .8s linear infinite; }
    .oc-job-label { margin: 0; font-size: .875rem; font-weight: 600; line-height: 1.25rem; color: var(--ink-900); overflow-wrap: anywhere; }
    .oc-job-meta { margin: .125rem 0 0; font-size: .8125rem; color: var(--ink-500); }
    .oc-job-message { margin: 0; font-size: .8125rem; color: var(--ink-700); overflow-wrap: anywhere; }
    .oc-job-stale { display: flex; align-items: center; gap: .375rem; margin: 0; font-size: .75rem; color: var(--warning-subtle-foreground); }
    .oc-job-stale[hidden] { display: none; }
    .oc-job-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
    .oc-job-actions[hidden] { display: none; }
    .oc-job-toast { align-items: flex-start; }
    .oc-job-toast-title { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
    .oc-job-toast-meta, .oc-job-toast-msg { margin: 0; font-size: .8125rem; }
    .oc-job-toast .oc-progress { --oc-progress-fill: currentColor; background-color: color-mix(in srgb, currentColor 18%, transparent); }
    .oc-job-toast .oc-progress[hidden] { display: none; }
    .oc-job-toast .oc-job-actions .btn-ghost, .oc-job-toast .oc-job-actions .btn-outline { color: inherit; }
    @media (prefers-reduced-motion: reduce) { .oc-job-spin { animation-duration: 2.4s; } }

    /* ---------- Split view (_SplitView.cshtml, octacer-splitview.js) ---------- */
    .oc-split { display: grid; gap: 1rem; min-width: 0; --oc-split-list: 20rem; }
    .oc-split-w-sm { --oc-split-list: 16rem; }
    .oc-split-w-lg { --oc-split-list: 26rem; }
    .oc-split-list, .oc-split-detail { min-width: 0; }
    .oc-split-detail { min-height: 18rem; }
    .oc-split-detail:focus, .oc-split-detail-body [tabindex="-1"]:focus { outline: none; }
    .oc-split-detail-bar { display: none; }
    .oc-split-detail-body { min-width: 0; }
    .oc-split-detail-body[aria-busy="true"] { pointer-events: none; }
    .oc-split-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .75rem; min-height: 16rem; padding: 2rem 1.25rem; text-align: center; }
    .oc-split[data-oc-split-mode="side"] { grid-template-columns: var(--oc-split-list) minmax(0, 1fr); align-items: start; }
    .oc-split[data-oc-split-mode="side"] .oc-split-list { position: sticky; top: calc(var(--oc-appbar-h, 3.5rem) + 1rem); max-height: calc(100dvh - var(--oc-appbar-h, 3.5rem) - 2rem); overflow-y: auto; overscroll-behavior: contain; }
    @media (min-width: 1024px) { .oc-split:not([data-oc-split-mode]) { grid-template-columns: var(--oc-split-list) minmax(0, 1fr); align-items: start; } }
    .oc-split[data-oc-split-mode="stack"][data-oc-split-view="list"] .oc-split-detail { display: none; }
    .oc-split[data-oc-split-mode="stack"][data-oc-split-view="detail"] .oc-split-list { display: none; }
    .oc-split[data-oc-split-mode="stack"] .oc-split-detail-bar { display: flex; position: sticky; top: var(--oc-appbar-h, 0px); z-index: 1; padding: .375rem .5rem; background: var(--surface); border-bottom: 1px solid var(--line-2); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
    /* Default row styling for links in the list (any markup works; the current row is aria-current="true"). */
    .oc-split-row { display: flex; align-items: center; gap: .75rem; min-height: 3rem; padding: .625rem 1rem; color: var(--ink-700); text-decoration: none; border-bottom: 1px solid var(--line-2); }
    .oc-split-row:last-child { border-bottom: 0; }
    @media (hover: hover) { .oc-split-row:hover { background: var(--surface-muted); } }
    .oc-split-row:focus-visible { outline: none; box-shadow: var(--ring-inset); }
    .oc-split-row[aria-current="true"] { background: var(--primary-tint); box-shadow: inset 3px 0 0 var(--primary); color: var(--ink-900); }
    .oc-split-row[aria-current="true"]:focus-visible { box-shadow: inset 3px 0 0 var(--primary), var(--ring-inset); }
    html.oc-split-focus .oc-tabbar, html.oc-split-focus .oc-fab, html.oc-split-focus .oc-back-to-top { visibility: hidden; pointer-events: none; }
    html.oc-split-focus .oc-tabbar { transform: translateY(calc(100% + 1px)); }
    html.oc-split-focus, html.oc-split-focus:has(.oc-tabbar) { --oc-bottom-chrome: 0px; }

    /* ---------- Inline edit (_InlineEdit.cshtml, octacer-inlineedit.js) ---------- */
    .oc-inline { display: flex; flex-wrap: wrap; align-items: center; gap: .25rem .5rem; min-width: 0; }
    .oc-inline-view { display: inline-flex; align-items: center; gap: .375rem; max-width: 100%; min-height: 1.75rem; margin: -.25rem -.375rem; padding: .1875rem .375rem;
        border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; color: inherit; font: inherit; text-align: left; cursor: text; }
    .oc-inline-view[hidden] { display: none; }
    .oc-inline-view:focus-visible { outline: none; box-shadow: var(--ring); }
    .oc-inline-text { min-width: 0; white-space: pre-line; overflow-wrap: anywhere; }
    .oc-inline-text.is-empty { color: var(--ink-500); }
    .oc-inline-pen { color: var(--ink-400); opacity: 0; transition: opacity .12s ease; }
    .oc-inline-view:focus-visible .oc-inline-pen { opacity: 1; }
    @media (hover: hover) {
        .oc-inline-view:hover { background: var(--surface-muted); border-color: var(--line); }
        .oc-inline-view:hover .oc-inline-pen { opacity: 1; }
    }
    @media (hover: none) { .oc-inline-pen { opacity: .7; } .oc-inline-view { min-height: 2.75rem; } }
    .oc-inline-editor { display: flex; flex-direction: column; gap: .25rem; flex: 1 1 100%; min-width: 0; }
    .oc-inline-editor[hidden] { display: none; }
    .oc-inline-hint { margin: 0; font-size: .6875rem; color: var(--ink-500); }
    .oc-inline-error { margin: 0; flex-wrap: wrap; }
    .oc-inline-error[hidden] { display: none; }
    .oc-inline-retry { min-height: 1.5rem; padding: 0 .25rem; border: 0; background: transparent; color: inherit; font: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
    .oc-inline-retry[hidden] { display: none; }
    .oc-inline-status { font-size: .75rem; color: var(--ink-500); }
    .oc-inline-status:empty { display: none; }
    .oc-inline.is-saved .oc-inline-status { color: var(--success-subtle-foreground); }
    .oc-inline.is-saved .oc-inline-status::before { content: "✓ " / ""; }
    .oc-inline[data-oc-inline-state="saving"] .oc-inline-control { opacity: .7; }
}

/* =====================================================================================================================
   Form layout — .oc-form-grid (12-col field grid + span helpers), _FormSection (stacked | aside), _FormActions.
   Container-query driven: a form in a drawer / narrow card collapses by ITS width, never the viewport's.
   ===================================================================================================================== */
@layer components {
    /* 12-column field grid. A child spans the full row unless it says otherwise, so forms read top-to-bottom and short
       fields (date, time, number, difficulty) can sit side by side instead of a monotone 50/50 grid. */
    .oc-form-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 1.125rem 1rem; min-width: 0; container: oc-form-grid / inline-size; }
    .oc-form-grid > * { grid-column: 1 / -1; min-width: 0; }
    .oc-form-grid > .oc-span-full { grid-column: 1 / -1; }
    .oc-form-grid > .oc-span-two-thirds { grid-column: span 8; }
    .oc-form-grid > .oc-span-half { grid-column: span 6; }
    .oc-form-grid > .oc-span-third { grid-column: span 4; }
    .oc-form-grid > .oc-span-quarter { grid-column: span 3; }
    .oc-form-grid > .oc-span-start { grid-column-start: 1; }   /* force a new row */
    /* Narrow grids (a drawer / phone): quarters + thirds pair up as halves, wide spans go full. */
    @container oc-form-grid (width < 40rem) {
        .oc-form-grid > :is(.oc-span-quarter, .oc-span-third) { grid-column: span 6; }
        .oc-form-grid > :is(.oc-span-half, .oc-span-two-thirds) { grid-column: 1 / -1; }
    }
    @container oc-form-grid (width < 22rem) {
        .oc-form-grid > * { grid-column: 1 / -1 !important; }
    }
    /* Natural widths for short fields in a stacked (non-grid) form: a time box never stretches across a page. */
    .oc-field-w-xs { max-width: 8.5rem; }
    .oc-field-w-sm { max-width: 12rem; }
    .oc-field-w-md { max-width: 20rem; }
    .oc-field-w-lg { max-width: 32rem; }
    /* A group of related controls laid in one row (e.g. "Mo–Su" + "at 09:00"): wraps, never overflows. */
    .oc-field-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .75rem 1rem; min-width: 0; }
    .oc-field-row > * { min-width: 0; }

    /* _FormSection — a titled group of fields. Stacked: title + description above the fields. Aside (Stripe/Linear
       settings style): title + description in a ~16rem left column, fields on the right; stacks below 48rem. */
    .oc-form-sections { display: flex; flex-direction: column; gap: 2rem; min-width: 0; }
    .oc-form-section { min-width: 0; container: oc-form-section / inline-size; }
    .oc-form-section.is-divided { padding-top: 2rem; border-top: 1px solid var(--line); }
    .oc-form-sections > .oc-form-section.is-divided:first-child { padding-top: 0; border-top: 0; }
    .oc-form-section-inner { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; min-width: 0; }
    .oc-form-section-head { min-width: 0; }
    .oc-form-section-title { margin: 0; font-size: .9375rem; line-height: 1.375rem; font-weight: 600; color: var(--ink-900); text-wrap: balance; }
    .oc-form-section-desc { margin: .25rem 0 0; max-width: 42rem; font-size: .8125rem; line-height: 1.25rem; color: var(--ink-500); text-wrap: pretty; }
    .oc-form-section-body { min-width: 0; }
    .oc-form-section-body.oc-card { padding: 1.25rem; }
    @container oc-form-section (width >= 48rem) {
        .oc-form-section.is-aside > .oc-form-section-inner { grid-template-columns: 16rem minmax(0, 1fr); gap: 1rem 2.5rem; align-items: start; }
        .oc-form-section.is-aside .oc-form-section-head { padding-top: .125rem; }
    }

    /* _FormActions — the form footer. Order (portal-ux §108): destructive at the START, secondary then primary at the
       END (primary rightmost). Phones: full-width, primary on top. Sticky: pinned above the bottom chrome. */
    .oc-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; min-width: 0; padding-top: 1rem; margin-top: .5rem; border-top: 1px solid var(--line-2); }
    .oc-form-actions.is-plain { border-top: 0; padding-top: 0; }
    .oc-form-actions-start, .oc-form-actions-end { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; min-width: 0; }
    .oc-form-actions-end { margin-inline-start: auto; }
    .oc-form-actions-note { min-width: 0; font-size: .75rem; color: var(--ink-500); }
    .oc-form-actions.is-sticky { position: sticky; bottom: var(--oc-bottom-chrome, 0px); z-index: var(--z-sticky); margin-inline: -1rem; padding: .75rem 1rem calc(.75rem + var(--oc-safe-bottom, 0px)); background: color-mix(in srgb, var(--surface) 92%, transparent); -webkit-backdrop-filter: saturate(1.4) blur(8px); backdrop-filter: saturate(1.4) blur(8px); border-top: 1px solid var(--line); }
    .oc-card-body > .oc-form-actions.is-sticky:last-child { margin-bottom: -1rem; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
    @media (max-width: 639px) {
        .oc-form-actions { flex-direction: column-reverse; align-items: stretch; }
        .oc-form-actions-start, .oc-form-actions-end { flex-direction: column-reverse; align-items: stretch; margin-inline-start: 0; }
        .oc-form-actions :is(.btn) { width: 100%; justify-content: center; }
        /* Sticky on a phone: ONE thumb row — [destructive icon] [secondary] [primary] — never a 3-button tower that
           eats a third of the screen. The destructive label stays in the DOM (visually hidden) as its accessible name. */
        .oc-form-actions.is-sticky { flex-direction: row; flex-wrap: nowrap; align-items: center; }
        .oc-form-actions.is-sticky > .oc-form-actions-start { flex: 0 0 auto; flex-direction: row; }
        .oc-form-actions.is-sticky > .oc-form-actions-end { flex: 1 1 auto; flex-direction: row; flex-wrap: nowrap; }
        .oc-form-actions.is-sticky > .oc-form-actions-end > .btn { flex: 1 1 0; width: auto; min-width: 0; }
        .oc-form-actions.is-sticky > .oc-form-actions-start > .btn { width: auto; padding-inline: .75rem; }
        .oc-form-actions.is-sticky > .oc-form-actions-start > .btn > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
        .oc-form-actions.is-sticky .oc-form-actions-note { display: none; }
        html.oc-kb-open .oc-form-actions.is-sticky { position: static; }
    }
}
