/* ============================================================================
   Orcanex design tokens — single source of truth for the redesigned UI.
   Loaded once from Headcss.razor BEFORE every other stylesheet so scoped
   .razor.css files can reference var(--color-accent) etc.
   ============================================================================ */

:root {
    /* Surface */
    --color-bg:           #F7F8FA;
    --color-panel:        #FFFFFF;
    --color-border:       #E6E8EC;
    --color-border-soft:  #EFF1F4;

    /* Text */
    --color-text:         #0F1115;
    --color-text-muted:   #6B7280;
    --color-text-subtle:  #9AA0AA;

    /* Accent (single restrained brand colour). Slate is the system default —
       calm, corporate, "serious software". Other accents override these
       variables under [data-accent="…"] further down. */
    --color-accent:       #475569;
    --color-accent-soft:  #E2E8F0;
    --color-accent-hover: #334155;
    --color-accent-ring:  rgba(71, 85, 105, 0.20);   /* used for focus rings & "is-active" glows */

    /* Semantic tones */
    --color-success:      #0E8F5A;
    --color-success-soft: #E6F4ED;
    --color-warn:         #B6781F;
    --color-warn-soft:    #FBF1DF;
    --color-danger:       #C0322B;
    --color-danger-soft:  #FBE9E7;

    /* Icon-rail palette — rail-bg derives from the user's accent so the menu
       column visibly tints with their chosen palette. 22% accent over a
       mid-dark slate base produces a readable accent presence while keeping
       the rail clearly darker than the page panel. Falls back to flat #0F1115
       on browsers without color-mix support (Chrome <111, Firefox <113). */
    --color-rail-bg:      #0F1115;
    --color-rail-bg:      color-mix(in srgb, var(--color-accent) 22%, #1B1F28);
    --color-rail-fg:      #FFFFFF;
    --color-rail-fg-muted:#8B9099;
    --color-rail-active:  rgba(71, 85, 105, 0.18);
    --color-rail-active-fg:#94A3B8;

    /* Avatar palette (hashed by name) */
    --avatar-1: #E55C5C;
    --avatar-2: #E5904A;
    --avatar-3: #E5B83D;
    --avatar-4: #62B36A;
    --avatar-5: #3FAFA3;
    --avatar-6: #3F8FE5;
    --avatar-7: #7560E5;
    --avatar-8: #C455B0;

    /* Type */
    --font-family: "Inter", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", monospace;

    /* Spacing scale */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-7: 32px;
    --space-8: 48px;

    /* Radius */
    --radius-sm: 6px;   /* chips */
    --radius-md: 8px;   /* fields, buttons */
    --radius-lg: 12px;  /* cards */
    --radius-pill: 999px;

    /* Shadow */
    --shadow-overlay: 0 8px 24px rgba(0, 0, 0, 0.12);
    --shadow-modal:   0 20px 60px rgba(0, 0, 0, 0.30);
    --shadow-toast:   0 8px 24px rgba(0, 0, 0, 0.18);

    /* Heights — field/button heights are calc() so they grow with the user's
       font-scale (the rem term reflects the root font-size). The px term
       is the density component; the rem term is the font-scale component.
       Net result: field text always has comfortable breathing room, even at
       xlarge. Row/topbar heights stay px because they don't contain text. */
    --h-topbar:    52px;
    --h-row:       64px;
    --h-row-md:    48px;
    --h-field:     calc(20px + 1.4rem);   /* ≈38 @ medium / ≈42 @ xlarge */
    --h-button:    calc(18px + 1.4rem);   /* ≈36 / ≈40 */
    --h-button-sm: calc(12px + 1.4rem);   /* ≈30 / ≈34 */

    /* Tight-form variants — used inside .orcanex-form-grid-tight (case form,
       specialist form, configuration pages). These scale with data-density
       so a user who picks comfortable/large still gets bigger fields on tight
       sections, but proportionally smaller than the standard form heights.
       Font tokens are in rem (relative to the 13px medium baseline) so the
       user's data-font-scale preference reaches them via html { font-size }. */
    --h-field-tight:        calc(12px + 1.4rem);   /* ≈30 @ medium / ≈34 @ xlarge */
    --font-tight-field:     0.96rem;
    --font-tight-label:     0.85rem;
    --h-textarea-tight-min: 64px;

    /* Vertical breathing room inside Field primitive: gap between the uppercase
       label and the input below it. Density-aware so larger densities get more
       air to read. */
    --field-label-gap:      6px;

    /* Widths */
    --w-icon-rail: 56px;
    --w-rail-expanded: 248px;   /* wide-rail mode (data-rail-expanded="1"): full logo + labels + sub-menu inline */
    --w-sub-rail:  224px;
    --w-drawer:    320px;

    /* Breakpoints — Bootstrap 5.3 aligned. CSS @media rules can't read custom
       properties, so these are reference constants for documentation and any
       JS that needs them (ViewportService.js mirrors the same numbers). The
       Orcanex viewports map: mobile <768, tablet 768–1199, desktop ≥1200. */
    --bp-mobile-l:    576px;
    --bp-tablet:      768px;
    --bp-tablet-l:    992px;
    --bp-desktop:    1200px;
    --bp-desktop-xl: 1400px;

    /* Mobile bottom-tab nav height (Phase 12). */
    --h-mobile-tabs: 60px;
    /* Mobile-only touch-target floor — Apple HIG / WCAG 2.5.5 AAA. Density
       and font-scale tokens normally drive --h-button etc.; the floor is
       applied via [data-viewport="mobile"] further down. */
    --touch-target: 44px;

    /* Z-index */
    --z-topbar: 30;
    --z-drawer: 40;
    --z-modal:  50;
    --z-toast:  60;

    /* Motion */
    --ease-hover: cubic-bezier(0.2, 0, 0, 1);
    --ease-enter: cubic-bezier(0.4, 0, 0.2, 1);
    --duration-hover: 120ms;
    --duration-enter: 160ms;
}

/* ============================================================================
   Dynamic Theming v1 — attribute-scoped overrides on <html>.

   Driven by user preferences stored on userProfiles and applied client-side
   via /js/user-settings.js applyUserPreferences(). The five axes are:

     data-theme         light (default) | dark
     data-density       compact (default) | comfortable | large
     data-font-scale    small | medium (default) | large | xlarge
     data-accent        blue (default) | teal | indigo | violet | magenta
                        | pink | crimson | amber | forest
     data-list-mode     card (default) | tabular        (consumed by Cases /
                                                         Specialists scoped CSS)

   Plus two boolean toggles:
     data-reduce-motion 0 (default) | 1
     data-high-contrast 0 (default) | 1

   See DOCS/Plans/dynamic-theming-and-user-customisation.md.
   ============================================================================ */

/* ----------------------------------------------------------------------------
   data-theme="dark" — full palette inversion.
   Components stay token-driven; nothing else needs to change.
   ---------------------------------------------------------------------------- */
:root[data-theme="dark"] {
    /* Surface */
    --color-bg:           #0F1115;
    --color-panel:        #161A22;
    --color-border:       #252B36;
    --color-border-soft:  #1D222C;

    /* Text */
    --color-text:         #E5E7EB;
    --color-text-muted:   #9AA0AA;
    --color-text-subtle:  #6B7280;

    /* Accent — lifted to keep contrast on dark surfaces. Slate is the dark
       default; other accents override this under [data-theme="dark"][data-accent="…"]. */
    --color-accent:       #94A3B8;
    --color-accent-soft:  rgba(148, 163, 184, 0.16);
    --color-accent-hover: #B0BFD0;
    --color-accent-ring:  rgba(148, 163, 184, 0.30);

    /* Semantic tones */
    --color-success:      #2DB378;
    --color-success-soft: rgba(45, 179, 120, 0.16);
    --color-warn:         #D89A4A;
    --color-warn-soft:    rgba(216, 154, 74, 0.16);
    --color-danger:       #E5645D;
    --color-danger-soft:  rgba(229, 100, 93, 0.16);

    /* Icon-rail palette — tinted with the accent at 28% over a near-black base
       so the rail visibly picks up the user's chosen palette. */
    --color-rail-bg:      #0A0C10;
    --color-rail-bg:      color-mix(in srgb, var(--color-accent) 28%, #0E1118);
    --color-rail-fg:      #E5E7EB;
    --color-rail-fg-muted:#6B7280;
    --color-rail-active:  rgba(148, 163, 184, 0.22);
    --color-rail-active-fg:#B0BFD0;

    /* Avatar palette — slight desaturation for dark mode legibility */
    --avatar-1: #D44A4A;
    --avatar-2: #D17B33;
    --avatar-3: #D1A22B;
    --avatar-4: #4FA258;
    --avatar-5: #2F9C92;
    --avatar-6: #2F7BC5;
    --avatar-7: #6555C5;
    --avatar-8: #B045A0;

    /* Shadows — deeper to read against dark surfaces */
    --shadow-overlay: 0 8px 24px rgba(0, 0, 0, 0.50);
    --shadow-modal:   0 20px 60px rgba(0, 0, 0, 0.65);
    --shadow-toast:   0 8px 24px rgba(0, 0, 0, 0.55);
}

/* ----------------------------------------------------------------------------
   data-density — comfortable / large overrides.
   Compact is the :root baseline (--h-row 64, --h-field 36, etc.).
   ---------------------------------------------------------------------------- */
:root[data-density="comfortable"] {
    --h-row:        72px;
    --h-row-md:     56px;
    --h-field:      calc(24px + 1.4rem);   /* ≈42 @ medium / ≈46 @ xlarge */
    --h-button:     calc(22px + 1.4rem);
    --h-button-sm:  calc(16px + 1.4rem);
    --space-1: 5px;
    --space-2: 10px;
    --space-3: 14px;
    --space-4: 18px;
    --space-5: 22px;
    --space-6: 28px;
    --space-7: 36px;
    --space-8: 56px;
    --h-field-tight:        calc(20px + 1.4rem);   /* ≈38 @ medium / ≈42 @ xlarge */
    --font-tight-field:     1.04rem;
    --font-tight-label:     0.92rem;
    --h-textarea-tight-min: 80px;
    --field-label-gap:      10px;
}

:root[data-density="large"] {
    --h-row:        84px;
    --h-row-md:     64px;
    --h-field:      calc(32px + 1.4rem);   /* ≈50 @ medium / ≈54 @ xlarge */
    --h-button:     calc(28px + 1.4rem);
    --h-button-sm:  calc(20px + 1.4rem);
    --space-1: 6px;
    --space-2: 12px;
    --space-3: 16px;
    --space-4: 22px;
    --space-5: 28px;
    --space-6: 36px;
    --space-7: 48px;
    --space-8: 72px;
    --h-field-tight:        calc(28px + 1.4rem);   /* ≈46 @ medium / ≈50 @ xlarge */
    --font-tight-field:     1.12rem;
    --font-tight-label:     1rem;
    --h-textarea-tight-min: 96px;
    --field-label-gap:      14px;
}

/* ----------------------------------------------------------------------------
   data-font-scale — html { font-size } drives the rem-based type ramp below.
   Medium is the :root baseline (14px) so no override is needed for it.

   Ramp: 12 / 14 / 16 / 18 px — each step +2px. Medium picked at 14px because
   the previous 13px baseline (Hyper era) felt cramped at standard density.

   These MUST be in px (not rem) because they set the html element's
   font-size, which is the rem reference itself — using rem here would be a
   circular reference.
   ---------------------------------------------------------------------------- */
:root[data-font-scale="small"]  { font-size: 12px; }   /* lint:allow-px — defines the rem reference */
:root[data-font-scale="large"]  { font-size: 16px; }   /* lint:allow-px — defines the rem reference */
:root[data-font-scale="xlarge"] { font-size: 18px; }   /* lint:allow-px — defines the rem reference */

/* ----------------------------------------------------------------------------
   data-accent — 16 curated palettes. Each overrides only the accent + ring;
   semantic tones (success/warn/danger) are unchanged. Dark-mode counterparts
   are scoped under [data-theme="dark"][data-accent="..."] further below.
   "slate" is the :root default and needs no light-mode block.
   ---------------------------------------------------------------------------- */
:root[data-accent="blue"] {
    --color-accent:       #2F62FF;
    --color-accent-soft:  #EAF0FF;
    --color-accent-hover: #1E51EE;
    --color-accent-ring:  rgba(47, 98, 255, 0.20);
    --color-rail-active:  rgba(47, 98, 255, 0.18);
    --color-rail-active-fg:#7B9CFF;
}
:root[data-accent="teal"] {
    --color-accent:       #0E8F8F;
    --color-accent-soft:  #DAF1F1;
    --color-accent-hover: #077676;
    --color-accent-ring:  rgba(14, 143, 143, 0.20);
    --color-rail-active:  rgba(14, 143, 143, 0.18);
    --color-rail-active-fg:#5BC4C4;
}
:root[data-accent="indigo"] {
    --color-accent:       #5C4DE0;
    --color-accent-soft:  #ECEAF9;
    --color-accent-hover: #4A3BCA;
    --color-accent-ring:  rgba(92, 77, 224, 0.20);
    --color-rail-active:  rgba(92, 77, 224, 0.18);
    --color-rail-active-fg:#9990F0;
}
:root[data-accent="violet"] {
    --color-accent:       #7C3AED;
    --color-accent-soft:  #F2EBFB;
    --color-accent-hover: #6A2DD6;
    --color-accent-ring:  rgba(124, 58, 237, 0.20);
    --color-rail-active:  rgba(124, 58, 237, 0.18);
    --color-rail-active-fg:#B791F4;
}
:root[data-accent="magenta"] {
    --color-accent:       #C8359E;
    --color-accent-soft:  #F9E5F0;
    --color-accent-hover: #B22A8B;
    --color-accent-ring:  rgba(200, 53, 158, 0.20);
    --color-rail-active:  rgba(200, 53, 158, 0.18);
    --color-rail-active-fg:#E08CC8;
}
:root[data-accent="pink"] {
    --color-accent:       #E14B89;
    --color-accent-soft:  #FCE6EE;
    --color-accent-hover: #C73B75;
    --color-accent-ring:  rgba(225, 75, 137, 0.20);
    --color-rail-active:  rgba(225, 75, 137, 0.18);
    --color-rail-active-fg:#F197B6;
}
:root[data-accent="crimson"] {
    --color-accent:       #C0322B;
    --color-accent-soft:  #FBE9E7;
    --color-accent-hover: #A52822;
    --color-accent-ring:  rgba(192, 50, 43, 0.20);
    --color-rail-active:  rgba(192, 50, 43, 0.18);
    --color-rail-active-fg:#E08881;
}
:root[data-accent="amber"] {
    --color-accent:       #B6781F;
    --color-accent-soft:  #FBF1DF;
    --color-accent-hover: #9C681A;
    --color-accent-ring:  rgba(182, 120, 31, 0.20);
    --color-rail-active:  rgba(182, 120, 31, 0.18);
    --color-rail-active-fg:#E0AC65;
}
:root[data-accent="forest"] {
    --color-accent:       #286A47;
    --color-accent-soft:  #DCEDE2;
    --color-accent-hover: #1F5739;
    --color-accent-ring:  rgba(40, 106, 71, 0.20);
    --color-rail-active:  rgba(40, 106, 71, 0.18);
    --color-rail-active-fg:#7FBE99;
}
/* Cyan — modern AI / medical-tech / dashboards. */
:root[data-accent="cyan"] {
    --color-accent:       #06B6D4;
    --color-accent-soft:  #CFFAFE;
    --color-accent-hover: #0891B2;
    --color-accent-ring:  rgba(6, 182, 212, 0.20);
    --color-rail-active:  rgba(6, 182, 212, 0.18);
    --color-rail-active-fg:#67E8F9;
}
/* Emerald — clean, healthy, success-focused — sits well on clinical pages. */
:root[data-accent="emerald"] {
    --color-accent:       #10B981;
    --color-accent-soft:  #D1FAE5;
    --color-accent-hover: #059669;
    --color-accent-ring:  rgba(16, 185, 129, 0.20);
    --color-rail-active:  rgba(16, 185, 129, 0.18);
    --color-rail-active-fg:#6EE7B7;
}
/* Rose — softer alternative to crimson; polished, modern, less aggressive. */
:root[data-accent="rose"] {
    --color-accent:       #F43F5E;
    --color-accent-soft:  #FFE4E6;
    --color-accent-hover: #E11D48;
    --color-accent-ring:  rgba(244, 63, 94, 0.20);
    --color-rail-active:  rgba(244, 63, 94, 0.18);
    --color-rail-active-fg:#FB7185;
}
/* Navy — premium corporate; pairs especially well with the dark sidebar. */
:root[data-accent="navy"] {
    --color-accent:       #1E3A8A;
    --color-accent-soft:  #DBE5F7;
    --color-accent-hover: #172E6E;
    --color-accent-ring:  rgba(30, 58, 138, 0.20);
    --color-rail-active:  rgba(30, 58, 138, 0.18);
    --color-rail-active-fg:#7FA0F0;
}
/* Graphite — minimalist mono; "Linear.app"-style understated chrome. */
:root[data-accent="graphite"] {
    --color-accent:       #3F3F46;
    --color-accent-soft:  #E4E4E7;
    --color-accent-hover: #27272A;
    --color-accent-ring:  rgba(63, 63, 70, 0.20);
    --color-rail-active:  rgba(63, 63, 70, 0.22);
    --color-rail-active-fg:#A1A1AA;
}
/* Copper — premium warm; sits naturally with Orca branding. */
:root[data-accent="copper"] {
    --color-accent:       #B45309;
    --color-accent-soft:  #FFEDD5;
    --color-accent-hover: #92400E;
    --color-accent-ring:  rgba(180, 83, 9, 0.20);
    --color-rail-active:  rgba(180, 83, 9, 0.18);
    --color-rail-active-fg:#E0A45F;
}

/* Dark-mode accent variants — boost lightness for contrast on dark surfaces. */
:root[data-theme="dark"][data-accent="teal"] {
    --color-accent:       #4FBDB5;
    --color-accent-soft:  rgba(79, 189, 181, 0.16);
    --color-accent-hover: #6CCFC8;
    --color-accent-ring:  rgba(79, 189, 181, 0.32);
    --color-rail-active:  rgba(79, 189, 181, 0.22);
    --color-rail-active-fg:#7FD4CC;
}
:root[data-theme="dark"][data-accent="indigo"] {
    --color-accent:       #8B7BFF;
    --color-accent-soft:  rgba(139, 123, 255, 0.16);
    --color-accent-hover: #A294FF;
    --color-accent-ring:  rgba(139, 123, 255, 0.32);
    --color-rail-active:  rgba(139, 123, 255, 0.22);
    --color-rail-active-fg:#A99CFF;
}
:root[data-theme="dark"][data-accent="violet"] {
    --color-accent:       #A77AFF;
    --color-accent-soft:  rgba(167, 122, 255, 0.16);
    --color-accent-hover: #B894FF;
    --color-accent-ring:  rgba(167, 122, 255, 0.32);
    --color-rail-active:  rgba(167, 122, 255, 0.22);
    --color-rail-active-fg:#C2A5FF;
}
:root[data-theme="dark"][data-accent="magenta"] {
    --color-accent:       #E27DC0;
    --color-accent-soft:  rgba(226, 125, 192, 0.16);
    --color-accent-hover: #EA98CD;
    --color-accent-ring:  rgba(226, 125, 192, 0.32);
    --color-rail-active:  rgba(226, 125, 192, 0.22);
    --color-rail-active-fg:#EBA5D2;
}
:root[data-theme="dark"][data-accent="pink"] {
    --color-accent:       #F285AD;
    --color-accent-soft:  rgba(242, 133, 173, 0.16);
    --color-accent-hover: #F69EBF;
    --color-accent-ring:  rgba(242, 133, 173, 0.32);
    --color-rail-active:  rgba(242, 133, 173, 0.22);
    --color-rail-active-fg:#F4A8C0;
}
:root[data-theme="dark"][data-accent="crimson"] {
    --color-accent:       #E5736C;
    --color-accent-soft:  rgba(229, 115, 108, 0.16);
    --color-accent-hover: #ED8E88;
    --color-accent-ring:  rgba(229, 115, 108, 0.32);
    --color-rail-active:  rgba(229, 115, 108, 0.22);
    --color-rail-active-fg:#EE9690;
}
:root[data-theme="dark"][data-accent="amber"] {
    --color-accent:       #E0A45F;
    --color-accent-soft:  rgba(224, 164, 95, 0.16);
    --color-accent-hover: #ECB97D;
    --color-accent-ring:  rgba(224, 164, 95, 0.32);
    --color-rail-active:  rgba(224, 164, 95, 0.22);
    --color-rail-active-fg:#ECBC85;
}
:root[data-theme="dark"][data-accent="forest"] {
    --color-accent:       #5DAE82;
    --color-accent-soft:  rgba(93, 174, 130, 0.16);
    --color-accent-hover: #76C09A;
    --color-accent-ring:  rgba(93, 174, 130, 0.32);
    --color-rail-active:  rgba(93, 174, 130, 0.22);
    --color-rail-active-fg:#85C8A4;
}
:root[data-theme="dark"][data-accent="blue"] {
    --color-accent:       #5C82FF;
    --color-accent-soft:  rgba(92, 130, 255, 0.16);
    --color-accent-hover: #7090FF;
    --color-accent-ring:  rgba(92, 130, 255, 0.32);
    --color-rail-active:  rgba(92, 130, 255, 0.22);
    --color-rail-active-fg:#7B9CFF;
}
:root[data-theme="dark"][data-accent="cyan"] {
    --color-accent:       #22D3EE;
    --color-accent-soft:  rgba(34, 211, 238, 0.16);
    --color-accent-hover: #67E8F9;
    --color-accent-ring:  rgba(34, 211, 238, 0.32);
    --color-rail-active:  rgba(34, 211, 238, 0.22);
    --color-rail-active-fg:#67E8F9;
}
:root[data-theme="dark"][data-accent="emerald"] {
    --color-accent:       #34D399;
    --color-accent-soft:  rgba(52, 211, 153, 0.16);
    --color-accent-hover: #6EE7B7;
    --color-accent-ring:  rgba(52, 211, 153, 0.32);
    --color-rail-active:  rgba(52, 211, 153, 0.22);
    --color-rail-active-fg:#6EE7B7;
}
:root[data-theme="dark"][data-accent="rose"] {
    --color-accent:       #FB7185;
    --color-accent-soft:  rgba(251, 113, 133, 0.16);
    --color-accent-hover: #FDA4AF;
    --color-accent-ring:  rgba(251, 113, 133, 0.32);
    --color-rail-active:  rgba(251, 113, 133, 0.22);
    --color-rail-active-fg:#FDA4AF;
}
:root[data-theme="dark"][data-accent="navy"] {
    --color-accent:       #6F8AE0;
    --color-accent-soft:  rgba(111, 138, 224, 0.16);
    --color-accent-hover: #8FA5E8;
    --color-accent-ring:  rgba(111, 138, 224, 0.32);
    --color-rail-active:  rgba(111, 138, 224, 0.22);
    --color-rail-active-fg:#8FA5E8;
}
:root[data-theme="dark"][data-accent="graphite"] {
    --color-accent:       #A1A1AA;
    --color-accent-soft:  rgba(161, 161, 170, 0.16);
    --color-accent-hover: #BCBCC4;
    --color-accent-ring:  rgba(161, 161, 170, 0.32);
    --color-rail-active:  rgba(161, 161, 170, 0.22);
    --color-rail-active-fg:#BCBCC4;
}
:root[data-theme="dark"][data-accent="copper"] {
    --color-accent:       #D97A28;
    --color-accent-soft:  rgba(217, 122, 40, 0.16);
    --color-accent-hover: #E59B5B;
    --color-accent-ring:  rgba(217, 122, 40, 0.32);
    --color-rail-active:  rgba(217, 122, 40, 0.22);
    --color-rail-active-fg:#E59B5B;
}
/* The dark+slate combination is already correct via the dark base palette,
   so no override is needed for [data-theme="dark"][data-accent="slate"]. */

/* ----------------------------------------------------------------------------
   data-reduce-motion — disable transitions and animations.
   Honours an OS-level prefers-reduced-motion if the user hasn't set it.
   ---------------------------------------------------------------------------- */
:root[data-reduce-motion="1"] {
    --duration-hover: 0ms;
    --duration-enter: 0ms;
}

:root[data-reduce-motion="1"] *,
:root[data-reduce-motion="1"] *::before,
:root[data-reduce-motion="1"] *::after {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
}

@media (prefers-reduced-motion: reduce) {
    :root:not([data-reduce-motion="0"]) {
        --duration-hover: 0ms;
        --duration-enter: 0ms;
    }
}

/* ----------------------------------------------------------------------------
   data-viewport — sixth axis. Set on <html> by App.razor's inline boot script
   and re-asserted on debounced window.resize by user-settings.js. Drives the
   mobile/tablet/desktop touch-target floor below and is consumed by primitives
   and shell components. See DOCS/Architecture/responsive-design.md.
   Values: mobile, mobile-l, tablet, tablet-l, desktop, desktop-xl.
   ---------------------------------------------------------------------------- */
:root[data-viewport="mobile"],
:root[data-viewport="mobile-l"] {
    /* Touch-target floor — Apple HIG / WCAG 2.5.5 AAA. Field/Button heights
       always meet 44px regardless of density or font-scale. */
    --h-button:     max(var(--touch-target), calc(20px + 1.4rem));
    --h-button-sm:  max(var(--touch-target), calc(14px + 1.4rem));
    --h-field:      max(var(--touch-target), calc(22px + 1.4rem));
    --h-field-tight:max(var(--touch-target), calc(14px + 1.4rem));
    --h-row:        max(56px, var(--h-row));
}

/* Display utility classes — escape hatch for one-off cases primitives don't
   cover. Use sparingly; primitives should handle the common reflow. Mirrors
   Bootstrap d-* responsive utilities but avoids importing the whole utility
   layer.

   Show-only logic: rather than force the element hidden by default and use
   `display: revert` to reveal it (which forces `display: block` and beats
   any layout-critical `display: flex/grid` on the same element), we only
   apply `display: none !important` at the WRONG breakpoints. At the right
   breakpoint the element renders with its natural display value. */
@media (min-width: 768px) {
    .show-mobile-only { display: none !important; }
}
@media (max-width: 767.98px), (min-width: 1200px) {
    .show-tablet-only { display: none !important; }
}
@media (max-width: 1199.98px) {
    .show-desktop-only { display: none !important; }
}

@media (max-width: 767.98px)   { .hide-mobile { display: none !important; } }
@media (max-width: 1199.98px)  { .hide-tablet-down { display: none !important; } }
@media (min-width: 1200px)     { .hide-desktop-up { display: none !important; } }

/* ----------------------------------------------------------------------------
   Mobile bottom-tab clearance — global page-root padding.

   The mobile bottom-tab strip is `position: fixed` at the bottom of the
   viewport and renders OVER the bottom of the scrollable page. Every
   page wrapper that scrolls inside `.orcanex-frame-content` needs an
   internal padding-bottom equal to the strip's full rendered height
   (60px + safe-area-inset on iOS) plus visual breathing room — without
   it, the last form field / row gets hidden behind the strip.

   The padding MUST live on the page WRAPPER (a block element, not the
   flex scroll container) — Chromium has a long-standing bug where
   padding-bottom on a `display: flex; overflow: auto;` container is
   NOT included in the scrollable area
   (https://bugs.chromium.org/p/chromium/issues/detail?id=748518). The
   user reported "can't scroll past the last field" on SpecialistForm,
   UserDetails and friends — that's exactly this bug. Putting the
   padding on the block child makes the child taller; the flex parent
   then naturally extends its scroll area to fit. No bug, no spacer
   tricks needed.

   Pages with their OWN internal scroll (e.g. `.orcanex-cases-page`
   uses an inner virtualised list that handles its own bottom inset)
   don't need this — when the page root is itself flex-fill-height and
   doesn't bubble scroll up to `.orcanex-frame-content`, the padding
   here is harmless (it pads a non-scrolling box).

   Belt-and-braces approach because the previous single-rule fixes
   didn't stick visually for the user:
     1. `padding-bottom` on the last direct child of frame-content
        (block element, no Chromium flex/padding bug).
     2. `::after` flex spacer on frame-content itself as a fallback
        when the page wrapper has `min-height: 100%` and the browser
        keeps its scroll region at exactly the parent height.
     3. `scroll-padding-bottom` on frame-content so any scroll-into-
        view calls also respect the bottom inset. */
:root[data-viewport="mobile"]   .orcanex-frame-content > *:last-child,
:root[data-viewport="mobile-l"] .orcanex-frame-content > *:last-child {
    padding-bottom: calc(var(--h-mobile-tabs) + env(safe-area-inset-bottom, 0px) + var(--space-4)) !important;
}

/* CRITICAL: target the INNER content wrapper, not the page wrapper.
   The user's dev tools confirmed `.orcanex-user-details-page` is
   clamped to ~591 px by `min-height: 100%` interacting with flex,
   while its CHILD `.orcanex-user-details-body` is the element whose
   box actually grows with content (1245 px in the user's case). The
   form fields live inside the body, so the body's bottom edge is
   what ends up clipped behind the bottom-tab strip — adding padding
   to the page wrapper above is useless because the body overflows
   it anyway.

   Pattern: apply the bottom inset to the element whose box grows
   with the content. For UserDetails that's `.orcanex-user-details-body`;
   for SpecialistForm that's `.orcanex-specialist-tab-content`; for
   ClientDetails the equivalent inner content wrapper. */
:root[data-viewport="mobile"]   .orcanex-user-details-body,
:root[data-viewport="mobile-l"] .orcanex-user-details-body,
:root[data-viewport="mobile"]   .orcanex-specialist-tab-content,
:root[data-viewport="mobile-l"] .orcanex-specialist-tab-content,
:root[data-viewport="mobile"]   .orcanex-client-details-content,
:root[data-viewport="mobile-l"] .orcanex-client-details-content {
    padding-bottom: calc(var(--h-mobile-tabs) + env(safe-area-inset-bottom, 0px) + var(--space-4)) !important;
}

/* Keep the page-wrapper rule as a fallback for pages that DO grow
   their wrapper with content (rather than clamping at viewport
   height). Harmless on pages where the wrapper is clamped — the
   padding is inside the clamped box and ignored. */
:root[data-viewport="mobile"]   .orcanex-user-details-page,
:root[data-viewport="mobile-l"] .orcanex-user-details-page,
:root[data-viewport="mobile"]   .orcanex-specialist-form,
:root[data-viewport="mobile-l"] .orcanex-specialist-form,
:root[data-viewport="mobile"]   .orcanex-client-details-page,
:root[data-viewport="mobile-l"] .orcanex-client-details-page,
:root[data-viewport="mobile"]   .orcanex-external-user-details-page,
:root[data-viewport="mobile-l"] .orcanex-external-user-details-page {
    padding-bottom: calc(var(--h-mobile-tabs) + env(safe-area-inset-bottom, 0px) + var(--space-4)) !important;
}

:root[data-viewport="mobile"]   .orcanex-frame-content::after,
:root[data-viewport="mobile-l"] .orcanex-frame-content::after {
    content: "" !important;
    display: block !important;
    flex-shrink: 0 !important;
    height: calc(var(--h-mobile-tabs) + env(safe-area-inset-bottom, 0px) + var(--space-4)) !important;
    width: 100% !important;
}

:root[data-viewport="mobile"]   .orcanex-frame-content,
:root[data-viewport="mobile-l"] .orcanex-frame-content {
    scroll-padding-bottom: calc(var(--h-mobile-tabs) + env(safe-area-inset-bottom, 0px) + var(--space-4)) !important;
    /* CACHE-BUSTER MARKER 2026-05-11-A — if you can't see this property
       in dev tools when inspecting `<main class="orcanex-frame-content">`,
       your browser is serving a cached tokens.css. */
    --bottom-tab-clearance: 76px;
}

/* ----------------------------------------------------------------------------
   Bootstrap legacy modals — mobile full-screen.

   `<OrcanexModal>` already goes full-screen at mobile via its own scoped CSS.
   This block does the same for any raw Bootstrap `.modal-dialog` markup that
   hasn't been migrated yet. Apply globally so we don't have to copy these
   overrides into every page that hosts a legacy modal.

   The recipe (and the two common mistakes) is documented in
   DOCS/Architecture/responsive-design.md under "Modal full-screen at mobile
   (Bootstrap legacy)". Per-page overrides can still raise specificity for
   bespoke needs, but the default mobile experience is now sane.
   ---------------------------------------------------------------------------- */
:root[data-viewport="mobile"]   .modal-dialog,
:root[data-viewport="mobile-l"] .modal-dialog {
    max-width: 100% !important;
    width: 100%;
    margin: 0 !important;
    height: 100dvh;
    max-height: 100dvh;
}

/* Bootstrap's `.modal-dialog-centered` adds `align-items: center` which
   vertically centers a short modal-content within the full-height dialog.
   Override to `stretch` so content fills the dialog. */
:root[data-viewport="mobile"]   .modal-dialog-centered,
:root[data-viewport="mobile-l"] .modal-dialog-centered {
    align-items: stretch !important;
}

/* Modal-content fills the dialog; flex-column so body grows and footer
   shrinks. Body's `max-height: none` lifts any desktop-era `Nvh` cap that
   would otherwise prevent flex-grow (a common pattern in older modal CSS). */
:root[data-viewport="mobile"]   .modal-dialog .modal-content,
:root[data-viewport="mobile-l"] .modal-dialog .modal-content {
    height: 100%;
    border-radius: 0;
    border: none;
    display: flex;
    flex-direction: column;
}

/* Common pattern: `<EditForm>` (which Blazor renders as `<form>`) wraps
   both `.modal-body` and `.modal-footer` so the submit button can post the
   form. The form then becomes the direct child of `.modal-content`, and
   the body/footer aren't direct children of any flex container — so the
   `flex: 1 1 auto` on body and `flex-shrink: 0` on footer don't kick in,
   body collapses to content height, and the footer drifts mid-modal with
   form fields overflowing into the backdrop.

   Fix: any single wrapper element (`<form>`, `<EditForm>` → `<form>`,
   plain `<div>`) that sits as a direct child of `.modal-content` becomes
   a flex-column of its own, transparently passing the flex context down
   to the body/footer it wraps. Body still grows, footer still pins. */
:root[data-viewport="mobile"]   .modal-dialog .modal-content > form,
:root[data-viewport="mobile-l"] .modal-dialog .modal-content > form,
:root[data-viewport="mobile"]   .modal-dialog .modal-content > .modal-content-wrap,
:root[data-viewport="mobile-l"] .modal-dialog .modal-content > .modal-content-wrap {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

:root[data-viewport="mobile"]   .modal-dialog .modal-content .modal-body,
:root[data-viewport="mobile-l"] .modal-dialog .modal-content .modal-body {
    flex: 1 1 auto;
    max-height: none !important;
    overflow-y: auto;
    min-height: 0;
}

/* Footer flush at the bottom via flex (NOT `position: sticky` — sticky only
   activates on overflow, leaving the footer floating mid-modal on short
   forms). iOS safe-area-inset for the home bar. */
:root[data-viewport="mobile"]   .modal-dialog .modal-content .modal-footer,
:root[data-viewport="mobile-l"] .modal-dialog .modal-content .modal-footer {
    flex-shrink: 0;
    background: var(--color-panel);
    border-top: 1px solid var(--color-border);
    padding: var(--space-3) var(--space-4);
    padding-bottom: max(var(--space-3), env(safe-area-inset-bottom));
}

/* ----------------------------------------------------------------------------
   data-high-contrast — boost border darkness, deepen muted text, thicker focus.
   ---------------------------------------------------------------------------- */
:root[data-high-contrast="1"] {
    --color-border:       #B5BAC4;
    --color-border-soft:  #C8CCD3;
    --color-text-muted:   #4B5260;
    --color-text-subtle:  #6B7280;
}
:root[data-theme="dark"][data-high-contrast="1"] {
    --color-border:       #4D5666;
    --color-border-soft:  #3C4452;
    --color-text-muted:   #C8CCD3;
    --color-text-subtle:  #9AA0AA;
}

:root[data-high-contrast="1"] :focus-visible {
    outline-width: 3px !important;
    outline-offset: 2px;
}

/* ----------------------------------------------------------------------------
   App-wide font + reset.
   The Hyper theme's app-modern.css sets font-family on body — we override here
   so Inter wins until Hyper is removed in Phase 11.
   ---------------------------------------------------------------------------- */
/* Root font-size = 13px baseline. Overridden by data-font-scale (above) so
   `rem`-based type-ramp utilities (.t-h1, .t-body etc.) scale automatically.
   Body inherits from html so the cascade isn't broken by an explicit body
   font-size. */
html { font-size: 14px; }   /* lint:allow-px — rem baseline, overridden by [data-font-scale] above */

html,
body {
    margin: 0;
    padding: 0;
    font-family: var(--font-family);
    line-height: 1.5;
    color: var(--color-text);
    background: var(--color-bg);
}

/* Tabular numerics for any list/table cell */
.orcanex-num,
.orcanex-list td,
.orcanex-list th {
    font-variant-numeric: tabular-nums;
}

/* Type ramp utility classes — rem-based so they scale with data-font-scale
   (medium baseline = 13px; small=12, large=14, xlarge=16). */
.t-display-l   { font-size: 2.77rem; font-weight: 600; line-height: 1.15; letter-spacing: -0.6px; }   /* ≈36px */
.t-h1          { font-size: 1.69rem; font-weight: 600; line-height: 1.25; letter-spacing: -0.3px; }   /* ≈22px */
.t-h2          { font-size: 1.38rem; font-weight: 600; line-height: 1.3;  }                          /* ≈18px */
.t-h3          { font-size: 1.08rem; font-weight: 600; line-height: 1.4;  }                          /* ≈14px */
.t-body        { font-size: 1rem;    font-weight: 400; line-height: 1.5;  }                          /* =13px */
.t-body-strong { font-size: 1rem;    font-weight: 600; line-height: 1.5;  }
.t-label       { font-size: 0.92rem; font-weight: 500; line-height: 1.4;  }                          /* ≈12px */
.t-meta        { font-size: 0.85rem; font-weight: 500; line-height: 1.4;  color: var(--color-text-muted); }   /* ≈11px */
.t-kicker      { font-size: 0.85rem; font-weight: 600; line-height: 1.4;  letter-spacing: 1.2px; text-transform: uppercase; color: var(--color-text-muted); }
.t-mono        { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* Focus ring — never remove default focus, just restyle */
.orcanex-focus:focus-visible,
.orcanex-focus:focus-within {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* Suppress focus rings for programmatic .focus() calls — keyboard users
   still see the ring via :focus-visible. */
:focus:not(:focus-visible) {
    outline: none;
}

/* Headings are never interactive, but Blazor's <FocusOnNavigate Selector="h1">
   in Routes.razor programmatically focuses the page heading after every
   navigation so screen readers announce the new page. Chrome treats focus on
   page-load as :focus-visible (no prior mouse interaction to disqualify it),
   so we have to suppress the outline explicitly on headings — including
   :focus-visible — to stop the black border appearing around the page title.
   Keyboard users tabbing the page never reach a non-interactive heading
   anyway because it's not in the tab order. */
h1:focus, h1:focus-visible,
h2:focus, h2:focus-visible,
h3:focus, h3:focus-visible,
h4:focus, h4:focus-visible,
h5:focus, h5:focus-visible,
h6:focus, h6:focus-visible {
    outline: none;
}

/* Hover lift — used on rows and cards */
.orcanex-hover:hover {
    background: var(--color-bg);
    transition: background var(--duration-hover) var(--ease-hover);
}

/* ============================================================================
   Bootstrap / Hyper retrofit overrides.
   The big-bang migration keeps Bootstrap markup on legacy pages but repaints
   the common utility classes with Orcanex tokens. Pages that already use
   Orcanex primitives (Btn, Card, Pill, Field) ignore these — primitives win
   via class specificity.
   ============================================================================ */

/* Surface */
body, .content-page, .wrapper {
    background: var(--color-bg) !important;
}

/* Cards */
.card {
    background: var(--color-panel);
    border: 1px solid var(--color-border) !important;
    border-radius: var(--radius-lg) !important;
    box-shadow: none !important;
}
.card.shadow-sm {
    box-shadow: none !important;
}
.card-header {
    background: var(--color-panel) !important;
    border-bottom: 1px solid var(--color-border-soft) !important;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0 !important;
    padding: 12px 16px !important;
    font-size: 1.08rem !important;
    font-weight: 600 !important;
    color: var(--color-text) !important;
}
.card-body { padding: 16px; }
.card-footer {
    background: var(--color-panel) !important;
    border-top: 1px solid var(--color-border-soft) !important;
}

/* Buttons */
.btn {
    border-radius: var(--radius-md) !important;
    font-weight: 500 !important;
    font-size: 1rem !important;
    padding: 0 12px !important;
    height: var(--h-button);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    line-height: 1;
    transition: background var(--duration-hover) var(--ease-hover),
                border-color var(--duration-hover) var(--ease-hover),
                color var(--duration-hover) var(--ease-hover);
}
.btn-sm, .btn-group-sm > .btn {
    height: var(--h-button-sm);
    padding: 0 10px !important;
    font-size: 0.92rem !important;
}
.btn-primary {
    background: var(--color-accent) !important;
    border-color: var(--color-accent) !important;
    color: #fff !important;
}
.btn-primary:hover, .btn-primary:focus {
    background: var(--color-accent-hover) !important;
    border-color: var(--color-accent-hover) !important;
    color: #fff !important;
}
.btn-outline-primary {
    color: var(--color-accent) !important;
    border-color: var(--color-border) !important;
    background: var(--color-panel) !important;
}
.btn-outline-primary:hover {
    background: var(--color-accent-soft) !important;
    color: var(--color-accent) !important;
    border-color: var(--color-accent) !important;
}
.btn-secondary, .btn-light, .btn-outline-secondary {
    background: var(--color-panel) !important;
    border-color: var(--color-border) !important;
    color: var(--color-text) !important;
}
.btn-secondary:hover, .btn-light:hover, .btn-outline-secondary:hover {
    background: var(--color-bg) !important;
    border-color: var(--color-border) !important;
    color: var(--color-text) !important;
}
.btn-success {
    background: var(--color-success) !important;
    border-color: var(--color-success) !important;
    color: #fff !important;
}
.btn-warning {
    background: var(--color-warn) !important;
    border-color: var(--color-warn) !important;
    color: #fff !important;
}
.btn-danger {
    background: var(--color-danger) !important;
    border-color: var(--color-danger) !important;
    color: #fff !important;
}
.btn-outline-danger {
    color: var(--color-danger) !important;
    border-color: var(--color-border) !important;
    background: var(--color-panel) !important;
}
.btn-outline-danger:hover {
    background: var(--color-danger-soft) !important;
    color: var(--color-danger) !important;
    border-color: var(--color-danger) !important;
}
.btn-link {
    color: var(--color-accent) !important;
    text-decoration: none !important;
}
.btn-link:hover { text-decoration: underline !important; }

/* Badges */
.badge {
    font-weight: 500 !important;
    font-size: 0.85rem !important;
    padding: 2px 8px !important;
    border-radius: var(--radius-pill) !important;
    line-height: 1.4;
    letter-spacing: 0.1px;
}
.badge.bg-primary, .bg-primary { background: var(--color-accent-soft) !important; color: var(--color-accent) !important; }
.badge.bg-success, .bg-success { background: var(--color-success-soft) !important; color: var(--color-success) !important; }
.badge.bg-warning, .bg-warning { background: var(--color-warn-soft) !important; color: var(--color-warn) !important; }
.badge.bg-danger, .bg-danger   { background: var(--color-danger-soft) !important; color: var(--color-danger) !important; }
.badge.bg-info,    .bg-info    { background: var(--color-accent-soft) !important; color: var(--color-accent) !important; }
.badge.bg-secondary, .bg-secondary { background: #F1F3F6 !important; color: #3B414B !important; }
.badge.bg-light    { background: var(--color-bg) !important; color: var(--color-text) !important; }

/* Form fields */
.form-control, .form-select {
    height: var(--h-field);
    padding: 0 12px !important;
    border: 1px solid var(--color-border) !important;
    border-radius: var(--radius-md) !important;
    background: var(--color-panel) !important;
    color: var(--color-text) !important;
    font-size: 1rem !important;
    line-height: 1.4;
    box-shadow: none !important;
    transition: border-color var(--duration-hover) var(--ease-hover);
}
textarea.form-control { height: auto; min-height: 80px; padding: 8px 12px !important; }

/* Native file inputs need the button to fill the full input height — without
   this rule the "Choose file" button + filename hug the top of the box and
   leave dead space below. Bootstrap's vendor CSS sets a NEGATIVE margin on
   ::file-selector-button (margin: -.45rem -.9rem) so the button fills the
   parent's padding-box. Because our global .form-control has padding: 0 12px,
   the button's negative top-margin pulls it above the box. We override both:
   reset the parent padding/layout AND zero-out the button's negative margin. */
.form-control[type="file"] {
    padding: 0 !important;
    display: inline-flex !important;
    align-items: stretch !important;
    overflow: hidden;
    cursor: pointer;
    line-height: 1 !important;
}
.form-control[type="file"]::file-selector-button {
    margin: 0 12px 0 0 !important;
    margin-inline-end: 12px !important;
    padding: 0 14px !important;
    height: auto !important;
    align-self: stretch;
    border: 0 !important;
    border-right: 1px solid var(--color-border) !important;
    border-inline-end: 1px solid var(--color-border) !important;
    background-color: var(--color-bg) !important;
    color: var(--color-text) !important;
    font-family: var(--font-family) !important;
    font-size: 1rem !important;
    font-weight: 500 !important;
    line-height: var(--h-field) !important;
    cursor: pointer;
    transition: background-color var(--duration-hover) var(--ease-hover), color var(--duration-hover) var(--ease-hover);
}
.form-control[type="file"]::-webkit-file-upload-button {
    margin: 0 12px 0 0 !important;
    padding: 0 14px !important;
    height: auto !important;
    border: 0 !important;
    border-right: 1px solid var(--color-border) !important;
    background-color: var(--color-bg) !important;
    color: var(--color-text) !important;
    font-family: var(--font-family) !important;
    font-size: 1rem !important;
    font-weight: 500 !important;
    line-height: var(--h-field) !important;
    cursor: pointer;
}
.form-control[type="file"]::file-selector-button:hover {
    background-color: var(--color-accent-soft) !important;
    color: var(--color-accent) !important;
}
.form-control[type="file"]::-webkit-file-upload-button:hover {
    background-color: var(--color-accent-soft) !important;
    color: var(--color-accent) !important;
}
.form-control[type="file"]:disabled,
.form-control[type="file"][disabled] {
    cursor: not-allowed;
}
.form-control[type="file"]:disabled::file-selector-button {
    cursor: not-allowed;
    opacity: 0.6;
}
.form-control-sm, .form-select-sm {
    height: var(--h-button-sm);
    padding: 0 10px !important;
    font-size: 0.92rem !important;
}
.form-control:focus, .form-select:focus {
    outline: none !important;
    border-color: var(--color-accent) !important;
    box-shadow: 0 0 0 3px var(--color-accent-ring) !important;
}
.form-control::placeholder, .form-select::placeholder {
    color: var(--color-text-subtle);
}
.form-label {
    font-size: 0.92rem !important;
    font-weight: 500 !important;
    color: var(--color-text) !important;
    margin-bottom: 6px;
}
.input-group-text {
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    color: var(--color-text-muted);
    font-size: 0.92rem;
}

/* Tables */
.table {
    --bs-table-bg: var(--color-panel);
    --bs-table-color: var(--color-text);
    --bs-table-border-color: var(--color-border-soft);
    font-size: 1rem;
    color: var(--color-text);
}
.table > thead {
    background: var(--color-bg);
}
.table > thead th {
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: var(--color-text-muted);
    border-bottom: 1px solid var(--color-border) !important;
    padding: 10px 12px;
}
.table tbody tr:hover {
    background: var(--color-bg);
}
.table tbody td {
    padding: 10px 12px;
    border-color: var(--color-border-soft);
    vertical-align: middle;
}

/* Alerts */
.alert {
    border-radius: var(--radius-md) !important;
    border: none !important;
    padding: 10px 12px !important;
    font-size: 1rem !important;
    line-height: 1.45;
}
.alert-success { background: var(--color-success-soft) !important; color: var(--color-success) !important; }
.alert-warning { background: var(--color-warn-soft) !important;    color: var(--color-warn) !important; }
.alert-danger  { background: var(--color-danger-soft) !important;  color: var(--color-danger) !important; }
.alert-info    { background: var(--color-accent-soft) !important;  color: var(--color-accent) !important; }

/* ----------------------------------------------------------------------------
   Form check / radio / switch — Bootstrap retrofit.

   Bootstrap defaults render `.form-check-input` with a faint 1px border in
   `#dee2e6` and the checked state in Bootstrap's primary blue (`#0d6efd`).
   Against an Orcanex panel surface that's barely visible, which is why the
   user reported "checkboxes are particularly hard to see".

   Three-state visual progression so the user always knows what they're
   looking at:
     1. **Unchecked** — 2 px border in a 55 % blend of `--color-accent` and
        `--color-border`. The accent influence carries the active theme
        colour (e.g. pink for the user's current palette) so the box reads
        as a themed UI element, not a generic gray box. The blend keeps it
        clearly subordinate to the hover and checked states.
     2. **Hover** — bumps the border up to the full `--color-accent` and
        adds a soft accent-tinted background fill. Signals "about to be
        toggled."
     3. **Checked / indeterminate** — solid `--color-accent` fill, white
        SVG mark inside, full accent border. Maximally prominent.

   The `color-mix()` value is the modern path; a `--color-text-muted` solid
   colour acts as the fallback for any browser that doesn't support it
   (none of the currently shipping evergreen browsers fall back, but the
   declaration order keeps the cascade safe). */
.form-check-input {
    width: 18px;
    height: 18px;
    margin-top: 0.15rem;
    background-color: var(--color-panel);
    /* Solid fallback first, color-mix override second. */
    border: 2px solid var(--color-text-muted);
    border: 2px solid color-mix(in srgb, var(--color-accent) 55%, var(--color-border) 45%);
    box-shadow: none !important;
    cursor: pointer;
    transition: background-color var(--duration-hover) var(--ease-hover),
                border-color var(--duration-hover) var(--ease-hover),
                box-shadow var(--duration-hover) var(--ease-hover);
}

.form-check-input:hover:not(:disabled):not(:checked) {
    border-color: var(--color-accent);
    background-color: var(--color-accent-soft);
}

.form-check-input:focus,
.form-check-input:focus-visible {
    outline: none !important;
    border-color: var(--color-accent) !important;
    box-shadow: 0 0 0 3px var(--color-accent-ring) !important;
}

.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
    background-color: var(--color-accent) !important;
    border-color: var(--color-accent) !important;
}

.form-check-input:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.form-check-label {
    color: var(--color-text);
    font-size: 1rem;
    margin-left: 4px;
    cursor: pointer;
}

.form-check-label:has(+ .form-check-input:disabled),
.form-check-input:disabled + .form-check-label {
    color: var(--color-text-subtle);
    cursor: not-allowed;
}

/* Switch — horizontal track + knob. Bootstrap renders an SVG circle as
   background-image for the knob; we keep the default white knob and
   override only the track tint. */
.form-switch .form-check-input {
    width: 36px;
    height: 20px;
    margin-top: 0.2rem;
    background-color: var(--color-bg);
    border-color: var(--color-border);
}

.form-switch .form-check-input:checked {
    background-color: var(--color-accent) !important;
    border-color: var(--color-accent) !important;
}

/* Range slider — track in border colour, thumb in accent. WebKit and
   Mozilla pseudo-elements need separate rules. */
.form-range {
    height: 1.5rem;
    padding: 0;
    background-color: transparent;
    appearance: none;
}

.form-range::-webkit-slider-runnable-track {
    height: 4px;
    background: var(--color-border);
    border-radius: var(--radius-pill);
}
.form-range::-moz-range-track {
    height: 4px;
    background: var(--color-border);
    border-radius: var(--radius-pill);
}

.form-range::-webkit-slider-thumb {
    width: 16px;
    height: 16px;
    margin-top: -6px;
    background-color: var(--color-accent);
    border: 2px solid var(--color-panel);
    border-radius: 50%;
    appearance: none;
    cursor: pointer;
    box-shadow: var(--shadow-elevated, 0 1px 2px rgba(0,0,0,0.1));
}
.form-range::-moz-range-thumb {
    width: 16px;
    height: 16px;
    background-color: var(--color-accent);
    border: 2px solid var(--color-panel);
    border-radius: 50%;
    cursor: pointer;
}

.form-range:focus {
    outline: none;
}
.form-range:focus::-webkit-slider-thumb {
    box-shadow: 0 0 0 3px var(--color-accent-ring);
}
.form-range:focus::-moz-range-thumb {
    box-shadow: 0 0 0 3px var(--color-accent-ring);
}

/* ----------------------------------------------------------------------------
   Progress bars — Bootstrap default is the primary blue. Retrofit to
   `--color-accent` with token-based bg, and respect the tone helper
   classes (`.bg-success` / `.bg-warning` / `.bg-danger`).
   ---------------------------------------------------------------------------- */
.progress {
    background-color: var(--color-bg);
    border: 1px solid var(--color-border-soft);
    border-radius: var(--radius-pill);
    height: 8px;
    overflow: hidden;
}

.progress-bar {
    background-color: var(--color-accent);
    color: #fff;
    transition: width var(--duration-enter) var(--ease-enter);
}

.progress-bar.bg-success { background-color: var(--color-success) !important; }
.progress-bar.bg-warning { background-color: var(--color-warn) !important; }
.progress-bar.bg-danger  { background-color: var(--color-danger) !important; }
.progress-bar.bg-info    { background-color: var(--color-accent) !important; }

/* ----------------------------------------------------------------------------
   Spinners — Bootstrap defaults use `currentColor`, so we retint the
   semantic helper classes to use Orcanex tokens. Bare `.spinner-border`
   inherits whatever colour the parent declares.
   ---------------------------------------------------------------------------- */
.spinner-border.text-primary,
.spinner-border.text-info     { color: var(--color-accent) !important; }
.spinner-border.text-success  { color: var(--color-success) !important; }
.spinner-border.text-warning  { color: var(--color-warn) !important; }
.spinner-border.text-danger   { color: var(--color-danger) !important; }
.spinner-border.text-secondary,
.spinner-border.text-muted    { color: var(--color-text-muted) !important; }

.spinner-grow.text-primary,
.spinner-grow.text-info       { color: var(--color-accent) !important; }
.spinner-grow.text-success    { color: var(--color-success) !important; }
.spinner-grow.text-warning    { color: var(--color-warn) !important; }
.spinner-grow.text-danger     { color: var(--color-danger) !important; }

/* ----------------------------------------------------------------------------
   List group — Bootstrap default panel + border + active state. Retrofit
   to Orcanex tokens so it matches Card / SectionCard chrome.
   ---------------------------------------------------------------------------- */
.list-group {
    border-radius: var(--radius-md);
    border: 1px solid var(--color-border);
    overflow: hidden;
}

.list-group-item {
    background-color: var(--color-panel);
    border-color: var(--color-border-soft);
    color: var(--color-text);
    padding: 10px 12px;
    font-size: 1rem;
}

.list-group-item:first-child { border-top: none; }
.list-group-item:last-child  { border-bottom: none; }

.list-group-item-action:hover,
.list-group-item-action:focus {
    background-color: var(--color-bg);
    color: var(--color-text);
}

.list-group-item.active {
    background-color: var(--color-accent-soft) !important;
    border-color: var(--color-accent) !important;
    color: var(--color-accent) !important;
}

.list-group-item.disabled,
.list-group-item:disabled {
    color: var(--color-text-subtle);
    background-color: var(--color-bg);
    pointer-events: none;
}

/* ----------------------------------------------------------------------------
   Close button (`.btn-close`) — Bootstrap's default is a dark SVG that
   reads as nearly black against the panel. Soften to text-muted and bump
   on hover. Bootstrap renders the X via background-image (currentColor),
   so we control colour via the standard `color` property combined with
   `filter` for the SVG fill tint.
   ---------------------------------------------------------------------------- */
.btn-close {
    opacity: 0.6;
    transition: opacity var(--duration-hover) var(--ease-hover);
}
.btn-close:hover {
    opacity: 1;
}
.btn-close:focus {
    outline: none;
    box-shadow: 0 0 0 3px var(--color-accent-ring);
}

/* ----------------------------------------------------------------------------
   Breadcrumb — Orcanex pages mostly use the custom `.orcanex-page-header-
   crumbs` pattern, but legacy code paths still emit the Bootstrap
   `.breadcrumb` markup. Tint links and the separator to match the rest
   of the chrome.
   ---------------------------------------------------------------------------- */
.breadcrumb {
    background-color: transparent;
    padding: 0;
    margin-bottom: 0;
    font-size: 0.92rem;
}

.breadcrumb-item a {
    color: var(--color-accent);
    text-decoration: none;
}
.breadcrumb-item a:hover { text-decoration: underline; }

.breadcrumb-item.active {
    color: var(--color-text-muted);
}

.breadcrumb-item + .breadcrumb-item::before {
    color: var(--color-text-subtle);
    content: "›";
    padding: 0 4px;
}

/* Modals — Bootstrap modal markup */
.modal-content {
    border-radius: var(--radius-lg) !important;
    border: 1px solid var(--color-border) !important;
    box-shadow: var(--shadow-modal) !important;
}
.modal-header {
    border-bottom: 1px solid var(--color-border) !important;
    padding: 14px 18px !important;
}
.modal-header .modal-title {
    font-size: 1.08rem !important;
    font-weight: 600 !important;
    color: var(--color-text) !important;
}
.modal-body { padding: 18px !important; font-size: 1rem; line-height: 1.55; }
.modal-footer { border-top: 1px solid var(--color-border) !important; padding: 12px 18px !important; gap: 8px; }

/* Pagination */
.page-link {
    border: 1px solid var(--color-border);
    color: var(--color-text);
    border-radius: var(--radius-sm) !important;
    margin: 0 2px;
    background: var(--color-panel);
}
.page-item.active .page-link {
    background: var(--color-accent);
    border-color: var(--color-accent);
}

/* Nav tabs / pills */
.nav-tabs {
    border-bottom: 1px solid var(--color-border-soft);
}
.nav-tabs .nav-link {
    border: none;
    color: var(--color-text-muted);
    font-size: 1rem;
    font-weight: 500;
    padding: 8px 14px;
    border-bottom: 2px solid transparent;
}
.nav-tabs .nav-link:hover {
    background: transparent;
    color: var(--color-text);
    border-bottom-color: var(--color-border);
}
.nav-tabs .nav-link.active {
    color: var(--color-accent);
    font-weight: 600;
    border-bottom-color: var(--color-accent);
    background: transparent;
}

.nav-pills .nav-link {
    border-radius: var(--radius-md);
    color: var(--color-text);
    font-size: 1rem;
    font-weight: 500;
    padding: 6px 12px;
}
.nav-pills .nav-link.active {
    background: var(--color-accent-soft);
    color: var(--color-accent);
}

/* Dropdowns */
.dropdown-menu {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-overlay);
    padding: 4px;
    font-size: 1rem;
}
.dropdown-item {
    border-radius: var(--radius-sm);
    padding: 6px 10px;
    color: var(--color-text);
}
.dropdown-item:hover, .dropdown-item:focus {
    background: var(--color-bg);
    color: var(--color-text);
}
.dropdown-item.active, .dropdown-item:active {
    background: var(--color-accent-soft) !important;
    color: var(--color-accent) !important;
}

/* Page surface containers — pages typically wrap in container-fluid + content */
.content-page > .content {
    padding: 0;
}
.container-fluid { padding-left: 16px; padding-right: 16px; }

/* ----------------------------------------------------------------------------
   Master-data list pages — shared page-shell chrome that mirrors the
   Cases / Specialists list-page pattern.

   Master-data pages (Configuration/* and CRM/*) used to wrap their content
   in legacy Bootstrap `<div class="content"><div class="container-fluid">`,
   which produced an extra box + visible border around the inner Card that
   didn't match the Cases page (the theme default). `.orcanex-masterdata-page`
   replaces both legacy wrappers with a single flex-column shell, and a
   direct-child rule below gives the page's Card the same side / top /
   bottom margin the Cases content area uses — without affecting the
   page-header chrome above, which keeps its edge-to-edge panel bar. */
.orcanex-masterdata-page {
    display: flex;
    flex-direction: column;
    flex: 1;
}

/* The Card hosting the table sits flush against the page-header above;
   give it the same 14/24/24 inset that .orcanex-cases-content uses so
   master-data and Cases pages share a visual rhythm.

   Strip the Card's panel chrome (background / border / border-radius) on
   master-data pages — the table inside (.orcanex-mdtable) renders its
   own header band + per-row borders, so the outer Card frame produced a
   visible "extra box" double-border effect the user flagged. Keeping the
   .orcanex-card class on the markup but nulling its visible chrome means
   we don't have to refactor 28 pages to drop the primitive; the Cases
   page (the theme default) doesn't wrap its rows in a Card and now
   master-data renders the same way visually.

   !important is required (not redundant): Card.razor.css sets the card's
   border / background / border-radius as a SCOPED rule — it compiles to
   `.orcanex-card[b-xxxx]` (specificity 0,2,0) and the scoped-styles bundle
   loads AFTER tokens.css. This strip selector (0,2,0) ties that specificity
   but loses the cascade on load order, so the box silently came back when
   Card.razor.css was added (2026-05-28), defeating the original strip
   (2026-05-11). !important makes the strip win regardless of load order. */
.orcanex-masterdata-page > .orcanex-card {
    margin: 14px 24px 24px;
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

/* Mobile: tighter side-margin so the table hugs the viewport edges, exactly
   like the Cases rows do at mobile. */
:root[data-viewport="mobile"]   .orcanex-masterdata-page > .orcanex-card,
:root[data-viewport="mobile-l"] .orcanex-masterdata-page > .orcanex-card {
    margin: var(--space-2);
}

/* Old leftbar / topbar — disable everything from Hyper that we no longer use */
.leftside-menu,
.navbar-custom,
.topbar,
.footer { display: none !important; }
.wrapper { display: block; padding: 0; margin: 0; }
.wrapper .content-page {
    margin: 0 !important;
    padding: 0 !important;
    min-height: auto;
}

/* ============================================================================
   Common page-internal class retrofits (custom classes we keep)
   ============================================================================ */

/* Welcome cards (Dashboard) */
.welcome-card {
    background: var(--color-panel) !important;
    border: 1px solid var(--color-border) !important;
    border-radius: var(--radius-lg) !important;
    box-shadow: none !important;
    padding: 16px 20px !important;
    color: var(--color-text);
}
.welcome-card .welcome-title { font-size: 1.38rem; font-weight: 600; color: var(--color-text); margin: 0 0 4px; letter-spacing: -0.2px; }
.welcome-card .welcome-subtitle { font-size: 1rem; color: var(--color-text-muted); margin: 0; }

/* Stats cards (AdminDashboard / mini KPIs) */
.stats-card {
    background: var(--color-panel) !important;
    border: 1px solid var(--color-border) !important;
    border-radius: var(--radius-lg) !important;
    padding: 14px 16px !important;
    display: flex;
    align-items: center;
    gap: 12px;
    box-shadow: none !important;
    transition: border-color var(--duration-hover) var(--ease-hover);
}
.stats-card:hover { border-color: var(--color-accent); }
.stats-card-warning { border-color: var(--color-warn) !important; }
.stats-card-danger { border-color: var(--color-danger) !important; }
.stats-card .stats-icon {
    width: 36px;
    height: 36px;
    border-radius: var(--radius-md);
    background: var(--color-accent-soft);
    color: var(--color-accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1.38rem;
    flex-shrink: 0;
}
.stats-card .stats-content { min-width: 0; }
.stats-card .stats-value {
    font-size: 1.69rem;
    font-weight: 600;
    line-height: 1.1;
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.3px;
}
.stats-card .stats-label {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    margin-top: 2px;
}

.mini-stat-card {
    background: var(--color-panel);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 10px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}
.mini-stat-card .mini-stat-label {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--color-text-muted);
}
.mini-stat-card .mini-stat-value { font-size: 1rem; font-weight: 600; color: var(--color-text); }

/* Search inputs in headers (cases/clients/users etc.) */
.cases-header-search,
.clients-header-search,
.users-header-search,
.specialists-header-search {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.cases-header-search-icon,
.clients-header-search-icon,
.users-header-search-icon,
.specialists-header-search-icon {
    position: absolute;
    left: 10px;
    color: var(--color-text-muted);
    font-size: 1.08rem;
    pointer-events: none;
}

.cases-header-search-input,
.clients-header-search-input,
.users-header-search-input,
.specialists-header-search-input {
    padding-left: 30px !important;
    width: 280px !important;
    background: var(--color-panel) !important;
    border: 1px solid var(--color-border) !important;
    border-radius: var(--radius-md) !important;
    height: 30px !important;
    font-size: 1rem !important;
    transition: border-color var(--duration-hover) var(--ease-hover);
}

.cases-header-search-input:focus,
.clients-header-search-input:focus,
.users-header-search-input:focus,
.specialists-header-search-input:focus {
    border-color: var(--color-accent) !important;
    box-shadow: 0 0 0 3px var(--color-accent-ring) !important;
}

.cases-header-search-clear,
.clients-header-search-clear,
.users-header-search-clear,
.specialists-header-search-clear {
    position: absolute;
    right: 8px;
    background: transparent;
    border: none;
    color: var(--color-text-muted);
    cursor: pointer;
    padding: 0;
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
}

/* Status pipeline bar (Cases legacy — kept for cases not yet migrated) */
.status-pipeline-bar {
    display: flex !important;
    gap: 0 !important;
    background: var(--color-panel) !important;
    border: 1px solid var(--color-border) !important;
    border-radius: var(--radius-lg) !important;
    overflow: hidden !important;
    margin-bottom: 12px !important;
    box-shadow: none !important;
}
.pipeline-stat {
    flex: 1;
    padding: 10px 14px !important;
    border-right: 1px solid var(--color-border-soft) !important;
    background: transparent !important;
    cursor: pointer;
    position: relative;
}
.pipeline-stat:last-child { border-right: none; }
.pipeline-stat:hover { background: var(--color-bg) !important; }
.pipeline-stat.active::after {
    content: "";
    position: absolute;
    inset: auto 0 -1px;
    height: 2px;
    background: var(--pipeline-color, var(--color-accent));
}
.pipeline-stat .pipeline-label {
    font-size: 0.77rem !important;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
    color: var(--pipeline-color, var(--color-text-muted)) !important;
}
.pipeline-stat .pipeline-value {
    font-size: 1.69rem !important;
    font-weight: 600 !important;
    color: var(--color-text) !important;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.3px;
}
.pipeline-stat .pipeline-progress {
    height: 4px !important;
    background: var(--color-border-soft) !important;
    border-radius: 2px;
    overflow: hidden;
    margin-top: 6px;
}
.pipeline-stat .pipeline-progress-fill {
    height: 100% !important;
    background: var(--pipeline-color, var(--color-accent)) !important;
}
.pipeline-total {
    flex: 1;
    padding: 10px 14px !important;
    background: var(--color-bg) !important;
}
.pipeline-total .pipeline-value-total {
    font-size: 1.69rem;
    font-weight: 600;
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
}

/* Status pills inside list rows (cases, etc.) */
.status-pill {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px !important;
    border-radius: var(--radius-pill) !important;
    font-size: 0.85rem !important;
    font-weight: 500 !important;
    line-height: 1.4;
    letter-spacing: 0.1px;
    border: 1px solid var(--color-border) !important;
}

/* Loading spinner inline (Hyper's custom one) */
.loading-spinner-inline {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.spinner-ring-inline {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-accent);
    animation: orcanex-bounce 1.2s ease-in-out infinite;
}
.spinner-ring-inline:nth-child(2) { animation-delay: 0.15s; }
.spinner-ring-inline:nth-child(3) { animation-delay: 0.3s; }
@keyframes orcanex-bounce {
    0%, 80%, 100% { transform: translateY(0); opacity: 0.4; }
    40% { transform: translateY(-6px); opacity: 1; }
}

/* Avatar circles (legacy specialist-avatar, examinee-avatar etc.) */
.specialist-avatar,
.examinee-avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    color: white;
    font-weight: 600;
    font-size: 0.77rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--color-panel);
    flex-shrink: 0;
}
.team-avatars { display: inline-flex; align-items: center; }
.team-avatars > * + * { margin-left: -8px; }
.specialist-more { background: var(--color-text-muted) !important; }

/* ============================================================================
   ORCANEX FORM PATTERN — the standard form-field layout used across the app.
   See CLAUDE.md / copilot-instructions.md "UI Design System" for the spec.

   Visual language:
     [icon-box]  4px gap  [field]
     - both have their own 1px border + 8px radius
     - icon-box is a square equal to the field height
     - field height: 32px (default) / 28px (tight) — controlled by .orcanex-form-grid
     - focus ring: var(--color-accent) border + 3px accent-soft glow on the field
     - select: a chevron carat appears on the right via background-image
   ============================================================================ */

/* Input group — icon-box prefix sits next to a flex input, both bordered. */
.orcanex-igroup {
    display: flex;
    align-items: stretch;
    gap: 4px;
    width: 100%;
    min-width: 0;
}

.orcanex-igroup-prefix,
.orcanex-igroup-suffix {
    height: var(--h-field);
    min-width: var(--h-field);
    padding: 0 8px;
    background: var(--color-panel);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-text-muted);
    font-size: 0.92rem;
    flex-shrink: 0;
    gap: 6px;
}

.orcanex-igroup-prefix-mono {
    font-family: var(--font-mono);
    font-weight: 600;
}

.orcanex-igroup-input {
    flex: 1;
    min-width: 0;
}

/* The input/select inside an igroup keeps its own border for the "two adjacent
   bordered boxes" look. */
.orcanex-igroup .form-control,
.orcanex-igroup .form-select,
.orcanex-igroup input[type="text"],
.orcanex-igroup input[type="email"],
.orcanex-igroup input[type="tel"],
.orcanex-igroup input[type="date"],
.orcanex-igroup input[type="number"],
.orcanex-igroup input[type="search"] {
    flex: 1;
    min-width: 0;
}

/* Form grid — N-column layout for fields inside a card body. Default
   gap is 10px vertical / 16px horizontal. The -tight modifier collapses
   field height + font for case-form density. */
.orcanex-form-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px 16px;
    min-width: 0;
}
.orcanex-form-grid-1 { grid-template-columns: 1fr; }
.orcanex-form-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.orcanex-form-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.orcanex-form-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* Span helpers for individual fields that need to break the grid (e.g. a
   full-width textarea inside a 3-col grid). */
.orcanex-form-grid > .span-2 { grid-column: span 2; }
.orcanex-form-grid > .span-3 { grid-column: span 3; }
.orcanex-form-grid > .span-4 { grid-column: span 4; }

/* Responsive collapse: 3+ cols → 2 on tablet, all → 1 on mobile.
   Span helpers also clamp so a `.span-2` inside a 1-col grid doesn't break.
   Bootstrap-aligned breakpoints — see DOCS/Architecture/responsive-design.md. */
@media (max-width: 1199.98px) {
    .orcanex-form-grid-4 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 991.98px) {
    .orcanex-form-grid-3,
    .orcanex-form-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .orcanex-form-grid > .span-3,
    .orcanex-form-grid > .span-4 { grid-column: span 2; }
}
@media (max-width: 575.98px) {
    .orcanex-form-grid-2,
    .orcanex-form-grid-3,
    .orcanex-form-grid-4 { grid-template-columns: 1fr; }
    .orcanex-form-grid > .span-2,
    .orcanex-form-grid > .span-3,
    .orcanex-form-grid > .span-4 { grid-column: span 1; }
}

/* Tight density variant — used inside .orcanex-form-grid-tight (case form,
   specialist form, configuration pages). At the default user density (compact)
   this collapses to 28px / 12.5px so sections fit more rows on screen. The
   --h-field-tight / --font-tight-* tokens scale with the user's density
   preference (data-density) so a user who picks comfortable/large still gets
   bigger fields on tight forms — proportionally smaller than the standard
   form, but never the original cramped 28px. */
.orcanex-form-grid-tight {
    --h-field: var(--h-field-tight);
}
.orcanex-form-grid-tight .orcanex-igroup-prefix,
.orcanex-form-grid-tight .orcanex-igroup-suffix {
    height: var(--h-field-tight);
    min-width: var(--h-field-tight);
}
.orcanex-form-grid-tight .form-control,
.orcanex-form-grid-tight .form-select,
.orcanex-form-grid-tight input,
.orcanex-form-grid-tight select,
.orcanex-form-grid-tight textarea {
    height: var(--h-field-tight) !important;
    font-size: var(--font-tight-field) !important;
}
.orcanex-form-grid-tight textarea {
    height: auto !important;
    min-height: var(--h-textarea-tight-min);
}
.orcanex-form-grid-tight .orcanex-field-label {
    font-size: var(--font-tight-label) !important;
    font-weight: 600 !important;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-text-muted);
}

/* Dropdown carat — every <select.form-select> gets a chevron-down icon on
   the right via SVG data-URI. This is the standard regardless of where the
   select renders. */
.form-select {
    appearance: none !important;
    -webkit-appearance: none !important;
    -moz-appearance: none !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
    background-repeat: no-repeat !important;
    background-position: right 10px center !important;
    background-size: 14px !important;
    padding-right: 30px !important;
}

/* Read-only / display-mode appearance for form fields. When the page is in
   read-only mode, every input/select/textarea should flatten visually:
   muted background, muted text, no dropdown carat. This is the "display
   mode" look that signals the field is not editable. */
.form-control:disabled,
.form-select:disabled,
.form-control[readonly],
.form-select[readonly] {
    background-color: var(--color-bg) !important;
    color: var(--color-text-muted) !important;
    cursor: default !important;
    opacity: 1 !important;
}
.form-select:disabled {
    background-image: none !important;
    padding-right: 10px !important;
}

/* Field card titlebar — the standard "icon-box + label + optional action"
   row at the top of every card body. Replaces the heavy SectionCard header. */
.orcanex-card-titlebar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: var(--space-3);
    font-size: 1.04rem;
    font-weight: 600;
    color: var(--color-text);
}

