/* =====================================================================
   CLIENT CRM -- GLASSMORPHIC 3D DESIGN SYSTEM
   =====================================================================

   One design language for the whole app: a deep ambient background,
   translucent glass surfaces floating on it, layered shadows for real
   depth, gradient buttons with a sheen sweep, and inline SVG icons that
   take their colour from the text they sit in.

   Dark is the default because the system is built dark-first -- the
   glass, the gradient wash and the shadow stack all assume a deep
   ground. Light is a full, deliberate alternative, not an afterthought:
   every token is redefined under [data-theme="light"], so nothing in
   here needs a second rule to work in both.

   Bootstrap 5 is still loaded, for its grid, dropdowns and modals. This
   sheet overrides its visual layer wholesale rather than fighting it
   selector by selector.

   Contents
     1.  Tokens
     2.  Reset, ambient background, scrollbars
     3.  Typography and text utilities
     4.  Bootstrap bridge
     5.  Layout shell -- sidebar, topbar, content
     6.  Topbar chrome
     7.  Page header and filter chips
     8.  Cards and panels
     9.  Buttons
     10. Forms
     11. Tables
     12. Badges and status
     13. KPI tiles and quick actions
     14. Service catalog
     15. Case entry and selection
     16. Messaging
     17. Files, galleries and the lightbox
     18. Tasks
     19. Accounting
     20. Danger zones and deletion
     21. Auth page
     22. Odds and ends
     23. Responsive, motion and print
   ===================================================================== */

/* ---------- 1. Tokens ------------------------------------------------ */
:root {
    /* Brand ramp. Three stops, used as a gradient nearly everywhere a
       surface needs to read as "ours" rather than as chrome. */
    --brand-1: #6366f1;
    --brand-2: #8b5cf6;
    --brand-3: #d946ef;
    --accent:  #22d3ee;

    --success: #10b981;
    --warning: #f59e0b;
    --danger:  #ef4444;
    --info:    #3b82f6;

    /* Surface stack, darkest first. */
    --bg-0: #070b18;
    --bg-1: #0b1124;
    --bg-2: #101a35;

    --glass:         rgba(255, 255, 255, .055);
    --glass-strong:  rgba(255, 255, 255, .085);
    --glass-hover:   rgba(255, 255, 255, .11);
    --stroke:        rgba(255, 255, 255, .10);
    --stroke-soft:   rgba(255, 255, 255, .06);
    --stroke-bright: rgba(255, 255, 255, .20);

    --text-1: #eef2ff;
    --text-2: #a9b4d8;
    --text-3: #6f7ba3;

    /* Elevation. Two shadows per level -- a tight contact shadow and a
       wide ambient one -- because one shadow alone never reads as depth. */
    --sh-1: 0 1px 2px rgba(0,0,0,.30), 0 4px 12px rgba(0,0,0,.22);
    --sh-2: 0 2px 6px rgba(0,0,0,.32), 0 12px 30px rgba(0,0,0,.34);
    --sh-3: 0 4px 12px rgba(0,0,0,.34), 0 26px 60px rgba(0,0,0,.46);
    --sh-4: 0 10px 24px rgba(0,0,0,.38), 0 44px 100px rgba(0,0,0,.58);
    --glow: 0 0 0 1px rgba(139,92,246,.45), 0 3px 12px rgba(99,102,241,.20);

    --inset-top: inset 0 1px 0 rgba(255,255,255,.10);

    --r-sm:  10px;
    --r-md:  14px;
    --r-lg:  20px;
    --r-xl:  28px;
    --r-pill: 999px;

    --sidebar-w: 268px;
    --topbar-h:  74px;

    --ease:      cubic-bezier(.22, 1, .36, 1);
    --ease-soft: cubic-bezier(.4, 0, .2, 1);

    --font: 'Plus Jakarta Sans', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

    /* Aliases kept for anything still reaching for the old names. */
    --brand-primary: var(--brand-1);
    --brand-accent:  var(--accent);
    --surface:       var(--bg-2);
    --surface-muted: var(--bg-1);
    --border-soft:   var(--stroke);
    --text-main:     var(--text-1);
    --text-muted:    var(--text-2);
    --radius-md:     var(--r-md);
    --radius-lg:     var(--r-lg);
    --shadow-sm:     var(--sh-1);
    --shadow-md:     var(--sh-2);
    --shadow-lg:     var(--sh-3);

    color-scheme: dark;
}

/* Light theme. Only the tokens change; not one component rule below
   needs a light-specific twin because of it. */
[data-theme="light"] {
    --bg-0: #eef1f9;
    --bg-1: #f6f8fd;
    --bg-2: #ffffff;

    --glass:         rgba(255, 255, 255, .70);
    --glass-strong:  rgba(255, 255, 255, .86);
    --glass-hover:   rgba(255, 255, 255, .95);
    --stroke:        rgba(15, 23, 42, .10);
    --stroke-soft:   rgba(15, 23, 42, .06);
    --stroke-bright: rgba(15, 23, 42, .18);

    --text-1: #0f172a;
    --text-2: #475569;
    --text-3: #94a3b8;

    --sh-1: 0 1px 2px rgba(15,23,42,.05), 0 4px 12px rgba(15,23,42,.06);
    --sh-2: 0 2px 6px rgba(15,23,42,.07), 0 12px 30px rgba(15,23,42,.09);
    --sh-3: 0 4px 12px rgba(15,23,42,.08), 0 26px 60px rgba(15,23,42,.13);
    --sh-4: 0 10px 24px rgba(15,23,42,.10), 0 44px 100px rgba(15,23,42,.18);
    --glow: 0 0 0 1px rgba(139,92,246,.40), 0 3px 12px rgba(99,102,241,.14);

    --inset-top: inset 0 1px 0 rgba(255,255,255,.60);

    color-scheme: light;
}

/* ---------- 2. Reset, ambient background, scrollbars ----------------- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
    font-family: var(--font);
    background: var(--bg-0);
    color: var(--text-1);
    min-height: 100vh;
    line-height: 1.6;
    font-size: 15px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

/* The depth behind the glass. Four coloured pools, blurred and drifting
   slowly, so surfaces above them pick up a different tint depending on
   where they sit -- which is what makes translucency read as real. */
body::before {
    content: '';
    position: fixed;
    inset: -20%;
    z-index: -2;
    background:
        radial-gradient(46rem 46rem at 12% 8%,  rgba(99,102,241,.28), transparent 62%),
        radial-gradient(40rem 40rem at 88% 12%, rgba(217,70,239,.20), transparent 60%),
        radial-gradient(50rem 50rem at 60% 92%, rgba(34,211,238,.16), transparent 62%),
        radial-gradient(36rem 36rem at 8% 88%,  rgba(139,92,246,.20), transparent 60%);
    filter: blur(20px);
    animation: drift 26s var(--ease-soft) infinite alternate;
}

/* A faint grid, masked to fade out at the edges. Gives the eye something
   to measure the glass blur against. */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image:
        linear-gradient(rgba(255,255,255,.022) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255,255,255,.022) 1px, transparent 1px);
    background-size: 56px 56px;
    mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, #000 20%, transparent 80%);
    -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, #000 20%, transparent 80%);
}

[data-theme="light"] body::before { opacity: .55; }
[data-theme="light"] body::after {
    background-image:
        linear-gradient(rgba(15,23,42,.035) 1px, transparent 1px),
        linear-gradient(90deg, rgba(15,23,42,.035) 1px, transparent 1px);
}

@keyframes drift {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    50%  { transform: translate3d(2%, -2%, 0) scale(1.06); }
    100% { transform: translate3d(-2%, 2%, 0) scale(1.02); }
}

img, video { display: block; max-width: 100%; }
svg { max-width: 100%; }

a { color: inherit; text-decoration: none; }
a:hover { color: inherit; }
button, input, select, textarea { font-family: inherit; }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: linear-gradient(var(--brand-1), var(--brand-2));
    border-radius: 99px;
    border: 3px solid transparent;
    background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
    background: linear-gradient(var(--brand-2), var(--brand-3));
    background-clip: content-box;
}
::selection { background: rgba(139,92,246,.42); color: #fff; }

/* ---------- 3. Typography and text utilities ------------------------- */
h1, h2, h3, h4, h5, h6 {
    line-height: 1.22;
    font-weight: 700;
    letter-spacing: -.021em;
    color: var(--text-1);
}
h1 { font-size: clamp(1.5rem, 2.2vw, 1.95rem); }
h2 { font-size: clamp(1.2rem, 1.7vw, 1.5rem); }
h3 { font-size: 1.1rem; }
h4 { font-size: 1rem; }
h5 { font-size: .95rem; }
h6 { font-size: .875rem; }

.section-title {
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--text-1);
}

.grad-text {
    background: linear-gradient(110deg, var(--brand-1), var(--brand-2) 42%, var(--brand-3) 72%, var(--accent));
    background-size: 220% auto;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: shimmer 7s linear infinite;
}
@keyframes shimmer { to { background-position: 220% center; } }

.text-muted-soft { color: var(--text-2) !important; }
.mono { font-family: var(--mono); }

.eyebrow,
.topbar-eyebrow,
.page-header-eyebrow,
.nav-section-label,
.detail-label {
    text-transform: uppercase;
    letter-spacing: .16em;
    font-size: .68rem;
    font-weight: 700;
    color: var(--text-3);
}

/* Inline icons sit on the text baseline instead of forcing their own
   line box. Inside a flex or grid parent they still centre exactly. */
.ic {
    display: inline-block;
    vertical-align: -0.16em;
    flex: 0 0 auto;
}
h1 .ic, h2 .ic, h3 .ic, h4 .ic, h5 .ic, h6 .ic { margin-right: .14em; }

.min-w-0 { min-width: 0; }
.req-star { color: var(--danger); font-weight: 700; }

/* ---------- 4. Bootstrap bridge -------------------------------------- */
/*
   Bootstrap stays loaded for the grid, dropdowns, modals and collapse.
   Its look does not. Rather than chase individual pages, its surface
   components are redefined here once, in the same glass language as
   everything else.
*/
.card {
    background: var(--glass);
    backdrop-filter: blur(20px) saturate(150%);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    border: 1px solid var(--stroke);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2), var(--inset-top);
    color: var(--text-1);
}

