/*
 * Dijiwa Back Office — shared design tokens + component styles.
 *
 * Linked (plain <link>, no build step) from layouts/app.blade.php, layouts/auth.blade.php,
 * and every standalone view (pages that render their own <html> instead of extending a
 * layout — signer/approval/verify pages). Centralizing here means a palette or nav change
 * only touches this one file instead of being re-applied by hand across ~11 places.
 *
 * DIRECTION (v2, radical pass): true near-black + true white, flat and hard-edged — no
 * blur/backdrop-filter, no gradients, no glow shadows on static chrome. The accent (the
 * reference's "Aqua Blue" tone, #00B9E4 — used raw, no blending needed, since it's already
 * bright enough for on-black legibility) is spent ONCE per moment — a wordmark, an active
 * nav state, a focus ring, one outlined pill CTA — rather than tinting every border/
 * background the way v1 did. The structural rule throughout: hairlines and dividers are
 * neutral (rgba(var(--paper-rgb), alpha)); the accent appears specifically to mean active /
 * focused / primary-action, never as ambient decor. Buttons are outlined pills (transparent
 * fill, colored border+text) that invert to a solid fill only on hover — the one digital
 * precedent found in the brand reference.
 *
 * v3 note (2026-07-04): swapped the accent hue from "Aged Gold" (#866200) to "Aqua Blue"
 * (#00B9E4) — both are real named tones from the brand reference's 8-color "Color Scenes"
 * palette (style-extraction.md), but gold still read too close to the app's old bronze
 * identity and risked semantic collision with nothing; the deeper problem was picking a
 * warm hue at all when the brief asked to move away from warm/gold. Aqua Blue also can't be
 * confused with the existing --danger-rgb/--success-rgb semantics the way a red brand tone
 * would (Oxide Red / Terracotta Red were the other strong candidates from the palette, ruled
 * out for exactly that collision risk). Deep Ocean Blue (#094F6E), the same "cool water"
 * family's deeper tone, is the companion color for label text / secondary wash.
 */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;0,9..144,700;1,9..144,400&display=swap');

:root {
    /* Surfaces — true near-black canvas; one flat, neutral (not warm-tinted) lift for
       cards/dropdowns/modals, separated from the canvas by a hairline, not a shadow. */
    --ink-rgb: 10, 10, 10;           /* page background */
    --topbar-rgb: 10, 10, 10;        /* topbar — flush with the canvas, hairline-separated */
    --surface-rgb: 19, 19, 19;       /* card / dropdown / modal surfaces — opaque, flat */

    /* Text — true white. A single token (both tiers now share the same base) so every
       existing rgba(var(--paper-soft-rgb), alpha) call site still works: the alpha values
       already tuned during the 2026-06-23/26 a11y passes keep their contrast ratios (a
       brighter true-white base only ever *raises* the resulting contrast, never lowers it),
       while the page reads unambiguously black-and-white instead of warm-cream-tinted. */
    --paper-rgb: 255, 255, 255;
    --paper-soft-rgb: 255, 255, 255;

    /* Brand accent — the reference's "Aqua Blue" tone, used raw (no white-blend needed —
       it's already high-luminance enough for on-black text/borders, unlike the old gold
       pigment). Reserved for active/focus/primary-action states only — see the direction
       note above. */
    --accent-rgb: 0, 185, 228;        /* #00B9E4 — raw, unblended */
    --accent: #00B9E4;
    --accent-soft: #4DCEEC;           /* blended 30% toward white — badges/small text */
    --accent-strong: #094F6E;         /* "Deep Ocean Blue" — the accent's deeper companion
                                         tone, used for field-label caps */
    --accent2-rgb: 9, 79, 110;        /* #094F6E "Deep Ocean Blue" — rare secondary, one
                                         static wash on the login stage, nowhere else */

    /* Status — standard semantic colors, not part of the brand style reference */
    --success-rgb: 47, 158, 111;
    --success-text: #86efac;
    --danger-rgb: 192, 88, 79;       /* buttons/badges danger */
    --danger-text: #f0a8a1;
    --flash-danger-rgb: 220, 38, 38; /* flash/field-error red — a distinct, cooler red from
                                         --danger-rgb; both pre-date this file. */
    --flash-danger-text: #fca5a5;

    --font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    /* Architectural high-contrast serif for headline/hero moments only (page titles,
       login title) — kept OFF dense UI chrome (tables/forms/buttons/nav) so daily task
       legibility never regresses; those stay on --font-sans. Pushed to a bigger, bolder
       scale in this pass (see .page-head h1) — the "monumental" register of the reference. */
    --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
    font-family: var(--font-sans);
    background: rgb(var(--ink-rgb)); color: #fff; min-height: 100vh;
}
a { color: inherit; }
.icon { display: inline-block; vertical-align: middle; flex-shrink: 0; }
.shell { position: relative; z-index: 1; max-width: 1080px; margin: 0 auto; padding: 18px 24px 64px; }