.orcanex-card-titlebar-label {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.orcanex-card-titlebar > .orcanex-btn,
.orcanex-card-titlebar > .orcanex-card-titlebar-action {
    margin-left: auto;
}

/* Coloured icon-box that prefixes the card title. The variant determines the
   tint (default = accent, blue, amber, red, success). */
.orcanex-card-titlebar-icon {
    width: 22px;
    height: 22px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-soft);
    color: var(--color-accent);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.orcanex-card-titlebar-icon-blue    { background: var(--color-accent-soft);  color: var(--color-accent); }
.orcanex-card-titlebar-icon-amber   { background: var(--color-warn-soft);    color: var(--color-warn); }
.orcanex-card-titlebar-icon-red     { background: var(--color-danger-soft);  color: var(--color-danger); }
.orcanex-card-titlebar-icon-success { background: var(--color-success-soft); color: var(--color-success); }

/* Country picker prefix — used on phone fields. Renders a small flag + a
   native <select> for the dial code, all inside the standard prefix box.
   The select keeps its native chevron so the country picker is obviously
   interactive. */
.orcanex-igroup-prefix-country {
    padding: 0 !important;
    overflow: hidden;
    gap: 4px;
}
.orcanex-igroup-prefix-country .orcanex-country-flag {
    width: 18px;
    height: 13px;
    margin-left: 8px;
    object-fit: cover;
    border-radius: 2px;
    flex-shrink: 0;
    background: var(--color-bg);
}
.orcanex-igroup-prefix-country .orcanex-country-flag-fallback {
    width: 22px;
    height: 14px;
    margin-left: 6px;
    border-radius: 2px;
    background: var(--color-border);
    color: var(--color-text-muted);
    font-size: 0.69rem;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    letter-spacing: 0.4px;
}
.orcanex-igroup-prefix-country select {
    border: none !important;
    background: transparent !important;
    background-image: none !important;
    appearance: auto !important;
    -webkit-appearance: menulist !important;
    -moz-appearance: menulist !important;
    font-family: var(--font-mono);
    font-size: 0.92rem;
    color: var(--color-text);
    cursor: pointer;
    padding: 0 4px !important;
    height: 100% !important;
    box-shadow: none !important;
    outline: none;
    width: auto !important;
}
.orcanex-igroup-prefix-country select:disabled {
    cursor: not-allowed;
    opacity: 0.7;
}

/* ============================================================================
   ORCANEX BUTTON — promoted from Btn.razor.css to global so raw <button>
   markup with .orcanex-btn classes (e.g. <button type="submit" form="…">
   that can't go through the Btn component) still picks up styling.
   ============================================================================ */
.orcanex-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    line-height: 1;
    transition: background var(--duration-hover) var(--ease-hover),
                color var(--duration-hover) var(--ease-hover),
                border-color var(--duration-hover) var(--ease-hover);
}