.dropdown-menu {
    background: linear-gradient(150deg, rgba(255,255,255,.11), rgba(255,255,255,.045));
    backdrop-filter: blur(30px) saturate(160%);
    -webkit-backdrop-filter: blur(30px) saturate(160%);
    border: 1px solid var(--stroke-bright);
    border-radius: var(--r-md);
    box-shadow: var(--sh-3);
    padding: 6px;
    color: var(--text-1);
}
[data-theme="light"] .dropdown-menu {
    background: linear-gradient(150deg, rgba(255,255,255,.97), rgba(255,255,255,.92));
}
.dropdown-item {
    border-radius: var(--r-sm);
    padding: 8px 12px;
    font-size: .875rem;
    font-weight: 600;
    color: var(--text-2);
    display: flex;
    align-items: center;
    gap: 9px;
    transition: background .2s var(--ease), color .2s var(--ease);
}
.dropdown-item:hover,
.dropdown-item:focus {
    background: var(--glass-hover);
    color: var(--text-1);
}
.dropdown-item.text-danger:hover { background: rgba(239,68,68,.16); color: #fca5a5; }
[data-theme="light"] .dropdown-item.text-danger:hover { color: #b91c1c; }
.dropdown-header { color: var(--text-3); font-size: .74rem; letter-spacing: .04em; }
.dropdown-item-text { color: var(--text-2); }
.dropdown-divider { border-color: var(--stroke-soft); }

.modal-content {
    background: linear-gradient(150deg, rgba(255,255,255,.11), rgba(255,255,255,.045));
    backdrop-filter: blur(34px) saturate(160%);
    -webkit-backdrop-filter: blur(34px) saturate(160%);
    border: 1px solid var(--stroke-bright);
    border-radius: var(--r-xl);
    box-shadow: var(--sh-4), inset 0 1px 0 rgba(255,255,255,.20);
    color: var(--text-1);
}
[data-theme="light"] .modal-content {
    background: linear-gradient(150deg, rgba(255,255,255,.97), rgba(255,255,255,.92));
}
.modal-header, .modal-footer { border-color: var(--stroke-soft); }
.modal-backdrop.show { opacity: .68; backdrop-filter: blur(8px); }

.alert {
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    box-shadow: var(--sh-1), var(--inset-top);
    color: var(--text-1);
    padding: 13px 17px;
    font-size: .89rem;
    position: relative;
    overflow: hidden;
    animation: slideIn .35s var(--ease);
}
/* The type reads off a coloured spine rather than a wash of colour, so
   three stacked alerts do not turn the page into a traffic light. */
.alert::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--brand-2);
}
.alert-success::before { background: var(--success); }
.alert-danger::before  { background: var(--danger); }
.alert-warning::before { background: var(--warning); }
.alert-info::before    { background: var(--info); }
.alert-success { background: rgba(16,185,129,.12);  border-color: rgba(16,185,129,.28); }
.alert-danger  { background: rgba(239,68,68,.12);   border-color: rgba(239,68,68,.28); }
.alert-warning { background: rgba(245,158,11,.12);  border-color: rgba(245,158,11,.28); }
.alert-info    { background: rgba(59,130,246,.12);  border-color: rgba(59,130,246,.28); }
@keyframes slideIn { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

.btn-close {
    filter: invert(1) grayscale(1) brightness(1.6);
    opacity: .55;
}
[data-theme="light"] .btn-close { filter: none; }
.btn-close:hover { opacity: 1; }

.progress {
    height: 6px;
    border-radius: 99px;
    background: rgba(0,0,0,.30);
    overflow: hidden;
    box-shadow: inset 0 1px 3px rgba(0,0,0,.3);
}
[data-theme="light"] .progress { background: rgba(15,23,42,.10); }
.progress-bar {
    border-radius: 99px;
    background: linear-gradient(90deg, var(--tint, var(--brand-1)), var(--accent));
    box-shadow: 0 0 12px var(--tint, var(--brand-1));
    transition: width .8s var(--ease);
}

hr { border-color: var(--stroke-soft); opacity: 1; }

.text-danger  { color: #fca5a5 !important; }
.text-success { color: #6ee7b7 !important; }
.text-warning { color: #fcd34d !important; }
[data-theme="light"] .text-danger  { color: #b91c1c !important; }
[data-theme="light"] .text-success { color: #047857 !important; }
[data-theme="light"] .text-warning { color: #b45309 !important; }
.bg-light { background: var(--glass-strong) !important; }
.text-dark { color: var(--text-1) !important; }

/* ---------- 5. Layout shell ------------------------------------------ */
.app-shell {
    display: flex;
    min-height: 100vh;
}

.sidebar {
    width: var(--sidebar-w);
    flex: 0 0 var(--sidebar-w);
    position: sticky;
    top: 0;
    height: 100vh;
    padding: 22px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    background: linear-gradient(180deg, rgba(255,255,255,.075), rgba(255,255,255,.028));
    backdrop-filter: blur(26px) saturate(150%);
    -webkit-backdrop-filter: blur(26px) saturate(150%);
    border-right: 1px solid var(--stroke);
    z-index: 60;
    transition: transform .38s var(--ease);
    overflow-y: auto;
    overflow-x: hidden;
}
[data-theme="light"] .sidebar {
    background: linear-gradient(180deg, rgba(255,255,255,.85), rgba(255,255,255,.65));
}

.sidebar .brand {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 8px 20px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--stroke-soft);
    font-weight: 800;
    letter-spacing: -.02em;
    font-size: 1.03rem;
    color: var(--text-1);
}

/* The mark tips towards the cursor on hover -- a small, cheap piece of
   dimensionality that sets the tone for the rest of the interface. */
.logo-dot {
    width: 42px;
    height: 42px;
    flex: 0 0 42px;
    border-radius: 13px;
    display: grid;
    place-items: center;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));
    box-shadow: 0 3px 10px rgba(99,102,241,.24), inset 0 1px 0 rgba(255,255,255,.42);
    color: #fff;
    font-weight: 800;
    font-size: 1.05rem;
}

.nav-section-label { padding: 16px 12px 8px; }

.sidebar nav { display: flex; flex-direction: column; gap: 3px; }

.sidebar nav a {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 13px;
    border-radius: var(--r-md);
    color: var(--text-2);
    font-weight: 600;
    font-size: .905rem;
    position: relative;
    border: 1px solid transparent;
    transition: color .18s var(--ease-soft), background .18s var(--ease-soft),
                border-color .18s var(--ease-soft);
}
.sidebar nav a:hover {
    color: var(--text-1);
    background: var(--glass);
    border-color: var(--stroke-soft);
}
.sidebar nav a.active {
    color: #fff;
    background: linear-gradient(100deg, rgba(99,102,241,.30), rgba(139,92,246,.16));
    border-color: rgba(139,92,246,.42);
    box-shadow: 0 2px 9px rgba(99,102,241,.13), inset 0 1px 0 rgba(255,255,255,.14);
}
[data-theme="light"] .sidebar nav a.active { color: var(--brand-1); }
.sidebar nav a.active::before {
    content: '';
    position: absolute;
    left: -16px;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 22px;
    border-radius: 0 4px 4px 0;
    background: linear-gradient(var(--brand-2), var(--accent));
    box-shadow: 0 0 14px var(--brand-2);
}
.sidebar nav a .ic { opacity: .92; }

.unread-badge {
    margin-left: auto;
    font-size: .68rem;
    font-weight: 800;
    padding: 2px 8px;
    border-radius: var(--r-pill);
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
    color: #fff;
    box-shadow: 0 4px 12px rgba(99,102,241,.4);
}

.nav-dot {
    width: 8px;
    height: 8px;
    border-radius: 99px;
    margin-left: auto;
    background: var(--warning);
    box-shadow: 0 0 0 3px rgba(245,158,11,.22), 0 0 10px var(--warning);
    animation: pulseDot 2s var(--ease-soft) infinite;
}
@keyframes pulseDot { 0%,100% { opacity: 1; } 50% { opacity: .45; } }

.main-area {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.page-content {
    flex: 1 1 auto;
    padding: clamp(20px, 2.6vw, 32px) clamp(16px, 2.4vw, 32px) 64px;
    max-width: 1560px;
    width: 100%;
    margin: 0 auto;
}

.sidebar-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(2,4,12,.6);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: 55;
    display: none;
}
.sidebar-backdrop.open { display: block; animation: fadeIn .25s var(--ease); }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.sidebar-toggle-btn { display: none; }

/* ---------- 6. Topbar chrome ----------------------------------------- */
.topbar {
    min-height: var(--topbar-h);
    position: sticky;
    top: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 12px clamp(16px, 2.4vw, 32px);
    background: rgba(11,17,36,.55);
    backdrop-filter: blur(22px) saturate(160%);
    -webkit-backdrop-filter: blur(22px) saturate(160%);
    border-bottom: 1px solid var(--stroke);
}
[data-theme="light"] .topbar { background: rgba(255,255,255,.66); }

.topbar-left  { display: flex; align-items: center; gap: 12px; min-width: 0; }
.topbar-right { display: flex; align-items: center; gap: 10px; }
.topbar-eyebrow { margin-bottom: 1px; }

.topbar-search {
    position: relative;
    align-items: center;
    flex: 1 1 260px;
    max-width: 380px;
}
.topbar-search .ic {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-3);
    pointer-events: none;
}
.topbar-search input {
    width: 100%;
    padding: 9px 16px 9px 42px;
    border-radius: var(--r-pill);
    border: 1px solid var(--stroke);
    background: rgba(0,0,0,.20);
    color: var(--text-1);
    font-size: .875rem;
    transition: border-color .22s, box-shadow .22s, background .22s;
    box-shadow: inset 0 2px 6px rgba(0,0,0,.20);
}
[data-theme="light"] .topbar-search input {
    background: rgba(255,255,255,.80);
    box-shadow: inset 0 2px 5px rgba(15,23,42,.05);
}
.topbar-search input::placeholder { color: var(--text-3); }
.topbar-search input:focus {
    outline: none;
    border-color: var(--brand-2);
    box-shadow: 0 0 0 3px rgba(139,92,246,.22), inset 0 2px 6px rgba(0,0,0,.20);
}

.icon-btn {
    position: relative;
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: grid;
    place-items: center;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-2);
    cursor: pointer;
    box-shadow: var(--sh-1);
    transition: color .24s var(--ease), background .24s var(--ease),
                transform .24s var(--ease), box-shadow .24s var(--ease);
}
.icon-btn:hover {
    color: var(--text-1);
    background: var(--glass-hover);
    border-color: var(--stroke-bright);
}

.icon-btn-badge,
.sample-count-badge,
.thread-tab-badge {
    position: absolute;
    top: -5px;
    right: -5px;
    min-width: 19px;
    padding: 1px 5px;
    border-radius: var(--r-pill);
    font-size: .64rem;
    font-weight: 800;
    line-height: 17px;
    text-align: center;
    color: #fff;
    background: linear-gradient(120deg, #f43f5e, var(--danger));
    box-shadow: 0 4px 12px rgba(239,68,68,.45);
}

.theme-toggle-btn {
    position: relative;
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: grid;
    place-items: center;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-2);
    cursor: pointer;
    box-shadow: var(--sh-1);
    overflow: hidden;
    transition: color .24s var(--ease), background .24s var(--ease), transform .24s var(--ease);
}
.theme-toggle-btn:hover { color: var(--text-1); background: var(--glass-hover); border-color: var(--stroke-bright); }
/* Both glyphs live in the button and swap on a rotate, so the change
   reads as one control turning over rather than two icons blinking. */
.theme-toggle-btn .ic {
    grid-area: 1 / 1;
    transition: transform .45s var(--ease), opacity .3s var(--ease);
}
.theme-toggle-btn .ic:first-child { transform: rotate(0deg) scale(1); opacity: 1; }
.theme-toggle-btn .ic:last-child  { transform: rotate(-90deg) scale(.4); opacity: 0; }
[data-theme="light"] .theme-toggle-btn .ic:first-child { transform: rotate(90deg) scale(.4); opacity: 0; }
[data-theme="light"] .theme-toggle-btn .ic:last-child  { transform: rotate(0deg) scale(1); opacity: 1; }

.user-chip {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 12px 5px 5px;
    border-radius: var(--r-pill);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-1);
    cursor: pointer;
    box-shadow: var(--sh-1);
    transition: background .24s var(--ease), transform .24s var(--ease), box-shadow .24s var(--ease);
}
.user-chip:hover { background: var(--glass-hover); border-color: var(--stroke-bright); }
.user-chip-text { flex-direction: column; align-items: flex-start; line-height: 1.15; }
.user-chip-name { font-weight: 700; font-size: .845rem; }
.user-chip-role { font-size: .68rem; color: var(--text-3); font-weight: 600; }
.user-chip-caret { color: var(--text-3); transition: transform .3s var(--ease); }
.user-chip[aria-expanded="true"] .user-chip-caret { transform: rotate(180deg); }
.user-chip-menu { min-width: 220px; }

.avatar-placeholder {
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    border-radius: 99px;
    display: grid;
    place-items: center;
    font-weight: 800;
    font-size: .85rem;
    color: #fff;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));
    box-shadow: 0 2px 7px rgba(99,102,241,.21), inset 0 1px 0 rgba(255,255,255,.35);
}

/* ---------- 7. Page header and filter chips -------------------------- */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    margin-bottom: 24px;
}
.page-header-title {
    font-size: clamp(1.4rem, 2.1vw, 1.8rem);
    font-weight: 800;
    letter-spacing: -.03em;
    line-height: 1.15;
    margin: 2px 0 0;
}
.page-header-subtitle {
    color: var(--text-2);
    margin-top: 7px;
    max-width: 68ch;
    font-size: .9rem;
}
.page-header-actions {
    display: flex;
    align-items: center;
    gap: 9px;
    flex-wrap: wrap;
}

.filter-chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 18px; }

/*
   Two jobs, one chip. As a filter toggle it is quiet until chosen; as the
   "you are looking at a filtered list" indicator (the variant carrying a
   clear button) it is always lit, because that is the whole point of it.
*/
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border-radius: var(--r-pill);
    font-size: .81rem;
    font-weight: 650;
    color: var(--text-2);
    background: var(--glass-strong);
    border: 1px solid var(--stroke);
    box-shadow: var(--sh-1);
    transition: color .18s var(--ease-soft), background .18s var(--ease-soft),
                border-color .18s var(--ease-soft);
}
.filter-chip:hover { color: var(--text-1); background: var(--glass-hover); border-color: var(--stroke-bright); }
.filter-chip.active,
.filter-chip:has(.filter-chip-clear) {
    color: #fff;
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
    border-color: transparent;
    box-shadow: 0 2px 7px rgba(99,102,241,.20);
}
.filter-chip.active:hover,
.filter-chip:has(.filter-chip-clear):hover { color: #fff; }
.filter-chip:has(.filter-chip-clear) { padding-right: 8px; }
.filter-chip-clear {
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 99px;
    background: rgba(255,255,255,.22);
    color: #fff;
    transition: background .18s var(--ease-soft);
}
.filter-chip-clear:hover { background: rgba(255,255,255,.4); }

.upgrade-banner {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px 20px;
    border-radius: var(--r-lg);
    margin-bottom: 22px;
    background: linear-gradient(135deg, rgba(245,158,11,.18), rgba(217,70,239,.10));
    border: 1px solid rgba(245,158,11,.34);
    box-shadow: var(--sh-2), var(--inset-top);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
}
.upgrade-banner-icon {
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    border-radius: 14px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--warning), #ea580c);
    box-shadow: 0 3px 9px rgba(245,158,11,.21), inset 0 1px 0 rgba(255,255,255,.35);
}

/* ---------- 8. Cards and panels -------------------------------------- */
.card-elevated,
.glass-panel {
    position: relative;
    background: var(--glass);
    backdrop-filter: blur(20px) saturate(150%);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    border: 1px solid var(--stroke);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2), var(--inset-top);
    overflow: hidden;
    transition: transform .4s var(--ease), box-shadow .4s var(--ease),
                border-color .3s var(--ease), background .3s var(--ease);
}

/* A single diagonal sheen across the top-left corner. It is what stops a
   flat translucent rectangle from looking like a flat translucent
   rectangle -- glass catches light unevenly. */
.card-elevated::after,
.glass-panel::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(150deg, rgba(255,255,255,.13), transparent 42%);
    opacity: .8;
}

.card-elevated > * { position: relative; z-index: 1; }

.card-elevated .card-header,
.card .card-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 15px 20px;
    background: transparent;
    border-bottom: 1px solid var(--stroke-soft);
    font-weight: 700;
    font-size: .95rem;
    letter-spacing: -.012em;
    color: var(--text-1);
}
.card-header-note {
    margin-left: auto;
    font-size: .74rem;
    font-weight: 600;
    color: var(--text-3);
    text-transform: none;
    letter-spacing: 0;
}

.card-elevated .card-body,
.card .card-body { padding: 20px; }
.card-elevated .card-body.border-top { border-top: 1px solid var(--stroke-soft) !important; }

/*
 * Hover, across this whole stylesheet, follows one rule: only things you
 * can act on react to the pointer, and they react once -- a step in edge
 * and fill, no lift, no growing shadow, no motion.
 *
 * This file used to track the cursor and paint a moving highlight across
 * every card, static panels included. It demonstrated well and worked
 * badly: on a page of eight tiles the whole interface shimmered as the
 * mouse crossed it, and a panel that lights up when you are only passing
 * over it on the way somewhere else is telling you something untrue.
 * A `.card-elevated` that just holds content now does nothing at all on
 * hover, which is the correct amount.
 */

.detail-label { margin-bottom: 10px; display: flex; align-items: center; gap: 7px; }

.detail-fact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 14px;
}
.detail-fact {
    padding: 13px 15px;
    border-radius: var(--r-md);
    background: var(--glass);
    border: 1px solid var(--stroke-soft);
    min-width: 0;
}
.detail-fact-label {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .14em;
    font-weight: 700;
    color: var(--text-3);
}
.detail-fact-value {
    margin-top: 5px;
    font-weight: 700;
    font-size: .95rem;
    color: var(--text-1);
    word-break: break-word;
}