/* App shell — sidebar + main content, a flex row. The sidebar scales by *scrolling*
   vertically, which is the actual fix for the old horizontal .topnav's recurring
   width-budget problem (see git history / CLAUDE.md — six separate max-width bumps,
   one per module added). Adding a module here costs nothing shared/finite; it just
   adds one more row that scrolls if the list ever outgrows the viewport height. */
.app-shell { display: flex; min-height: 100vh; }

.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; flex-shrink: 0; }
.brand-logo { height: 32px; width: auto; }
.brand-text { font-size: 12px; font-weight: 800; letter-spacing: 0.30em; text-transform: uppercase; color: var(--accent); line-height: 1.2; }
.brand-text small { display: block; font-size: 9.5px; letter-spacing: 0.16em; color: rgba(var(--paper-rgb),0.5); margin-top: 2px; font-weight: 600; }

/* Sidebar — sticky full-height column on desktop (>640px); becomes a fixed off-canvas
   drawer under the phone media query below. `.sidebar` and `.mobile-topbar` each hold
   their OWN `.brand` instance (not one CSS-repositioned node) — the inactive copy is
   excluded from tab order via `display:none`, not just hidden visually. */
.sidebar { width: 260px; flex-shrink: 0; display: flex; flex-direction: column; gap: 4px;
    padding: 20px 16px; background: rgba(var(--topbar-rgb),0.97);
    border-right: 1px solid rgba(var(--paper-rgb),0.12);
    position: sticky; top: 0; height: 100vh; overflow-y: auto;
    scrollbar-width: thin; scrollbar-color: rgba(var(--paper-rgb),0.3) transparent; }
.sidebar::-webkit-scrollbar { width: 4px; }
.sidebar::-webkit-scrollbar-thumb { background: rgba(var(--paper-rgb),0.3); border-radius: 4px; }
.sidebar::-webkit-scrollbar-track { background: transparent; }
.sidebar > .brand { padding: 4px 8px 18px; }

/* Primary nav — top-level: Dashboard + one entry per module, plus (nested directly
   under whichever module is currently active) that module's own sub-pages, if it has
   more than one — see .sidenav-sub, which replaces the old separate horizontal
   .subnav bar. */
.sidenav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.sidenav a { position: relative; display: flex; align-items: center; gap: 9px;
    color: rgba(var(--paper-rgb),0.6); text-decoration: none; font-size: 13.5px; font-weight: 500;
    padding: 9px 12px; border-radius: 9px; transition: color .15s ease, background .15s ease; }