.orcanex-btn-md {
    height: var(--h-button);
    padding: 0 12px;
    font-size: 1rem;
}

.orcanex-btn-sm {
    height: var(--h-button-sm);
    padding: 0 10px;
    font-size: 0.92rem;
    gap: 5px;
}

.orcanex-btn-default {
    background: var(--color-panel);
    color: var(--color-text);
    border-color: var(--color-border);
}
.orcanex-btn-default:hover:not(:disabled) {
    background: var(--color-bg);
}

.orcanex-btn-ghost {
    background: transparent;
    color: var(--color-text-muted);
}
.orcanex-btn-ghost:hover:not(:disabled) {
    background: var(--color-bg);
    color: var(--color-text);
}

.orcanex-btn-primary {
    background: var(--color-accent);
    color: #fff;
    border-color: var(--color-accent);
}
.orcanex-btn-primary:hover:not(:disabled) {
    background: var(--color-accent-hover);
    border-color: var(--color-accent-hover);
}

.orcanex-btn-soft {
    background: var(--color-accent-soft);
    color: var(--color-accent);
}
.orcanex-btn-soft:hover:not(:disabled) {
    background: #DBE5FF;
}

.orcanex-btn-danger {
    background: var(--color-danger);
    color: #fff;
    border-color: var(--color-danger);
}
.orcanex-btn-danger:hover:not(:disabled) {
    background: #A12A24;
    border-color: #A12A24;
}