.empty-note,
.chat-empty,
.file-grid-empty,
.catalog-no-results,
.search-no-results,
.sample-modal-empty {
    text-align: center;
    padding: 40px 24px;
    border-radius: var(--r-lg);
    background: var(--glass);
    border: 1px dashed var(--stroke-bright);
    color: var(--text-2);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
}
.empty-note .ic,
.chat-empty .ic,
.file-grid-empty .ic {
    color: var(--brand-2);
    margin-bottom: 10px;
    opacity: .85;
}
.empty-note > div:first-of-type { font-weight: 700; color: var(--text-1); }
.empty-note .small { color: var(--text-3); margin-top: 4px; }

/* ---------- 9. Buttons ----------------------------------------------- */
/*
   One button shape for the whole app. The sheen sweep on hover is the
   detail that makes them feel like objects rather than rectangles: a
   diagonal band of light crossing the face, once, on the way in.
*/
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 10px 18px;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-1);
    font-weight: 650;
    font-size: .9rem;
    line-height: 1.35;
    cursor: pointer;
    position: relative;
    white-space: nowrap;
    text-decoration: none;
    box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,255,255,.12);
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft),
                color .18s var(--ease-soft), filter .18s var(--ease-soft);
}
/* The face lightens and the edge sharpens. The button does not rise off
   the page, and no band of light sweeps across it. */
.btn:hover {
    background: var(--glass-hover);
    border-color: var(--stroke-bright);
    color: var(--text-1);
}
/* Press is the one place motion earns its keep: a control that yields
   under the cursor confirms the click before the page has answered. */
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; box-shadow: none; }
.btn:disabled, .btn.disabled { opacity: .45; pointer-events: none; }

.btn-brand,
.btn-primary {
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 9px rgba(99,102,241,.21), inset 0 1px 0 rgba(255,255,255,.30);
}
.btn-brand:hover,
.btn-primary:hover {
    color: #fff;
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));
    filter: brightness(1.08);
}