.sidenav a .mod-ico { opacity: 0.8; flex-shrink: 0; }
.sidenav a:hover { color: #fff; background: rgba(var(--paper-rgb),0.06); }
/* box-shadow:inset (not a negative-offset ::before) for the active accent bar — .sidebar
   has overflow-y:auto, which the CSS spec forces to also compute overflow-x as auto (not
   visible) once either axis is non-visible, so anything positioned outside the link's own
   border box would risk being clipped/scrolled. An inset shadow never triggers that. */
.sidenav a.active { color: #fff; background: rgba(var(--accent-rgb),0.14); box-shadow: inset 3px 0 0 var(--accent); }

/* Contextual sub-links — the module you're currently inside's own pages (e.g.
   Reimbursement's My Batches/Approvals). role="group" (set in the Blade template, not
   here) gives assistive tech the same "you're in a sub-section" cue the old standalone
   <nav aria-label="… sections"> gave, without nesting a second <nav> landmark inside
   .sidenav. Only rendered per-module, and only when that module is both active AND has
   more than one link — never adds chrome with nothing to switch to (Wiki, AI Media,
   Meetings all render none). */
.sidenav-sub { display: flex; flex-direction: column; gap: 1px; margin: 2px 0 6px 30px; }
.sidenav-sub a { padding: 7px 10px; font-size: 12.5px; font-weight: 600; border-radius: 8px; }
.sidenav-sub a.active { color: #fff; box-shadow: inset 2px 0 0 var(--accent); }

/* Bottom-of-sidebar cluster: admin (if applicable), account, logout — was the .account
   cluster at the tail end of the old horizontal .topnav; the reason it lived outside
   .topnav there ("that bar clips, this can't") no longer applies once the sidebar
   scrolls instead of clipping, but keeping this trio visually grouped at the bottom
   still reads correctly. */
.sidebar-footer { margin-top: auto; padding-top: 14px; border-top: 1px solid rgba(var(--paper-rgb),0.12);
    display: flex; flex-direction: column; gap: 10px; }

.nav-admin { position: relative; }
.nav-admin > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
    color: rgba(var(--paper-rgb),0.6); font-size: 13.5px; font-weight: 500; padding: 9px 12px; border-radius: 9px; }
.nav-admin > summary::-webkit-details-marker { display: none; }
.nav-admin > summary::after { content: '▾'; font-size: 10px; opacity: 0.7; margin-left: auto; }
.nav-admin > summary:hover { color: #fff; background: rgba(var(--paper-rgb),0.06); }
.nav-admin[open] > summary { color: #fff; }
.nav-admin-menu { display: flex; flex-direction: column; margin: 2px 0 0 18px; gap: 1px; }
.nav-admin-menu a { padding: 8px 10px; border-radius: 8px; font-size: 12.5px; }

.account { display: flex; align-items: center; gap: 10px; padding: 6px 8px; }
.userchip { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; color: rgba(var(--paper-rgb),0.72); text-decoration: none; transition: color .15s ease; flex: 1; min-width: 0; }
a.userchip:hover { color: #fff; }
.role-badge { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; padding: 3px 8px; border-radius: 999px;
    background: transparent; border: 1px solid rgba(var(--accent-rgb),0.5); color: var(--accent-soft); flex-shrink: 0; }
.logout-form { display: flex; }
.btn-logout { width: 100%; background: none; border: 1px solid rgba(var(--paper-rgb),0.18); color: rgba(var(--paper-rgb),0.7); border-radius: 999px;
    padding: 9px 14px; font-size: 12px; font-weight: 600; cursor: pointer; transition: all .15s ease; }
.btn-logout:hover { border-color: rgba(var(--paper-rgb),0.4); color: #fff; background: rgba(var(--paper-rgb),0.05); }

/* Main content column — .shell (below) keeps its existing max-width/centering,
   now centered within whatever width main-col has left next to the sidebar
   instead of the full viewport. */
.main-col { flex: 1; min-width: 0; }

/* Mobile-only slim top bar (brand + hamburger) — hidden on desktop, shown ≤640px,
   sticky. z-index deliberately stays well below .modal-overlay's (100): that alone
   makes the hamburger unclickable/covered whenever a modal is open, which is what
   actually prevents the drawer's focus trap and a modal's from ever needing to run
   at once — cheaper and more robust than coordinating three traps at runtime. */
.mobile-topbar { display: none; position: sticky; top: 0; z-index: 40; align-items: center; justify-content: space-between;
    gap: 12px; padding: 14px 18px; background: rgba(var(--topbar-rgb),0.97); border-bottom: 1px solid rgba(var(--paper-rgb),0.12); }

.sidebar-backdrop { display: none; }

/* Shared accent badge (admin nav pending-count chips) — a small, deliberate, filled
   accent chip (a notification count), the one badge that stays filled rather than
   outlined since it's signalling "count > 0", not a static label. */
.badge-accent { background: rgba(var(--accent-rgb),0.18); color: var(--accent-soft); border: 1px solid rgba(var(--accent-rgb),0.4); }

/* Headings + flash */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin: 14px 0 22px; flex-wrap: wrap; }
.page-head h1 { margin: 0; font-family: var(--font-display); font-size: clamp(2rem, 4.2vw, 3.1rem); font-weight: 600; letter-spacing: -0.02em; text-wrap: balance; }
.page-head p { margin: 8px 0 0; font-size: 13px; color: rgba(var(--paper-rgb),0.5); }
.flash { border-radius: 12px; padding: 13px 16px; font-size: 13px; font-weight: 600; margin-bottom: 18px; }
.flash-success { background: rgba(var(--success-rgb),0.14); border: 1px solid rgba(var(--success-rgb),0.35); color: var(--success-text); }
.flash-error { background: rgba(var(--flash-danger-rgb),0.14); border: 1px solid rgba(var(--flash-danger-rgb),0.32); color: var(--flash-danger-text); }

/* Cards / panels — flat and opaque, no blur, no translucency, no glow shadow. A card
   reads as a card purely from its hairline border + the one-step surface lift. */
.panel { background: rgb(var(--surface-rgb)); border: 1px solid rgba(var(--paper-rgb),0.12); border-radius: 16px; padding: 24px; }
/* :not(.tile) — this rule spaces vertically-STACKED .panel sections in normal flow
   (e.g. batches/approvals pages). .tile-grid tiles also carry the .panel class, so
   the plain sibling selector was ALSO matching every tile after the first in the
   horizontal dashboard grid, giving it an un-collapsed top margin the grid's gap
   already accounts for — tiles never need it. */
.panel + .panel:not(.tile) { margin-top: 18px; }

/* Dashboard module launcher — responsive auto-fit grid, no empty trailing column. */
/* align-items defaults to `normal`, which doesn't reliably stretch flex-container
   grid items (each .tile) to match its row's tallest sibling — cards with a longer
   description (wrapping to more lines) end up visibly shorter/taller than others. */
.tile-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; align-items: stretch; }
.tile { align-self: stretch; height: 100%; }
.tile { padding: 22px; text-decoration: none; display: flex; flex-direction: column; gap: 10px; min-height: 150px; }
.tile-ico { color: var(--accent); }
.tile-name { font-weight: 700; font-size: 16px; }
.tile-desc { font-size: 12px; margin-top: 3px; }
.tile-stat { margin-top: auto; padding-top: 10px; }
.tile-stat-value { font-size: 24px; font-weight: 800; color: var(--accent); }
.tile-stat-label { font-size: 12px; margin-left: 6px; }

/* Buttons — outlined pills that invert to a solid fill on hover. The one digital UI
   precedent found in the brand reference (a top-right outlined pill CTA), applied as
   the whole system's primary-action language instead of the old filled gradient. */
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 11px 20px; border-radius: 999px; font-size: 13px; font-weight: 700;
    cursor: pointer; text-decoration: none; border: 1.5px solid transparent; transition: background .18s ease, color .18s ease, border-color .18s ease, transform .18s ease; }
.btn-primary { background: transparent; color: var(--accent); border-color: var(--accent);
    text-transform: uppercase; letter-spacing: 0.07em; font-size: 12px; }
.btn-primary:hover { background: var(--accent); color: rgb(var(--ink-rgb)); transform: translateY(-1px); }
.btn-ghost { background: transparent; color: rgba(var(--paper-rgb),0.78); border-color: rgba(var(--paper-rgb),0.22); }
.btn-ghost:hover { background: rgba(var(--paper-rgb),0.07); color: #fff; border-color: rgba(var(--paper-rgb),0.4); }
.btn-danger { background: transparent; color: var(--danger-text); border-color: rgba(var(--danger-rgb),0.55); }
.btn-danger:hover { background: rgb(var(--danger-rgb)); color: #fff; border-color: rgb(var(--danger-rgb)); }
.btn-sm { padding: 7px 14px; font-size: 12px; }
.btn-primary.btn-sm { font-size: 11px; }

/* Forms */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-strong); margin-bottom: 7px; }
.field input:not([type="checkbox"]):not([type="radio"]), .field textarea, .field select {
    width: 100%; padding: 12px 15px; background: rgba(var(--paper-rgb),0.04); border: 1px solid rgba(var(--paper-rgb),0.16);
    border-radius: 10px; color: #fff; font-size: 14px; outline: 2px solid transparent; outline-offset: 1px; transition: all 0.18s ease; }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--accent); background: rgba(var(--paper-rgb),0.07); }
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.field .err { color: var(--flash-danger-text); font-size: 12px; margin-top: 6px; }
/* Checkboxes/radios inside a .field must not inherit the text-input sizing above
   (2026-07-07 fix — the AI Media voice form was the first .field to ever nest a
   checkbox, and it inherited width:100%+padding+border, splitting the tick box
   away from its label text inside the flex label wrapper). */
.field input[type="checkbox"], .field input[type="radio"] { width: auto; flex-shrink: 0; margin: 0; accent-color: var(--accent); }
.field-row { display: flex; gap: 14px; flex-wrap: wrap; }
.field-row > .field { flex: 1; min-width: 150px; }

/* Tables */
table.data { width: 100%; border-collapse: collapse; font-size: 14px; }
table.data th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent-soft); font-weight: 700; padding: 10px 12px; border-bottom: 1px solid rgba(var(--paper-rgb),0.14); }
table.data td { padding: 12px; border-bottom: 1px solid rgba(var(--paper-rgb),0.08); }
table.data tr:last-child td { border-bottom: none; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.muted { color: rgba(var(--paper-rgb),0.55); }

.status-badge { display: inline-block; font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: 999px; }

.empty { text-align: center; padding: 48px 24px; color: rgba(var(--paper-rgb),0.55); }
.empty .big { font-size: 15px; color: rgba(var(--paper-rgb),0.7); margin-bottom: 6px; }

/* Confirm modal */
.modal-overlay { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center;
    padding: 20px; background: rgba(var(--ink-rgb),0.8); backdrop-filter: blur(3px); opacity: 0; pointer-events: none;
    transition: opacity 0.2s ease; }
.modal-overlay.open { opacity: 1; pointer-events: auto; }
.modal-card { width: 100%; max-width: 420px; background: rgb(var(--surface-rgb)); border: 1px solid rgba(var(--paper-rgb),0.16);
    border-radius: 16px; padding: 26px 24px 22px; box-shadow: 0 20px 60px rgba(0,0,0,0.45);
    transform: translateY(12px) scale(0.98); transition: transform 0.2s ease; }
.modal-overlay.open .modal-card { transform: translateY(0) scale(1); }
.modal-card h3 { margin: 0 0 8px; font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }
.modal-card p { margin: 0; font-size: 14px; line-height: 1.5; color: rgba(var(--paper-rgb),0.62); }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px; }

/* Mobile nav toggle — hidden on desktop, shown ≤640px. */
.nav-toggle { display: none; align-items: center; justify-content: center; width: 44px; height: 44px;
    background: rgba(var(--paper-rgb),0.05); border: 1px solid rgba(var(--paper-rgb),0.2); color: #fff;
    border-radius: 10px; font-size: 19px; line-height: 1; cursor: pointer; flex-shrink: 0; }
.nav-toggle:hover { border-color: rgba(var(--paper-rgb),0.4); }

/* ---- Tablet ---- */
@media (max-width: 768px) {
    .shell { padding: 14px 18px 56px; }
    /* Dashboard 3-up stat grid → 2-up. */
    [style*="grid-template-columns:repeat(3,1fr)"] { grid-template-columns: repeat(2, 1fr) !important; }
}

/* ---- Phone ---- */
@media (max-width: 640px) {
    .shell { padding: 12px 14px 48px; }

    .mobile-topbar { display: flex; }
    .nav-toggle { display: inline-flex; }
    .mobile-topbar .brand-text { font-size: 11px; }

    /* Off-canvas drawer: fixed full-height panel sliding in from the left, revealed via
       .open (JS also toggles `inert` alongside .open — see the script at the bottom of
       layouts/app.blade.php — since `transform` alone does not remove a closed drawer
       from the tab order or accessibility tree the way the old display:none/:flex toggle
       did). */
    .sidebar { position: fixed; top: 0; left: 0; z-index: 55; width: 280px; height: 100vh;
        transform: translateX(-100%); transition: transform .22s ease;
        border-right: 1px solid rgba(var(--paper-rgb),0.16); box-shadow: 0 0 40px rgba(0,0,0,0.5); }
    .sidebar.open { transform: translateX(0); }
    .sidebar > .brand { display: none; } /* .mobile-topbar's own .brand is the visible one here */

    .sidebar-backdrop { display: block; position: fixed; inset: 0; z-index: 54;
        background: rgba(0,0,0,0.6); opacity: 0; pointer-events: none; transition: opacity .22s ease; }
    .sidebar-backdrop.open { opacity: 1; pointer-events: auto; }

    /* Tap targets ≥44px — the sidebar's desktop padding is already close but not quite. */
    .sidenav a, .sidenav-sub a, .nav-admin > summary, .nav-admin-menu a { min-height: 44px; }
    .userchip { min-height: 44px; }
    .btn-logout { min-height: 44px; }

    /* Headings + spacing. */
    .page-head { margin: 22px 0 18px; }
    .field-row { flex-direction: column; gap: 0; }

    /* Tap targets — keep every actionable control ≥44px tall. */
    .btn { min-height: 44px; }
    .btn-sm { padding: 9px 13px; min-height: 40px; }

    /* Wide tables scroll horizontally instead of overflowing the viewport.
       display:block turns the table into its own scroll container; nowrap keeps
       columns at a readable width and pushes the excess into the scroll. */
    .table-scroll { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    table.data { white-space: nowrap; font-size: 13px; }
    .table-hint { display: block; font-size: 11px; color: rgba(var(--paper-rgb),0.4); margin: 4px 2px 0; }

    /* Stacked single-column for the inline-edit grid and the batch-upload split. */
    [style*="grid-template-columns:repeat(2,minmax(0,1fr))"] { grid-template-columns: 1fr !important; }
    [style*="grid-template-columns:1fr 1fr"] { grid-template-columns: 1fr !important; }
    [style*="grid-template-columns:repeat(3,1fr)"] { grid-template-columns: 1fr !important; }

    .modal-actions { flex-direction: column-reverse; }
    .modal-actions .btn { width: 100%; justify-content: center; }
}

.table-hint { display: none; }

/* Skip link — visually hidden until focused. */
.skip-link { position: fixed; top: 8px; left: 8px; z-index: 200; transform: translateY(-150%);
    background: var(--accent); color: #0a0a0a; font-weight: 700; font-size: 13px; padding: 10px 16px;
    border-radius: 999px; text-decoration: none; transition: transform .18s ease; }
.skip-link:focus { transform: translateY(0); outline: 2px solid #fff; outline-offset: 2px; }

/* Visually hidden but still reachable by screen readers (e.g. "opens in a new tab" hints). */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* Small inline glyph marking a link that opens in a new tab. */
.ext-ico { opacity: 0.55; margin-left: 4px; vertical-align: -1px; }

/* Interactive cards (dashboard tiles): flat hover + keyboard focus feedback — a brighter
   hairline and a small lift. Flat (no shadow) at rest; hover only gains a soft drop
   shadow + a faint accent-tinted glow underneath — see the DASHBOARD v3 note below for
   why this is additive, not a departure from "flat chrome at rest". */
a.panel { transition: border-color .18s ease, background .18s ease, transform .18s ease, box-shadow .18s ease; }
a.panel:hover { border-color: rgba(var(--paper-rgb),0.32); background: rgb(24,24,24); transform: translateY(-2px);
    box-shadow: 0 12px 32px rgba(0,0,0,0.35), 0 4px 24px rgba(var(--accent-rgb),0.08); }
a.panel:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Consistent keyboard focus ring on links/buttons over the dark theme. */
.sidenav a:focus-visible, .sidenav-sub a:focus-visible, .userchip:focus-visible, .btn-logout:focus-visible,
.btn:focus-visible, .brand:focus-visible, .nav-toggle:focus-visible,
.nav-admin > summary:focus-visible, .nav-admin-menu a:focus-visible {
    outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 9px; }

/* Horizontal-scroll wrapper for wide tables — keeps the <table> semantics intact
   (display:block on <table> itself breaks screen-reader row/column association). */
.table-scroll { width: 100%; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; scroll-behavior: auto !important; }
    a.panel:hover { transform: none; }
    .modal-card { transform: none; }
    /* DASHBOARD v3 additions — belt-and-suspenders alongside the universal
       0.01ms rule above (matches the explicit-override convention the login
       page's own reduced-motion block already uses for its `rise` elements). */
    .dashboard-glow > .page-head { animation: none !important; opacity: 1 !important; }
    .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
    .pending-queue-item .pq-row-link:hover .pq-cta,
    .pending-queue-item .pq-row-link:focus-visible .pq-cta,
    .flash.flash-cta:hover .flash-cta-cta,
    .flash.flash-cta:focus-visible .flash-cta-cta { transform: none; }
}

/* ============================================================================
   DASHBOARD v2 — new sections for the redesigned launcher
   - .dashboard-section: vertical stack wrapper for each dashboard region
   - .section-head: heading row with optional right-side actions
   - .pending-queue / .pending-queue-item: "My queue" pending items
   - .recent-activity / .recent-activity-item: "Recent activity" timeline
   - .system-status / .system-status-row: admin-only footer
   - .release-chip: inline "What's New" announcement
   - .flash.flash-cta: lift of dashboard's existing inline-style onboarding banner
   - .queue-empty: empty-state for queue / activity sections

   All rules use existing :root tokens only — no new colors, no shadows, no
   gradients. Hairlines stay neutral (rgba(var(--paper-rgb), alpha)); the
   accent appears only on the .tile-ico / focus / .badge-accent-style slots
   already established in the v2 base. Existing `a.panel:hover` (the lift on
   interactive cards) and `a.panel:focus-visible` (the accent focus ring)
   apply unmodified to anything that renders as `a.panel.tile`.
   ============================================================================ */
.dashboard-section { margin-top: 28px; }
.dashboard-section:first-of-type { margin-top: 0; }

.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.section-head h2 { margin: 0; font-family: var(--font-display); font-size: 18px; font-weight: 600; letter-spacing: -0.01em; color: #fff; }
.section-head p { margin: 0; font-size: 12px; color: rgba(var(--paper-rgb),0.5); }
.section-head .section-actions { display: inline-flex; gap: 8px; }

/* "My queue" — a flat list of pending items, one row per item. Each row is its
   own surface (not a child of a parent card) so long lists can scroll inside a
   fixed-height region without nested overflow gymnastics. */
.pending-queue { list-style: none; padding: 0; margin: 0; }
.pending-queue-item { display: flex; align-items: stretch; }
.pending-queue-item + .pending-queue-item { margin-top: 8px; }
/* The entire row is the link target (matches the module-tile pattern) so the
   click + tap target stays well above 44px without padding hacks. Visually the
   row keeps its surface — the <a> just fills the .pending-queue-item box. */
.pending-queue-item .pq-row-link { display: flex; align-items: center; gap: 12px; padding: 12px 14px;
    min-height: 44px; width: 100%;
    background: rgb(var(--surface-rgb)); border: 1px solid rgba(var(--paper-rgb),0.12); border-radius: 12px;
    color: #fff; text-decoration: none; transition: border-color .18s ease, box-shadow .18s ease; }
/* Same "flat at rest, soft shadow + faint accent glow on hover" treatment as
   a.panel:hover above — kept as its own declaration since .pq-row-link isn't
   an `a.panel`. */
.pending-queue-item .pq-row-link:hover { border-color: rgba(var(--paper-rgb),0.22);
    box-shadow: 0 12px 32px rgba(0,0,0,0.35), 0 4px 24px rgba(var(--accent-rgb),0.08); }
.pending-queue-item .pq-ico { color: var(--accent); flex-shrink: 0; }
.pending-queue-item .pq-body { flex: 1; min-width: 0; font-weight: 600; font-size: 14px; color: #fff; }
.pending-queue-item .pq-meta { font-size: 12px; color: rgba(var(--paper-rgb),0.5); margin-top: 2px; font-weight: 400; }
/* Arrow-shift micro-interaction: the row already renders "→" glyph inside
   .pq-cta; nudge it a few px on parent hover/focus. .pq-cta is a flex item of
   the flex-container .pq-row-link, so it's blockified and transform already
   applies without needing an explicit display change. */
.pending-queue-item .pq-cta { flex-shrink: 0; transition: transform .18s cubic-bezier(0.16,1,0.3,1); }
.pending-queue-item .pq-row-link:hover .pq-cta,
.pending-queue-item .pq-row-link:focus-visible .pq-cta { transform: translateX(4px); }
/* Neutral pill matching the existing .role-badge look. Callers can swap in
   .badge-accent for an accent-tinted variant when the count itself is the
   message (admin nav notification chip); .pq-badge here is the calm default. */
.pending-queue-item .pq-badge { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em;
    padding: 3px 8px; border-radius: 999px; background: transparent;
    border: 1px solid rgba(var(--paper-rgb),0.22); color: rgba(var(--paper-rgb),0.78); flex-shrink: 0; }

/* "Recent activity" — a vertical timeline of recent items. Rows are flat (no
   surface) and separated by a hairline divider, the same pattern tables/data
   lists use, so this section reads as a denser list than .pending-queue. */
.recent-activity { list-style: none; padding: 0; margin: 0; }
.recent-activity-item { display: flex; align-items: center; gap: 12px; min-height: 44px;
    padding: 10px 8px; border-bottom: 1px solid rgba(var(--paper-rgb),0.08);
    border-radius: 6px; }
/* No row-level :hover background here — unlike .pending-queue-item, the row
   itself isn't a click target (only .ra-title is, see dashboard.blade.php's
   comment on why these rows have no <a> wrapper). A whole-row hover highlight
   would be a misleading affordance (hover area != click area), so the only
   hover cue is .ra-title:hover's underline below. */
.recent-activity-item:last-child { border-bottom: 0; }
.recent-activity-item .ra-type { color: var(--accent); flex-shrink: 0; }
.recent-activity-item .ra-body { flex: 1; min-width: 0; }
.recent-activity-item .ra-title { font-size: 14px; color: #fff; text-decoration: none; }
.recent-activity-item .ra-title:hover { text-decoration: underline; }
.recent-activity-item .ra-meta { font-size: 12px; color: rgba(var(--paper-rgb),0.5); margin-top: 2px; }
.recent-activity-item .ra-time { font-size: 12px; color: rgba(var(--paper-rgb),0.4); flex-shrink: 0; }

/* Admin-only "system status" footer — a single surface card stacked with key/
   value rows. Borders are hairline (no shadow), label tier is the existing
   uppercase-track label style; value tier borrows .success-text / .danger-text
   for the OK / warn states so the color semantics stay aligned with the rest
   of the app. */
.system-status { display: flex; flex-direction: column; padding: 20px;
    background: rgb(var(--surface-rgb)); border: 1px solid rgba(var(--paper-rgb),0.12); border-radius: 16px; }
.system-status-row { display: flex; justify-content: space-between; gap: 12px; padding: 10px 0;
    border-bottom: 1px solid rgba(var(--paper-rgb),0.08); }
.system-status-row:last-child { border-bottom: 0; }
.system-status-row .ss-label { font-size: 12px; color: rgba(var(--paper-rgb),0.5); text-transform: uppercase; letter-spacing: 0.08em; }
.system-status-row .ss-value { font-size: 13px; color: #fff; font-weight: 600; }
.system-status-row .ss-value.ss-warn { color: var(--danger-text); }
.system-status-row .ss-value.ss-ok { color: var(--success-text); }

/* Inline "What's New" announcement pill — a clickable chip in the accent
   wash, sized to live inside a .section-head or just under a page title. */
.release-chip { display: inline-flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 999px;
    background: rgba(var(--accent-rgb),0.14); border: 1px solid rgba(var(--accent-rgb),0.35); color: #fff;
    font-size: 13px; text-decoration: none; }
.release-chip:hover { background: rgba(var(--accent-rgb),0.22); border-color: rgba(var(--accent-rgb),0.55); }
.release-chip .rc-ico { color: var(--accent); }
.release-chip .rc-meta { color: rgba(var(--paper-rgb),0.6); font-size: 12px; }

/* Lift of dashboard's existing inline-styled onboarding banner. The .flash
   base gives the rounded border + padding; this override supplies the flex
   layout + accent wash so callers can render the same banner as
   `<a class="flash flash-cta">…</a>` and get the same look as the inline-style
   version it's replacing. */
.flash.flash-cta { display: flex; align-items: center; justify-content: space-between; gap: 12px; text-decoration: none;
    background: rgba(var(--accent-rgb),0.14); border: 1px solid rgba(var(--accent-rgb),0.4); color: #ffffff; }
.flash.flash-cta:hover { background: rgba(var(--accent-rgb),0.22); }
/* Arrow-shift micro-interaction: the CTA already renders "Review now →"; nudge
   just the glyph-bearing span a few px on parent hover/focus. .flash-cta-cta is
   a flex item of the flex-container .flash.flash-cta, so it's blockified and
   transform already applies without needing an explicit display change. */
.flash.flash-cta .flash-cta-cta { white-space: nowrap; transition: transform .18s cubic-bezier(0.16,1,0.3,1); }
.flash.flash-cta:hover .flash-cta-cta,
.flash.flash-cta:focus-visible .flash-cta-cta { transform: translateX(4px); }

/* Keyboard focus rings on the dashboard v2's new interactive surfaces. Matches
   the existing `.btn:focus-visible` style at lines 365-368 (don't touch those). */
.release-chip:focus-visible,
.pq-title:focus-visible,
.ra-title:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}
.flash.flash-cta:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Empty state for the queue / activity sections when there's nothing to show.
   Borrows the .empty spacing language (centered, muted) but on a smaller
   scale so it fits inside a single dashboard region rather than a full page. */
.queue-empty { padding: 24px; text-align: center; color: rgba(var(--paper-rgb),0.5); font-size: 13px; }
.queue-empty .big { font-size: 15px; color: #fff; margin-bottom: 6px; font-weight: 600; }

/* ---- Tablet overrides ---- */
@media (max-width: 768px) {
    /* Section heads often get cramped at tablet widths when a long title
       meets a pair of right-aligned actions; stack them vertically. */
    .section-head { flex-direction: column; align-items: flex-start; }
}

/* ---- Phone overrides ---- */
@media (max-width: 640px) {
    .dashboard-section { margin-top: 20px; }
    /* Queue/activity rows can overflow on phones when the title + meta + CTA
       + time all line up horizontally; allow them to wrap onto a second line
       rather than clipping. */
    .pending-queue-item,
    .recent-activity-item { flex-wrap: wrap; }
}

/* ============================================================================
   DASHBOARD v3 — Lighthouse-inspired (mylighthouse.com) motion/depth layer,
   additive on top of v2 above. Nothing here renames/restructures anything
   from v2; it's a new wrapper class, a new keyframe, and a new reveal
   utility class, all opted into from dashboard.blade.php only.
   - .dashboard-glow: static dual radial wash behind the hero, same token
     math as layouts/auth.blade.php's `.login-glow` (rgba(accent,0.1) /
     rgba(accent2,0.07)) — deliberately non-animated, per this app's existing
     "no busy ambient motion" direction (see that file's own comment).
   - @keyframes dashboard-rise + .dashboard-glow > .page-head: the hero's
     one-time fade+rise on load, same timing/easing family as the login
     page's `rise` keyframe (kept as a separate name/rule here — theme.css
     is shared across pages the login page's inline `rise` never reaches).
   - .reveal / .reveal.is-visible: the scroll-reveal utility the
     IntersectionObserver in dashboard.blade.php's @push('scripts') block
     adds/toggles at runtime. The class is only ever added by that script
     (never server-rendered), and that script itself skips adding it at all
     under prefers-reduced-motion or without IntersectionObserver support —
     so there is no code path where an element is left stuck at opacity:0.
   Hover-shadow (a.panel:hover / .pq-row-link:hover) and arrow-shift
   (.pq-cta / .flash-cta-cta) micro-interactions live inline next to the
   rules they extend, further up this file (see DASHBOARD v2's pq-cta/
   flash-cta-cta rules, and the shared a.panel:hover rule near the top).
   ============================================================================ */
.dashboard-glow { position: relative; overflow: hidden; isolation: isolate; }
.dashboard-glow::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(55% 60% at 15% 15%, rgba(var(--accent-rgb), 0.1), transparent 70%),
        radial-gradient(45% 55% at 85% 85%, rgba(var(--accent2-rgb), 0.07), transparent 70%);
}
.dashboard-glow > .page-head {
    position: relative;
    z-index: 1;
    opacity: 0;
    animation: dashboard-rise 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.05s forwards;
}
@keyframes dashboard-rise { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }

.reveal { opacity: 0; transform: translateY(16px); transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); }
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ============================================================================
   AI CHAT BUBBLE — a read-only "here's what the AI found/said" message,
   used in the Reimbursement receipt-review edit row (batches/show.blade.php)
   and the Meetings minutes preview (meetings/show.blade.php). Ported from
   dijiwa-login-dashboard-starter/'s component gallery (built after a design
   gap-check against askernest.ai) — trimmed to only what these two views
   actually use (no .chat-bubble-user / .chat-typing "thinking" state, since
   neither view has a user-reply or async-wait moment to show one for).
   The accent-tinted border (rather than a plain hairline) is deliberate: this
   is one of the few places this app's accent is used as an inline signal
   rather than active/focus/CTA — it marks "this text is AI-authored".
   ============================================================================ */
.chat-thread { display: flex; flex-direction: column; gap: 12px; }
.chat-row { display: flex; }
.chat-bubble { max-width: 100%; padding: 12px 16px; border-radius: 14px; font-size: 13.5px; line-height: 1.55; }
.chat-bubble-ai { background: rgb(var(--surface-rgb)); border: 1px solid rgba(var(--accent-rgb),0.25); color: #fff; border-bottom-left-radius: 4px; }
.chat-highlight { color: var(--accent-soft); font-weight: 600; }