.orcanex-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ============================================================================
   Global page-header layout (used by Cases.razor + CompactPageHeader rewrite +
   any page that renders <div class="orcanex-page-header"> directly).
   These were originally scoped inside PageHeader.razor.css; promoting them
   here makes them apply wherever the markup appears.
   ============================================================================ */

.orcanex-page-header {
    padding: 16px 28px 14px;
    background: var(--color-panel);
    border-bottom: 1px solid var(--color-border);
}

.orcanex-page-header-crumbs {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.92rem;
    color: var(--color-text-muted);
    margin-bottom: 6px;
}

.orcanex-page-header-crumb {
    color: var(--color-text-muted);
    text-decoration: none;
}
.orcanex-page-header-crumb:hover { color: var(--color-text); }
.orcanex-page-header-crumb-active { color: var(--color-text); font-weight: 500; }
.orcanex-page-header-crumb-sep { color: var(--color-text-subtle); }

.orcanex-page-header-row {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    flex-wrap: wrap;
}

/* When a Toolbar slot is rendered, the row vertically-centres so the
   search input / filter buttons line up with the title block, and the
   text shrinks instead of growing. */
.orcanex-page-header-row.has-toolbar {
    align-items: center;
}

.orcanex-page-header-row.has-toolbar .orcanex-page-header-text {
    flex: 0 0 auto;
}