.btn-danger {
    background: linear-gradient(120deg, #f43f5e, var(--danger));
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 9px rgba(239,68,68,.19), inset 0 1px 0 rgba(255,255,255,.24);
}
.btn-danger:hover { color: #fff; background: linear-gradient(120deg, #f43f5e, var(--danger)); filter: brightness(1.07); }

.btn-success {
    background: linear-gradient(120deg, #34d399, var(--success));
    border-color: transparent;
    color: #04231a;
    box-shadow: 0 2px 9px rgba(16,185,129,.17), inset 0 1px 0 rgba(255,255,255,.28);
}
.btn-success:hover { color: #04231a; background: linear-gradient(120deg, #34d399, var(--success)); filter: brightness(1.06); }

.btn-warning {
    background: linear-gradient(120deg, #fbbf24, var(--warning));
    border-color: transparent;
    color: #2a1a02;
    box-shadow: 0 2px 9px rgba(245,158,11,.17), inset 0 1px 0 rgba(255,255,255,.30);
}
.btn-warning:hover { color: #2a1a02; background: linear-gradient(120deg, #fbbf24, var(--warning)); filter: brightness(1.06); }

/* The quiet button. Most of the app is quiet buttons. */
.btn-light,
.btn-secondary,
.btn-outline-secondary {
    background: var(--glass-strong);
    border-color: var(--stroke);
    color: var(--text-2);
}
.btn-light:hover,
.btn-secondary:hover,
.btn-outline-secondary:hover { background: var(--glass-hover); color: var(--text-1); }
.btn-light.text-danger:hover { background: rgba(239,68,68,.18); border-color: rgba(239,68,68,.4); }

.btn-soft {
    background: rgba(99,102,241,.14);
    border-color: rgba(139,92,246,.32);
    color: var(--text-1);
    box-shadow: var(--sh-1);
}
.btn-soft:hover { background: rgba(99,102,241,.24); border-color: rgba(139,92,246,.5); }

/* Outline buttons keep a tinted edge and fill in on hover. */
.btn-outline-primary {
    background: transparent;
    border-color: rgba(139,92,246,.45);
    color: var(--brand-2);
    box-shadow: none;
}
.btn-outline-primary:hover {
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
    border-color: transparent;
    color: #fff;
}
[data-theme="light"] .btn-outline-primary { color: var(--brand-1); }

.btn-outline-danger {
    background: transparent;
    border-color: rgba(239,68,68,.45);
    color: #fca5a5;
    box-shadow: none;
}
.btn-outline-danger:hover {
    background: linear-gradient(120deg, #f43f5e, var(--danger));
    border-color: transparent;
    color: #fff;
}
[data-theme="light"] .btn-outline-danger { color: #b91c1c; }

.btn-outline-success {
    background: transparent;
    border-color: rgba(16,185,129,.45);
    color: #6ee7b7;
    box-shadow: none;
}
.btn-outline-success:hover {
    background: linear-gradient(120deg, #34d399, var(--success));
    border-color: transparent;
    color: #04231a;
}
[data-theme="light"] .btn-outline-success { color: #047857; }

.btn-outline-warning {
    background: transparent;
    border-color: rgba(245,158,11,.45);
    color: #fcd34d;
    box-shadow: none;
}
.btn-outline-warning:hover {
    background: linear-gradient(120deg, #fbbf24, var(--warning));
    border-color: transparent;
    color: #2a1a02;
}
[data-theme="light"] .btn-outline-warning { color: #b45309; }

.btn-sm { padding: 7px 13px; font-size: .82rem; border-radius: var(--r-sm); gap: 7px; }
.btn-lg { padding: 14px 26px; font-size: 1rem; border-radius: var(--r-lg); }

/* A square icon-only button, used in table rows and file tiles. */
.btn-sm.btn-light > .ic:only-child { margin: 0 -1px; }

.btn-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

/* ---------- 10. Forms ------------------------------------------------- */
.form-label {
    display: block;
    font-size: .795rem;
    font-weight: 700;
    color: var(--text-2);
    margin-bottom: 7px;
    letter-spacing: .015em;
}

.form-control,
.form-select {
    width: 100%;
    padding: 11px 14px;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: rgba(0,0,0,.20);
    color: var(--text-1);
    font-size: .92rem;
    box-shadow: inset 0 2px 6px rgba(0,0,0,.20);
    transition: border-color .22s, box-shadow .22s, background .22s;
}
[data-theme="light"] .form-control,
[data-theme="light"] .form-select {
    background: rgba(255,255,255,.80);
    box-shadow: inset 0 2px 5px rgba(15,23,42,.05);
}
.form-control::placeholder { color: var(--text-3); }
.form-control:focus,
.form-select:focus {
    outline: none;
    border-color: var(--brand-2);
    background: rgba(0,0,0,.28);
    color: var(--text-1);
    box-shadow: 0 0 0 3px rgba(139,92,246,.22), inset 0 2px 6px rgba(0,0,0,.20);
}
[data-theme="light"] .form-control:focus,
[data-theme="light"] .form-select:focus { background: #fff; }
.form-control:disabled,
.form-control[readonly],
.form-select:disabled { opacity: .6; background: var(--glass); }

.form-control-sm, .form-select-sm { padding: 8px 12px; font-size: .845rem; border-radius: var(--r-sm); }
.form-control-lg, .form-select-lg { padding: 13px 17px; font-size: 1rem; }

textarea.form-control { min-height: 110px; resize: vertical; line-height: 1.62; }

.form-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a9b4d8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
    padding-right: 38px;
    cursor: pointer;
}
.form-select option { background: var(--bg-1); color: var(--text-1); }
[data-theme="light"] .form-select option { background: #fff; }

.form-text, .form-action-hint { font-size: .765rem; color: var(--text-3); }

.input-group-text {
    background: var(--glass-strong);
    border: 1px solid var(--stroke);
    color: var(--text-2);
    border-radius: var(--r-md);
    font-size: .875rem;
}

.form-check-input {
    width: 1.15em;
    height: 1.15em;
    margin-top: .2em;
    background-color: rgba(0,0,0,.28);
    border: 1px solid var(--stroke-bright);
    box-shadow: inset 0 1px 3px rgba(0,0,0,.3);
    cursor: pointer;
}
[data-theme="light"] .form-check-input { background-color: rgba(255,255,255,.9); }
.form-check-input:checked {
    background-color: var(--brand-1);
    border-color: transparent;
    box-shadow: 0 3px 10px rgba(99,102,241,.42);
}
.form-check-input:focus { border-color: var(--brand-2); box-shadow: 0 0 0 3px rgba(139,92,246,.22); }
.form-check-label { color: var(--text-2); cursor: pointer; }

/*
   Bootstrap draws the switch knob as a background-image and the track as
   background-color. Only the track colour changes here -- overwriting
   background-image would delete the knob and leave a bare pill.
*/
.form-switch .form-check-input {
    width: 2.6em;
    height: 1.4em;
    border-radius: 99px;
    background-color: rgba(0,0,0,.35);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23a9b4d8'/%3E%3C/svg%3E");
    box-shadow: inset 0 2px 5px rgba(0,0,0,.28);
}
[data-theme="light"] .form-switch .form-check-input { background-color: rgba(15,23,42,.16); }
.form-switch .form-check-input:checked {
    background-color: var(--brand-1);
    border-color: transparent;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");
    box-shadow: 0 4px 12px rgba(99,102,241,.42), inset 0 1px 0 rgba(255,255,255,.28);
}
.form-switch .form-check-input:focus {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23a9b4d8'/%3E%3C/svg%3E");
}
.form-switch .form-check-input:checked:focus {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E");
}

.form-action-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 16px 20px;
    margin-top: 20px;
    border-radius: var(--r-lg);
    background: var(--glass-strong);
    border: 1px solid var(--stroke);
    box-shadow: var(--sh-1), var(--inset-top);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
}
.form-action-bar .btn:last-child { margin-left: auto; }

/* Drop zone. The icon floats, which is the one hint people need that
   the whole panel is a target and not a decoration. */
.upload-dropzone {
    border: 2px dashed var(--stroke-bright);
    border-radius: var(--r-lg);
    padding: 30px 22px;
    text-align: center;
    cursor: pointer;
    background: rgba(0,0,0,.16);
    transition: border-color .18s var(--ease-soft), background .18s var(--ease-soft);
    position: relative;
}
[data-theme="light"] .upload-dropzone { background: rgba(255,255,255,.5); }
.upload-dropzone:hover,
.upload-dropzone.is-dragover {
    border-color: var(--brand-2);
    background: rgba(139,92,246,.09);
}
.dz-icon {
    width: 58px;
    height: 58px;
    margin: 0 auto 13px;
    border-radius: 18px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2));
    box-shadow: 0 4px 13px rgba(99,102,241,.21), inset 0 1px 0 rgba(255,255,255,.35);
}
.dz-title { font-weight: 700; color: var(--text-1); }
.dz-hint  { font-size: .78rem; color: var(--text-3); margin-top: 5px; }
.dz-filelist { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; text-align: left; }
.dz-filelist > div,
.dz-filelist > span {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 13px;
    border-radius: var(--r-sm);
    background: var(--glass-strong);
    border: 1px solid var(--stroke-soft);
    font-size: .84rem;
    animation: slideIn .3s var(--ease);
}

/* ---------- 11. Tables ------------------------------------------------ */
.table-modern {
    width: 100%;
    border-collapse: collapse;
    font-size: .875rem;
    color: var(--text-1);
    margin-bottom: 0;
    --bs-table-bg: transparent;
    --bs-table-color: var(--text-1);
}
.table-modern > :not(caption) > * > * { background: transparent; color: inherit; box-shadow: none; }

.table-modern thead th {
    text-align: left;
    padding: 13px 16px;
    font-size: .72rem;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--text-3);
    border-bottom: 1px solid var(--stroke);
    white-space: nowrap;
    background: transparent;
}
.table-modern tbody td {
    padding: 13px 16px;
    border-bottom: 1px solid var(--stroke-soft);
    vertical-align: middle;
}
.table-modern tbody tr:last-child td { border-bottom: none; }
.table-modern tbody tr { transition: background .2s var(--ease); }
.table-modern tbody tr:hover { background: var(--glass-strong); }

/* A table inside a card should look like part of the card, not like a
   second surface stacked on it. */
.card-elevated > .table-responsive,
.card-elevated > .table-modern { border-radius: 0; }

.row-link { cursor: pointer; }
.row-link:hover { background: var(--glass-hover) !important; }
.row-link:focus-visible { outline: 2px solid var(--brand-2); outline-offset: -2px; }

/* ---------- 12. Badges and status ------------------------------------- */
.badge-soft,
.badge-status-active,
.badge-status-inactive,
.badge-status-cancelled,
.badge-status-paid,
.badge-status-partial,
.task-status-badge,
.thread-scope-chip,
.task-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 8px;
    font-size: .69rem;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: .06em;
    white-space: nowrap;
    border: 1px solid var(--stroke-soft);
    background: var(--glass-strong);
    color: var(--text-3);
}
.badge-soft .ic,
.task-status-badge .ic { width: 13px; height: 13px; }

.badge-status-active,
.badge-status-paid,
.task-done {
    background: rgba(16,185,129,.18);
    color: #6ee7b7;
    border-color: rgba(16,185,129,.32);
}
.badge-status-partial,
.task-progress {
    background: rgba(245,158,11,.18);
    color: #fcd34d;
    border-color: rgba(245,158,11,.32);
}
.badge-status-cancelled,
.task-cancelled {
    background: rgba(239,68,68,.18);
    color: #fca5a5;
    border-color: rgba(239,68,68,.32);
}
.badge-status-inactive,
.task-pending {
    background: var(--glass-strong);
    color: var(--text-3);
    border-color: var(--stroke-soft);
}
[data-theme="light"] .badge-status-active,
[data-theme="light"] .badge-status-paid,
[data-theme="light"] .task-done { color: #047857; }
[data-theme="light"] .badge-status-partial,
[data-theme="light"] .task-progress { color: #b45309; }
[data-theme="light"] .badge-status-cancelled,
[data-theme="light"] .task-cancelled { color: #b91c1c; }

/* A pill rather than a rectangle, for chips that sit inline in prose. */
.thread-scope-chip,
.task-chip,
.addon-picker-count,
.inbox-service-count,
.sample-pager-label {
    border-radius: var(--r-pill);
    text-transform: none;
    letter-spacing: 0;
    font-size: .73rem;
    font-weight: 650;
    padding: 4px 11px;
    color: var(--text-2);
}
.thread-scope-chip.is-general {
    background: rgba(99,102,241,.16);
    border-color: rgba(139,92,246,.34);
    color: #c7d2fe;
}
[data-theme="light"] .thread-scope-chip.is-general { color: var(--brand-1); }

/* ---------- 13. KPI tiles and quick actions ---------------------------- */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
    gap: 16px;
}

/*
   A whole tile is one link. The blurred colour pool in the corner is the
   only place the accent shows at full strength -- the rest of the tile
   stays neutral so eight of them side by side still read as a set.
*/
.kpi-card {
    position: relative;
    display: block;
    padding: 20px;
    border-radius: var(--r-lg);
    background: var(--glass);
    backdrop-filter: blur(20px) saturate(150%);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    border: 1px solid var(--stroke);
    box-shadow: var(--sh-2), var(--inset-top);
    color: var(--text-1);
    overflow: hidden;
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.kpi-card::before {
    content: '';
    position: absolute;
    right: -34px;
    top: -34px;
    width: 118px;
    height: 118px;
    border-radius: 50%;
    background: var(--kpi-accent, var(--brand-1));
    opacity: .16;
    filter: blur(22px);
    transition: opacity .35s var(--ease);
}
.kpi-card:hover {
    background: var(--glass-strong);
    border-color: var(--stroke-bright);
    color: var(--text-1);
}
.kpi-card:hover::before { opacity: .24; }

.kpi-card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    position: relative;
    z-index: 1;
}
.kpi-icon {
    width: 44px;
    height: 44px;
    border-radius: 14px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--kpi-accent, var(--brand-1)),
                color-mix(in srgb, var(--kpi-accent, var(--brand-1)) 55%, #000));
    box-shadow: 0 8px 20px var(--kpi-accent-soft, rgba(99,102,241,.40)), inset 0 1px 0 rgba(255,255,255,.35);
}

.kpi-arrow {
    color: var(--text-3);
    opacity: 0;
    transform: translate(-6px, 6px);
    transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.kpi-card:hover .kpi-arrow { opacity: 1; transform: none; }

.kpi-value {
    position: relative;
    z-index: 1;
    margin-top: 16px;
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -.032em;
    line-height: 1;
}
.kpi-label {
    position: relative;
    z-index: 1;
    font-size: .79rem;
    color: var(--text-2);
    margin-top: 7px;
    font-weight: 600;
}

.quick-card {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
    padding: 20px;
    border-radius: var(--r-lg);
    background: var(--glass);
    backdrop-filter: blur(20px) saturate(150%);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    border: 1px solid var(--stroke);
    box-shadow: var(--sh-2), var(--inset-top);
    color: var(--text-1);
    overflow: hidden;
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.quick-card::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(150deg, var(--kpi-accent, var(--brand-1)) 0%, transparent 55%);
    opacity: .12;
    transition: opacity .4s var(--ease);
}
.quick-card:hover {
    background: var(--glass-strong);
    border-color: var(--stroke-bright);
    color: var(--text-1);
}
.quick-card:hover::before { opacity: .18; }
.quick-card > * { position: relative; z-index: 1; }

.quick-card-icon {
    width: 46px;
    height: 46px;
    border-radius: 15px;
    display: grid;
    place-items: center;
    color: #fff;
    margin-bottom: 14px;
    background: linear-gradient(140deg, var(--kpi-accent, var(--brand-1)),
                color-mix(in srgb, var(--kpi-accent, var(--brand-1)) 52%, #000));
    box-shadow: 0 9px 24px var(--kpi-accent-soft, rgba(99,102,241,.38)), inset 0 1px 0 rgba(255,255,255,.35);
}
.quick-card-title { font-weight: 700; font-size: 1.02rem; letter-spacing: -.015em; }
.quick-card-desc  { color: var(--text-2); font-size: .85rem; margin-top: 7px; flex: 1 1 auto; }
.quick-card-cta {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 15px;
    font-weight: 700;
    font-size: .83rem;
    color: var(--brand-2);
    transition: color .18s var(--ease-soft);
}
.quick-card:hover .quick-card-cta { color: var(--text-1); }
[data-theme="light"] .quick-card-cta { color: var(--brand-1); }

/* ---------- 14. Service catalog ---------------------------------------- */
.catalog-table { font-size: .875rem; }

.catalog-category-row td {
    padding: 16px 16px 8px;
    border-bottom: 1px solid var(--stroke);
    font-size: .7rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .16em;
    color: var(--text-3);
    background: transparent;
}

.catalog-row { cursor: pointer; }
.catalog-row:focus-visible { outline: 2px solid var(--brand-2); outline-offset: -2px; }
.catalog-chevron { color: var(--text-3); transition: transform .3s var(--ease), color .3s var(--ease); }
.catalog-row[aria-expanded="true"] .catalog-chevron { transform: rotate(90deg); color: var(--brand-2); }
.catalog-row[aria-expanded="true"] { background: var(--glass-strong); }

.catalog-detail-row td { padding: 0; border-bottom: 1px solid var(--stroke); }
.catalog-detail-cell { background: rgba(0,0,0,.14); }
[data-theme="light"] .catalog-detail-cell { background: rgba(15,23,42,.025); }
.catalog-detail { padding: 20px; animation: fadeUp .35s var(--ease); }
@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.service-price {
    font-family: var(--mono);
    font-weight: 700;
    font-size: .92rem;
    letter-spacing: -.02em;
    color: var(--text-1);
    white-space: nowrap;
}

.addon-table th, .addon-summary-table th { font-size: .68rem; }
.addon-section {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--stroke-soft);
}

.addon-picker {
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass);
    overflow: hidden;
}
.addon-picker-list { max-height: 320px; overflow-y: auto; }
.addon-picker-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 14px;
    border-bottom: 1px solid var(--stroke-soft);
    cursor: pointer;
    transition: background .2s var(--ease);
}
.addon-picker-item:last-child { border-bottom: none; }
.addon-picker-item:hover { background: var(--glass-strong); }
.addon-picker-amount {
    margin-left: auto;
    font-family: var(--mono);
    font-weight: 700;
    font-size: .85rem;
    white-space: nowrap;
}
.addon-check { flex: 0 0 auto; }

/* ---------- 15. Case entry and selection -------------------------------- */
.selection-panel {
    border-radius: var(--r-lg);
    border: 1px solid var(--stroke);
    background: var(--glass);
    box-shadow: var(--sh-2), var(--inset-top);
    overflow: hidden;
}
.selection-table, .case-entry-table { font-size: .87rem; width: 100%; }
.selection-table th, .case-entry-table th {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .1em;
    font-weight: 750;
    color: var(--text-3);
    padding: 12px 14px;
    border-bottom: 1px solid var(--stroke);
    text-align: left;
}
.selection-table td, .case-entry-table td {
    padding: 11px 14px;
    border-bottom: 1px solid var(--stroke-soft);
    vertical-align: middle;
}
.selection-main-row td { font-weight: 650; }
.selection-total-row td {
    border-top: 1px solid var(--stroke);
    border-bottom: none;
    font-weight: 800;
    font-family: var(--mono);
    background: var(--glass-strong);
}

.case-serial {
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    font-family: var(--mono);
    font-weight: 700;
    font-size: .8rem;
    background: var(--glass-strong);
    border: 1px solid var(--stroke);
    color: var(--text-2);
}
.case-remove {
    color: var(--text-3);
    cursor: pointer;
    transition: color .18s var(--ease-soft);
}
.case-remove:hover { color: var(--danger); }

.slot-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 11px;
}
.slot-box {
    padding: 13px;
    border-radius: var(--r-md);
    border: 1px dashed var(--stroke-bright);
    background: var(--glass);
    text-align: center;
    cursor: pointer;
    transition: border-color .18s var(--ease-soft), background .18s var(--ease-soft);
}
.slot-box:hover { border-color: var(--brand-2); background: rgba(139,92,246,.10); }
.slot-box.slot-chosen {
    border-style: solid;
    border-color: rgba(139,92,246,.5);
    background: rgba(99,102,241,.14);
    box-shadow: 0 2px 8px rgba(99,102,241,.11);
}
.slot-label { font-size: .74rem; color: var(--text-3); font-weight: 700; text-transform: uppercase; letter-spacing: .1em; }

/* ---------- 16. Messaging ---------------------------------------------- */
.chat-shell {
    display: flex;
    flex-direction: column;
    border-radius: var(--r-lg);
    border: 1px solid var(--stroke);
    background: var(--glass);
    backdrop-filter: blur(20px) saturate(150%);
    -webkit-backdrop-filter: blur(20px) saturate(150%);
    box-shadow: var(--sh-2), var(--inset-top);
    overflow: hidden;
}

.chat-head {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 15px 20px;
    border-bottom: 1px solid var(--stroke-soft);
}
.chat-head-title { font-weight: 700; font-size: 1rem; letter-spacing: -.015em; }
.chat-head-sub   { font-size: .78rem; color: var(--text-3); margin-top: 3px; }

.chat-thread {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 20px;
    height: 58vh;
    min-height: 320px;
    overflow-y: auto;
    background: rgba(0,0,0,.14);
}
[data-theme="light"] .chat-thread { background: rgba(15,23,42,.02); }
.chat-shell-compact .chat-thread { height: 340px; min-height: 0; }

.msg-row { display: flex; }
.msg-row.mine   { justify-content: flex-end; }
.msg-row.theirs { justify-content: flex-start; }

/*
   Bubbles. The sender's own messages take the brand gradient; the other
   side stays glass. One tail corner is squared off on each so a run of
   messages reads as a column rather than a stack of lozenges.
*/
.msg-bubble {
    max-width: min(72ch, 78%);
    padding: 11px 15px;
    border-radius: var(--r-lg);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    box-shadow: var(--sh-1), var(--inset-top);
    animation: msgIn .35s var(--ease);
}
@keyframes msgIn { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
.msg-row.mine .msg-bubble {
    background: linear-gradient(125deg, rgba(99,102,241,.34), rgba(139,92,246,.22));
    border-color: rgba(139,92,246,.42);
    border-bottom-right-radius: 6px;
}
.msg-row.theirs .msg-bubble { border-bottom-left-radius: 6px; }

.msg-sender-label {
    font-size: .72rem;
    font-weight: 750;
    color: var(--brand-2);
    margin-bottom: 5px;
    letter-spacing: .02em;
}
[data-theme="light"] .msg-sender-label { color: var(--brand-1); }
.msg-sender-label .text-capitalize { color: var(--text-3); font-weight: 600; }

.msg-text { font-size: .9rem; line-height: 1.6; word-break: break-word; }

.msg-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 7px;
    font-size: .7rem;
    color: var(--text-3);
}
.msg-row.mine .msg-meta { justify-content: flex-end; }
.msg-status { display: inline-flex; align-items: center; gap: 4px; }

.msg-attachments {
    display: flex;
    flex-direction: column;
    gap: 9px;
    margin-top: 9px;
}
.msg-image-btn {
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    border-radius: var(--r-md);
    overflow: hidden;
    line-height: 0;
    box-shadow: var(--sh-1);
    outline: 1px solid transparent;
    outline-offset: -1px;
    transition: outline-color .18s var(--ease-soft);
}
.msg-image-btn:hover { outline-color: var(--stroke-bright); }
.msg-image { max-width: 260px; max-height: 260px; object-fit: cover; }
.msg-video { max-width: 320px; border-radius: var(--r-md); box-shadow: var(--sh-1); }

.msg-audio {
    padding: 10px 12px;
    border-radius: var(--r-md);
    background: rgba(0,0,0,.24);
    border: 1px solid var(--stroke-soft);
}
[data-theme="light"] .msg-audio { background: rgba(255,255,255,.65); }
.msg-audio-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .78rem;
    font-weight: 650;
    margin-bottom: 7px;
    color: var(--text-2);
}
.msg-audio-size { margin-left: auto; color: var(--text-3); font-weight: 600; }
.msg-audio audio { width: 100%; height: 38px; }
audio { border-radius: var(--r-pill); }

.msg-file-chip {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 13px;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke-soft);
    background: var(--glass-strong);
    color: inherit;
    text-align: left;
    cursor: pointer;
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.msg-file-chip:hover { background: var(--glass-hover); border-color: var(--stroke); }
.msg-file-meta { display: flex; flex-direction: column; min-width: 0; }
.msg-file-name { font-size: .83rem; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Composer. One rounded slab holding the growing textarea and a row of
   round glass buttons, so it reads as a single control. */
.chat-composer { padding: 15px 20px 18px; border-top: 1px solid var(--stroke-soft); }

.composer-box {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    padding: 8px 10px;
    border-radius: var(--r-lg);
    border: 1px solid var(--stroke);
    background: rgba(0,0,0,.20);
    box-shadow: inset 0 2px 6px rgba(0,0,0,.20);
    transition: border-color .22s, box-shadow .22s;
}
[data-theme="light"] .composer-box { background: rgba(255,255,255,.80); box-shadow: inset 0 2px 5px rgba(15,23,42,.05); }
.composer-box:focus-within {
    border-color: var(--brand-2);
    box-shadow: 0 0 0 3px rgba(139,92,246,.22), inset 0 2px 6px rgba(0,0,0,.20);
}

.composer-input {
    flex: 1 1 auto;
    min-width: 0;
    max-height: 180px;
    padding: 8px 6px;
    border: none;
    background: none;
    color: var(--text-1);
    font-size: .92rem;
    line-height: 1.55;
    resize: none;
    outline: none;
}
.composer-input::placeholder { color: var(--text-3); }

.composer-tools { display: flex; align-items: center; gap: 6px; }

.composer-btn {
    width: 36px;
    height: 36px;
    flex: 0 0 36px;
    display: grid;
    place-items: center;
    border-radius: 99px;
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-2);
    cursor: pointer;
    margin: 0;
    transition: color .18s var(--ease-soft), background .18s var(--ease-soft),
                border-color .18s var(--ease-soft);
}
.composer-btn:hover { color: var(--text-1); background: var(--glass-hover); border-color: var(--stroke-bright); }

.composer-send {
    width: 40px;
    height: 40px;
    flex: 0 0 40px;
    display: grid;
    place-items: center;
    border-radius: 99px;
    border: none;
    color: #fff;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));
    box-shadow: 0 3px 9px rgba(99,102,241,.23), inset 0 1px 0 rgba(255,255,255,.32);
    cursor: pointer;
    transition: filter .18s var(--ease-soft);
}
.composer-send:hover { filter: brightness(1.08); }
.composer-send:active { transform: translateY(1px); }

.composer-attachments { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 11px; }
.composer-attachments > span,
.composer-attachments > div {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 11px;
    border-radius: var(--r-pill);
    font-size: .78rem;
    background: var(--glass-strong);
    border: 1px solid var(--stroke-soft);
    color: var(--text-2);
    animation: slideIn .28s var(--ease);
}

.composer-hint {
    display: flex;
    align-items: flex-start;
    gap: 7px;
    margin-top: 11px;
    font-size: .74rem;
    color: var(--text-3);
    line-height: 1.5;
}

/* Recording state: the mic button turns red and pulses a ring outward. */
.voice-record-btn.is-recording {
    color: #fff;
    background: linear-gradient(140deg, #f43f5e, var(--danger));
    border-color: transparent;
    animation: recPulse 1.5s ease-in-out infinite;
}
@keyframes recPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(239,68,68,.6), 0 6px 18px rgba(239,68,68,.4); }
    50%      { box-shadow: 0 0 0 12px rgba(239,68,68,0), 0 6px 18px rgba(239,68,68,.4); }
}
.voice-status { font-size: .76rem; color: var(--text-3); font-family: var(--mono); }
.rec-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 99px;
    background: var(--danger);
    margin-right: 5px;
    animation: pulseDot 1.2s ease-in-out infinite;
}
.voice-preview { width: 100%; margin-top: 10px; }

/* Inbox: a client, their services, and the threads under each. */
.inbox-client {
    border-radius: var(--r-lg);
    border: 1px solid var(--stroke);
    background: var(--glass);
    box-shadow: var(--sh-1), var(--inset-top);
    overflow: hidden;
    margin-bottom: 14px;
}
.inbox-service-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 16px;
    background: var(--glass-strong);
    border-bottom: 1px solid var(--stroke-soft);
    font-size: .74rem;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--text-3);
}
.inbox-service-count { margin-left: auto; }
.inbox-avatar {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-weight: 800;
    color: #fff;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2));
    box-shadow: 0 2px 7px rgba(99,102,241,.20), inset 0 1px 0 rgba(255,255,255,.32);
}

.thread-row {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--stroke-soft);
    color: var(--text-1);
    transition: background .18s var(--ease-soft);
}
.thread-row:last-child { border-bottom: none; }
.thread-row:hover { background: var(--glass-strong); color: var(--text-1); }
.thread-row.unread { background: rgba(99,102,241,.10); }
.thread-row.unread .thread-row-title { font-weight: 800; }

.thread-row-icon {
    width: 38px;
    height: 38px;
    flex: 0 0 38px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    background: var(--glass-strong);
    border: 1px solid var(--stroke-soft);
    color: var(--text-2);
}
.thread-row-main { flex: 1 1 auto; min-width: 0; }
.thread-row-title { font-weight: 650; font-size: .9rem; }
.thread-row-sub, .thread-row-preview {
    font-size: .78rem;
    color: var(--text-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.thread-row-side { text-align: right; flex: 0 0 auto; }
.thread-row-time { font-size: .72rem; color: var(--text-3); }
.thread-row-count {
    display: inline-block;
    margin-top: 4px;
    padding: 1px 8px;
    border-radius: var(--r-pill);
    font-size: .68rem;
    font-weight: 800;
    color: #fff;
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
}

.thread-switcher { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 16px; }
.thread-switcher-label { width: 100%; }
.thread-tab-sub { display: block; font-size: .68rem; opacity: .75; font-weight: 600; }

/* The per-case message log on a case page. */
.case-message-log { display: flex; flex-direction: column; gap: 10px; }
.case-message-row {
    display: flex;
    gap: 12px;
    padding: 11px 14px;
    border-radius: var(--r-md);
    background: var(--glass);
    border: 1px solid var(--stroke-soft);
}
.case-message-meta { flex: 0 0 auto; font-size: .72rem; color: var(--text-3); min-width: 116px; }
.case-message-body { flex: 1 1 auto; min-width: 0; font-size: .87rem; }

/* ---------- 17. Files, galleries and the lightbox ---------------------- */
/*
   One tile shape serves every file surface in the app: case documents,
   sample galleries, add-on strips. Images show a real thumbnail, PDFs a
   first-page preview, audio a play button; anything else falls back to
   its type glyph. Everything is square so a mixed set still lines up.
*/
.file-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    gap: 14px;
}
/* The View Sample gallery is its own grid, not a .file-grid, so it
   carries its own display -- four across, as the design asks for. */
.sample-quad-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
}

.file-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass);
    box-shadow: var(--sh-1), var(--inset-top);
    overflow: hidden;
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.file-tile:hover { background: var(--glass-strong); border-color: var(--stroke-bright); }

.file-tile-thumb {
    position: relative;
    aspect-ratio: 1 / 1;
    display: grid;
    place-items: center;
    background: linear-gradient(140deg, rgba(255,255,255,.07), rgba(0,0,0,.25));
    cursor: pointer;
    overflow: hidden;
}
[data-theme="light"] .file-tile-thumb { background: linear-gradient(140deg, rgba(15,23,42,.04), rgba(15,23,42,.09)); }
.file-tile-thumb img,
.file-tile-thumb canvas {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* The big glyph in the middle of a non-image tile. Its gradient is tinted
   by file kind so a folder of mixed uploads is scannable by colour. */
.file-tile-icon {
    width: 52px;
    height: 52px;
    border-radius: 16px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--tint, var(--brand-1)),
                color-mix(in srgb, var(--tint, var(--brand-1)) 52%, #000));
    box-shadow: 0 9px 24px rgba(0,0,0,.32), inset 0 1px 0 rgba(255,255,255,.32);
}
.file-tile-pdf   { --tint: #f43f5e; }
.file-tile-audio { --tint: var(--brand-3); }
.file-tile-video { --tint: var(--info); }
.file-tile-image { --tint: var(--success); }
.file-tile-other { --tint: var(--brand-1); }

/* The extension label, bottom-left of the thumbnail. */
.file-tile-kind {
    position: absolute;
    left: 8px;
    bottom: 8px;
    padding: 2px 7px;
    border-radius: 6px;
    background: rgba(0,0,0,.82);
    color: #fff;
    font-family: var(--mono);
    font-size: .66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* Bottom-right so it never sits on top of the type glyph. */
.file-tile-play {
    position: absolute;
    right: 8px;
    bottom: 8px;
    width: 30px;
    height: 30px;
    border-radius: 99px;
    display: grid;
    place-items: center;
    color: #fff;
    background: rgba(0,0,0,.72);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,.2);
    transition: background .18s var(--ease-soft);
}
.file-tile:hover .file-tile-play { background: var(--brand-1); }
.file-tile.is-playing .file-tile-play { background: var(--brand-2); }

.file-tile-body { padding: 10px 12px 12px; }
.file-tile-name {
    font-size: .8rem;
    font-weight: 650;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.file-tile-meta { font-size: .7rem; color: var(--text-3); margin-top: 3px; }
.file-tile-actions {
    display: flex;
    gap: 5px;
    padding: 0 12px 12px;
    margin-top: auto;
}
.file-tile-actions .btn { flex: 1 1 auto; padding: 5px 8px; }

.doc-thumb,
.addon-sample-thumb {
    width: 62px;
    height: 62px;
    border-radius: var(--r-sm);
    object-fit: cover;
    border: 1px solid var(--stroke);
    box-shadow: var(--sh-1);
    transition: border-color .18s var(--ease-soft);
    cursor: pointer;
}
.doc-thumb:hover, .addon-sample-thumb:hover { border-color: var(--stroke-bright); }
.addon-sample-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 9px; }

/* The View Sample modal. */
.sample-modal-backdrop,
.sample-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1090;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(4,7,18,.78);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.sample-modal-backdrop.is-open,
.sample-lightbox.is-open { display: flex; animation: fadeIn .22s var(--ease); }

.sample-modal-panel,
.sample-lightbox-inner {
    position: relative;
    width: 100%;
    max-width: 980px;
    max-height: 92vh;
    display: flex;
    flex-direction: column;
    border-radius: var(--r-xl);
    background: linear-gradient(150deg, rgba(255,255,255,.11), rgba(255,255,255,.045));
    backdrop-filter: blur(34px) saturate(160%);
    -webkit-backdrop-filter: blur(34px) saturate(160%);
    border: 1px solid var(--stroke-bright);
    box-shadow: var(--sh-4), inset 0 1px 0 rgba(255,255,255,.20);
    animation: popIn .4s var(--ease);
    overflow: hidden;
}
[data-theme="light"] .sample-modal-panel,
[data-theme="light"] .sample-lightbox-inner {
    background: linear-gradient(150deg, rgba(255,255,255,.97), rgba(255,255,255,.92));
}
@keyframes popIn {
    from { opacity: 0; transform: translateY(24px) scale(.96); }
    to   { opacity: 1; transform: none; }
}

.sample-modal-head {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 18px 22px;
    border-bottom: 1px solid var(--stroke-soft);
}
.sample-modal-eyebrow { font-size: .66rem; text-transform: uppercase; letter-spacing: .16em; font-weight: 700; color: var(--text-3); }
.sample-modal-title { font-weight: 700; font-size: 1.05rem; letter-spacing: -.02em; }
.sample-modal-sub   { font-size: .78rem; color: var(--text-3); }
.sample-modal-body  { padding: 20px 22px; overflow-y: auto; flex: 1 1 auto; }
.sample-modal-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 22px;
    border-top: 1px solid var(--stroke-soft);
    background: rgba(0,0,0,.14);
}
[data-theme="light"] .sample-modal-foot { background: rgba(15,23,42,.03); }
.sample-modal-legend { font-size: .74rem; color: var(--text-3); }
.sample-pager { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.sample-modal-close,
.sample-lightbox-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 38px;
    height: 38px;
    border-radius: 99px;
    display: grid;
    place-items: center;
    border: 1px solid rgba(255,255,255,.22);
    background: rgba(255,255,255,.12);
    color: inherit;
    cursor: pointer;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: background .18s var(--ease-soft);
    z-index: 5;
}
.sample-modal-close:hover,
.sample-lightbox-close:hover { background: var(--danger); color: #fff; }

.sample-modal-loading,
.sample-modal-error { text-align: center; padding: 40px 20px; color: var(--text-2); }
.sample-modal-error { color: #fca5a5; }

.sample-lightbox-body { display: grid; place-items: center; padding: 26px; overflow: auto; }
.sample-lightbox-body img,
.sample-lightbox-body video,
.sample-lightbox-body iframe {
    max-width: min(1180px, 92vw);
    max-height: 78vh;
    border-radius: var(--r-lg);
    box-shadow: var(--sh-3);
}
.sample-lightbox-body iframe { width: min(1180px, 92vw); height: 78vh; border: 0; background: #1e1e1e; }
.sample-lightbox-caption {
    padding: 12px 22px 18px;
    text-align: center;
    font-size: .82rem;
    color: var(--text-2);
}

.lightbox-audio-art {
    width: 132px;
    height: 132px;
    margin: 0 auto 18px;
    border-radius: 34px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));
    box-shadow: 0 4px 14px rgba(99,102,241,.22), inset 0 1px 0 rgba(255,255,255,.35);
}
.lightbox-audio-title { text-align: center; font-weight: 700; margin-bottom: 14px; }
.lightbox-fallback-name { text-align: center; color: var(--text-2); }

.sample-del {
    position: absolute;
    top: 7px;
    right: 7px;
    z-index: 3;
}

/* ---------- 18. Tasks -------------------------------------------------- */
.task-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }

.task-item {
    display: flex;
    align-items: flex-start;
    gap: 13px;
    padding: 13px 15px;
    border-radius: var(--r-md);
    background: var(--glass);
    border: 1px solid var(--stroke-soft);
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.task-item:hover { background: var(--glass-strong); border-color: var(--stroke); }
.task-item.is-inactive { opacity: .55; }
.task-item.is-done .task-title { text-decoration: line-through; opacity: .7; }

/* The step marker doubles as the status light: a numbered chip on the
   template list, a status glyph once work is under way. */
.task-marker {
    width: 32px;
    height: 32px;
    flex: 0 0 32px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    font-family: var(--mono);
    font-weight: 700;
    font-size: .8rem;
    background: var(--glass-strong);
    border: 1px solid var(--stroke);
    color: var(--text-2);
}
.task-item.is-done .task-marker {
    background: linear-gradient(140deg, #34d399, var(--success));
    border-color: transparent;
    color: #04231a;
    box-shadow: 0 2px 6px rgba(16,185,129,.17);
}
.task-item.is-progress .task-marker {
    background: linear-gradient(140deg, #fbbf24, var(--warning));
    border-color: transparent;
    color: #2a1a02;
    box-shadow: 0 2px 6px rgba(245,158,11,.17);
}
.task-item.is-cancelled .task-marker { background: rgba(239,68,68,.2); border-color: rgba(239,68,68,.34); color: #fca5a5; }

.task-body { flex: 1 1 auto; min-width: 0; }
.task-title-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.task-title { font-weight: 650; font-size: .91rem; }
.task-description { font-size: .82rem; color: var(--text-2); margin-top: 5px; line-height: 1.55; }
.task-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 7px;
    font-size: .74rem;
    color: var(--text-3);
}
.task-meta span { display: inline-flex; align-items: center; gap: 5px; }
.task-note { font-size: .78rem; color: var(--text-2); margin-top: 6px; font-style: italic; }
.task-actions { display: flex; align-items: center; gap: 5px; flex: 0 0 auto; }
.task-actions .d-inline { display: inline-flex !important; }

.task-progress-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 9px;
    font-size: .82rem;
    font-weight: 650;
    color: var(--text-2);
}
.task-progress-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 10px;
    font-size: .73rem;
    color: var(--text-3);
}
.task-progress-legend span { display: inline-flex; align-items: center; gap: 6px; }

/* A vertical list of checks: a coloured dot, a label, and a detail line.
   Rows, not chips -- the detail under each label is the point. */
.status-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.status-list li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 12px 20px;
    border-bottom: 1px solid var(--stroke-soft);
    font-size: .875rem;
}
.status-list li:last-child { border-bottom: none; }
.status-list li > span:last-child { min-width: 0; }

/* ---------- 19. Accounting --------------------------------------------- */
.pay-progress {
    height: 7px;
    border-radius: 99px;
    background: rgba(0,0,0,.30);
    overflow: hidden;
    box-shadow: inset 0 1px 3px rgba(0,0,0,.3);
}
[data-theme="light"] .pay-progress { background: rgba(15,23,42,.10); }
.pay-progress-bar {
    height: 100%;
    border-radius: 99px;
    background: linear-gradient(90deg, var(--success), var(--accent));
    box-shadow: 0 0 12px rgba(16,185,129,.6);
    transition: width .8s var(--ease);
}

.case-total, .case-remaining {
    font-family: var(--mono);
    font-weight: 800;
    letter-spacing: -.02em;
    white-space: nowrap;
}
.case-total { color: var(--text-1); }
.case-remaining { color: #fcd34d; }
[data-theme="light"] .case-remaining { color: #b45309; }
.case-addon { font-size: .8rem; color: var(--text-3); }

/* ---------- 20. Danger zones and deletion ------------------------------ */
/*
   Destructive screens should look destructive. Warm red, a clear edge,
   and enough padding that nobody clicks through one by accident.
*/
.danger-zone,
.danger-panel {
    border-radius: var(--r-lg);
    border: 1px solid rgba(239,68,68,.38);
    background: linear-gradient(135deg, rgba(239,68,68,.14), rgba(217,70,239,.06));
    box-shadow: var(--sh-2), var(--inset-top);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    overflow: hidden;
}
.danger-zone { padding: 20px; margin-top: 24px; }
.danger-zone-title,
.danger-panel-title {
    display: flex;
    align-items: center;
    gap: 9px;
    font-weight: 800;
    color: #fca5a5;
    letter-spacing: -.015em;
}
[data-theme="light"] .danger-zone-title,
[data-theme="light"] .danger-panel-title { color: #b91c1c; }
.danger-zone-sub,
.danger-panel-sub { font-size: .82rem; color: var(--text-2); margin-top: 6px; }
.danger-zone-text { font-size: .87rem; color: var(--text-2); margin: 10px 0 14px; line-height: 1.6; }

.danger-panel-head {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 20px;
    border-bottom: 1px solid rgba(239,68,68,.24);
}
.danger-panel-body { padding: 20px; }
.danger-panel-icon {
    width: 46px;
    height: 46px;
    flex: 0 0 46px;
    border-radius: 15px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, #f43f5e, var(--danger));
    box-shadow: 0 3px 11px rgba(239,68,68,.21), inset 0 1px 0 rgba(255,255,255,.3);
}

.delete-manifest {
    margin: 0;
    padding: 14px 16px 14px 32px;
    border-radius: var(--r-md);
    background: rgba(0,0,0,.24);
    border: 1px solid var(--stroke-soft);
    font-size: .84rem;
    color: var(--text-2);
    line-height: 1.8;
}
[data-theme="light"] .delete-manifest { background: rgba(255,255,255,.6); }

/* ---------- 21. Auth page ---------------------------------------------- */
.auth-page {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 28px 18px;
}
.auth-page .auth-card {
    width: 100%;
    max-width: 430px;
    padding: 38px 34px;
    border-radius: var(--r-xl);
    background: linear-gradient(155deg, rgba(255,255,255,.12), rgba(255,255,255,.05));
    backdrop-filter: blur(34px) saturate(160%);
    -webkit-backdrop-filter: blur(34px) saturate(160%);
    border: 1px solid var(--stroke-bright);
    box-shadow: var(--sh-4), inset 0 1px 0 rgba(255,255,255,.22);
    position: relative;
    overflow: hidden;
}
[data-theme="light"] .auth-page .auth-card {
    background: linear-gradient(155deg, rgba(255,255,255,.95), rgba(255,255,255,.85));
}
.auth-page .logo-dot {
    width: 66px;
    height: 66px;
    flex-basis: 66px;
    margin: 0 auto 18px;
    border-radius: 21px;
    font-size: 1.6rem;
    box-shadow: 0 4px 14px rgba(99,102,241,.22), inset 0 1px 0 rgba(255,255,255,.4);
}
.auth-page .theme-toggle-btn { z-index: 5; }

/* ---------- 22. Odds and ends ------------------------------------------ */
.spinner {
    width: 20px;
    height: 20px;
    border-radius: 99px;
    border: 2px solid var(--stroke-bright);
    border-top-color: var(--brand-2);
    animation: spin .8s linear infinite;
    display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

.console-log {
    font-family: var(--mono);
    font-size: .8rem;
    line-height: 1.65;
    padding: 16px;
    border-radius: var(--r-md);
    background: rgba(0,0,0,.42);
    border: 1px solid var(--stroke);
    color: var(--text-2);
    max-height: 340px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
}
[data-theme="light"] .console-log { background: rgba(15,23,42,.05); }

/* The searchable-select enhancement rendered by script.js. */
.search-no-results { padding: 20px; font-size: .85rem; }

/* Toasts. Flash messages are promoted into these by script.js; the
   markup keeps the plain .alert as a no-JS fallback. */
.toasts {
    position: fixed;
    top: 20px;
    right: 20px;
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: 11px;
    max-width: 380px;
}
.toast-item {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 14px 17px;
    border-radius: var(--r-md);
    background: rgba(16,26,53,.92);
    backdrop-filter: blur(22px);
    -webkit-backdrop-filter: blur(22px);
    border: 1px solid var(--stroke-bright);
    box-shadow: var(--sh-3);
    font-size: .875rem;
    color: var(--text-1);
    position: relative;
    overflow: hidden;
    animation: toastIn .45s var(--ease);
}
[data-theme="light"] .toast-item { background: rgba(255,255,255,.96); }
.toast-item::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: var(--brand-2);
}
.toast-item.is-success::before { background: var(--success); }
.toast-item.is-danger::before  { background: var(--danger); }
.toast-item.is-warning::before { background: var(--warning); }
.toast-item.is-info::before    { background: var(--info); }
.toast-item .ic { flex: 0 0 auto; margin-top: 1px; }
/* Only the leading glyph takes the type colour -- the close button is a
   control, not a status, and a red X reads as "this will delete". */
.toast-item.is-success > .ic:first-child { color: var(--success); }
.toast-item.is-danger  > .ic:first-child { color: var(--danger); }
.toast-item.is-warning > .ic:first-child { color: var(--warning); }
.toast-item.is-info    > .ic:first-child { color: var(--info); }
.toast-close {
    margin-left: auto;
    border: none;
    background: none;
    color: var(--text-3);
    cursor: pointer;
    padding: 0;
    line-height: 1;
}
.toast-close:hover { color: var(--text-1); }
@keyframes toastIn  { from { opacity: 0; transform: translateX(90px) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes toastOut { to { opacity: 0; transform: translateX(90px) scale(.9); } }
.toast-item.is-out { animation: toastOut .3s var(--ease) forwards; }

/* Entry animation for content blocks, staggered by script.js. */
.fade-up { animation: fadeUp .5s var(--ease) both; }

/* ---------- 23. Responsive, motion and print ---------------------------- */
@media (max-width: 1024px) {
    .sidebar {
        position: fixed;
        inset-inline-start: 0;
        top: 0;
        transform: translateX(-100%);
        box-shadow: var(--sh-4);
    }
    /* The drawer comes from the edge reading starts at, so on an Urdu
       page it slides in from the right. */
    [dir="rtl"] .sidebar { transform: translateX(100%); }
    .sidebar.open,
    [dir="rtl"] .sidebar.open { transform: none; }
    .sidebar-toggle-btn {
        display: grid;
        place-items: center;
        width: 40px;
        height: 40px;
        flex: 0 0 40px;
        padding: 0;
    }
    .sample-quad-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 768px) {
    body { font-size: 14.5px; }
    .page-content { padding: 18px 14px 52px; }
    .topbar { padding: 10px 14px; gap: 10px; }
    .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
    .kpi-card { padding: 16px; }
    .kpi-value { font-size: 1.6rem; }
    .page-header { margin-bottom: 18px; }
    .card-elevated .card-body, .card .card-body { padding: 16px; }
    .card-elevated .card-header, .card .card-header { padding: 13px 16px; }
    .chat-thread { height: 52vh; padding: 15px; }
    .chat-composer { padding: 12px 15px 15px; }
    .msg-bubble { max-width: 88%; }
    .file-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 11px; }
    .sample-quad-grid { grid-template-columns: repeat(2, 1fr); }
    .toasts { left: 12px; right: 12px; max-width: none; }
    .table-modern thead th, .table-modern tbody td { padding: 10px 12px; }
    .form-action-bar { padding: 14px; }
    .form-action-bar .btn:last-child { margin-left: 0; }
}

@media (max-width: 480px) {
    .btn { padding: 9px 15px; }
    .sample-quad-grid, .file-grid { grid-template-columns: repeat(2, 1fr); }
    .page-header-actions { width: 100%; }
    .page-header-actions .btn { flex: 1 1 auto; }
    .detail-fact-grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    body::before { animation: none; }
}

@media print {
    .sidebar, .topbar, .btn, .task-actions, .form-action-bar,
    .chat-composer, .toasts, .sidebar-backdrop { display: none !important; }
    body::before, body::after { display: none; }
    body { background: #fff; color: #000; }
    .card-elevated, .glass-panel, .kpi-card {
        background: #fff;
        border: 1px solid #ddd;
        box-shadow: none;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
}

/* =====================================================================
   24. Surfaces built in JavaScript
   =====================================================================
   Everything below is markup script.js creates at run time -- the sample
   gallery tiles, the searchable select, upload chips. Same tokens, same
   shapes; it just could not be written in PHP.
   ===================================================================== */

/* The View Sample modal is the fixed layer; the backdrop is the veil
   inside it, so the panel can sit above the blur without a stacking
   context fight. */
.sample-modal {
    position: fixed;
    inset: 0;
    z-index: 1085;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.sample-modal.is-open { display: flex; animation: fadeIn .22s var(--ease); }
.sample-modal-backdrop {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: block;
    background: rgba(4,7,18,.78);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    padding: 0;
}
/* Above the veil, or the veil swallows every click meant for the panel. */
.sample-modal-panel { z-index: 1; }

body.modal-locked { overflow: hidden; }

/* Sample tiles: square art, an optional inline audio player, a caption
   and two actions. Four across in the modal, fewer as it narrows. */
.sample-tile {
    display: flex;
    flex-direction: column;
    margin: 0;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass);
    box-shadow: var(--sh-1), var(--inset-top);
    overflow: hidden;
    transition: background .18s var(--ease-soft), border-color .18s var(--ease-soft);
}
.sample-tile:hover { background: var(--glass-strong); border-color: var(--stroke-bright); }
.sample-tile.is-playing { border-color: rgba(139,92,246,.5); box-shadow: var(--glow); }

.sample-tile-art {
    position: relative;
    aspect-ratio: 1 / 1;
    width: 100%;
    display: grid;
    place-items: center;
    padding: 0;
    border: none;
    cursor: pointer;
    overflow: hidden;
    background: linear-gradient(140deg, rgba(255,255,255,.07), rgba(0,0,0,.25));
}
[data-theme="light"] .sample-tile-art { background: linear-gradient(140deg, rgba(15,23,42,.04), rgba(15,23,42,.09)); }
.sample-tile-art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* A scaled, non-interactive iframe gives a real PDF first page with no
   library. pointer-events off so the click lands on the tile. */
.sample-pdf-preview {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    background: #fff;
}
.sample-pdf-preview iframe {
    width: 200%;
    height: 200%;
    border: 0;
    transform: scale(.5);
    transform-origin: 0 0;
    pointer-events: none;
}

.sample-tile-icon {
    width: 52px;
    height: 52px;
    border-radius: 16px;
    display: grid;
    place-items: center;
    color: #fff;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2));
    box-shadow: 0 3px 11px rgba(99,102,241,.18), inset 0 1px 0 rgba(255,255,255,.32);
}
.sample-tile-glyph {
    position: absolute;
    left: 8px;
    top: 8px;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    display: grid;
    place-items: center;
    color: #fff;
    background: rgba(0,0,0,.72);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.sample-tile-ext {
    position: absolute;
    right: 8px;
    bottom: 8px;
    padding: 2px 7px;
    border-radius: 6px;
    background: rgba(0,0,0,.82);
    color: #fff;
    font-family: var(--mono);
    font-size: .66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
}

.sample-audio {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 11px;
    border-top: 1px solid var(--stroke-soft);
    background: rgba(0,0,0,.22);
}
[data-theme="light"] .sample-audio { background: rgba(15,23,42,.035); }
.sample-audio audio { display: none; }
.sample-audio-play {
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    border-radius: 99px;
    border: none;
    display: grid;
    place-items: center;
    color: #fff;
    cursor: pointer;
    background: linear-gradient(140deg, var(--brand-1), var(--brand-2));
    box-shadow: 0 2px 6px rgba(99,102,241,.21), inset 0 1px 0 rgba(255,255,255,.3);
    transition: filter .18s var(--ease-soft);
}
.sample-audio-play:hover { filter: brightness(1.08); }
.sample-audio-bar {
    flex: 1 1 auto;
    height: 5px;
    border-radius: 99px;
    background: rgba(0,0,0,.35);
    cursor: pointer;
    overflow: hidden;
}
[data-theme="light"] .sample-audio-bar { background: rgba(15,23,42,.12); }
.sample-audio-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 99px;
    background: linear-gradient(90deg, var(--brand-2), var(--accent));
}
.sample-audio-time {
    flex: 0 0 auto;
    font-family: var(--mono);
    font-size: .68rem;
    color: var(--text-3);
}

.sample-tile-body { display: flex; flex-direction: column; padding: 10px 12px 4px; }
.sample-tile-name {
    font-size: .8rem;
    font-weight: 650;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sample-tile-meta { font-size: .69rem; color: var(--text-3); margin-top: 2px; }
.sample-tile-actions { display: flex; gap: 5px; padding: 8px 12px 12px; margin-top: auto; }
.sample-tile-actions .btn { flex: 1 1 auto; padding: 5px 8px; }

.sample-pager-dot {
    width: 28px;
    height: 28px;
    border-radius: 9px;
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-2);
    font-size: .76rem;
    font-weight: 700;
    cursor: pointer;
    transition: all .22s var(--ease);
}
.sample-pager-dot:hover { background: var(--glass-hover); color: var(--text-1); }
.sample-pager-dot.active {
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 6px rgba(99,102,241,.20);
}

.lightbox-audio { text-align: center; padding: 20px; min-width: min(420px, 80vw); }
.lightbox-audio audio { width: 100%; }
.lightbox-fallback { text-align: center; padding: 40px 24px; color: var(--text-2); }
.lightbox-fallback .ic { color: var(--brand-2); margin-bottom: 12px; }

/* Searchable select: a text input over a glass panel of options. */
.search-select-wrap { position: relative; }
.search-select-panel {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 6px);
    z-index: 40;
    display: none;
    max-height: 280px;
    overflow-y: auto;
    padding: 6px;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke-bright);
    background: linear-gradient(150deg, rgba(255,255,255,.11), rgba(255,255,255,.045));
    backdrop-filter: blur(30px) saturate(160%);
    -webkit-backdrop-filter: blur(30px) saturate(160%);
    box-shadow: var(--sh-3);
}
[data-theme="light"] .search-select-panel {
    background: linear-gradient(150deg, rgba(255,255,255,.97), rgba(255,255,255,.92));
}
.search-select-panel.open { display: block; animation: fadeUp .2s var(--ease); }

.ss-option {
    padding: 8px 12px;
    border-radius: var(--r-sm);
    font-size: .875rem;
    color: var(--text-2);
    cursor: pointer;
    transition: background .18s var(--ease), color .18s var(--ease);
}
.ss-option:hover, .ss-option.active { background: var(--glass-hover); color: var(--text-1); }
.ss-option.active { font-weight: 700; }
.ss-group-label {
    padding: 10px 12px 5px;
    font-size: .66rem;
    font-weight: 750;
    text-transform: uppercase;
    letter-spacing: .14em;
    color: var(--text-3);
}
.ss-empty { padding: 16px 12px; text-align: center; font-size: .84rem; color: var(--text-3); }

/* Chips for pending uploads, in the dropzone and in the composer. */
.dz-filechip,
.composer-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 11px;
    border-radius: var(--r-pill);
    font-size: .78rem;
    background: var(--glass-strong);
    border: 1px solid var(--stroke-soft);
    color: var(--text-2);
    animation: slideIn .28s var(--ease);
}
.dz-filechip { margin: 4px 4px 0 0; }

.case-marker { display: none; }
.case-row td { vertical-align: middle; }

.composer-form { margin: 0; }
.composer-voice { display: flex; align-items: center; gap: 6px; }
.voice-recorder-widget { display: flex; align-items: center; gap: 8px; }
.voice-discard-btn:hover { color: #fca5a5; }

.template-task-list .task-marker { font-family: var(--mono); }
.is-editing { box-shadow: 0 0 0 3px rgba(139,92,246,.22); border-radius: var(--r-md); }

.inbox-service { border-bottom: 1px solid var(--stroke-soft); }
.inbox-service:last-child { border-bottom: none; }

.user-chip-avatar { width: 30px; height: 30px; flex-basis: 30px; font-size: .78rem; }

/* =====================================================================
   25. Fit and finish
   =====================================================================
   Adjustments made after looking at real pages at real widths, kept
   together at the end so the reasoning stays with the rule.
   ===================================================================== */

/* Names in the topbar chip are one line -- "Iftikhar Afzal" wrapping to
   two made the whole topbar taller than the avatar needed. */
.user-chip-name, .user-chip-role { white-space: nowrap; }

/* Wide tables carry a row of icon buttons at the end. Tighter cells and
   tighter buttons keep the common case inside the card; anything still
   wider scrolls in place rather than pushing the page sideways. */
.table-modern thead th,
.table-modern tbody td { padding: 11px 13px; }
.table-modern td .btn-sm { padding: 6px 9px; }
.table-modern td .d-flex.gap-1 > .btn { flex: 0 0 auto; }

/* The action column never wraps -- a button stack broken across two
   lines reads as two different controls. */
.table-modern td:last-child .btn { white-space: nowrap; }

/* Inner scrollers get the thin scrollbar; the fat gradient one belongs
   to the page, not to a strip inside a card. */
.table-responsive,
.chat-thread,
.sample-modal-body,
.addon-picker-list,
.console-log { scrollbar-width: thin; }
.table-responsive::-webkit-scrollbar,
.chat-thread::-webkit-scrollbar,
.sample-modal-body::-webkit-scrollbar,
.addon-picker-list::-webkit-scrollbar,
.console-log::-webkit-scrollbar { width: 7px; height: 7px; }
.table-responsive::-webkit-scrollbar-thumb,
.chat-thread::-webkit-scrollbar-thumb,
.sample-modal-body::-webkit-scrollbar-thumb,
.addon-picker-list::-webkit-scrollbar-thumb,
.console-log::-webkit-scrollbar-thumb { border-width: 2px; }

/* Bootstrap sets its own bottom margin on tables inside a card, which
   left a bar of card background under the last row. */
.card-elevated .table-responsive { margin-bottom: 0; }
.card-elevated .table-responsive > .table-modern { margin-bottom: 0; }

/* Filter rows above a table: same glass, same radius, so the controls
   read as part of the table's frame rather than as loose widgets. */
.page-content > form.row.g-2,
.page-content > .row.g-2.mb-3 { align-items: end; }

/*
   Scroll affordance on wide tables.

   A table with eleven columns will not fit a laptop, and a button clipped
   flat against the card edge reads as a bug rather than as "there is more
   this way". These two gradients are painted as background layers: the
   shadow pair scrolls with the content and the cover pair is pinned to
   the viewport of the scroller, so each shadow is hidden while that end
   is at rest and fades in the moment there is something past it. No
   JavaScript, no scroll listener.
*/
.table-responsive {
    background-image:
        linear-gradient(to right, var(--bg-1), transparent),
        linear-gradient(to left,  var(--bg-1), transparent),
        radial-gradient(farthest-side at 0 50%,   rgba(0,0,0,.34), transparent),
        radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.34), transparent);
    background-position: 0 0, 100% 0, 0 0, 100% 0;
    background-repeat: no-repeat;
    background-size: 34px 100%, 34px 100%, 15px 100%, 15px 100%;
    background-attachment: local, local, scroll, scroll;
}
[data-theme="light"] .table-responsive {
    background-image:
        linear-gradient(to right, var(--bg-2), transparent),
        linear-gradient(to left,  var(--bg-2), transparent),
        radial-gradient(farthest-side at 0 50%,   rgba(15,23,42,.14), transparent),
        radial-gradient(farthest-side at 100% 50%, rgba(15,23,42,.14), transparent);
}

/* A client with a photo gets the photo; a client without gets their
   initial on the same gradient. Both are the same size and shape. */
img.inbox-avatar { object-fit: cover; background: var(--glass-strong); }

/* Thread tabs -- the sibling threads under one service. Same shape as the
   filter chips, but they carry a second line and an unread count. */
.thread-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: var(--r-md);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-2);
    font-size: .855rem;
    font-weight: 650;
    line-height: 1.25;
    box-shadow: var(--sh-1);
    transition: color .18s var(--ease-soft), background .18s var(--ease-soft),
                border-color .18s var(--ease-soft);
}
.thread-tab:hover { color: var(--text-1); background: var(--glass-hover); border-color: var(--stroke-bright); }
.thread-tab.active {
    color: #fff;
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
    border-color: transparent;
    box-shadow: 0 2px 8px rgba(99,102,241,.20);
}
.thread-tab.active .thread-tab-sub { color: rgba(255,255,255,.8); }
.thread-tab .thread-tab-sub { color: var(--text-3); }
.thread-switcher-label {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .16em;
    font-weight: 700;
    color: var(--text-3);
    margin-bottom: 2px;
}

/* A progress ring drawn from one conic gradient, with the percentage
   punched out of the middle by a second, opaque circle. No SVG, no
   canvas, and it animates by changing a single custom property. */
.task-progress-ring {
    position: relative;
    width: 78px;
    height: 78px;
    flex: 0 0 78px;
    border-radius: 99px;
    display: grid;
    place-items: center;
    background:
        conic-gradient(var(--brand-2) calc(var(--pct, 0) * 1%), rgba(255,255,255,.10) 0);
    box-shadow: var(--sh-1);
}
[data-theme="light"] .task-progress-ring {
    background: conic-gradient(var(--brand-1) calc(var(--pct, 0) * 1%), rgba(15,23,42,.10) 0);
}
.task-progress-ring.is-complete { background: conic-gradient(var(--success) 100%, var(--success) 0); }
.task-progress-ring::after {
    content: '';
    position: absolute;
    inset: 8px;
    border-radius: 99px;
    background: var(--bg-1);
}
[data-theme="light"] .task-progress-ring::after { background: var(--bg-2); }
.task-progress-ring > span {
    position: relative;
    z-index: 1;
    font-weight: 800;
    font-size: 1.15rem;
    letter-spacing: -.03em;
}
.task-progress-ring small { font-size: .62rem; opacity: .7; margin-left: 1px; }

/* The four one-click status buttons on a case task. */
.task-quick { padding: 5px 10px; font-size: .74rem; }
.task-quick.task-done:hover    { border-color: rgba(16,185,129,.5); }
.task-quick.task-progress:hover{ border-color: rgba(245,158,11,.5); }
.task-quick.task-cancelled:hover { border-color: rgba(239,68,68,.5); }

/* System check list: a coloured dot carrying a tick, cross or warning. */
.status-dot {
    width: 26px;
    height: 26px;
    flex: 0 0 26px;
    border-radius: 99px;
    display: inline-grid;
    place-items: center;
    color: #fff;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.28);
}
.status-dot.ok   { background: linear-gradient(140deg, #34d399, var(--success)); color: #04231a; }
.status-dot.bad  { background: linear-gradient(140deg, #f43f5e, var(--danger)); }
.status-dot.warn { background: linear-gradient(140deg, #fbbf24, var(--warning)); color: #2a1a02; }

.assign-addon-check { flex: 0 0 auto; }

/* Native file inputs. The button half is the browser's own widget, so it
   is restyled through ::file-selector-button rather than replaced -- the
   control keeps its keyboard behaviour and its accessible name. */
input[type="file"].form-control { padding: 6px 10px; cursor: pointer; }
input[type="file"]::file-selector-button {
    margin: -6px 12px -6px -10px;
    padding: 10px 14px;
    border: 0;
    border-right: 1px solid var(--stroke);
    background: var(--glass-strong);
    color: var(--text-2);
    font-weight: 650;
    font-size: .85rem;
    cursor: pointer;
    transition: background .22s var(--ease), color .22s var(--ease);
}
input[type="file"]::file-selector-button:hover { background: var(--glass-hover); color: var(--text-1); }
input[type="file"].form-control-sm::file-selector-button { padding: 7px 12px; margin: -8px 10px -8px -12px; }

/* The switch track is wider than Bootstrap's default, so the row's
   left padding has to grow with it or the label sits on the knob. */
.form-switch { padding-left: 3.35em; }
.form-switch .form-check-input { margin-left: -3.35em; }
.form-switch .form-check-label { padding-top: 1px; }

/* =====================================================================
   26. Bilingual: Urdu typography and right-to-left layout
   =====================================================================

   Two things change when Urdu is selected, and they are separate
   problems. The FONT changes because Nastaliq is a different shape of
   writing that needs different vertical room. The DIRECTION changes
   because the whole interface mirrors.

   Direction is handled almost entirely by logical properties -- the
   rules above say `margin-inline-start` rather than `margin-left`, so
   they mirror on their own. What is left here is the handful of places
   that genuinely have to know which way round they are.
   ===================================================================== */

/* ---- typography ---------------------------------------------------- */
:root {
    /* Urdu leads the stack; Latin falls through to the sans face, which
       is what should happen for a case reference inside an Urdu line. */
    --font-urdu: 'Noto Nastaliq Urdu', 'Jameel Noori Nastaleeq', 'Alvi Nastaleeq',
                 'Scheherazade New', 'Noto Naskh Arabic', serif;
}

[lang="ur"],
[dir="rtl"] {
    font-family: var(--font-urdu);
    /*
     * Nastaliq cascades: each word steps down and to the left, so a
     * descender reaches well into the line below. At Latin line heights
     * the words collide. This is the single most important number on
     * the page for Urdu legibility.
     */
    line-height: 2.05;
}

[dir="rtl"] h1, [dir="rtl"] h2, [dir="rtl"] h3,
[dir="rtl"] h4, [dir="rtl"] h5, [dir="rtl"] h6 {
    line-height: 1.9;
    /* Nastaliq is already dense; the tight Latin tracking closes it up
       to the point of touching. */
    letter-spacing: 0;
}

[dir="rtl"] .page-header-title { line-height: 1.8; }
[dir="rtl"] .kpi-value,
[dir="rtl"] .stat-val { line-height: 1.35; }

/* Buttons, chips and table cells hold single words, so they can be
   tighter than running prose without risking a collision. */
[dir="rtl"] .btn,
[dir="rtl"] .badge-soft,
[dir="rtl"] .task-status-badge,
[dir="rtl"] .filter-chip,
[dir="rtl"] .thread-tab,
[dir="rtl"] .table-modern td,
[dir="rtl"] .table-modern th { line-height: 1.75; }

/* Latin runs inside an Urdu page keep the Latin face. Nastaliq has no
   real Latin, and a reference code set in it is unreadable. */
[dir="rtl"] .mono,
[dir="rtl"] code,
[dir="rtl"] pre,
[dir="rtl"] .service-price,
[dir="rtl"] .case-total,
[dir="rtl"] .case-remaining,
[dir="rtl"] .sample-tile-ext,
[dir="rtl"] .file-tile-kind,
[dir="rtl"] .rec-time,
[dir="rtl"] .console-log,
[dir="rtl"] input[type="email"],
[dir="rtl"] input[type="url"],
[dir="rtl"] input[type="number"],
[dir="rtl"] input[type="date"],
[dir="rtl"] input[type="password"] {
    font-family: var(--mono);
    line-height: 1.6;
}

/* Urdu needs a little more size to stay legible at the same rank --
   Nastaliq's x-height is small relative to its em. */
[dir="rtl"] body { font-size: 15.5px; }
[dir="rtl"] .small, [dir="rtl"] small { font-size: .9rem; }

/* ---- the switcher --------------------------------------------------- */
.lang-switch {
    display: inline-flex;
    align-items: stretch;
    padding: 3px;
    border-radius: var(--r-pill);
    border: 1px solid var(--stroke);
    background: var(--glass-strong);
    box-shadow: var(--sh-1);
    flex: 0 0 auto;
}
.lang-switch-option {
    display: inline-flex;
    align-items: center;
    padding: 4px 13px;
    border-radius: var(--r-pill);
    font-size: .8rem;
    font-weight: 700;
    line-height: 1.7;
    color: var(--text-2);
    white-space: nowrap;
    transition: color .18s var(--ease-soft), background .18s var(--ease-soft);
}
.lang-switch-option:hover { color: var(--text-1); background: var(--glass-hover); }
.lang-switch-option.active {
    color: #fff;
    background: linear-gradient(120deg, var(--brand-1), var(--brand-2));
    box-shadow: 0 2px 7px rgba(99,102,241,.21);
}
[data-theme="light"] .lang-switch-option.active { color: #fff; }
/* Urdu is set in Nastaliq even while the interface is still English --
   the label has to look like the thing it switches to. */
.lang-switch-option[lang="ur"] { font-family: var(--font-urdu); font-size: .92rem; padding-block: 1px; }

/* On a phone the switcher, the bell, the theme button and the avatar all
   compete for one row. The switcher keeps both labels -- someone who
   cannot read the current language still needs to see the way out -- so
   it gives up padding instead, and the topbar heading truncates rather
   than wrapping down over the icons. */
@media (max-width: 575.98px) {
    .lang-switch { padding: 2px; }
    .lang-switch-option { padding: 3px 8px; font-size: .72rem; }
    .lang-switch-option[lang="ur"] { font-size: .82rem; }
    /* Many pages carry no in-page heading, so the topbar title is the
       only one they have -- it cannot be truncated away. The bar wraps
       into two rows instead: controls above, heading across the full
       width below. */
    .topbar { flex-wrap: wrap; row-gap: 4px; padding-block: 9px; }
    .topbar-right { order: 1; flex: 1 1 100%; justify-content: flex-end; gap: 6px; }
    .topbar-left  { order: 2; flex: 1 1 100%; gap: 9px; }
    .topbar-left > div { min-width: 0; }
    .topbar-eyebrow { display: none; }
    .topbar .section-title {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        font-size: 1rem;
    }
}

.auth-controls {
    position: fixed;
    top: 14px;
    inset-inline-end: 14px;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 9px;
}

/* ---- direction ------------------------------------------------------ */
/*
 * The sidebar sits against the start edge and its border faces inward,
 * whichever way round the page is.
 */
[dir="rtl"] .sidebar { border-right: 0; border-left: 1px solid var(--stroke); }
[dir="rtl"] .sidebar nav a.active::before { left: auto; right: -16px; border-radius: 4px 0 0 4px; }
[dir="rtl"] .unread-badge, [dir="rtl"] .nav-dot { margin-left: 0; margin-right: auto; }

[dir="rtl"] .topbar-search .ic { left: auto; right: 14px; }
[dir="rtl"] .topbar-search input { padding: 9px 42px 9px 16px; }

[dir="rtl"] .icon-btn-badge,
[dir="rtl"] .sample-count-badge,
[dir="rtl"] .thread-tab-badge { right: auto; left: -5px; }

[dir="rtl"] .table-modern thead th,
[dir="rtl"] .table-modern tbody td,
[dir="rtl"] .selection-table th, [dir="rtl"] .selection-table td,
[dir="rtl"] .case-entry-table th, [dir="rtl"] .case-entry-table td { text-align: right; }

[dir="rtl"] .form-select { background-position: left 13px center; padding-right: 14px; padding-left: 38px; }

[dir="rtl"] .toasts { right: auto; left: 20px; }
[dir="rtl"] .toast-item::before { left: auto; right: 0; }
[dir="rtl"] .alert::before { left: auto; right: 0; }
[dir="rtl"] .note-card::before { left: auto; right: 0; }
[dir="rtl"] .sample-modal-close,
[dir="rtl"] .sample-lightbox-close { right: auto; left: 14px; }
[dir="rtl"] .sample-tile-glyph { left: auto; right: 8px; }
[dir="rtl"] .sample-tile-ext,
[dir="rtl"] .file-tile-kind { left: auto; right: 8px; }
[dir="rtl"] .file-tile-play { right: auto; left: 8px; }
[dir="rtl"] .sample-del { right: auto; left: 7px; }
[dir="rtl"] .kpi-card::before { right: auto; left: -34px; }
[dir="rtl"] .card-bar { left: auto; right: 0; }
[dir="rtl"] .delete-manifest { padding: 14px 32px 14px 16px; }
[dir="rtl"] .form-switch { padding-left: 0; padding-right: 3.35em; }
[dir="rtl"] .form-switch .form-check-input { margin-left: 0; margin-right: -3.35em; }
[dir="rtl"] .form-check { padding-left: 0; padding-right: 1.5em; }
[dir="rtl"] .form-check .form-check-input { margin-left: 0; margin-right: -1.5em; }

/* The chat keeps its own sides: your messages hug the start edge of the
   reading direction, the other side hugs the end. */
[dir="rtl"] .msg-row.mine .msg-bubble { border-bottom-right-radius: var(--r-lg); border-bottom-left-radius: 6px; }
[dir="rtl"] .msg-row.theirs .msg-bubble { border-bottom-left-radius: var(--r-lg); border-bottom-right-radius: 6px; }

/* The scroll-shadow gradients are painted left and right explicitly, so
   they need swapping rather than mirroring. */
[dir="rtl"] .table-responsive { background-position: 100% 0, 0 0, 100% 0, 0 0; }

/*
 * Data is not interface. A client's English name inside an Urdu page
 * still reads left to right, so every field that holds free text is
 * marked dir="auto" in the markup and the browser decides per value.
 * These two rules make sure the box itself lines up with whatever the
 * browser chose.
 */
input[dir="auto"], textarea[dir="auto"] { text-align: start; }
[dir="rtl"] .msg-text, [dir="rtl"] .detail-fact-value { text-align: start; }

/* ---------- 27. Phones and tablets: touch, reading, and tables ---------- */
/*
 * Everything in this section is about a hand holding a phone rather than
 * a mouse on a desk. It is deliberately last so it wins over the
 * component rules above without any of them needing to know about it.
 */

/* A tap should feel instant and leave no grey flash behind it. The 300ms
   click delay only disappears when the browser is told the element will
   not be double-tapped to zoom. */
a, button, [role="button"], .btn, .icon-btn, label, select, summary {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* iPhone and iPad, standalone or not: keep content clear of the notch,
   the rounded corners and the home indicator. On every other device
   these resolve to 0, so the rules are inert. */
.topbar { padding-top: max(12px, env(safe-area-inset-top)); }
.sidebar { padding-inline-start: max(18px, env(safe-area-inset-left)); }
.page-content { padding-bottom: max(52px, calc(32px + env(safe-area-inset-bottom))); }

@media (pointer: coarse), (max-width: 767.98px) {
    /* ---- iOS zoom ----------------------------------------------------
     * Safari zooms the whole page whenever a focused field is set below
     * 16px, and it does not zoom back out afterwards. Every control that
     * can take focus is therefore 16px on a phone, small variants
     * included -- they stay visually smaller through padding, not type.
     */
    input, select, textarea,
    .form-control, .form-select,
    .form-control-sm, .form-select-sm,
    .form-control-lg, .form-select-lg {
        font-size: 16px;
    }
    .form-control-sm, .form-select-sm { padding: 8px 12px; }
    /* The topbar search sets its own size further up the sheet. */
    .topbar-search input { font-size: 16px; }

    /* ---- tap targets -------------------------------------------------
     * Apple asks for 44pt, Android for 48dp. 44px is the floor here.
     * Where a control has to stay visually small -- an icon button in a
     * table row -- the box stays small and the touchable area is grown
     * with a transparent ::after, so the layout does not change.
     */
    .btn {
        min-height: 44px;
        padding-block: 10px;
    }
    .btn-sm {
        min-height: 40px;
        padding-block: 8px;
    }
    .icon-btn,
    .theme-toggle-btn,
    .sidebar-toggle-btn {
        min-width: 44px;
        min-height: 44px;
    }
    .user-chip { min-height: 44px; }

    .lang-switch-option {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        padding-inline: 14px;
    }

    /* A checkbox you cannot hit is a checkbox you cannot use. The box
       itself grows a little; the row it sits in carries the rest of the
       44px, because the label is part of the target too. */
    .form-check {
        display: flex;
        align-items: center;
        min-height: 44px;
    }
    .form-check-input {
        width: 24px;
        height: 24px;
        margin-top: 0;
        flex: 0 0 24px;
    }
    .form-check-label { padding-block: 6px; }
    .form-switch .form-check-input { width: 52px; height: 30px; flex-basis: 52px; }

    /* Links that act as navigation -- a "back to the client" row, a
       thread heading -- are targets, not prose. */
    .thread-row a.text-decoration-none,
    .card-header a.text-decoration-none,
    .page-header a.text-decoration-none,
    a.text-decoration-none.d-inline-flex {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    .filter-chip { min-height: 44px; }
    .toast-close { min-width: 44px; min-height: 44px; }

    /* Row actions: keep the drawn button, widen what the finger hits. */
    .table-modern td .btn-sm,
    .addon-table td .btn-sm {
        position: relative;
    }
    .table-modern td .btn-sm::after,
    .addon-table td .btn-sm::after {
        content: '';
        position: absolute;
        inset: -7px -5px;
    }

    /* ---- reading -----------------------------------------------------
     * 10.9px is a caption on a monitor and a smudge on a phone.
     */
    .nav-section-label,
    .topbar-eyebrow,
    .user-chip-role,
    .page-header-eyebrow,
    .sample-modal-eyebrow,
    .thread-row-count,
    .card-header-note,
    .detail-label,
    .detail-fact-label { font-size: .78rem; }
    .text-muted-soft { font-size: inherit; }
    .badge { font-size: .74rem; }
    .text-muted-soft.small, .form-text { font-size: .82rem; }

    /* Two buttons per row beats four ragged ones. */
    .page-header-actions { display: flex; flex-wrap: wrap; gap: 8px; }
    .page-header-actions > * { flex: 1 1 calc(50% - 4px); }
}

/* ---- data tables become cards ----------------------------------------
 * A ten-column table on a 390px screen shows three columns and hides the
 * rest behind a sideways scroll, which is how you lose a row you were
 * halfway through reading. Below this width each row is redrawn as a
 * card: one record, its fields stacked, each labelled.
 *
 * The labels come from the table's own <thead> -- script.js copies them
 * onto every cell as data-label on load. No page has to be edited, and
 * with JavaScript off the table simply stays a table and scrolls, which
 * is what it did before.
 */
@media (max-width: 767.98px) {
    table.table-as-cards,
    table.table-as-cards tbody,
    table.table-as-cards tr,
    table.table-as-cards td {
        display: block;
        width: auto;
    }
    table.table-as-cards thead { display: none; }

    table.table-as-cards tbody tr {
        position: relative;
        margin-bottom: 12px;
        padding: 4px 2px;
        border: 1px solid var(--stroke);
        border-radius: var(--r-lg);
        background: var(--glass);
    }
    table.table-as-cards tbody tr:last-child { margin-bottom: 0; }
    [data-theme="light"] table.table-as-cards tbody tr { background: var(--glass-strong); }

    /* A whole card is one tap when the row was clickable. */
    table.table-as-cards tbody tr[data-href] { cursor: pointer; }
    table.table-as-cards tbody tr[data-href]:active { background: var(--glass-hover); }

    /* Grid rather than flex, because a cell's contents are several
       inline boxes -- a badge, a figure, a note -- and flex would glue
       them into one unbreakable item that runs off the card edge. In a
       grid they land in a column with a real width and wrap inside it. */
    table.table-as-cards tbody td {
        display: grid;
        grid-template-columns: minmax(0, 38%) minmax(0, 1fr);
        align-items: baseline;
        gap: 6px 14px;
        padding: 10px 14px;
        border: 0;
        border-bottom: 1px solid var(--stroke-soft);
        text-align: start;
        white-space: normal;
        overflow-wrap: anywhere;
    }
    table.table-as-cards tbody td:last-child { border-bottom: 0; }

    /* One box for the value, so a cell holding a name and a code under
       it stays one field rather than becoming two. */
    table.table-as-cards tbody td > .td-value {
        display: block;
        min-width: 0;
    }
    table.table-as-cards tbody td[data-label=""] > .td-value {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 8px;
    }

    /* The label sits on the reading edge, the value opposite it. */
    table.table-as-cards tbody td::before {
        content: attr(data-label);
        font-size: .74rem;
        font-weight: 700;
        letter-spacing: .04em;
        text-transform: uppercase;
        color: var(--text-3);
        text-align: start;
        line-height: 1.5;
    }
    /* A cell whose column had no heading -- the action column -- has
       nothing to label, so it gives its whole width to the buttons. */
    table.table-as-cards tbody td[data-label=""] {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 8px;
        padding-top: 12px;
        padding-bottom: 12px;
    }
    table.table-as-cards tbody td[data-label=""]::before { display: none; }
    /* An empty cell would otherwise show a label pointing at nothing. */
    table.table-as-cards tbody td.is-empty { display: none; }

    /* Alignment utilities are about columns; a card has no columns. */
    table.table-as-cards tbody td.text-end,
    table.table-as-cards tbody td.text-center { text-align: start; }

    /* The wrapper no longer needs to scroll, and its edge shadows would
       be pointing at nothing. */
    /* The class is put there by script.js rather than matched with
       :has(), which older phone browsers do not have. */
    .table-responsive.has-cards {
        overflow-x: visible;
        background: none;
    }
    .table-responsive.has-cards::before,
    .table-responsive.has-cards::after { display: none; }
}

/* A "nothing matched" row is a message about the table, not a record in
   it. It keeps its own shape inside the card layout. */
@media (max-width: 767.98px) {
    table.table-as-cards tbody tr.is-message-row {
        border: 0;
        background: none;
        margin-bottom: 0;
    }
    table.table-as-cards tbody tr.is-message-row td {
        display: block;
        text-align: center;
        border-bottom: 0;
    }
    table.table-as-cards tbody tr.is-message-row td::before { display: none; }
}

/* While the drawer is open the page behind it must not scroll -- on a
   phone that reads as the drawer being broken rather than as a feature. */
body.sidebar-locked { overflow: hidden; }

/* The wrapper script.js puts around each table cell's contents exists
   only for the phone card layout; everywhere else it must not be a box
   at all, or it would break table cell alignment and the utilities
   applied to the cell itself. */
.td-value { display: contents; }