.orcanex-page-header-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: wrap;
}

.orcanex-page-header-text {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
}

.orcanex-page-header-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    text-decoration: none;
    flex-shrink: 0;
}
.orcanex-page-header-back:hover {
    background: var(--color-bg);
    color: var(--color-text);
}

.orcanex-page-header-titles { min-width: 0; }
.orcanex-page-header-title { margin: 0; color: var(--color-text); }
.orcanex-page-header-subtitle {
    margin-top: 4px;
    font-size: 0.92rem;
    color: var(--color-text-muted);
}

.orcanex-page-header-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-shrink: 0;
    margin-left: auto;
}

.orcanex-page-header-below { margin-top: 12px; }

/* ============================================================================
   Global Orcanex card — covers card markup written directly in pages.
   The <Card> primitive still works via its scoped CSS; this just covers any
   direct `.orcanex-card` markup in page-level Razor files.
   ============================================================================ */

.orcanex-card {
    background: var(--color-panel);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    color: var(--color-text);
}
.orcanex-card-padded { padding: var(--space-4); }
.orcanex-card-accent { border-left: 4px solid var(--color-accent); }
.orcanex-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
}
.orcanex-card-head-text { min-width: 0; }
.orcanex-card-title { margin: 2px 0 0; font-size: 1.08rem; font-weight: 600; line-height: 1.4; }
.orcanex-card-actions { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }

/* Modal show — old SOS modal sometimes uses position absolute */
.modal.fade.show.d-block {
    background: rgba(15, 17, 21, 0.45) !important;
}
.modal.fade.show.d-block .modal-dialog { margin: 1.75rem auto; }
.modal.fade.show.d-block .modal-content {
    background: var(--color-panel);
    border-radius: var(--radius-lg) !important;
    border: 1px solid var(--color-border) !important;
    box-shadow: var(--shadow-modal) !important;
}

/* ============================================================================
   Segment cards (.orcanex-segments / .orcanex-segment)

   Reusable rich-data-card strip used at the top of list pages (Cases pipeline
   stages, Specialists workload buckets, etc.) to visualise category counts
   and the share of the total. Each card is also click-to-filter — pages bind
   their own onClick and toggle `.is-active` on the selected card.

   Per-card colour comes from inline `--seg-color` and `--seg-color-soft`
   custom properties (the soft tone is just the same hue at ~12% opacity for
   the icon-tile background). Pages should always set both inline.

   Visual rhythm — top to bottom:
     • orcanex-segment-head     icon-tile + uppercase label + share %
     • orcanex-segment-value-row  big bold count + optional unit word
     • orcanex-segment-bar      thin progress fill = share of total
     • orcanex-segment-meta     bottom muted line ("No active", "12 today", …)

   The TOTAL card is a dedicated dark variant via `.orcanex-segment-total`.
   ============================================================================ */
.orcanex-segments {
    /* Single, non-wrapping row. Cards flex to fill when there's room and shrink to
       their min-width when crowded; whatever still doesn't fit is CLIPPED
       (overflow:hidden) rather than wrapping onto a new row — so the strip stays one
       row tall and never pushes the list below down. Mobile overrides this to a
       horizontal scroll-snap rail (see the data-viewport rule below). */
    display: flex;
    flex-wrap: nowrap;
    overflow: hidden;
    gap: 6px;
    flex-shrink: 0;
}

/* Mobile: switch the segments strip from a wrapping grid to a horizontal
   scroll-snap rail so the user can swipe through stages without the page
   ballooning vertically. Each card snaps to the start. */
:root[data-viewport="mobile"] .orcanex-segments,
:root[data-viewport="mobile-l"] .orcanex-segments {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: var(--space-2);
    /* Allow the cards to overflow the scroll container's edge by extending
       the padding into the strip — looks like a normal page edge but the
       last card can scroll fully into view. */
    margin-inline: calc(-1 * var(--space-3));
    padding-inline: var(--space-3);
    /* Hide scrollbar visually but keep keyboard/screen-reader scrollability. */
    scrollbar-width: none;
}
:root[data-viewport="mobile"]   .orcanex-segments::-webkit-scrollbar,
:root[data-viewport="mobile-l"] .orcanex-segments::-webkit-scrollbar {
    display: none;
}
:root[data-viewport="mobile"]   .orcanex-segments > .orcanex-segment,
:root[data-viewport="mobile-l"] .orcanex-segments > .orcanex-segment {
    flex: 0 0 auto;
    min-width: 120px;
    scroll-snap-align: start;
}

.orcanex-segment {
    background: var(--color-panel);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: 6px 8px 7px;
    display: flex;
    /* Grow to share the row when there's space; shrink down to min-width when crowded.
       min-width is the floor — once the cards hit it the row overflows and is clipped. */
    flex: 1 1 0;
    min-width: 92px;
    flex-direction: column;
    gap: 4px;
    cursor: pointer;
    text-align: left;
    font: inherit;
    color: var(--color-text);
    position: relative;
    overflow: hidden;
    transition: border-color var(--duration-hover) var(--ease-hover),
                background var(--duration-hover) var(--ease-hover),
                transform var(--duration-hover) var(--ease-hover);
}

.orcanex-segment:hover {
    border-color: var(--seg-color, var(--color-border));
}

.orcanex-segment.is-active {
    border-color: var(--seg-color, var(--color-accent));
    box-shadow: 0 0 0 3px var(--seg-color-soft, var(--color-accent-soft));
}

.orcanex-segment-head {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
}

.orcanex-segment-icon {
    width: 16px;
    height: 16px;
    border-radius: 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--seg-color-soft, var(--color-bg));
    color: var(--seg-color, var(--color-text-muted));
    flex-shrink: 0;
}

.orcanex-segment-label {
    flex: 1;
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.orcanex-segment-pct {
    font-size: 0.65rem;
    font-weight: 500;
    color: var(--color-text-muted);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.orcanex-segment-value-row {
    display: flex;
    align-items: baseline;
    gap: 4px;
    min-height: 16px;
}

.orcanex-segment-value {
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1;
    color: var(--color-text);
    letter-spacing: -0.5px;
    font-variant-numeric: tabular-nums;
}

.orcanex-segment-value.is-zero {
    color: var(--color-text-subtle);
    font-weight: 600;
}

.orcanex-segment-unit {
    font-size: 0.62rem;
    font-weight: 500;
    color: var(--color-text-muted);
    text-transform: lowercase;
}

.orcanex-segment-bar {
    height: 2px;
    background: var(--color-border-soft);
    border-radius: 2px;
    overflow: hidden;
}

.orcanex-segment-bar-fill {
    height: 100%;
    background: var(--seg-color, var(--color-accent));
    border-radius: 2px;
    transition: width 250ms ease;
    min-width: 0;
}

.orcanex-segment-meta {
    font-size: 0.62rem;
    color: var(--color-text-muted);
    display: flex;
    align-items: center;
    gap: 4px;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.orcanex-segment-meta-success {
    color: var(--color-success);
    font-weight: 500;
}

.orcanex-segment-meta-warn {
    color: var(--color-warn);
    font-weight: 500;
}

.orcanex-segment-meta-danger {
    color: var(--color-danger);
    font-weight: 500;
}

/* TOTAL — dark gradient card. Use on the trailing position of the strip. */
.orcanex-segment-total {
    background: linear-gradient(135deg, #1A1F2A 0%, #0F1115 100%);
    border-color: #1A1F2A;
    cursor: default;
}

.orcanex-segment-total:hover {
    border-color: #1A1F2A;
}

.orcanex-segment-total .orcanex-segment-icon {
    background: rgba(255, 255, 255, 0.08);
    color: #fff;
}

.orcanex-segment-total .orcanex-segment-label {
    color: rgba(255, 255, 255, 0.7);
}

.orcanex-segment-total .orcanex-segment-value {
    color: #fff;
}

.orcanex-segment-total .orcanex-segment-pct,
.orcanex-segment-total .orcanex-segment-unit,
.orcanex-segment-total .orcanex-segment-meta {
    color: rgba(255, 255, 255, 0.55);
}

.orcanex-segment-total .orcanex-segment-bar {
    background: rgba(255, 255, 255, 0.12);
}

.orcanex-segment-total .orcanex-segment-bar-fill {
    background: linear-gradient(90deg, #2F62FF 0%, #C455B0 50%, #E5904A 100%);
    width: 100% !important;
}

/* Toggle button "pressed" state — used by buttons that open/close a panel
   (filter strip, advanced search, etc.). When the panel is open, pages add
   `.is-open` to the button so the user sees a visibly-active control rather
   than a flat ghost button that gives no hint it can be re-clicked to close. */
.orcanex-toggle-btn.is-open {
    background: var(--color-accent-soft) !important;
    color: var(--color-accent) !important;
    border-color: var(--color-accent) !important;
    box-shadow: 0 0 0 3px var(--color-accent-ring) !important;
}
.orcanex-toggle-btn.is-open:hover {
    background: var(--color-accent-soft) !important;
    color: var(--color-accent-hover) !important;
}

/* Active-filter indicator — when a list page has filters applied, the toggle picks up the
   warn (orange) tone so the active state reads at a glance. Source-ordered AFTER `.is-open`
   so an open panel WITH active filters still surfaces orange — the "active filters" signal
   communicates more than open/closed (the chevron already tells you the panel state). */
.orcanex-toggle-btn.has-active,
.orcanex-toggle-btn.has-active.is-open {
    background: var(--color-warn-soft) !important;
    color: var(--color-warn) !important;
    border-color: var(--color-warn) !important;
    box-shadow: none !important;
}
.orcanex-toggle-btn.has-active:hover,
.orcanex-toggle-btn.has-active.is-open:hover {
    background: var(--color-warn-soft) !important;
    color: var(--color-warn) !important;
}

/* Count badge — pill rendered to the right of the label inside a toggle button. White text on
   the warn token so it stays legible in both light and dark mode (the tokens shift to a more
   saturated amber in dark mode — see tokens.css line ~193). */
.orcanex-toggle-btn-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 6px;
    margin-left: 6px;
    background: var(--color-warn);
    color: #fff;
    border-radius: var(--radius-pill);
    font-size: 0.72rem;
    font-weight: 600;
    line-height: 1;
}

/* ============================================================================
   Toast notifications (jquery-toast-plugin) — Orcanex retrofit.

   Replaces the plugin's default coloured-block toasts with clean Orcanex
   cards: panel background, subtle border, semantic colour stripe down the
   left edge, circular icon tile, kicker-style heading, and a top loader bar
   tinted to match the variant.

   Variants:
     .jq-icon-success  — uses --color-success (green)
     .jq-icon-warning  — uses --color-warn    (amber)
     .jq-icon-error    — uses --color-danger  (red)
     .jq-icon-info     — uses --color-accent  (the user's chosen accent —
                                                follows pink/teal/etc.)

   Status semantics (success/warning/error) deliberately stay on the fixed
   semantic tones; only info follows the user's accent. That way an error
   never reads as "celebratory pink" because the user picked pink as their
   accent — danger is always danger.
   ============================================================================ */

.jq-toast-wrap {
    width: 320px !important;
    z-index: 9000 !important;
}

/* Single toast — Orcanex card. */
.jq-toast-single {
    position: relative;
    display: block;
    width: 100%;
    padding: 14px 40px 14px 56px !important;
    margin: 0 0 10px !important;
    background-color: var(--color-panel) !important;
    background-image: none !important;
    color: var(--color-text) !important;
    border: 1px solid var(--color-border) !important;
    border-left-width: 4px !important;
    border-radius: var(--radius-md) !important;
    box-shadow: var(--shadow-overlay) !important;
    font-family: var(--font-family) !important;
    font-size: 0.92rem !important;
    line-height: 1.45 !important;
    pointer-events: all;
}

.jq-toast-single h2 {
    font-family: var(--font-family) !important;
    font-size: 0.77rem !important;
    font-weight: 700 !important;
    text-transform: uppercase !important;
    letter-spacing: 0.08em !important;
    color: var(--color-text-muted) !important;
    margin: 0 0 4px !important;
    line-height: 1.3 !important;
    background: none !important;
}

/* Icon tile — circular dot on the left containing a white SVG glyph. We
   override the plugin's background-image data URI with our own minimal
   inline SVG so the icon style matches the rest of the IconBox set. */
.jq-toast-single.jq-has-icon::before {
    content: "";
    position: absolute;
    left: 14px;
    top: 14px;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background-color: var(--color-text-muted);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
}

/* Plugin paints its own embedded data URI on .jq-has-icon as a background-
   image on the SINGLE element. We've nulled that on the rule above and put
   the icon on ::before instead. */
.jq-has-icon {
    padding-left: 56px !important;
    background-image: none !important;
}

/* SUCCESS — green. */
.jq-icon-success {
    border-left-color: var(--color-success) !important;
    background-color: var(--color-panel) !important;
    background-image: none !important;
}
.jq-icon-success h2 { color: var(--color-success) !important; }
.jq-icon-success::before {
    background-color: var(--color-success);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
}

/* INFO — uses the user's accent so it follows pink / teal / etc. */
.jq-icon-info {
    border-left-color: var(--color-accent) !important;
    background-color: var(--color-panel) !important;
    background-image: none !important;
}
.jq-icon-info h2 { color: var(--color-accent) !important; }
.jq-icon-info::before {
    background-color: var(--color-accent);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'/><line x1='12' y1='16' x2='12' y2='12'/><line x1='12' y1='8' x2='12' y2='8'/></svg>");
}

/* WARNING — amber. */
.jq-icon-warning {
    border-left-color: var(--color-warn) !important;
    background-color: var(--color-panel) !important;
    background-image: none !important;
}
.jq-icon-warning h2 { color: var(--color-warn) !important; }
.jq-icon-warning::before {
    background-color: var(--color-warn);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z'/><line x1='12' y1='9' x2='12' y2='13'/><line x1='12' y1='17' x2='12' y2='17'/></svg>");
}

/* ERROR — red. */
.jq-icon-error {
    border-left-color: var(--color-danger) !important;
    background-color: var(--color-panel) !important;
    background-image: none !important;
}
.jq-icon-error h2 { color: var(--color-danger) !important; }
.jq-icon-error::before {
    background-color: var(--color-danger);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg>");
}

/* Close button — subtle, top-right corner. */
.close-jq-toast-single {
    position: absolute !important;
    top: 8px !important;
    right: 10px !important;
    width: 22px;
    height: 22px;
    background: transparent;
    color: var(--color-text-muted);
    font-size: 1.23rem !important;   /* 16px @ 13px baseline — scales with data-font-scale */
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-sm);
    transition: background var(--duration-hover) var(--ease-hover),
                color var(--duration-hover) var(--ease-hover);
}

.close-jq-toast-single:hover {
    background: var(--color-bg);
    color: var(--color-text);
}

/* Loader bar — sits along the top edge of the toast. Coloured per variant
   so the dwindling-time cue reads at a glance. */
.jq-toast-loader {
    height: 2px !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    border-radius: var(--radius-md) var(--radius-md) 0 0 !important;
    background: var(--color-text-muted) !important;
}

.jq-icon-success .jq-toast-loader { background: var(--color-success) !important; }
.jq-icon-info    .jq-toast-loader { background: var(--color-accent) !important; }
.jq-icon-warning .jq-toast-loader { background: var(--color-warn) !important; }
.jq-icon-error   .jq-toast-loader { background: var(--color-danger) !important; }

/* Reduce-motion: kill the loader animation so the bar just sits there. */
:root[data-reduce-motion="1"] .jq-toast-loaded {
    transition: none !important;
}

/* ============================================================================
   Master-data list-mode chrome (.orcanex-mdtable[data-list-mode])

   The .orcanex-mdtable primitive is used by every CRM and MasterData list
   page. Each page keeps its own grid-template-columns in scoped CSS, but the
   card-vs-tabular chrome is centralised here so the user's `data-list-mode`
   preference flows through every page automatically.

   These rules sit unscoped so they win against the per-page scoped row
   defaults: scoped `.orcanex-mdtable-row[b-xxx]` is specificity 0,2,0; the
   selectors below are 0,3,0 (.orcanex-mdtable + [data-list-mode] + .orcanex-mdtable-row).

   Card (default) — rows are individual panels with rounded chrome and a
                    breathing gap; the head sits transparently above them.
   Tabular        — rows pack inside a single panel with divider lines only.
   ============================================================================ */
.orcanex-mdtable[data-list-mode="card"] {
    gap: 8px;
}
.orcanex-mdtable[data-list-mode="card"] .orcanex-mdtable-head {
    background: transparent;
    border: none;
    padding-bottom: var(--space-1);
}
.orcanex-mdtable[data-list-mode="card"] .orcanex-mdtable-row {
    background: var(--color-panel);
    border: 1px solid var(--color-border);
    border-radius: 10px;
}

.orcanex-mdtable[data-list-mode="tabular"] {
    background: var(--color-panel);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.orcanex-mdtable[data-list-mode="tabular"] .orcanex-mdtable-row:last-child {
    border-bottom: none;
}

/* ============================================================================
   Mobile master-data card recipe.

   Compact 2-line card per row. The HEAD row hides (table is now a list of
   cards, not a grid with column headers). Each row becomes a compact card:

     ┌──────────────────────────────────┐
     │ CODE (mono, muted)               │ │
     │ Name / description (bold)        │ │ ← chevron
     │ status · flags · meta info       │ │
     └──────────────────────────────────┘

   Card height ~70-90 px (vs the previous ~130 px). The chevron is
   absolute-positioned right-of-content so it doesn't take a full row. All
   cell-* classes get reduced font sizes + muted secondary tones to make the
   primary "Name" cell stand out.

   Pages with a genuinely tabular display they want to preserve at mobile
   should wrap the table in `<div class="orcanex-mdtable-wide">` (the one
   exception documented in CLAUDE.md / responsive-design.md).
   ============================================================================ */
:root[data-viewport="mobile"]   .orcanex-mdtable .orcanex-mdtable-head,
:root[data-viewport="mobile-l"] .orcanex-mdtable .orcanex-mdtable-head {
    display: none;
}

:root[data-viewport="mobile"]   .orcanex-mdtable[data-list-mode="card"] .orcanex-mdtable-row,
:root[data-viewport="mobile-l"] .orcanex-mdtable[data-list-mode="card"] .orcanex-mdtable-row,
:root[data-viewport="mobile"]   .orcanex-mdtable[data-list-mode="tabular"] .orcanex-mdtable-row,
:root[data-viewport="mobile-l"] .orcanex-mdtable[data-list-mode="tabular"] .orcanex-mdtable-row {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 10px 36px 10px 12px;
    position: relative;
    grid-template-columns: none !important;
    min-height: 0;
}

:root[data-viewport="mobile"]   .orcanex-mdtable-row > [class*="orcanex-mdtable-cell-"],
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > [class*="orcanex-mdtable-cell-"] {
    width: 100%;
    min-width: 0;
}

/* Code cell — small muted uppercase identifier label above the name. */
:root[data-viewport="mobile"]   .orcanex-mdtable-row > .orcanex-mdtable-cell-code,
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > .orcanex-mdtable-cell-code {
    font-size: 0.7rem;
    color: var(--color-text-muted);
    font-family: var(--font-mono);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.3;
}

/* Name / description cell — primary text, bold, slightly larger. */
:root[data-viewport="mobile"]   .orcanex-mdtable-row > .orcanex-mdtable-cell-name,
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > .orcanex-mdtable-cell-name {
    font-weight: 600;
    font-size: 0.95rem;
    color: var(--color-text);
    line-height: 1.25;
}

/* Secondary cells — description / sequence / flags / status pill row. */
:root[data-viewport="mobile"]   .orcanex-mdtable-row > .orcanex-mdtable-cell-desc,
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > .orcanex-mdtable-cell-desc,
:root[data-viewport="mobile"]   .orcanex-mdtable-row > .orcanex-mdtable-cell-flags,
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > .orcanex-mdtable-cell-flags,
:root[data-viewport="mobile"]   .orcanex-mdtable-row > .orcanex-mdtable-cell-status,
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > .orcanex-mdtable-cell-status {
    font-size: 0.78rem;
    color: var(--color-text-muted);
    line-height: 1.3;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    margin-top: 2px;
}

/* Chevron — absolute-positioned at the right vertical centre of the card
   so it doesn't take a full row beneath the cells. */
:root[data-viewport="mobile"]   .orcanex-mdtable-row > .orcanex-mdtable-cell-actions,
:root[data-viewport="mobile-l"] .orcanex-mdtable-row > .orcanex-mdtable-cell-actions {
    position: absolute;
    top: 50%;
    right: 12px;
    transform: translateY(-50%);
    color: var(--color-text-muted);
    width: auto;
    margin: 0;
    padding: 0;
}

/* Tighten the card list gap so cards sit closer together. */
:root[data-viewport="mobile"]   .orcanex-mdtable[data-list-mode="card"],
:root[data-viewport="mobile-l"] .orcanex-mdtable[data-list-mode="card"] {
    gap: 6px;
}

/* "Card mode" rounded corners are still useful at mobile (gives each row
   visual definition), but tighten the radius a touch. */
:root[data-viewport="mobile"]   .orcanex-mdtable[data-list-mode="card"] .orcanex-mdtable-row,
:root[data-viewport="mobile-l"] .orcanex-mdtable[data-list-mode="card"] .orcanex-mdtable-row {
    border-radius: 8px;
}

/* Wide-table escape hatch — keep the grid layout but allow horizontal scroll
   inside a wrapper so the page never side-scrolls. */
.orcanex-mdtable-wide {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* ============================================================================
   Bootstrap `.sticky-top` z-index clamp — global.

   Bootstrap's `.sticky-top` ships with `z-index: 1020`, which is far too
   high for what a sticky table header actually needs to do (stay above the
   rows scrolling underneath it). On mobile it bleeds above tab strips and
   the MobileTabPicker trigger. On desktop it bleeds above the IconRail's
   hover popout sub-menus — when a user clicks a menu item with a sticky
   table on screen behind it, the popout disappears under the table header.

   Clamp globally: any `thead.sticky-top` (the Bootstrap pattern) gets
   `z-index: 1` so it stays sticky within its own `.table-responsive`
   scroll wrap without escaping into the page stacking context. Tables
   never need to render above their containing page chrome.

   Applies to every page in the app that uses `<thead class="sticky-top">`
   — EnvSettings (9 tables), LogExplorer, LogViewer, Specialist_Services
   (Service Types / Injury Types / Specialities), and any ad-hoc admin
   table. The previous mobile-only clamp was extended to all viewports
   because the desktop case has the same shape.
   ============================================================================ */
thead.sticky-top {
    z-index: 1 !important;
}
