/* Respect users who ask the OS for less motion: neutralise transitions and
   animations globally rather than per-component. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================================
   Design tokens
   ============================================================ */
:root {
    /* Canvas & surfaces */
    --canvas: #F6F7F9;
    --surface: #FFFFFF;
    --text: #172033;
    --text-secondary: #667085;
    --border: #E4E7EC;

    /* Brand */
    --orange: #F97316;
    --orange-dark: #B54F17;
    --orange-bg: #FFF1E8;
    /* Lighter shade for hovering filled orange buttons -- their label is
       dark text (see --text on --orange contrast note below), so the hover
       feedback lightens rather than darkens to keep text readable. */
    --orange-hover: #FB9143;

    /* Semantic */
    --success: #16A36A;
    --success-bg: #E7F6EF;
    --warning: #F59E0B;
    --warning-bg: #FEF3E2;
    --danger: #DC3545;
    --danger-bg: #FBEAEC;

    /* Darker text-safe variants of the semantic colors above. The base
       colors read well as accents/icons/dots/borders, but at their literal
       values none of them reach 4.5:1 contrast as *text* on a light or white
       background (WCAG AA) -- these do, and are used only for `color:`. */
    --success-text: #0F7A4F;
    --warning-text: #8A5A0A;
    --danger-text: #C42D3C;
    --steel-text: #5B6472;

    /* Mid neutral gray for a chart segment / badge that must read as
       "informational, not a problem" (e.g. service-not-required) and stay
       distinct from the darker --steel used for "missing". */
    --muted: #98A2B3;
    --muted-bg: #F2F4F7;

    /* Extra accents, used only for metric-card icon chips where a 4th/5th
       neutral hue is needed and none of the three semantic colors fit */
    --info: #2E90FA;
    --info-bg: #EAF2FE;
    --violet: #7A5AF8;
    --violet-bg: #F1EDFE;

    /* Sidebar (dark navy chrome) */
    --navy: #101A2E;
    --navy-raised: #16213A;
    --navy-border: #24304A;
    --navy-text: #B9C2D4;
    --navy-text-muted: #7C879D;

    /* Legacy token names: aliased to the new palette so every existing
       component class below keeps working without being individually
       rewritten. New CSS should prefer the tokens above. */
    --ink: var(--text);
    --paper: var(--canvas);
    --paper-raised: var(--surface);
    --green: var(--success);
    --green-bg: var(--success-bg);
    --steel: var(--text-secondary);
    --steel-light: #EEF1F4;
    --steel-border: var(--border);
    --clay: var(--danger);
    --clay-bg: var(--danger-bg);
    --amber: var(--warning);
    --amber-bg: var(--warning-bg);

    /* 8px spacing system */
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-5: 20px;
    --space-6: 24px;
    --space-8: 32px;

    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 12px;
    --control-height: 40px;
    --border-strong: #D6DAE1;
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06);
    --shadow-panel: 0 1px 2px rgba(16, 24, 40, 0.05),
                    0 8px 24px -8px rgba(16, 24, 40, 0.10);
    --shadow-raised: 0 2px 4px rgba(16, 24, 40, 0.06),
                     0 16px 40px -12px rgba(16, 24, 40, 0.14);
    --shadow-md: 0 4px 12px rgba(16, 24, 40, 0.08);
    --sidebar-width: 296px;
    --sidebar-width-collapsed: 76px;
}

/* ============================================================
   Base
   ============================================================ */
* { box-sizing: border-box; }

body {
    font-family: 'Inter', -apple-system, "Segoe UI", Arial, sans-serif;
    margin: 0;
    background: var(--canvas);
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

.mono {
    font-family: 'IBM Plex Mono', 'Courier New', monospace;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
}

a { color: inherit; }

:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

h1 { font-size: 24px; font-weight: 600; margin: 0 0 20px; letter-spacing: -0.01em; }
h2 { font-size: 17px; font-weight: 600; margin: 32px 0 12px; letter-spacing: -0.005em; }
h3 { font-size: 15px; font-weight: 600; margin: 0; }

.icon { flex-shrink: 0; }

.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;
}

/* ============================================================
   Application shell: sidebar + top bar
   ============================================================ */
.app-shell { display: flex; min-height: 100vh; }

.sidebar-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(16, 24, 40, 0.45);
    z-index: 40;
}

.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    background: var(--navy);
    color: var(--navy-text);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    z-index: 50;
    /* margin-right animates in step with width during the hover peek, so
       the sidebar's slot in the page never changes size (see .is-peek). */
    transition: width 0.15s ease, margin-right 0.15s ease;
}

.sidebar-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-3);
    flex-shrink: 0;
}
.sidebar-brand {
    /* Eyebrow over plate: the top of the sidebar names the CLIENT whose
       project this workspace is. */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-decoration: none;
    color: white;
    min-width: 0;
    flex: 1;
}
.sidebar-brand .client-eyebrow { display: block; }
/* Compact logo plate: ~50px internal height, just enough padding to keep
   the wordmark off the plate edges. */
.brand-plate {
    background: #ffffff;
    border-radius: var(--radius-sm);
    padding: 11px 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
}
.brand-plate img { display: block; height: 28px; width: auto; max-width: 100%; object-fit: contain; }
.sidebar-close-btn {
    display: none;
    background: transparent;
    border: none;
    color: var(--navy-text);
    padding: var(--space-1);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.sidebar-close-btn:hover { color: white; background: var(--navy-raised); }

/* The nav is the ONLY part of the sidebar allowed to scroll -- header and
   footer stay put. The scrollbar is thin and navy-toned so it reads as part
   of the dark chrome, and auto so it only appears when the nav overflows. */
.sidebar-nav {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--space-3) var(--space-3);
    display: flex;
    flex-direction: column;
    gap: 2px;
    scrollbar-width: thin;
    scrollbar-color: var(--navy-border) transparent;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.sidebar-nav::-webkit-scrollbar-thumb { background: var(--navy-border); border-radius: 999px; }
.sidebar-nav::-webkit-scrollbar-thumb:hover { background: #33415E; }
.nav-item {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: 9px var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--navy-text);
    text-decoration: none;
    font-size: 15px;
    font-weight: 500;
    white-space: nowrap;
    position: relative;
    min-width: 0;
}
.nav-item .nav-icon { display: flex; }
.nav-item:hover { background: var(--navy-raised); color: white; }
.nav-item.is-active { background: var(--navy-raised); color: white; }
.nav-item.is-active .nav-icon { color: var(--orange); }
.nav-item.is-active::before {
    content: '';
    position: absolute;
    left: -12px;
    top: 6px;
    bottom: 6px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: var(--orange);
}
/* min-width: 0 lets the label shrink inside its flex row; the ellipsis is
   only the fallback for a name the widened sidebar still cannot fit (the
   full name is then surfaced as a tooltip by app-shell.js). */
.nav-label { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Sub-item nested under a primary nav entry (e.g. Deliveries -> Recent arrivals) */
.nav-subitem { padding-left: 28px; font-size: 14px; }
.nav-subitem .nav-icon .icon { width: 16px; height: 16px; }

/* Grouped navigation (Inventory / Operations / Settings) */
.nav-group { display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-2); }
.nav-group > div[role="group"] { display: flex; flex-direction: column; gap: 2px; }
.nav-group-label {
    margin: var(--space-2) var(--space-3) 2px; padding: 0;
    font-size: 11px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--navy-text-muted);
}
/* The United Civil group is headed by the company's logo plate instead of a
   text label -- the same .brand-plate and 28px mark the brand wore at the
   top of the sidebar, so the logo keeps its size in the move down. */
.nav-brand-heading { margin: var(--space-3) var(--space-3) var(--space-2); }
/* Collapsed rail: the group labels would just be noise next to icon-only
   items, so hide them and keep a subtle divider between groups instead. */
.app-shell.is-collapsed .nav-group-label { display: none; }
.app-shell.is-collapsed .nav-group { border-top: 1px solid var(--navy-border); padding-top: var(--space-2); }

/* ---- Expandable nav groups (Stock, Equipment) --------------------------
   One implementation shared by every nested section -- see _nav.html. */
.nav-expandable { display: flex; flex-direction: column; gap: 2px; }
.nav-parent-row { display: flex; align-items: center; gap: 2px; }
.nav-parent-row .nav-parent { flex: 1; min-width: 0; }

.nav-toggle {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 30px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--navy-text-muted);
    border-radius: var(--radius-sm);
    cursor: pointer;
}
.nav-toggle:hover { background: var(--navy-raised); color: white; }
.nav-toggle-icon { display: flex; transition: transform 0.15s ease; }
.nav-expandable.is-open .nav-toggle-icon { transform: rotate(180deg); }

/* The parent stays lit while any child is the current page, so the section
   never reads as unselected from inside it. */
.nav-expandable.is-branch-active > .nav-parent-row > .nav-parent { color: white; }
.nav-expandable.is-branch-active > .nav-parent-row > .nav-parent .nav-icon { color: var(--orange); }

/* Shallow indent on purpose: enough to read as nested, but the width saved
   goes to the room names, which are the longest labels in the sidebar. */
.nav-children {
    list-style: none;
    margin: 2px 0 0;
    padding: 0 0 0 var(--space-2);
    display: none;
    flex-direction: column;
    gap: 2px;
    border-left: 1px solid var(--navy-border);
    margin-left: var(--space-3);
}
.nav-expandable.is-open > .nav-children { display: flex; }
/* Only a heading for the collapsed-rail popover; noise in the full sidebar. */
.nav-children-head { display: none; }

.nav-children .nav-subitem { padding-left: 10px; }
.nav-section-label {
    margin: var(--space-2) 0 2px var(--space-3);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    /* Lighter than --navy-text-muted: at this size the label needs to clear
       4.5:1 on the navy background, which the muted tone just misses. */
    color: #97A3B9;
}
.nav-dot {
    width: 5px; height: 5px; border-radius: 50%;
    background: var(--navy-text-muted); flex-shrink: 0; margin: 0 5px;
}
.nav-item.is-active .nav-dot { background: var(--orange); }

/* Company initials chip, where a per-company icon would be meaningless. */
.nav-initials {
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px;
    border-radius: var(--radius-sm);
    background: var(--navy-border);
    color: var(--navy-text);
    font-size: 9.5px; font-weight: 700; letter-spacing: 0.02em;
}
.nav-item.is-active .nav-initials { background: var(--orange); color: #fff; }

.nav-count-trailing { margin-left: auto; }
.nav-children .nav-count {
    background: var(--navy-border);
    color: var(--navy-text);
    font-weight: 600;
}
.nav-children .nav-item.is-active .nav-count { background: var(--orange); color: #fff; }

/* Collapsed rail: the children become a hover/focus flyout so a pinned room
   or a hire company is still reachable without expanding the sidebar. */
.app-shell.is-collapsed .nav-toggle { display: none; }
.app-shell.is-collapsed .nav-expandable { position: relative; }
.app-shell.is-collapsed .nav-expandable > .nav-children {
    display: none;
    position: absolute;
    left: calc(100% + 8px);
    top: 0;
    min-width: 200px;
    max-height: 70vh;
    overflow-y: auto;
    margin: 0;
    padding: var(--space-2);
    background: var(--navy-raised);
    border: 1px solid var(--navy-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    z-index: 60;
}
.app-shell.is-collapsed .nav-expandable:hover > .nav-children,
.app-shell.is-collapsed .nav-expandable:focus-within > .nav-children { display: flex; }
/* Inside the flyout, labels return to normal flow (undo the sr-only clip). */
.app-shell.is-collapsed .nav-expandable > .nav-children .nav-label {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    clip: auto;
    overflow: hidden;
}
.app-shell.is-collapsed .nav-children .nav-item { justify-content: flex-start; }
.app-shell.is-collapsed .nav-children-head {
    display: block;
    padding: 4px var(--space-3) var(--space-2);
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--navy-text-muted);
}
/* The parent's own tooltip would collide with the flyout. */
.app-shell.is-collapsed .nav-expandable .nav-parent[data-tooltip]:hover::after,
.app-shell.is-collapsed .nav-expandable .nav-parent[data-tooltip]:focus-visible::after { content: none; }

/* Fixed footer region: client identity + the collapse control. Never
   scrolls -- only .sidebar-nav above it does. */
.sidebar-footer { flex-shrink: 0; }
.sidebar-bottom {
    flex-shrink: 0;
    padding: var(--space-3);
    border-top: 1px solid var(--navy-border);
}
.sidebar-collapse-btn {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: 100%;
    padding: 9px var(--space-3);
    border-radius: var(--radius-sm);
    border: none;
    background: transparent;
    color: var(--navy-text-muted);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
}
.sidebar-collapse-btn:hover { background: var(--navy-raised); color: white; }

/* The client identity lives in .sidebar-top now (eyebrow + brand plate);
   only the eyebrow style and the collapsed-rail chip remain from the old
   footer block. */
.client-eyebrow {
    margin: 0 0 var(--space-2);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--navy-text-muted);
}
/* Collapsed-rail client chip; hidden whenever the full plate is shown. */
.client-mini {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin: 0 auto;
    background: var(--navy-raised);
    border: 1px solid var(--navy-border);
    border-radius: var(--radius-sm);
    color: var(--navy-text);
    position: relative;
}

/* Collapsed (desktop/tablet icon-only) state.

   Labels are visually clipped (sr-only style), NOT display:none: the links
   keep their accessible names for screen readers even though sighted users
   only see icons + tooltips. */
.app-shell.is-collapsed .sidebar { width: var(--sidebar-width-collapsed); }
.app-shell.is-collapsed .sidebar .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
}
.app-shell.is-collapsed .nav-item { justify-content: center; }
.app-shell.is-collapsed .nav-item.is-active::before { left: -12px; }
/* The rail still marks the section you are in, even with its children
   hidden: the parent keeps the raised plate and orange icon. */
.app-shell.is-collapsed .nav-expandable.is-branch-active > .nav-parent-row > .nav-parent {
    background: var(--navy-raised);
}
.app-shell.is-collapsed .sidebar-collapse-btn { justify-content: center; }
.app-shell.is-collapsed .sidebar-collapse-btn .icon { transform: rotate(180deg); }
.app-shell.is-collapsed .sidebar-top { justify-content: center; padding: var(--space-3) var(--space-2); }
/* The rail keeps only the client chip up top; both logo plates (the client's
   at the top, United Civil's heading its group) wait for the expanded view. */
.app-shell.is-collapsed .sidebar-brand,
.app-shell.is-collapsed .nav-brand-heading { display: none; }
.app-shell.is-collapsed .client-mini { display: flex; }

/* Collapsed tooltips: every icon-only control in the rail (nav items, the
   client chip, the expand button) names itself on hover/focus. */
.app-shell.is-collapsed .sidebar [data-tooltip] { position: relative; }
.app-shell.is-collapsed .sidebar [data-tooltip]:hover::after,
.app-shell.is-collapsed .sidebar [data-tooltip]:focus-visible::after {
    content: attr(data-tooltip);
    position: absolute;
    left: calc(100% + 10px);
    top: 50%;
    transform: translateY(-50%);
    background: var(--ink);
    color: white;
    font-size: 12px;
    font-weight: 500;
    padding: 5px 9px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
    z-index: 60;
    pointer-events: none;
    box-shadow: var(--shadow-md);
}

/* Hover peek. While the pointer rests on the collapsed rail, app-shell.js
   swaps is-collapsed for is-peek: every expanded style simply returns, and
   this rule widens the sidebar while the negative margin keeps its slot in
   the page at rail width -- the sidebar expands OVER the content (it sits
   at z-index 50, above the topbar's 30), and nothing on the page moves.
   Width and margin animate together, so the slot stays put mid-transition
   too. Letting go of the rail hands the classes back. */
.app-shell.is-peek .sidebar {
    width: var(--sidebar-width);
    margin-right: calc(var(--sidebar-width-collapsed) - var(--sidebar-width));
    box-shadow: 24px 0 48px -16px rgba(6, 18, 36, 0.5);
}

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

.topbar {
    height: 64px;
    flex-shrink: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: 0 var(--space-6);
    position: sticky;
    top: 0;
    z-index: 30;
}
.topbar-menu-btn {
    display: none;
    background: transparent;
    border: none;
    color: var(--text);
    padding: var(--space-1);
    cursor: pointer;
    border-radius: var(--radius-sm);
}
.topbar-search {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    background: var(--canvas);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    height: 38px;
    padding: 0 var(--space-3);
    width: 100%;
    max-width: 420px;
    color: var(--text-secondary);
}
.topbar-search-icon { display: flex; flex-shrink: 0; }
.topbar-search input {
    border: none;
    background: transparent;
    outline: none;
    font-size: 14px;
    font-family: inherit;
    color: var(--text);
    width: 100%;
}
.topbar-search input::placeholder { color: var(--text-secondary); }
.topbar-search input:disabled { cursor: not-allowed; }
.topbar-search { min-width: 0; }
.topbar-search-kbd {
    font-family: 'IBM Plex Mono', monospace;
    font-size: 11px;
    color: var(--text-secondary);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 1px 6px;
    flex-shrink: 0;
}
.topbar-spacer { flex: 1; }
.topbar-icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    border: none;
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
    flex-shrink: 0;
}
.topbar-icon-btn:hover:not(:disabled) { background: var(--canvas); color: var(--text); }
.topbar-icon-btn:disabled { cursor: not-allowed; opacity: 0.55; }
.topbar-weather {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 13px;
    color: var(--text-secondary);
    white-space: nowrap;
    flex-shrink: 0;
}

.topbar-profile { position: relative; flex-shrink: 0; }
.topbar-profile-btn {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    background: transparent;
    border: none;
    padding: var(--space-1) var(--space-2) var(--space-1) var(--space-1);
    border-radius: var(--radius);
    cursor: pointer;
    color: var(--text);
}
.topbar-profile-btn:hover { background: var(--canvas); }
.topbar-profile-name { font-size: 14px; font-weight: 500; white-space: nowrap; }
.avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--orange-bg);
    color: var(--orange-dark);
    font-size: 12px;
    font-weight: 700;
    flex-shrink: 0;
}

.dropdown-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    min-width: 180px;
    padding: var(--space-1);
    z-index: 45;
}
.dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    padding: var(--space-2) var(--space-2);
    border-radius: var(--radius-sm);
    border: none;
    background: transparent;
    font-size: 14px;
    font-family: inherit;
    color: var(--text);
    text-decoration: none;
    cursor: pointer;
    text-align: left;
}
.dropdown-item:hover { background: var(--canvas); }
.dropdown-item.danger { color: var(--danger-text); }

/* ============================================================
   Modal
   ============================================================ */
body.modal-open { overflow: hidden; }
/* Set while the mobile nav drawer is open, so the page cannot scroll
   underneath it. */
body.drawer-locked { overflow: hidden; }
.modal { position: fixed; inset: 0; z-index: 100; }
.modal-backdrop { position: absolute; inset: 0; background: rgba(16, 24, 40, 0.45); }
.modal-panel {
    position: relative;
    max-width: 560px;
    width: calc(100% - var(--space-6));
    max-height: calc(100vh - var(--space-8));
    margin: var(--space-8) auto 0;
    background: var(--surface);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}
.modal-header h2 { margin: 0; font-size: 16px; }
.modal-body { padding: var(--space-5); overflow-y: auto; }
.modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-5);
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}

.content {
    max-width: 1360px;
    width: 100%;
    margin: 0 auto;
    padding: var(--space-8) var(--space-6);
}

/* Progressively shed non-essential top bar items before anything overflows */
@media (max-width: 1100px) {
    .topbar-weather { display: none; }
}
@media (max-width: 860px) {
    .topbar-profile-name { display: none; }
}

/* Mobile drawer + hamburger */
@media (max-width: 767px) {
    .topbar-menu-btn { display: inline-flex; align-items: center; justify-content: center; }
    .topbar-search { display: none; }
    .sidebar-close-btn { display: inline-flex; }
    /* Never wider than the viewport allows: full hierarchy at 360px, and
       still room to reach the backdrop at 320px. */
    .sidebar {
        position: fixed;
        left: 0;
        top: 0;
        width: min(300px, 85vw) !important;
        transform: translateX(-100%);
    }
    .app-shell.drawer-open .sidebar { transform: translateX(0); }
    .app-shell.drawer-open .sidebar-backdrop { display: block; }
    /* The drawer always renders the EXPANDED layout, whatever the stored
       desktop preference: restore the plates, unclip the labels, and put
       the collapsed-rail client chip away. */
    .app-shell.is-collapsed .sidebar-brand { display: flex; }
    .app-shell.is-collapsed .nav-brand-heading { display: block; }
    .app-shell.is-collapsed .client-eyebrow { display: block; }
    .app-shell.is-collapsed .client-mini { display: none; }
    .app-shell.is-collapsed .sidebar-top { justify-content: space-between; padding: var(--space-3); }
    .app-shell.is-collapsed .sidebar .nav-label {
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        clip: auto;
        overflow: hidden;
    }
    .app-shell.is-collapsed .nav-expandable.is-branch-active > .nav-parent-row > .nav-parent {
        background: transparent;
    }
    /* Touch has no hover and the labels are visible anyway. */
    .app-shell .sidebar [data-tooltip]::after { content: none !important; }
    /* In the mobile drawer, group labels return and dividers are dropped. */
    .app-shell.is-collapsed .nav-group-label { display: block; }
    .app-shell.is-collapsed .nav-group { border-top: none; padding-top: 0; }
    /* The drawer is full-width, so nested items expand inline as usual --
       undo the collapsed rail's flyout treatment entirely. */
    .app-shell.is-collapsed .nav-toggle { display: inline-flex; }
    .app-shell.is-collapsed .nav-expandable > .nav-children {
        position: static; min-width: 0; max-height: none;
        margin: 2px 0 0 var(--space-4); padding: 0 0 0 var(--space-3);
        background: transparent; border: none;
        border-left: 1px solid var(--navy-border);
        border-radius: 0; box-shadow: none; display: none;
    }
    .app-shell.is-collapsed .nav-expandable.is-open > .nav-children { display: flex; }
    .app-shell.is-collapsed .nav-expandable:hover > .nav-children { display: none; }
    .app-shell.is-collapsed .nav-expandable.is-open:hover > .nav-children { display: flex; }
    .app-shell.is-collapsed .nav-children-head { display: none; }
    .app-shell.is-collapsed .nav-item { justify-content: flex-start; }
    .content { padding: var(--space-5) var(--space-4); }
}

/* ============================================================
   Cards / grids (shared)
   ============================================================ */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--space-4);
    margin-bottom: var(--space-3);
}
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-4) var(--space-5);
}
.card-link { text-decoration: none; color: inherit; transition: border-color .15s, box-shadow .15s; }
.card-link:hover { border-left-color: var(--orange); box-shadow: var(--shadow-sm); }
.card-label { font-size: 13px; color: var(--text-secondary); margin-bottom: 6px; }
.card-value { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; }
.card-hint { font-size: 13px; color: var(--orange-dark); margin-top: 4px; }
.card-danger { border-left-color: var(--danger); }
.card-danger .card-value { color: var(--danger-text); }
.card-warning { border-left-color: var(--warning); }
.card-warning .card-value { color: var(--warning-text); }

/* ============================================================
   Tables
   ============================================================ */
table.data-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border-radius: var(--radius);
    border: 1px solid var(--border);
}
.data-table thead tr:first-child th:first-child { border-top-left-radius: var(--radius); }
.data-table thead tr:first-child th:last-child { border-top-right-radius: var(--radius); }
.data-table tbody tr:last-child td:first-child { border-bottom-left-radius: var(--radius); }
.data-table tbody tr:last-child td:last-child { border-bottom-right-radius: var(--radius); }
.data-table th {
    text-align: left;
    background: var(--canvas);
    padding: 10px 14px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.data-table td {
    padding: 9px 14px;
    font-size: 14px;
    border-top: 1px solid var(--steel-light);
}
.data-table--compact th,
.data-table--compact td { padding: 8px 12px; font-size: 13px; }
.row-muted { opacity: 0.45; }
.row-needs-review { background: var(--warning-bg); }

/* Clickable rows (open their edit view directly) */
tr[data-rowlink] { cursor: pointer; }
tr[data-rowlink]:hover td { background: var(--orange-bg); }
tr[data-rowlink]:focus-visible {
    outline: 2px solid var(--orange);
    outline-offset: -2px;
}

.pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-4); flex-wrap: wrap; }
.pagination-status { font-size: 13px; color: var(--text-secondary); }
.pagination:has(.pagination-left) .pagination-status { flex: 1; text-align: center; }

.table-scroll { overflow-x: auto; }
.actions-cell { text-align: right; white-space: nowrap; }
/* Right-aligned numeric columns (hours, counts) - the general twin of the
   fit-out report's .fo-num. */
.data-table th.num, .data-table td.num { text-align: right; }
.actions-cell .menu-wrap { display: inline-block; }
/* Tick column (Stock issues): just wide enough for the box, so the columns
   that carry the reading — code, item, quantity — keep their room. */
.data-table th.cell-check, .data-table td.cell-check {
    width: 32px;
    padding-right: 0;
    text-align: center;
}
.data-table .cell-check input[type="checkbox"] {
    width: 15px;
    height: 15px;
    margin: 0;
    cursor: pointer;
    accent-color: var(--orange);
}
/* A ticked line has to stand out from a merely hovered one — they share the
   tint (see tr[data-rowlink]:hover above), so the picked row gets a bar down
   its edge as well. */
.data-table tbody tr:has(.cell-check input:checked) td { background: var(--orange-bg); }
.data-table tbody tr:has(.cell-check input:checked) td:first-child {
    box-shadow: inset 3px 0 0 var(--orange);
}
.result-count { font-size: 13px; color: var(--text-secondary); margin-bottom: var(--space-3); }

/* Equipment table: fixed column widths on desktop, card layout below 640px */
.equipment-table col.col-plant { width: 14%; }
.equipment-table col.col-type { width: 28%; }
.equipment-table col.col-vendor { width: 16%; }
.equipment-table col.col-status { width: 14%; }
.equipment-table col.col-due { width: 16%; }
.equipment-table col.col-actions { width: 12%; }
@media (max-width: 640px) {
    .equipment-table thead { display: none; }
    .equipment-table, .equipment-table tbody, .equipment-table tr, .equipment-table td { display: block; width: 100%; }
    .equipment-table { border: none; background: transparent; }
    .equipment-table tr {
        border: 1px solid var(--border);
        border-radius: var(--radius);
        margin-bottom: var(--space-3);
        padding: var(--space-3) var(--space-4);
        background: var(--surface);
    }
    .equipment-table td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: var(--space-3);
        padding: 6px 0;
        border-top: none;
        border-bottom: 1px solid var(--steel-light);
        font-size: 13px;
    }
    .equipment-table tr td:last-child { border-bottom: none; }
    .equipment-table td::before {
        content: attr(data-label);
        font-weight: 600;
        color: var(--text-secondary);
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        flex-shrink: 0;
    }
    .actions-cell { text-align: left; }
}

/* Room inventory rows become cards on phones: same data-label pattern as
   the equipment table, with the two-line cells kept intact. */
@media (max-width: 640px) {
    .stock-table thead { display: none; }
    .stock-table, .stock-table tbody, .stock-table tr, .stock-table td { display: block; width: 100%; }
    .stock-table { border: none; background: transparent; }
    .stock-table tbody tr {
        border: 1px solid var(--border);
        border-radius: var(--radius);
        margin-bottom: var(--space-3);
        padding: var(--space-3) var(--space-4);
        background: var(--surface);
    }
    .stock-table td {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        gap: var(--space-3);
        padding: 6px 0;
        border-top: none;
        border-bottom: 1px solid var(--steel-light);
        font-size: 13px;
    }
    .stock-table tr td:last-child { border-bottom: none; }
    .stock-table td::before {
        content: attr(data-label);
        font-weight: 600;
        color: var(--text-secondary);
        font-size: 11px;
        text-transform: uppercase;
        letter-spacing: 0.03em;
        flex-shrink: 0;
        padding-top: 2px;
    }
    /* Category returns on cards — vertical space is cheap there. */
    .stock-table .cell-category { display: flex; }
    .stock-table .cell-qty { text-align: right; }
    .stock-table .cell-item, .stock-table .cell-qty,
    .stock-table .cell-location { min-width: 0; }
    .item-spec { white-space: normal; }
    .stock-table tbody tr:hover td { background: inherit; }
    /* The expanded details row reads as a footnote card. */
    .stock-details-row { border-style: dashed; }
    .stock-details-row td { background: transparent; }
    .stock-table .actions-cell { justify-content: flex-end; }
    .stock-table .actions-cell::before { content: none; }
}

/* ============================================================
   Equipment page: full-width table + toolbar
   The hire-companies list moved into the sidebar, so the table now gets
   the whole content width.
   ============================================================ */
.equipment-layout { display: block; }
.equipment-main { min-width: 0; }

/* Toolbar: search grows, the rest sit at their natural width, and the
   column selector + result count are pushed to the trailing edge. */
.equipment-toolbar #equipment-search-input { flex: 1 1 240px; min-width: 200px; }
.equipment-toolbar .toolbar-columns { margin-left: auto; }
.equipment-toolbar .toolbar-count {
    font-size: 13px; color: var(--text-secondary);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.column-option { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; }
.column-option input { margin: 0; }

@media (max-width: 767px) {
    .equipment-toolbar .toolbar-columns { margin-left: 0; }
}

/* Sticky table header for long equipment lists */
.equipment-table--sticky thead th {
    position: sticky; top: 0; z-index: 2;
    background: var(--surface);
    box-shadow: inset 0 -1px 0 var(--border);
}
.plant-link { color: var(--text); font-weight: 600; text-decoration: none; }
.plant-link:hover { color: var(--orange-dark); text-decoration: underline; }
.cell-note { display: block; font-size: 11px; color: var(--text-secondary); font-weight: 400; }
#equipment-results[aria-busy="true"] { opacity: 0.55; transition: opacity 0.15s; }

.pagination-left, .pagination-right { display: flex; align-items: center; gap: var(--space-2); }
.rows-label { font-size: 13px; color: var(--text-secondary); }
.rows-select {
    height: 34px; border: 1px solid var(--border); border-radius: var(--radius-sm);
    padding: 0 var(--space-2); font-size: 13px; background: var(--surface);
}


/* ============================================================
   Badges
   ============================================================ */
.badge {
    display: inline-block;
    padding: 3px 9px 3px 7px;
    border-left: 3px solid var(--steel);
    background: var(--steel-light);
    color: var(--ink);
    font-size: 12px;
    font-weight: 500;
    border-radius: 2px;
    white-space: nowrap;
}
.badge-on_site { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-in_transit { border-left-color: var(--info); background: var(--info-bg); color: var(--info); }
.badge-awaiting_pickup { border-left-color: var(--orange); background: var(--orange-bg); color: var(--orange-dark); }
.badge-off_hired { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel); }
.badge-full { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-partial { border-left-color: var(--warning); background: var(--warning-bg); color: var(--warning-text); }
.badge-transferred_out { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel-text); }
.badge-service-ok { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-service-due-soon,
.badge-service-due_soon { border-left-color: var(--warning); background: var(--warning-bg); color: var(--warning-text); }
.badge-service-overdue { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger-text); }
/* Missing service info: a neutral *warning* (needs data), visually distinct
   from an urgent red overdue and from a calm "not required". */
.badge-service-missing,
.badge-service-no_date { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel-text); }
/* Service not required / archived: calm, low-emphasis grays -- never read as
   a problem. */
.badge-service-not-required { border-left-color: var(--muted); background: var(--muted-bg); color: var(--steel-text); }
.badge-archived { border-left-color: var(--muted); background: var(--muted-bg); color: var(--steel-text); }

.badge-delivery-pending { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel); }
.badge-delivery-arrived { border-left-color: var(--warning); background: var(--warning-bg); color: var(--warning-text); }
.badge-delivery-checked_in { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-delivery-partial { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger-text); }
.badge-delivery-pending_approval { border-left-color: var(--orange); background: var(--orange-bg); color: var(--orange-dark); }
.badge-delivery-cancelled { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel); text-decoration: line-through; }
.badge-delivery-late { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger-text); margin-left: 4px; }

.badge-scan-exact { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-scan-alias { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-scan-fuzzy { border-left-color: var(--warning); background: var(--warning-bg); color: var(--warning-text); }
.badge-scan-none { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger-text); }

.badge-role-admin { border-left-color: var(--orange); background: var(--orange-bg); color: var(--orange-dark); }
.badge-role-staff { border-left-color: var(--info); background: var(--info-bg); color: var(--info); }
.badge-role-viewer { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel-text); }

/* Asset register statuses. Unaccounted is the loud one; off-hired/unknown
   stay calm grays so the list reads at a glance. */
.badge-asset-in-store { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-asset-on-site { border-left-color: var(--info); background: var(--info-bg); color: var(--info); }
.badge-asset-unaccounted { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger-text); }
.badge-asset-off-hired { border-left-color: var(--steel); background: var(--steel-light); color: var(--steel-text); }
.badge-asset-faulty { border-left-color: var(--warning); background: var(--warning-bg); color: var(--warning-text); }
.badge-asset-calibration { border-left-color: var(--violet); background: var(--violet-bg); color: var(--violet); }
.badge-asset-unknown { border-left-color: var(--muted); background: var(--muted-bg); color: var(--steel-text); }

.text-overdue { color: var(--danger-text); font-weight: 500; }
.text-due-soon { color: var(--warning-text); font-weight: 500; }

.nav-count {
    display: inline-block;
    background: var(--orange);
    color: #fff;
    border-radius: 999px;
    font-size: 11px;
    line-height: 1.6;
    padding: 1px 7px;
    margin-left: 4px;
}

/* ============================================================
   Filters / tabs / search
   ============================================================ */
.filter-bar { margin-bottom: var(--space-3); display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.filter-bar select {
    height: var(--control-height);
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 14px;
    font-family: inherit;
    background: var(--surface);
    color: var(--text);
    flex: 0 1 auto;
    width: auto;
}
.filter-bar input[type="text"] {
    height: var(--control-height);
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 14px;
    font-family: inherit;
    background: var(--surface);
    color: var(--text);
    flex: 1 1 280px;
    min-width: 160px;
}
.filter-bar .btn-secondary { flex-shrink: 0; }
.filter-bar .back-link { display: inline-flex; align-items: center; height: var(--control-height); flex-shrink: 0; }
/* Tabs wrap onto a second line on narrow screens instead of showing the
   browser's horizontal scrollbar/scroll-arrows (which read as broken UI). */
.tab-bar { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: var(--space-5); border-bottom: 1px solid var(--border); }
.search-bar {
    display: flex;
    gap: var(--space-2);
    align-items: center;
    margin-bottom: var(--space-4);
    flex-wrap: wrap;
}
.search-bar input[type="text"], .search-bar input[type="date"] {
    height: var(--control-height);
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 14px;
    font-family: inherit;
    background: var(--surface);
    color: var(--text);
}
.search-bar input[type="text"] { min-width: 220px; flex: 1; }
.sort-link { color: inherit; text-decoration: none; cursor: pointer; }
.sort-link:hover { color: var(--orange-dark); }
.tab {
    padding: 9px 16px;
    font-size: 14px;
    text-decoration: none;
    color: var(--text-secondary);
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    white-space: nowrap;
}
.tab-active { color: var(--orange-dark); border-bottom-color: var(--orange); font-weight: 600; }
.tab-count {
    display: inline-block; margin-left: 5px; font-size: 12px;
    font-variant-numeric: tabular-nums; color: var(--text-secondary);
    background: var(--steel-light); padding: 0 7px; border-radius: 20px; line-height: 18px;
}
.tab-active .tab-count { background: var(--orange-bg); color: var(--orange-dark); }
.tab-count-danger { background: var(--danger-bg); color: var(--danger-text); }

/* Data-quality filter chips (stock room) */
.quality-chips { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin: 0 0 var(--space-3); font-size: 13px; }
.quality-chips-label { color: var(--text-secondary); font-weight: 600; }
.quality-chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px;
    border: 1px solid var(--border); border-radius: 20px; background: var(--surface);
    color: var(--text); text-decoration: none; font-size: 12px;
}
.quality-chip:hover { border-color: var(--text-secondary); }
.quality-chip.is-active { background: var(--warning-bg); border-color: var(--warning); color: var(--warning-text); font-weight: 600; }
.quality-chip-n { font-variant-numeric: tabular-nums; background: var(--steel-light); border-radius: 20px; padding: 0 7px; font-size: 11px; }
.quality-chip.is-active .quality-chip-n { background: var(--surface); }
.back-link { font-size: 13px; color: var(--orange-dark); text-decoration: none; }

/* Per-user permission checkboxes on the Manage users screens. One row per
   area, with its View/Edit boxes lined up so the grid can be read down a
   column as well as across. */
.perm-grid { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-3) var(--space-4) var(--space-4); margin: var(--space-4) 0 0; }
.perm-grid legend { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-secondary); padding: 0 6px; }
.perm-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); padding: 9px 0; border-bottom: 1px solid var(--steel-light); }
.perm-row:last-of-type { border-bottom: 0; }
.perm-area { font-size: 14px; font-weight: 500; }
.perm-boxes { display: flex; gap: var(--space-4); }
.perm-box { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); cursor: pointer; min-width: 62px; }
.perm-box input { accent-color: var(--orange); width: 15px; height: 15px; cursor: pointer; }
.perm-box input:disabled { cursor: not-allowed; opacity: 0.55; }
.perm-box input:disabled + span, .perm-box:has(input:disabled) { color: var(--text-secondary); cursor: not-allowed; }
.field-hint { font-size: 12px; color: var(--text-secondary); margin: 6px 0 0; }


/* Stock-group buttons on the room page. Same pill shape as the data-quality
   chips above, but the active state uses the app's primary orange because
   this is a normal navigation filter, not a warning about the data. */
.group-chips { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; margin: 0 0 var(--space-3); font-size: 13px; }
.group-chips-label { color: var(--text-secondary); font-weight: 600; }
.group-chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px;
    border: 1px solid var(--border); border-radius: 20px; background: var(--surface);
    color: var(--text); text-decoration: none; font-size: 13px;
}
.group-chip:hover { border-color: var(--text-secondary); }
.group-chip.is-active { background: var(--orange-bg); border-color: var(--orange); color: var(--orange-dark); font-weight: 600; }
.group-chip-n { font-variant-numeric: tabular-nums; background: var(--steel-light); border-radius: 20px; padding: 0 7px; font-size: 11px; }
.group-chip.is-active .group-chip-n { background: var(--surface); }

/* Compact summary strip: category shortcuts on a single scrollable row, so
   the table below stays the page's main visual element. Replaces the large
   tile grid; the per-category colours are unchanged. Drums stay collapsed
   behind these until a category is picked, so drum-heavy rooms don't bury
   their other stock. */
.summary-strip {
    display: flex; align-items: center; gap: var(--space-3);
    margin: 0 0 var(--space-3); min-width: 0;
}
.summary-strip-label {
    display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
    font-size: 12px; font-weight: 600; color: var(--text-secondary);
}
.summary-strip-items {
    display: flex; gap: var(--space-2); overflow-x: auto;
    padding-bottom: 2px; min-width: 0;
}
.summary-chip {
    display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
    padding: 5px 10px; border: 1px solid var(--border); border-radius: 20px;
    background: var(--surface); color: var(--text); text-decoration: none; font-size: 12.5px;
}
.summary-chip:hover { border-color: var(--text-secondary); text-decoration: none; }
.summary-chip-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex-shrink: 0; }
.summary-chip-name { font-weight: 600; white-space: nowrap; }
.summary-chip-value { font-variant-numeric: tabular-nums; font-weight: 700; }
.summary-chip-meta { font-size: 11px; color: var(--text-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.summary-chip.is-active { font-weight: 600; }
.drum-tile--all .summary-chip-dot { background: var(--text-secondary); }
.drum-tile--all.is-active { border-color: var(--text-secondary); background: var(--muted-bg); }
.drum-tile--11kv .summary-chip-dot { background: var(--info); }
.drum-tile--11kv.is-active { border-color: var(--info); background: var(--info-bg); }
.drum-tile--power .summary-chip-dot { background: var(--orange); }
.drum-tile--power.is-active { border-color: var(--orange); background: var(--orange-bg); }
.drum-tile--white .summary-chip-dot { background: var(--muted); border: 1px solid var(--border); }
.drum-tile--white.is-active { border-color: var(--muted); background: var(--muted-bg); }
.drum-tile--earth .summary-chip-dot { background: var(--success); }
.drum-tile--earth.is-active { border-color: var(--success); background: var(--success-bg); }
.drum-tile--fire .summary-chip-dot { background: var(--danger); }
.drum-tile--fire.is-active { border-color: var(--danger); background: var(--danger-bg); }
.drum-tile--uncat .summary-chip-dot { background: var(--warning); }
.drum-tile--uncat.is-active { border-color: var(--warning); background: var(--warning-bg); }

/* Room landing sections: one prominent button per kind of material the room
   holds (Cable Drums / Containment / Ladders). First-level navigation - the
   drum category chips above only appear once Cable Drums is opened. */
.room-sections {
    display: flex; flex-wrap: wrap; gap: var(--space-3);
    margin: 0 0 var(--space-4);
}
.room-section-btn {
    display: inline-flex; align-items: center; gap: 10px;
    flex: 1 1 180px; max-width: 300px; min-width: 0;
    padding: 12px 16px; border: 1px solid var(--border); border-radius: 10px;
    background: var(--surface); color: var(--text); text-decoration: none;
}
.room-section-btn:hover { border-color: var(--orange); text-decoration: none; }
.room-section-btn.is-active { border-color: var(--orange); background: var(--orange-bg); }
.room-section-btn.is-active .room-section-icon { color: var(--orange-dark); }
.room-section-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 8px; flex-shrink: 0;
    background: var(--muted-bg); color: var(--text-secondary);
}
.room-section-btn.is-active .room-section-icon { background: var(--surface); }
.room-section-text { display: flex; flex-direction: column; min-width: 0; }
.room-section-label { font-weight: 700; font-size: 14px; white-space: nowrap; }
.room-section-meta {
    font-size: 12px; color: var(--text-secondary);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Asset register category tiles: same idea as the cable drum tiles, but one
   tile per category with a headline count. */
.asset-tiles-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(172px, 1fr)); gap: 10px; margin-top: 16px; }
.asset-tile {
    display: block; background: var(--surface); border: 1px solid var(--border);
    border-radius: 8px; padding: 12px 14px; color: var(--ink);
}
.asset-tile:hover { border-color: var(--text-secondary); text-decoration: none; }
.asset-tile--all { border-color: var(--orange); }
.asset-tile--all:hover { background: var(--orange-bg); }
.asset-tile-name { display: block; font-weight: 600; font-size: 13.5px; }
.asset-tile-count { display: block; font-size: 22px; font-weight: 600; margin-top: 2px; font-variant-numeric: tabular-nums; }
.asset-tile-sub { display: block; font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.asset-tile-warn { display: block; font-size: 11.5px; color: var(--warning-text); margin-top: 4px; }
.asset-tile-warn .icon { vertical-align: -2px; }

.drum-view-bar {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
    flex-wrap: wrap; font-size: 13px; color: var(--text-secondary);
    margin: 0 0 var(--space-3);
}

.empty-state { color: var(--text-secondary); font-size: 14px; }

.breadcrumb { display: flex; align-items: center; gap: 6px; font-size: 13px; margin-bottom: var(--space-3); flex-wrap: wrap; }
.breadcrumb-link { color: var(--text-secondary); text-decoration: none; }
.breadcrumb-link:hover { color: var(--orange-dark); }
.breadcrumb-sep { color: var(--text-secondary); opacity: 0.5; }
.breadcrumb-current { color: var(--text); font-weight: 500; }

.empty-state-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-6) var(--space-4);
    color: var(--text-secondary);
    text-align: center;
}
.empty-state-block .icon { color: var(--success-text); }
.empty-state-block p { margin: 0; font-size: 13px; }

.page-header { display: flex; justify-content: space-between; align-items: center; gap: var(--space-4); margin-bottom: var(--space-4); flex-wrap: wrap; }
.page-header h1 { margin-bottom: 0; }
.page-header-actions { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.subtitle { color: var(--text-secondary); font-size: 14px; margin: var(--space-2) 0 var(--space-4); }

/* ============================================================
   Buttons
   ============================================================ */
.btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--control-height);
    padding: 0 var(--space-4);
    border: none;
    border-radius: var(--radius-sm);
    background: var(--orange);
    color: var(--text);
    font-size: 14px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
    text-decoration: none;
    box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--orange-hover); }
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }

.btn-secondary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: var(--control-height);
    padding: 0 var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    color: var(--text);
    text-decoration: none;
}
.btn-secondary:hover { border-color: var(--text-secondary); }
.btn-secondary:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-danger {
    display: inline-flex; align-items: center; gap: 6px;
    height: var(--control-height); padding: 0 var(--space-4);
    border: 1px solid var(--danger); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--danger-text);
    font-size: 14px; font-weight: 500; font-family: inherit; cursor: pointer; text-decoration: none;
}
.btn-danger:hover { background: var(--danger-bg); }

/* Danger zone: keeps destructive/irreversible actions visually separated
   from everyday form controls. */
.danger-zone {
    margin-top: var(--space-8);
    padding: var(--space-4) var(--space-5);
    border: 1px solid var(--danger-bg);
    border-left: 3px solid var(--danger);
    border-radius: var(--radius);
    background: var(--surface);
    max-width: 640px;
}
.danger-zone h2 { margin-top: 0; color: var(--danger-text); font-size: 15px; }

.field-hint { font-size: 12px; color: var(--text-secondary); margin: 4px 0 0; max-width: 60ch; }
.calendar-sync-card {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-lg); padding: var(--space-4) var(--space-5);
    margin-bottom: var(--space-5); max-width: 720px;
}
.calendar-sync-label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.calendar-sync-url { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
.calendar-sync-url input[type="text"] {
    flex: 1; min-width: 220px; height: var(--control-height); padding: 0 var(--space-3);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font-size: 13px; font-family: 'IBM Plex Mono', monospace; background: var(--canvas); color: var(--text);
}
.calendar-sync-manage { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-top: var(--space-3); }

/* Recent arrivals: aggregated product rows with expandable detail */
.arrival-group-parent { cursor: pointer; }
.arrival-group-parent:hover td { background: var(--orange-bg); }
.arrival-group-parent:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
.arrival-caret { display: inline-flex; vertical-align: middle; margin-right: 4px; color: var(--text-secondary); transition: transform 0.15s; }
.arrival-group-parent.is-open .arrival-caret { transform: rotate(90deg); }
.arrival-lines-note { margin-left: 6px; font-size: 11px; color: var(--text-secondary); background: var(--steel-light); padding: 1px 7px; border-radius: 20px; }
.arrival-barcode { font-size: 11px; color: var(--text-secondary); }
.arrival-qty { color: var(--success-text); font-weight: 600; }
.arrival-length { color: var(--text-secondary); font-weight: 400; }
.arrival-detail > td { background: var(--canvas); padding: 0 var(--space-4) var(--space-2); }
.arrival-detail-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.arrival-detail-table th { text-align: left; color: var(--text-secondary); font-weight: 600; padding: 6px 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; }
.arrival-detail-table td { padding: 4px 8px; border-top: 1px solid var(--border); }
@media (prefers-reduced-motion: reduce) { .arrival-caret { transition: none; } }

/* ============================================================
   New products: newly catalogued items still needing their details.
   A list of whole-row links rather than a table -- the row is one
   destination, and every column of a table would have been a
   fragment of the same sentence.
   ============================================================ */
.np-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-4); }
.np-stat { background: var(--muted-bg); border-radius: var(--radius); padding: var(--space-3) var(--space-4); }
.np-stat--attention { background: var(--orange-bg); }
.np-stat-label { display: block; font-size: 12px; color: var(--text-secondary); }
.np-stat--attention .np-stat-label { color: var(--orange-dark); }
.np-stat-value { display: block; font-size: 24px; font-weight: 600; margin-top: 2px; }
.np-stat--attention .np-stat-value { color: var(--orange-dark); }

.np-filter-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-secondary); white-space: nowrap; }
.np-filter-check input { width: auto; height: auto; margin: 0; }

.np-bulk { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; background: var(--muted-bg); border-radius: var(--radius); padding: var(--space-2) var(--space-4); margin-bottom: var(--space-3); font-size: 13px; color: var(--text-secondary); }

.np-list { list-style: none; margin: 0; padding: 0; }
/* The row is a link plus a sibling button, so the <li> does the laying out —
   the button cannot live inside the anchor. */
.np-row { display: flex; align-items: center; }
.np-row + .np-row { border-top: 1px solid var(--border); }
.np-row-action { flex-shrink: 0; padding-right: var(--space-3); display: flex; }
.np-row-link { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); color: inherit; text-decoration: none; }
a.np-row-link:hover { background: var(--orange-bg); }
a.np-row-link:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
.np-row-link--inert { cursor: default; }
.np-row-main { flex: 1; min-width: 0; }
.np-name { display: block; font-weight: 600; }
.np-meta { display: block; font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.np-row-side { display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0; }
.np-caret { display: inline-flex; color: var(--muted); }
/* Finished rows stay in the list so the day's history is intact, but they
   step back so the ones still needing work read first. */
.np-row--done .np-name { font-weight: 500; color: var(--text-secondary); }
/* Only visible under "Show reviewed", where the whole list is ticked off —
   the muting says "handled", not "ignore me". */
.np-row--reviewed .np-name { color: var(--text-secondary); }
.np-row--reviewed .np-row-link { opacity: 0.75; }

@media (max-width: 640px) {
    .np-stats { grid-template-columns: 1fr; gap: var(--space-2); }
    .np-stat { display: flex; align-items: baseline; justify-content: space-between; padding: var(--space-2) var(--space-3); }
    .np-stat-value { font-size: 18px; margin-top: 0; }
    .np-row-link { align-items: flex-start; flex-wrap: wrap; padding: var(--space-3); }
    .np-row-side { width: 100%; }
    .np-caret { display: none; }
}

/* ============================================================
   Scan review workspace (Phase 5)
   ============================================================ */
.review-toolbar { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-3); }
.review-progress { font-size: 13px; font-weight: 600; color: var(--text-secondary); }
.review-layout { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: var(--space-4); align-items: start; }

.review-queue {
    position: sticky; top: var(--space-4); background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm);
    display: flex; flex-direction: column; max-height: calc(100vh - var(--space-8)); overflow: hidden;
}
.review-queue-search { padding: var(--space-2); border-bottom: 1px solid var(--border); }
.review-queue-search input { width: 100%; height: 34px; padding: 0 var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 13px; }
.review-queue-list { overflow-y: auto; padding: var(--space-2); }
.review-sheet + .review-sheet { margin-top: var(--space-3); }
.review-sheet-head { margin: 0 0 4px; padding: 0 6px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-secondary); display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.review-sheet-meta { font-weight: 400; text-transform: none; letter-spacing: 0; }
.review-queue-item {
    display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
    padding: 7px var(--space-2); border: none; background: none; border-radius: var(--radius-sm);
    cursor: pointer; font-family: inherit; font-size: 13px; color: var(--text);
}
.review-queue-item:hover { background: var(--steel-light); }
.review-queue-item.is-active { background: var(--orange-bg); color: var(--orange-dark); font-weight: 600; }
.review-queue-item:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
.rqi-op { flex-shrink: 0; width: 18px; height: 18px; border-radius: 4px; font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
.rqi-op-add { background: var(--success-bg); color: var(--success-text); }
.rqi-op-remove { background: var(--warning-bg); color: var(--warning-text); }
.rqi-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rqi-conf { flex-shrink: 0; font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-secondary); background: var(--steel-light); padding: 1px 6px; border-radius: 20px; }
.rqi-conf-high { background: var(--success-bg); color: var(--success-text); font-weight: 600; }
.rqi-conf-none { background: var(--danger-bg); color: var(--danger-text); }

.review-workspace { min-width: 0; }
.review-panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); overflow: hidden; }
.review-panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.review-panel-nav { display: flex; gap: 6px; }
.btn-sm { height: 32px; padding: 0 var(--space-2); font-size: 12px; }
.review-panel-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: var(--space-4); padding: var(--space-4); }
.review-source { min-width: 0; }
.review-images { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
.review-image-link img { max-width: 100%; max-height: 320px; border-radius: var(--radius); border: 1px solid var(--border); }
.review-noimage { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: var(--space-6); color: var(--text-secondary); background: var(--canvas); border-radius: var(--radius); margin-bottom: var(--space-3); font-size: 13px; }
.review-facts { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 4px var(--space-3); font-size: 13px; }
.review-facts dt { color: var(--text-secondary); font-weight: 600; }
.review-facts dd { margin: 0; }
.review-decide { min-width: 0; }
.review-suggestions { border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-2) var(--space-3); margin: 0 0 var(--space-3); }
.review-suggestions legend { font-size: 12px; font-weight: 600; color: var(--text-secondary); padding: 0 4px; }
.review-suggestion { display: flex; align-items: baseline; gap: 8px; padding: 5px 2px; font-size: 13px; cursor: pointer; }
.review-suggestion-name { font-weight: 500; }
.review-suggestion-why { margin-left: auto; font-size: 11px; color: var(--text-secondary); white-space: nowrap; }
.review-nosuggest { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--warning-text); background: var(--warning-bg); padding: 8px 10px; border-radius: var(--radius-sm); margin: 0 0 var(--space-3); }
.review-qty-row { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.review-qty-row .form-row { flex: 1; min-width: 90px; }
.review-qty-row input { width: 100%; }
.review-allow-negative { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--warning-text); margin: var(--space-2) 0; }
.review-create { margin-top: var(--space-3); border-top: 1px solid var(--border); padding-top: var(--space-3); }
.review-create summary { cursor: pointer; font-size: 13px; color: var(--orange-dark); display: inline-flex; align-items: center; gap: 5px; }
.review-create[open] summary { margin-bottom: var(--space-2); }
.review-reject { display: flex; gap: var(--space-2); align-items: center; margin-top: var(--space-3); border-top: 1px solid var(--border); padding-top: var(--space-3); flex-wrap: wrap; }
.review-reject input { flex: 1; min-width: 160px; height: 34px; padding: 0 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 13px; }
.review-shortcuts { margin-top: var(--space-3); font-size: 12px; color: var(--text-secondary); }
.review-shortcuts kbd { background: var(--steel-light); border-radius: 3px; padding: 1px 5px; font-family: inherit; }
.review-history-row { margin-bottom: var(--space-3); }

@media (max-width: 860px) {
    .review-layout { grid-template-columns: 1fr; }
    .review-queue { position: static; max-height: 240px; }
    .review-panel-body { grid-template-columns: 1fr; }
}

/* Delivery progress timeline */
.delivery-timeline {
    list-style: none; margin: 0 0 var(--space-5); padding: 0;
    display: flex; flex-wrap: wrap; gap: var(--space-2);
}
.timeline-step {
    flex: 1; min-width: 120px; display: flex; flex-direction: column; gap: 2px;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); position: relative;
}
.timeline-step .timeline-dot { display: inline-flex; align-items: center; color: var(--text-secondary); }
.timeline-step.is-done { border-color: var(--success); background: var(--success-bg); }
.timeline-step.is-done .timeline-dot { color: var(--success-text); }
.timeline-step.is-current { border-color: var(--orange); background: var(--orange-bg); }
.timeline-label { font-weight: 600; font-size: 13px; }
.timeline-when { font-size: 11px; color: var(--text-secondary); font-family: 'IBM Plex Mono', monospace; }
.delivery-timeline.is-cancelled .timeline-step { opacity: 0.6; }

/* ---- Delivery check-in: attached paperwork + the two ways to check in ----
   Every colour here comes from a token, so body.theme-dark's remapping
   carries the whole block without a second set of rules. */
.checkin-banner {
    display: flex; align-items: center; gap: var(--space-2);
    margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4);
    border: 1px solid var(--success); border-left-width: 3px;
    border-radius: var(--radius-sm);
    background: var(--success-bg); color: var(--success-text); font-size: 14px;
}
.doc-strip {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
    margin: 0 0 var(--space-5);
}
.doc-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text); font-size: 13px; text-decoration: none;
}
.doc-chip:hover { border-color: var(--orange); color: var(--orange-dark); }
.doc-empty { font-size: 13px; color: var(--text-secondary); }
.doc-add { margin: 0; }
.doc-add-label { cursor: pointer; font-size: 13px; color: var(--text-secondary); }
.doc-add-label input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.doc-add-label span { text-decoration: underline; text-underline-offset: 3px; }
.doc-add-label:hover span,
.doc-add-label input:focus-visible + span { color: var(--orange-dark); }

.checkin-card {
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    background: var(--surface); margin: 0 0 var(--space-5); overflow: hidden;
}
.checkin-card-head { padding: var(--space-4) var(--space-5) 0; }
.checkin-card-head h2 { margin: 0; font-size: 17px; }
.checkin-card-head .subtitle { margin: 4px 0 0; max-width: 70ch; }
.checkin-options {
    display: grid; grid-template-columns: 1.15fr 1fr;
    gap: var(--space-4); padding: var(--space-4) var(--space-5) var(--space-5);
}
.checkin-option {
    display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2);
    margin: 0; padding: var(--space-4);
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--canvas);
}
.checkin-option--quiet { background: transparent; }
.checkin-option h3 {
    display: flex; align-items: center; gap: 7px;
    margin: 0; font-size: 15px; font-weight: 700;
}
.checkin-option p { margin: 0; font-size: 13px; color: var(--text-secondary); max-width: 46ch; }
.checkin-option .btn-primary,
.checkin-option .btn-secondary { margin-top: auto; }

.checkin-drop {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    width: 100%; padding: var(--space-4) var(--space-3);
    border: 1.5px dashed var(--border); border-radius: var(--radius-sm);
    background: var(--surface); text-align: center; cursor: pointer;
}
.checkin-drop:hover, .checkin-drop.is-over { border-color: var(--orange); background: var(--orange-bg); }
.checkin-drop.has-files { border-style: solid; border-color: var(--success); background: var(--success-bg); }
.checkin-drop input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.checkin-drop-main { font-size: 13px; font-weight: 600; }
.checkin-drop-hint { font-size: 12px; color: var(--text-secondary); }
.checkin-drop-files { font-size: 12px; font-weight: 600; color: var(--success-text); word-break: break-all; }
.checkin-drop input:focus-visible ~ .checkin-drop-main { outline: 2px solid var(--orange); outline-offset: 3px; }
.checkin-alt { margin: 0; padding: 0 var(--space-5) var(--space-4); font-size: 13px; }

@media (max-width: 720px) {
    .checkin-options { grid-template-columns: 1fr; }
}

/* ---- Invoice review: per-line destinations ----
   One invoice often splits across rooms, so each line carries its own
   destination. A line left on the main room must look untouched; a line sent
   elsewhere has to be visible while scanning the table, hence the row tint as
   well as the marked control. Tokens only, so theme-dark carries it. */
.line-room-select {
    width: 100%; min-height: 34px; padding: 6px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px;
}
.line-room-select.is-redirected {
    border-color: var(--orange); background: var(--orange-bg);
    color: var(--orange-dark); font-weight: 600;
}
.data-table tbody tr.row-redirected > td { background: var(--orange-bg); }

.dest-summary {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
    margin: var(--space-5) 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--muted-bg); font-size: 13px;
}
.dest-summary-label { font-weight: 600; }
.dest-chip {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 4px 12px; border: 1px solid var(--border); border-radius: 999px;
    background: var(--surface); font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}
.dest-chip-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--orange); flex: none;
}
.dest-chip--main .dest-chip-dot { background: var(--success); }

/* ---- Invoice review + plain check-in: the line table ----
   Proportional columns rather than min-widths, so the table fills the page
   it is given instead of forcing a scrollbar. Quantity, unit and length are
   one question -- how much arrived -- so they share the Amount cell, and the
   match badge sits under the product name it describes. */
#invoice-lines, #checkin-lines { width: 100%; table-layout: fixed; }
.col-product { width: 32%; }
.col-todo    { width: 21%; }
.col-send    { width: 20%; }
.col-amount  { width: 19%; }
.col-remove  { width: 8%; }
/* The plain check-in has no "what to do" column, so its four share the width
   differently. */
#checkin-lines .col-product { width: 38%; }
#checkin-lines .col-expected { width: 14%; }
#checkin-lines .col-amount { width: 24%; }
#checkin-lines .col-send { width: 24%; }

.line-product input[type="text"],
.line-todo select,
.line-room-select { width: 100%; }
.line-product input[type="text"] {
    min-height: 34px; padding: 6px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px;
}
.line-code { margin-top: 4px; font-size: 12px; color: var(--text-secondary); }
.line-match { margin-top: 6px; }
.row-action-select {
    min-height: 34px; padding: 6px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px;
}
.row-category-select { width: 100%; margin-top: 4px; }

.amount-row { display: flex; align-items: center; gap: 6px; }
.amount-qty {
    width: 100%; max-width: 88px; min-height: 34px; padding: 6px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px;
    font-variant-numeric: tabular-nums;
}
.amount-unit { font-size: 12px; color: var(--text-secondary); }
.amount-length { display: block; margin-top: 6px; }
.amount-length-label { display: block; font-size: 11px; color: var(--text-secondary); margin-bottom: 2px; }
.amount-length input {
    width: 100%; max-width: 110px; min-height: 32px; padding: 5px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px;
}
/* Only ever on screen when a cable line is about to create an implausible
   number of drums, so it is allowed to be loud - it is the last thing
   between a mistyped metre count and thousands of rows. */
.amount-confirm {
    display: flex; align-items: flex-start; gap: 6px; margin-top: 8px;
    padding: 6px 8px; border-radius: var(--radius-sm);
    border: 1px solid var(--warning); background: var(--warning-bg);
    color: var(--warning-text); font-size: 12px; line-height: 1.35;
    cursor: pointer;
}
.amount-confirm[hidden] { display: none; }
.amount-confirm input[type="checkbox"] { margin-top: 1px; flex: none; }

/* ---- Timesheet data check: the fix-it table ----
   The same card-at-narrow treatment as the check-in tables (it shares their
   container-query rules below). A flagged row keeps the warning tint even
   once it becomes a card, so the thing needing attention stays visible. */
#timesheet-checks input[type="time"] { min-height: 34px; padding: 5px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px; }
#timesheet-checks input[type="text"] { width: 100%; min-width: 120px;
    min-height: 34px; padding: 5px 8px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px; }

/* The per-cell heading, shown only once the rows become cards and the table
   head is gone. */
.cell-label {
    display: none;
    font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase; color: var(--text-secondary);
    margin-bottom: 4px;
}

/* Below this the columns stop fitting, so each line becomes a card you read
   down -- the same move the stock and equipment tables already make. Nothing
   scrolls sideways at any width.

   Measured against the table's own box, not the window: the sidebar takes
   296px (76px collapsed), so the same window width leaves very different
   room depending on whether it is open, and a viewport breakpoint gets one
   of the two cases wrong. Where container queries are unsupported the table
   simply stays a table and scrolls, which is what it did before. */
.line-table-wrap { container-type: inline-size; }

@container (max-width: 700px) {
    #invoice-lines thead, #checkin-lines thead, #timesheet-checks thead {
        position: absolute; width: 1px; height: 1px;
        overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
    }
    #invoice-lines, #invoice-lines tbody, #invoice-lines tr, #invoice-lines td,
    #checkin-lines, #checkin-lines tbody, #checkin-lines tr, #checkin-lines td,
    #timesheet-checks, #timesheet-checks tbody, #timesheet-checks tr, #timesheet-checks td {
        display: block; width: auto;
    }
    #invoice-lines tr, #checkin-lines tr, #timesheet-checks tr {
        position: relative;
        border: 1px solid var(--border); border-radius: var(--radius);
        background: var(--surface);
        padding: var(--space-4); margin-bottom: var(--space-3);
    }
    #invoice-lines td, #checkin-lines td, #timesheet-checks td { border: none; padding: 0; }
    #invoice-lines td + td, #checkin-lines td + td,
    #timesheet-checks td + td { margin-top: var(--space-3); }
    #invoice-lines .cell-label, #checkin-lines .cell-label,
    #timesheet-checks .cell-label { display: block; }
    /* The remove button rides in the card's top corner rather than taking a
       row of its own. */
    #invoice-lines .actions-cell {
        position: absolute; top: var(--space-3); right: var(--space-3); margin-top: 0;
    }
    #invoice-lines .line-product { padding-right: 48px; }
    .amount-qty, .amount-length input { max-width: 140px; }
    /* A redirected line becomes a tinted card. Scoped by the same ids as the
       card rules above, which set the surface background and would otherwise
       outrank a class-only selector. */
    #invoice-lines tr.row-redirected, #checkin-lines tr.row-redirected {
        background: var(--orange-bg); border-color: var(--orange);
    }
    #invoice-lines tr.row-redirected > td, #checkin-lines tr.row-redirected > td {
        background: transparent;
    }
    /* Same move for the timesheet fix-it rows: the id-scoped card rule above
       sets the surface background, so the warning tint needs the same id. */
    #timesheet-checks tr.row-needs-review {
        background: var(--warning-bg); border-color: var(--warning);
    }
    #timesheet-checks tr.row-needs-review > td { background: transparent; }
}

.dropdown-heading {
    margin: 0; padding: 6px 12px 2px; font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.04em; color: var(--danger-text);
}
.dropdown-menu form { margin: 0; }
.dropdown-menu form .dropdown-item { width: 100%; border: none; background: none; text-align: left; font-family: inherit; cursor: pointer; }
.form-row--checkbox { display: block; }
.checkbox-label { display: inline-flex; align-items: center; gap: var(--space-2); font-size: 14px; cursor: pointer; }
.checkbox-label input { width: 16px; height: 16px; }

.btn-icon-square {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--control-height);
    height: var(--control-height);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text-secondary);
    cursor: pointer;
    flex-shrink: 0;
}
.btn-icon-square:hover { border-color: var(--text-secondary); color: var(--text); }

.btn-remove {
    border: none;
    background: transparent;
    color: var(--danger-text);
    cursor: pointer;
    font-size: 14px;
    padding: 4px 8px;
}

/* ============================================================
   Forms
   ============================================================ */
.form { max-width: 640px; }
/* 640px is right for a column of stacked fields, and wrong for a form whose
   body is a wide table -- the invoice review was squeezing eight columns into
   it and scrolling sideways while half the page sat empty beside it. This
   opts one form out; every other form keeps the reading width. */
.form--wide { max-width: none; }
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--space-4); }
@media (max-width: 560px) { .form-grid-2 { grid-template-columns: 1fr; } }
.form-details { margin-bottom: var(--space-4); }
.form-details summary { cursor: pointer; font-size: 13px; color: var(--text-secondary); }
.checkbox-row { display: flex; align-items: center; gap: var(--space-2); font-size: 14px; cursor: pointer; }

/* Recount upload preview */
.recount-title-problem { color: var(--danger-text); }
.recount-qty-up { color: var(--success-text); font-weight: 600; }
.recount-qty-down { color: var(--danger-text); font-weight: 600; }

/* "Edit all counts" bulk mode on the room stock table */
/* ---- Room inventory table (stock_room.html) ----
   Scannable two-line cells: name over spec, quantity over unit, shelf over
   reference. Metadata is smaller and secondary; the details row holds the
   long stocktake/lot/PO text. */
.stock-table .cell-item { min-width: 220px; }
/* "My Code" column: codes are short and must never wrap or truncate —
   they get compared character-by-character against sheets. */
.stock-table .cell-code, .stock-table .col-code { white-space: nowrap; }
.stock-table .cell-code { font-size: 13px; }
/* Where a room numbers its own boxes, that number leads and the system-wide
   product code sits under it, quieter — both get read off the same cell. What
   sits under the code is a hint, not the record, so a note that runs to a whole
   delivery note is held to one short line with the rest of it on hover. */
.stock-table .cell-code .code-alt {
    display: block; font-size: 11px; color: var(--text-secondary); font-weight: 400;
    max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.item-name { display: block; font-weight: 600; font-size: 13px; line-height: 1.35; }
.item-spec {
    display: block; font-size: 12px; color: var(--text-secondary);
    max-width: 420px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stock-table .cell-qty, .stock-table .col-qty { text-align: right; }
.qty-value { display: block; font-weight: 600; font-variant-numeric: tabular-nums; font-size: 13.5px; }
.qty-unit { display: block; font-size: 11px; color: var(--text-secondary); }
.cell-location .loc-primary { display: block; font-weight: 500; font-size: 13px; white-space: nowrap; }
.cell-location .loc-ref {
    display: block; font-size: 11.5px; color: var(--text-secondary);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.stock-table tbody tr[data-rowlink]:hover td { background: var(--canvas); }

/* Status pill: dot + text, never colour alone. */
.stock-status {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px; font-weight: 600; padding: 2px 9px; border-radius: 20px;
    white-space: nowrap;
}
.status-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.stock-status--ok { background: var(--success-bg); color: var(--success-text); }
.stock-status--ok .status-dot { background: var(--success); }
.stock-status--low { background: var(--warning-bg); color: var(--warning-text); }
.stock-status--low .status-dot { background: var(--warning); }
.stock-status--out { background: var(--danger-bg); color: var(--danger-text); }
.stock-status--out .status-dot { background: var(--danger); }

/* Expanded details row, toggled by the chevron in the actions cell. */
.stock-details-row td {
    background: var(--canvas); font-size: 12px; color: var(--text-secondary);
    padding-top: 6px; padding-bottom: 10px;
}
.details-meta { display: inline-block; margin-left: var(--space-3); }
.actions-cell [data-details-toggle] .icon { transition: transform 0.15s ease; }
.actions-cell [data-details-toggle].is-open .icon { transform: rotate(180deg); }

/* Grouped cable-drum line: one row per cable, its drums in a nested table
   the chevron drops open. The group row itself links to the cable's
   register page, so both cells and caret must read as one clickable unit. */
.drum-group-row .item-name { font-weight: 600; }
.drum-units-row > td { padding: 8px 14px 12px; }
.drum-units {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-sm); overflow: hidden;
}
.drum-units-line {
    display: grid;
    grid-template-columns: minmax(64px, 0.7fr) minmax(80px, 0.8fr) minmax(70px, 0.7fr) minmax(90px, 1fr) minmax(0, 1.6fr) auto;
    gap: var(--space-3); align-items: center;
    padding: 5px 10px; font-size: 13px; color: var(--text);
    border-top: 1px solid var(--steel-light);
}
.drum-units-head {
    border-top: none; background: var(--canvas);
    font-size: 11px; font-weight: 600; text-transform: uppercase;
    letter-spacing: 0.04em; color: var(--text-secondary);
}
.drum-units-num { text-align: right; font-variant-numeric: tabular-nums; }
.drum-units-line.is-part { background: var(--warning-bg); }
.drum-units-line.is-hit { background: var(--orange-bg); }
.drum-units-notes { color: var(--text-secondary); font-size: 12px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drum-units-more { display: inline-flex; margin-top: 8px; }
@media (max-width: 720px) {
    /* The stacked mobile table turns the expander cell full-width; keep the
       drum lines readable as two rows of three. */
    .drum-units-line { grid-template-columns: 1fr 1fr 1fr; }
    .drum-units-head { display: none; }
}

/* The cable register page: part-used drums lead the table and carry the
   same amber the group expander uses; ?hl= highlights the searched drum. */
.drum-row-part td { background: var(--warning-bg); }
.drum-row-hit td { background: var(--orange-bg); }
.metric-card--accent { border-color: var(--orange); background: var(--orange-bg); }
.metric-card--accent .metric-value { color: var(--orange-dark); }
.badge-empty { border-left-color: var(--muted); background: var(--muted-bg); color: var(--steel-text); }

/* Low-emphasis third-tier button (the room header's "More"). */
.btn-tertiary {
    display: inline-flex; align-items: center; gap: var(--space-2);
    height: var(--control-height); padding: 0 var(--space-3);
    border: none; border-radius: var(--radius-sm); background: transparent;
    color: var(--text-secondary); font-size: 14px; font-weight: 500;
    font-family: inherit; cursor: pointer;
}
.btn-tertiary:hover { background: var(--steel-light); color: var(--text); }

/* Toolbar: search grows, selects stay natural width; everything stacks
   full-width on phones. */
.room-toolbar #room-search-input { flex: 1 1 240px; min-width: 200px; }
@media (max-width: 640px) {
    .room-toolbar #room-search-input,
    .room-toolbar select { flex: 1 1 100%; min-width: 0; }
    .room-actions { width: 100%; }
    .room-actions .btn-primary { flex: 1 1 100%; justify-content: center; }
}

/* Tablet only: Category is the first column to give way. Below 641px the
   rows become cards (rules further up), where Category returns as a line. */
@media (min-width: 641px) and (max-width: 1023px) {
    .stock-table .cell-category, .stock-table .col-category { display: none; }
}

.qty-cell { white-space: nowrap; }
.bulk-input, .drum-take-input {
    width: 96px;
    text-align: right;
    height: 32px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 13px;
    background: var(--surface);
    color: var(--text);
}
.bulk-input:focus, .drum-take-input:focus { border-color: var(--orange); }
.bulk-input-invalid { border-color: var(--danger); background: var(--danger-bg); }
.bulk-editing .bulk-current {
    display: block;
    font-size: 11px;
    color: var(--text-secondary);
    margin-bottom: 2px;
}
.bulk-editing .bulk-current::before { content: 'was '; }
.bulk-editing tr[data-rowlink] { cursor: default; }
.bulk-editing tr[data-rowlink]:hover td { background: inherit; }
tr.bulk-row-changed td { background: var(--warning-bg) !important; }

/* Drum stocktake mode (register page + room drum view). The Gone tick and
   the count inputs only exist while the mode is on; a ticked drum reads as
   struck through, on its way to the register's history section. */
.drum-take-input { width: 84px; }
.drum-take-gone-label {
    display: none;
    align-items: center; gap: 4px;
    font-size: 12px; color: var(--text-secondary);
    cursor: pointer; white-space: nowrap; user-select: none;
}
.bulk-editing .drum-take-gone-label { display: inline-flex; }
/* The tick lives in the Code cell (register page and room grid alike), so
   it reads as a checklist down the left edge; the cell is monospace, the
   word "Gone" is not. */
.cell-code .drum-take-gone-label, .drum-units-line .drum-take-gone-label {
    margin-right: var(--space-2); vertical-align: middle;
    font-family: 'Inter', -apple-system, "Segoe UI", Arial, sans-serif; letter-spacing: 0;
}
.bulk-editing .drum-take-hides, .bulk-editing .drum-units-more { display: none; }

/* Typing the code tags. The box takes the printed code's place while the
   mode is on — one column, either read or written, never both — and stays
   left-aligned: codes read as words, unlike the metres beside them. */
.drum-take-code {
    width: 88px;
    height: 32px;
    padding: 0 var(--space-2);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 13px;
    background: var(--surface);
    color: var(--text);
    text-transform: uppercase;
}
.drum-take-code:focus { border-color: var(--orange); }
.bulk-editing .drum-code-text { display: none; }
/* Writing tags needs more room in the drum column than reading them does —
   the tick and the box together are wider than a short code. Mobile keeps
   its stacked three-column grid. */
@media (min-width: 721px) {
    .bulk-editing .drum-units-line {
        grid-template-columns: minmax(160px, 1fr) minmax(80px, 0.8fr) minmax(70px, 0.7fr)
                               minmax(90px, 1fr) minmax(0, 1.6fr) auto;
    }
}

/* Retired drums (marked gone / moved out) and the way back: the register's
   history section, the room search's "not in stock any more" block and the
   global search all list them greyed, each with a one-line Restore form. */
.drum-row-retired td { color: var(--text-secondary); }
/* A stock line its room will not show (archived, or an issue) reads back
   like a retired drum: present, greyed, not pretending to be on the shelf. */
.stock-row-hidden td { color: var(--text-secondary); }
.drum-row-retired.drum-row-hit td { background: var(--orange-bg); }
.drum-restore-form { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.drum-restore-form .drum-take-input { width: 84px; }
.drum-restore-unit { font-size: 12px; color: var(--text-secondary); }
.retired-drums { margin-top: var(--space-8); }
.retired-drums h2 { display: flex; align-items: center; gap: var(--space-2); }
.retired-drums .subtitle { margin: 4px 0 12px; }

/* Split page: presets → editable list → one button. Two numbered cards
   because it really is a sequence: the presets only fill the list, the
   list is what gets saved. */
.split-card {
    background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
    padding: var(--space-4) var(--space-5); margin-bottom: var(--space-4);
}
.split-card h2 { font-size: 15px; margin: 0 0 4px; }
.split-card .field-hint { margin: 0 0 var(--space-3); max-width: 80ch; }
.split-preset { font-family: inherit; font-variant-numeric: tabular-nums; cursor: pointer; }
.split-custom { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-size: 14px; }
.split-custom .drum-take-input { width: 84px; }
.split-table .cell-qty .drum-take-input { width: 96px; }
.split-table .split-code { width: 84px; text-align: left; }
.split-table .cell-code .code-alt { display: block; font-size: 11px; color: var(--text-secondary); }
.split-table tr.split-row-self td { background: var(--orange-bg); }
.split-remove {
    border: none; background: none; color: var(--text-secondary); font-size: 18px; line-height: 1;
    padding: 2px 8px; border-radius: var(--radius-sm); cursor: pointer;
}
.split-remove:hover { background: var(--steel-light); color: var(--danger-text); }
.split-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; padding: var(--space-3) var(--space-2) 0; }
.split-foot .back-link { background: none; border: none; cursor: pointer; font-family: inherit; display: inline-flex; align-items: center; gap: 4px; padding: 0; }
.split-totals { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; font-size: 14px; }
.split-verdict { font-weight: 600; }
.split-verdict.is-ok { color: var(--success-text); }
.split-verdict.is-bad { color: var(--danger-text); }
.drum-bundle-note {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap;
    background: var(--warning-bg); color: var(--warning-text); border-left: 3px solid var(--warning);
    border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); margin-bottom: var(--space-4);
    font-size: 14px; max-width: 640px;
}
.drum-bundle-note .btn-secondary { flex-shrink: 0; }
/* While counting, amber means "you changed this" and nothing else: the
   part-used tint (room grid and register page alike) steps aside until
   the mode is off, so a row is never orange for two reasons at once. */
.bulk-editing .drum-units-line.is-part { background: transparent; }
.bulk-editing tr.drum-row-part td { background: transparent; }
.bulk-editing .drum-units-line.bulk-row-changed { background: var(--warning-bg); }
tr.drum-row-gone td { background: var(--danger-bg) !important; }
.bulk-editing .drum-units-line.drum-row-gone { background: var(--danger-bg); }
tr.drum-row-gone .cell-code, tr.drum-row-gone .qty-value,
.drum-units-line.drum-row-gone .mono { text-decoration: line-through; color: var(--text-secondary); }
.bulk-bar {
    position: sticky;
    bottom: 12px;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    flex-wrap: wrap;
    z-index: 10;
}
/* display:flex above would otherwise beat the browser's own [hidden] rule,
   leaving a closed tray on screen offering a Save it can't do. */
.bulk-bar[hidden] { display: none; }
.bulk-bar-status { font-size: 13px; }
.bulk-bar input[type="text"] {
    flex: 1 1 220px;
    height: 36px;
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 13px;
    font-family: inherit;
}
.bulk-invalid-note { color: var(--danger-text); }
/* "Number blanks from ___ [Fill down]" — a fixed-width field, so it keeps
   its shape while the reason box takes the rest of the tray. */
.bulk-bar-fill {
    display: flex; align-items: center; gap: var(--space-2);
    font-size: 13px; color: var(--text-secondary); white-space: nowrap;
}
.bulk-bar .drum-take-fill-input {
    flex: 0 0 96px; width: 96px; height: 36px;
    text-transform: uppercase; color: var(--text);
}
.form-row { display: flex; flex-direction: column; gap: 4px; margin-bottom: var(--space-4); }
.form-row label { font-size: 13px; color: var(--text-secondary); }
.form-row input, .form-row select, .form-row textarea {
    min-height: var(--control-height);
    padding: 8px 10px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 14px;
    font-family: inherit;
    background: var(--surface);
    color: var(--text);
}
.form-row input:disabled, .form-row select:disabled, .form-row textarea:disabled {
    background: var(--canvas);
    color: var(--text-secondary);
    cursor: not-allowed;
}
.item-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
    align-items: flex-start;
}
.item-row input, .item-row select {
    height: 36px;
    padding: 0 9px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    font-size: 13px;
    font-family: inherit;
    background: var(--surface);
    color: var(--text);
}
.item-row input[name="item_name[]"] { flex: 2; }
.item-row input[name="item_qty[]"] { width: 80px; }
.item-row input[name="item_length[]"] { width: 140px; }
.form-actions { margin-top: var(--space-5); }

.item-name-wrap { flex: 2; display: flex; flex-direction: column; gap: 2px; min-width: 160px; }
.item-name-wrap input { width: 100%; }
.item-tag { font-size: 11px; height: 14px; padding-left: 2px; }
.item-tag-existing { color: var(--success-text); }
.item-tag-new { color: var(--warning-text); }

.alert-banner {
    display: block;
    background: var(--orange-bg);
    color: var(--orange-dark);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--orange);
    text-decoration: none;
    font-size: 14px;
    font-weight: 500;
    margin-bottom: var(--space-5);
}
.alert-banner:hover { background: #FCE3D0; }
.alert-banner-split { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }

/* ============================================================
   Calendar widget (delivery date pickers)
   ============================================================ */
.calendar-wrap { max-width: 320px; }
.calendar-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--space-2);
    font-weight: 600;
    font-size: 14px;
}
.cal-nav {
    border: none;
    background: var(--steel-light);
    border-radius: var(--radius-sm);
    width: 28px;
    height: 28px;
    cursor: pointer;
    font-size: 14px;
    color: var(--text);
}
.calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 3px;
}
.cal-dow {
    text-align: center;
    font-size: 11px;
    color: var(--text-secondary);
    padding: 4px 0;
}
.cal-day {
    position: relative;
    text-align: center;
    padding: 8px 0;
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    border-radius: var(--radius-sm);
    cursor: pointer;
    background: var(--canvas);
}
.cal-day:hover { background: var(--steel-light); }
.cal-day-selected { background: var(--orange) !important; color: var(--text) !important; }
.cal-day-today { border: 1.5px solid var(--orange); }
.cal-day-has-deliveries { background: var(--warning-bg); font-weight: 700; }
.cal-day-has-deliveries:hover { background: #F7E5BC; }
.cal-count {
    position: absolute;
    top: 1px;
    right: 3px;
    font-size: 9px;
    background: var(--danger);
    color: white;
    border-radius: 50%;
    width: 14px;
    height: 14px;
    line-height: 14px;
}
.cal-selected { margin-top: var(--space-2); font-size: 13px; color: var(--text-secondary); }

/* Mobile: a full desktop month grid is unusable on a narrow screen, so it is
   collapsed by default in favour of the operational (late -> today -> ...)
   list below, and revealed on demand. The toggle button is desktop-hidden. */
.cal-mobile-toggle { display: none; }
@media (max-width: 640px) {
    .cal-mobile-toggle {
        display: inline-flex; align-items: center; gap: 6px; margin-bottom: var(--space-3);
        height: var(--control-height); padding: 0 var(--space-3);
        border: 1px solid var(--border); border-radius: var(--radius-sm);
        background: var(--surface); color: var(--text); font-size: 13px; font-family: inherit; cursor: pointer;
    }
    .calendar-wrap-large { display: none; }
    .calendar-wrap-large.is-shown { display: block; max-width: 100%; }
    /* When shown on mobile, keep the 7-column grid but shrink cells so every
       day is still a visible, tappable target (the reported "cells vanish"
       bug was cells collapsing to zero height). */
    .calendar-wrap-large.is-shown .cal-day { min-height: 40px; padding: 4px 2px; font-size: 13px; gap: 2px; }
    .calendar-wrap-large.is-shown .cal-day-dots { display: none; }
    .calendar-wrap-large.is-shown .calendar-header { font-size: 17px; }
}

.calendar-wrap-large { max-width: 900px; margin-left: auto; margin-right: auto; }
.calendar-wrap-large .calendar-header { font-size: 22px; margin-bottom: var(--space-4); gap: var(--space-3); }
.calendar-wrap-large .calendar-header-nav { display: flex; align-items: center; gap: var(--space-2); }
.calendar-wrap-large .cal-nav { width: 40px; height: 40px; font-size: 18px; }
.cal-today-btn {
    height: 32px;
    padding: 0 var(--space-3);
    border-radius: var(--radius-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
}
.cal-today-btn:hover { border-color: var(--text-secondary); }
.calendar-wrap-large .calendar-grid { gap: var(--space-2); }
.calendar-wrap-large .cal-dow { font-size: 13px; padding: var(--space-2) 0; font-weight: 600; }
.calendar-wrap-large .cal-day {
    min-height: 64px;
    padding: 8px 4px;
    font-size: 15px;
    border-radius: var(--radius-sm);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
}
button.cal-day {
    border: none;
    font-family: inherit;
    appearance: none;
    width: 100%;
}
button.cal-day:disabled { cursor: default; }
.calendar-wrap-large .cal-day-outside { background: transparent; color: var(--text-secondary); opacity: 0.5; }
.calendar-wrap-large .cal-day-outside:hover { background: transparent; }
.cal-day-num { font-variant-numeric: tabular-nums; }
.cal-day-dots { display: flex; align-items: center; gap: 3px; height: 6px; }
.cal-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.cal-dot-pending { background: var(--steel); }
.cal-dot-arrived { background: var(--warning); }
.cal-dot-checked_in { background: var(--success); }
.cal-dot-partial { background: var(--danger); }
.cal-dot-pending_approval { background: var(--orange); }
.cal-dot-cancelled { background: var(--steel); opacity: 0.5; }
.cal-day-more { font-size: 9px; color: var(--text-secondary); line-height: 1; }
.calendar-wrap-large .cal-count { top: 6px; right: 8px; font-size: 12px; width: 20px; height: 20px; line-height: 20px; }

.toolbar-results {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
    font-size: 13px;
    color: var(--text-secondary);
}
.table-row-link { color: var(--text); text-decoration: none; font-weight: 500; }
.table-row-link:hover { color: var(--orange-dark); text-decoration: underline; }

/* ============================================================
   Login
   ============================================================ */
/* Full-screen split login: welcome panel (~52%) + sign-in panel (~48%),
   fitting within 100svh with no vertical scroll on desktop. */
.login-shell {
    display: grid;
    grid-template-columns: 52% 48%;
    height: 100svh;
    min-height: 100vh; /* fallback for browsers without svh */
    overflow: hidden;
}

/* ---- Left: welcome / branding ---- */
.login-welcome {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--space-5);
    padding: clamp(28px, 4vw, 60px);
    color: #fff;
    background: radial-gradient(1200px 720px at 60% 36%, var(--navy-raised), var(--navy) 62%);
}
/* Decorative artwork: absolute background layer, never part of the flow. */
.login-welcome-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
}
/* Navy overlay to keep white text readable over the artwork. */
.login-welcome-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    background:
        linear-gradient(105deg, rgba(10,17,34,0.86) 0%, rgba(10,17,34,0.55) 48%, rgba(10,17,34,0.30) 100%),
        linear-gradient(0deg, rgba(10,17,34,0.55), rgba(10,17,34,0) 40%);
}
.login-welcome-top,
.login-welcome-main,
.login-welcome-bottom { position: relative; z-index: 2; }

.login-plate {
    background: #fff;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 16px;
    box-shadow: 0 8px 26px rgba(0,0,0,0.35);
}
.login-plate img { display: block; }
.login-plate--uc img { height: clamp(28px, 2.4vw, 36px); }
.login-plate--cdc img { height: clamp(38px, 3.4vw, 50px); }
.login-plate--grid img { height: clamp(24px, 2vw, 32px); }

.login-eyebrow {
    font-size: 12px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    font-weight: 700;
    color: #93A2BE;
    margin: 0 0 12px;
}
.login-welcome-main { display: flex; flex-direction: column; align-items: flex-start; }
.login-welcome-title {
    font-size: clamp(30px, 3.6vw, 52px);
    line-height: 1.06;
    font-weight: 800;
    letter-spacing: -0.02em;
    margin: 22px 0 14px;
    color: #fff;
}
.login-welcome-text {
    font-size: clamp(15px, 1.2vw, 17px);
    line-height: 1.55;
    color: #C4CEDE;
    max-width: 440px;
    margin: 0;
}
.login-welcome-bottom .login-eyebrow { margin-bottom: 10px; }

/* ---- Right: sign-in ---- */
.login-auth {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: clamp(24px, 3vw, 48px);
    background: var(--canvas);
    overflow-y: auto;
}
.login-card {
    width: 100%;
    max-width: 420px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 20px;
    box-shadow: 0 24px 60px rgba(16,24,40,0.10);
    padding: clamp(28px, 3vw, 44px);
    display: flex;
    flex-direction: column;
}
.login-card-title { font-size: clamp(26px, 2.6vw, 32px); font-weight: 800; letter-spacing: -0.02em; margin: 0; }
.login-card-sub { color: var(--text-secondary); font-size: 15px; margin: 8px 0 26px; }

.login-field { margin-bottom: 18px; display: flex; flex-direction: column; }
.login-field label { font-size: 14px; font-weight: 600; margin-bottom: 8px; color: var(--text); }
.login-input-wrap { position: relative; }
.login-card input {
    width: 100%;
    height: 52px;
    padding: 0 16px;
    border: 1px solid var(--border);
    border-radius: 12px;
    font-size: 15px;
    font-family: inherit;
    background: #fff;
    color: var(--text);
    transition: border-color 0.15s, box-shadow 0.15s;
}
.login-input-wrap input { padding-right: 46px; }
.login-card input::placeholder { color: #9AA4B2; }
.login-card input:focus-visible {
    outline: none;
    border-color: var(--orange);
    box-shadow: 0 0 0 4px rgba(249,115,22,0.16);
}
.login-eye {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: none;
    background: none;
    color: #9AA4B2;
    cursor: pointer;
    border-radius: 8px;
}
.login-eye:hover { color: var(--text-secondary); }
.login-eye:focus-visible { outline: 2px solid var(--orange); outline-offset: 1px; color: var(--text-secondary); }
.login-eye[aria-pressed="true"] { color: var(--orange-dark); }

.login-submit {
    height: 54px;
    margin-top: 6px;
    border: none;
    border-radius: 12px;
    background: var(--orange);
    color: #fff;
    font-size: 16px;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
    box-shadow: 0 12px 24px rgba(249,115,22,0.28);
    transition: background 0.15s, transform 0.05s;
}
.login-submit:hover { background: var(--orange-hover); }
.login-submit:active { transform: translateY(1px); }
.login-submit:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }

.login-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
    margin: 24px 0 0;
    color: var(--text-secondary);
    font-size: 13.5px;
}
.login-error {
    background: var(--danger-bg);
    color: var(--danger-text);
    border-left: 3px solid var(--danger);
    border-radius: var(--radius-sm);
    font-size: 13.5px;
    padding: 10px 12px;
    margin: 0 0 16px;
}

/* ---- Responsive: single column below 768px ---- */
@media (max-width: 768px) {
    .login-shell { grid-template-columns: 1fr; height: auto; min-height: 100svh; overflow: visible; }
    .login-welcome {
        min-height: auto;
        gap: var(--space-3);
        padding: 26px 22px 30px;
    }
    /* Reduce the artwork so it reads as a compact branded header, not a hero. */
    .login-welcome-bg { object-position: 60% 30%; opacity: 0.9; }
    .login-welcome-title { margin: 14px 0 10px; }
    .login-welcome-top { margin-bottom: 4px; }
    .login-welcome-bottom { margin-top: 8px; }
    .login-plate--cdc img { height: 40px; }
    .login-auth { padding: 26px 20px 40px; }
    .login-card { box-shadow: 0 12px 30px rgba(16,24,40,0.10); }
}

.flash-message {
    background: var(--danger-bg);
    color: var(--danger-text);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-sm);
    border-left: 3px solid var(--danger);
    font-size: 14px;
    margin-bottom: var(--space-4);
}
/* The rooms named under "this product is also in N other rooms". Inherits the
   banner's colour so the links stay legible on it in both themes; a long list
   of rooms wraps rather than stretching the banner. */
.other-rooms { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.other-rooms li {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
    padding: 3px 0; font-size: 13px;
}
.other-rooms a { color: inherit; font-weight: 600; }
.other-rooms-qty { font-variant-numeric: tabular-nums; }
.other-rooms-shelf { opacity: 0.8; }

.custom-values-list { list-style: none; padding: 0; margin: var(--space-2) 0; font-size: 14px; color: var(--text); }
.custom-values-list li { margin-bottom: 4px; }

.instructions-list { font-size: 14px; color: var(--text); line-height: 1.7; padding-left: 20px; }
.instructions-list a { color: var(--orange-dark); }

.btn-delete-link {
    border: none;
    background: transparent;
    color: var(--danger-text);
    font-size: 13px;
    cursor: pointer;
    padding: 4px 0;
    text-decoration: underline;
}
.btn-delete-link:hover { color: #A32C39; }

/* ============================================================
   Stock: location sidebar + summary cards
   ============================================================ */
/* ---- Compact room selector (Stock page header) ----
   Replaces the old always-visible location tree; see _room_selector.html. */
.room-selector-btn { display: inline-flex; align-items: center; gap: var(--space-2); }
.room-selector-current {
    max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.room-selector-menu { width: 320px; max-width: calc(100vw - var(--space-6)); padding: 0; }
.room-selector-search {
    display: flex; align-items: center; gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--border); color: var(--text-secondary);
}
.room-selector-search input {
    flex: 1; height: 30px; border: none; outline: none; font-size: 13px;
    font-family: inherit; background: transparent; color: var(--text);
}
.room-selector-list { max-height: 320px; overflow-y: auto; padding: var(--space-1); }
.room-selector-group + .room-selector-group { margin-top: var(--space-2); }
.room-selector-group-label {
    margin: var(--space-1) 0; padding: 0 var(--space-2);
    font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-secondary);
}
.room-selector-item { justify-content: space-between; }
.room-selector-item.is-active { background: var(--orange-bg); color: var(--orange-dark); font-weight: 600; }
.room-selector-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-selector-count {
    flex-shrink: 0; font-variant-numeric: tabular-nums; font-size: 11px;
    color: var(--text-secondary); background: var(--steel-light);
    padding: 1px 7px; border-radius: 20px;
}
.room-selector-item.is-active .room-selector-count { background: var(--surface); color: var(--orange-dark); }
.room-selector-empty { padding: var(--space-3); font-size: 13px; color: var(--text-secondary); text-align: center; margin: 0; }
.room-selector-foot { border-top: 1px solid var(--border); padding: var(--space-1); }

/* ---- Manage rooms (per-user sidebar shortcuts) ---- */
.manage-rooms-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: var(--space-4);
    align-items: start;
}
.manage-rooms-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
}
.manage-rooms-head {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--border);
}
.manage-rooms-title { font-size: 14px; font-weight: 600; margin: 0; }
.manage-rooms-hint { font-size: 12px; color: var(--text-secondary); display: block; }
.manage-rooms-search {
    display: flex; align-items: center; gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--border);
    color: var(--text-secondary);
}
.manage-rooms-search input {
    flex: 1; height: 34px; border: none; outline: none; font-size: 13px;
    font-family: inherit; background: transparent; color: var(--text);
}
.manage-rooms-list { max-height: 460px; overflow-y: auto; padding: var(--space-2); }
.manage-rooms-group + .manage-rooms-group { margin-top: var(--space-3); }
.manage-rooms-group-label {
    margin: 0 0 var(--space-1); padding: 0 var(--space-2);
    font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--text-secondary);
}
.manage-room-option {
    display: flex; align-items: center; gap: var(--space-3);
    padding: 7px var(--space-2); border-radius: var(--radius-sm); cursor: pointer;
}
.manage-room-option:hover { background: var(--steel-light); }
.manage-room-text { display: flex; flex-direction: column; min-width: 0; }
.manage-room-name { font-size: 13px; font-weight: 500; }
.manage-room-meta { font-size: 11px; color: var(--text-secondary); }
.manage-rooms-empty { padding: var(--space-3); font-size: 13px; color: var(--text-secondary); text-align: center; }

.manage-rooms-selected { list-style: none; margin: 0; padding: var(--space-2); }
.manage-room-row {
    display: flex; align-items: center; gap: var(--space-2);
    padding: 7px var(--space-2); border-radius: var(--radius-sm);
    border: 1px solid transparent; background: var(--canvas); margin-bottom: 4px;
}
.manage-room-row.is-dragging { opacity: 0.5; }
.manage-room-row.is-overflow { background: transparent; border-color: var(--border); border-style: dashed; }
.manage-room-handle { cursor: grab; color: var(--text-secondary); font-size: 14px; line-height: 1; }
.manage-room-pos {
    flex-shrink: 0; width: 20px; height: 20px; border-radius: var(--radius-sm);
    background: var(--orange-bg); color: var(--orange-dark);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 700;
}
.manage-room-row.is-overflow .manage-room-pos { background: var(--muted-bg); color: var(--steel-text); }
.manage-room-row .manage-room-text { flex: 1; }
.manage-room-controls { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.manage-room-controls .btn-icon-square { width: 26px; height: 26px; font-size: 13px; line-height: 1; }
.manage-room-controls .btn-icon-square[disabled] { opacity: 0.35; cursor: not-allowed; }
.manage-room-controls .btn-icon-square.danger { color: var(--danger-text); }
.manage-rooms-actions {
    display: flex; justify-content: flex-end; gap: var(--space-2);
    margin-top: var(--space-4); flex-wrap: wrap;
}

.stock-layout { display: flex; gap: var(--space-6); align-items: flex-start; }
/* Location tree removed from the content area -- the room selector in the
   page header replaces it, so the table gets the whole width. */
.stock-layout--full { display: block; }
.location-nav {
    width: 260px;
    flex-shrink: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}
.location-nav-search {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3);
    border-bottom: 1px solid var(--border);
    color: var(--text-secondary);
}
.location-nav-search input {
    border: none;
    background: transparent;
    outline: none;
    font-size: 13px;
    font-family: inherit;
    color: var(--text);
    width: 100%;
}
.location-nav-list { max-height: 480px; overflow-y: auto; padding: var(--space-2); }
.location-group { margin-bottom: var(--space-2); }
.location-group-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-secondary);
    padding: var(--space-2) var(--space-2) 4px;
}
.location-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: 7px var(--space-2);
    border-radius: var(--radius-sm);
    color: var(--text);
    text-decoration: none;
    font-size: 13px;
}
.location-item .icon { color: var(--text-secondary); flex-shrink: 0; }
.location-item:hover { background: var(--canvas); }
.location-item.is-active { background: var(--orange-bg); color: var(--orange-dark); font-weight: 600; }
.location-item.is-active .icon { color: var(--orange-dark); }
.location-item-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.location-item-count { font-size: 11px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.location-item.is-active .location-item-count { color: var(--orange-dark); }
.location-nav-empty { padding: var(--space-3); font-size: 13px; color: var(--text-secondary); text-align: center; }
.stock-content { flex: 1; min-width: 0; }

.location-card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-3); }
.location-card {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-4);
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow-sm);
    transition: box-shadow .15s, border-color .15s;
}
.location-card:hover { box-shadow: var(--shadow-md); border-color: #D6DAE1; }
.location-card-name { font-size: 14px; font-weight: 600; margin-bottom: var(--space-2); }
.location-card-stats { display: flex; gap: var(--space-3); margin-bottom: var(--space-3); flex: 1; }
.location-card-stat { display: flex; flex-direction: column; }
.location-card-stat-value { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.location-card-stat-label { font-size: 10px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.02em; }
.location-card-action { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; color: var(--orange-dark); }

/* ============================================================
   Stock dashboard: Quick access + Buildings quick-nav
   ============================================================ */
.dashboard-section { margin-bottom: var(--space-6); }
.dashboard-section-title { font-size: 16px; margin: 0 0 var(--space-3); }
.dashboard-section .page-header { margin-bottom: var(--space-3); }

.quick-access-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-3); }
.quick-access-card {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-4);
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    color: inherit;
    transition: box-shadow .15s, border-color .15s;
}
.quick-access-card:hover { box-shadow: var(--shadow-md); border-color: #D6DAE1; }
.quick-access-card:hover .quick-access-card-arrow { color: var(--orange-dark); transform: translateX(2px); }
.quick-access-card-text { display: flex; flex-direction: column; min-width: 0; }
.quick-access-card-arrow {
    margin-left: auto;
    color: var(--text-secondary);
    display: inline-flex;
    transition: transform .15s, color .15s;
}
.quick-access-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--radius-sm);
    background: var(--orange-bg);
    color: var(--orange-dark);
    flex-shrink: 0;
}
.quick-access-card-name { font-size: 14px; font-weight: 600; }
.quick-access-card-building { font-size: 12px; color: var(--text-secondary); margin-top: 1px; }

.building-nav-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--space-3); }
.building-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-4) var(--space-3);
    text-decoration: none;
    color: inherit;
    box-shadow: var(--shadow-sm);
    transition: box-shadow .15s, border-color .15s, background .15s;
}
.building-button:hover { box-shadow: var(--shadow-md); border-color: #D6DAE1; }
.building-button-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--radius);
    background: var(--info-bg);
    color: var(--info);
}
.building-button-code { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.building-button-meta { font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.02em; }
.building-button.is-active {
    border-color: var(--orange);
    background: var(--orange-bg);
    box-shadow: var(--shadow-md);
}
.building-button.is-active .building-button-icon { background: var(--orange); color: #fff; }
.building-button.is-active .building-button-code { color: var(--orange-dark); }

@media (max-width: 900px) {
    .stock-layout { flex-direction: column; align-items: stretch; }
    .location-nav { width: 100%; }
    .location-nav-list { max-height: 280px; }
    .building-nav-grid { grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); }
}

/* ============================================================
   Dashboard
   Compact and action-first: 1px borders instead of shadows, ~10-12px radii,
   and colour reserved for status and the primary action.
   ============================================================ */
.dash-header { align-items: flex-start; margin-bottom: var(--space-6); }
.dash-greeting { font-size: 22px; font-weight: 700; margin: 0 0 2px; letter-spacing: -0.01em; }
.dash-subtitle { font-size: 13px; color: var(--text-secondary); margin: 0; }
.menu-wrap { position: relative; }

/* Two columns: ~62% / ~38%. */
.dash-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr);
    gap: var(--space-4);
    align-items: start;
}
.dash-col-main, .dash-col-side { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
/* Without a deliveries column the main content takes the full width. */
.dash-grid--single { grid-template-columns: 1fr; }

.panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-4) var(--space-5) var(--space-5);
    min-width: 0;
}
.panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-3); gap: var(--space-3); }
/* Section-label treatment: at 14px/600 the panel headings sat one pixel away
   from the row titles beneath them, so nothing outranked anything. As small
   caps in the secondary colour they frame the content instead of competing
   with it, leaving h1 > KPI values > row titles as the type ramp. */
.panel-header h2 {
    display: flex; align-items: center; margin: 0;
    font-size: 12px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--text-secondary);
}
.panel-note { font-size: 12px; color: var(--text-secondary); margin: var(--space-3) 0 0; }
/* Dashboard panels are narrow: the generic empty state's 32px padding and
   large icon made "nothing here" the biggest thing on the page. */
.panel .empty-state-block { padding: var(--space-5) var(--space-4); }
.panel-link {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 12px; font-weight: 600; color: var(--orange-dark); text-decoration: none;
}
.panel-link:hover { text-decoration: underline; }

/* Today's priorities: icon, title, one supporting line, count on the right. */
.priority-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.priority-row {
    display: flex; align-items: center; gap: var(--space-3);
    padding: 10px var(--space-3);
    /* Filled rows, not outlined ones: a 1px border on every row inside an
       already-bordered panel drew boxes within boxes. The tint separates
       rows and the 3px accent carries the status. */
    background: var(--canvas);
    border-left: 3px solid transparent;
    border-radius: var(--radius-sm);
    text-decoration: none; color: inherit;
    transition: background .15s;
}
.priority-row:hover { background: var(--steel-light); }
.priority-icon { display: inline-flex; flex-shrink: 0; }
.priority-row--danger { border-left-color: var(--danger); }
.priority-row--danger .priority-icon { color: var(--danger-text); }
.priority-row--warning { border-left-color: var(--warning); }
.priority-row--warning .priority-icon { color: var(--warning-text); }
.priority-row--info { border-left-color: var(--info); }
.priority-row--info .priority-icon { color: var(--info); }
.priority-row--success { border-left-color: var(--success); }
.priority-row--success .priority-icon { color: var(--success-text); }
.priority-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.priority-title { font-size: 13px; font-weight: 600; }
.priority-detail { font-size: 12px; color: var(--text-secondary); }
.priority-count {
    flex-shrink: 0; font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
    /* Surface on the tinted row, so the pill stays visible on hover too. */
    background: var(--surface); color: var(--text);
    border-radius: 20px; padding: 1px 10px;
}
.priority-chevron { flex-shrink: 0; color: var(--text-secondary); display: inline-flex; }

/* Equipment health: compact stacked bar + labelled counts. */
.health-bar {
    display: flex; height: 10px; border-radius: 20px; overflow: hidden;
    background: var(--steel-light); margin-bottom: var(--space-3);
}
.health-seg { display: block; height: 100%; }
.health-seg + .health-seg { border-left: 1px solid var(--surface); }
.health-legend {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 6px var(--space-3);
}
.health-legend li { display: flex; align-items: center; gap: var(--space-2); font-size: 12px; min-width: 0; }
.legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.legend-count { font-weight: 700; font-variant-numeric: tabular-nums; }
.legend-label { color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Metric cards: the taller stacked treatment, used by the building summary
   on the Stock building page and the cable-drum pages. The dashboard's own
   summary panel restyles .metric-* under .summary-panel instead. */
.metric-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}
.metric-card {
    display: block;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
    text-decoration: none;
    color: inherit;
    transition: border-color .15s;
}
a.metric-card:hover { border-color: var(--text-secondary); }
.metric-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; border-radius: var(--radius-sm);
    margin-bottom: var(--space-3);
}
.metric-icon.tint-blue { background: var(--info-bg); color: var(--info); }
.metric-icon.tint-green { background: var(--success-bg); color: var(--success-text); }
.metric-icon.tint-red { background: var(--danger-bg); color: var(--danger-text); }
.metric-icon.tint-purple { background: var(--violet-bg); color: var(--violet); }
.metric-value { font-size: 26px; font-weight: 700; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; line-height: 1.15; }
.metric-label { font-size: 13px; font-weight: 500; margin-top: 2px; }
.metric-context { font-size: 12px; color: var(--text-secondary); margin-top: var(--space-2); }

/* Upcoming deliveries: only days that actually have one. */
.delivery-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.delivery-row {
    display: flex; align-items: center; gap: var(--space-3);
    padding: 8px var(--space-2); border-radius: var(--radius-sm);
    text-decoration: none; color: inherit;
}
.delivery-row:hover { background: var(--canvas); }
.delivery-date {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    width: 38px; height: 38px; flex-shrink: 0;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--canvas);
}
.delivery-date.is-today { border-color: var(--orange); background: var(--orange-bg); color: var(--orange-dark); }
.delivery-dow { font-size: 10px; font-weight: 700; letter-spacing: 0.04em; color: var(--text-secondary); }
.delivery-date.is-today .delivery-dow { color: var(--orange-dark); }
.delivery-daynum { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.delivery-text { display: flex; flex-direction: column; min-width: 0; }
.delivery-supplier { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.delivery-meta { font-size: 12px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Loading skeleton primitive */
.skeleton {
    background: linear-gradient(90deg, var(--steel-light) 25%, var(--surface) 37%, var(--steel-light) 63%);
    background-size: 400% 100%;
    animation: skeleton-shimmer 1.4s ease infinite;
    border-radius: var(--radius-sm);
}
.skeleton-text { height: 12px; width: 100%; }
.skeleton-block { height: 80px; width: 100%; }
@keyframes skeleton-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

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

/* Tablet: one dashboard column, a narrower rail and tighter page padding so
   the content keeps its width. */
@media (min-width: 768px) and (max-width: 1023px) {
    :root { --sidebar-width: 184px; }
    .content { padding: var(--space-5) var(--space-4); }
}
@media (max-width: 1023px) {
    .dash-grid { grid-template-columns: 1fr; }
    /* Stacked, the two column wrappers would keep their panels welded
       together in DOM order, leaving "Next drum code" last on a phone -- the
       one number you want before walking out to the store. `display:
       contents` drops the wrappers so every panel becomes a grid item in its
       own right, which is what makes `order` below able to move just one. */
    .dash-col-main, .dash-col-side { display: contents; }
    .panel--codes { order: -1; }
}
@media (max-width: 760px) {
    .dash-header { flex-direction: column; align-items: stretch; }
    .dash-header .page-header-actions { width: 100%; }
    .dash-header .btn-primary { flex: 1; justify-content: center; }
    .panel { padding: var(--space-3) var(--space-4) var(--space-4); }
}
/* Narrow phones: nothing may push the page wider than the viewport. */
@media (max-width: 400px) {
    .health-legend { grid-template-columns: 1fr; }
    .priority-row { gap: var(--space-2); padding: 10px var(--space-2); }
    .delivery-row { gap: var(--space-2); }
}

/* Dashboard "Next drum code": what to write on the next drum in each room.
   Codes are read as a set at a glance, so the row is name + tags rather
   than a table. */
.code-list { list-style: none; margin: 0; padding: 0; }
.code-row {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    padding: 8px var(--space-2); border-radius: var(--radius-sm);
    text-decoration: none; color: inherit;
}
.code-row:hover { background: var(--canvas); }
.code-room { font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.code-tags { display: flex; gap: 6px; flex-shrink: 0; }
.code-tag {
    font-family: 'IBM Plex Mono', 'Courier New', monospace;
    font-size: 12px; font-variant-numeric: tabular-nums;
    padding: 2px 7px; border-radius: var(--radius-sm);
    background: var(--orange-bg); color: var(--orange-dark);
}

/* Product autocomplete: the suggest-as-you-type list that replaced the
   whole-catalogue <datalist> on the scan/pending review screens. Nothing
   shows until typing starts, so it never opens as a giant scroll. */
.autocomplete-wrap { position: relative; display: block; }
.autocomplete-list {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    min-width: min(280px, 90vw);
    max-width: min(420px, 90vw);
    max-height: 280px;
    overflow-y: auto;
    padding: var(--space-1);
    z-index: 45;
}
.autocomplete-item {
    display: block;
    width: 100%;
    padding: 6px var(--space-2);
    border: none;
    border-radius: var(--radius-sm);
    background: transparent;
    font-family: inherit;
    font-size: 13px;
    color: var(--text);
    text-align: left;
    cursor: pointer;
}
.autocomplete-item:hover, .autocomplete-item.is-active { background: var(--canvas); }

/* ============================================================
   Dark enterprise chrome + dashboard
   ------------------------------------------------------------
   The chrome (sidebar, top bar) is dark on every page; the dashboard is
   the one page whose canvas is dark too, via `body.theme-dark`.

   The dark surfaces are applied by REMAPPING the existing design tokens
   inside that scope rather than by rewriting each component: .panel,
   .priority-row, .delivery-row, .code-tag and the rest keep their single
   definition above and pick up dark values here. Only the handful of
   places where a token cannot express the change (hover direction, ink on
   orange) get their own rule.
   ============================================================ */
:root {
    --navy-page: #061224;
    --navy-chrome: #07172C;
    --navy-summary: #0D2643;
    --navy-primary: #102D4F;
    --navy-secondary: #0C223C;

    --dark-text: #F7FAFF;
    --dark-text-secondary: #9FB0C7;
    --dark-border: rgba(255, 255, 255, 0.10);
    --dark-border-strong: rgba(255, 255, 255, 0.18);
    /* Hover/selected washes: lifting the surface with white beats a second
       hard-coded navy, because one value then works over all four panel
       shades. */
    --dark-raise: rgba(255, 255, 255, 0.05);
    --dark-raise-strong: rgba(255, 255, 255, 0.09);

    --blue: #2C8CFF;
    --orange-bright: #FF7417;
    /* Ink for text sitting ON bright orange. White on #FF7417 is 2.7:1 and
       fails AA outright; this is 6.9:1. The light theme already made the
       same call for --orange (see the note beside --orange-hover). */
    --on-orange: #08192E;
    /* Text-safe lifts of the semantic colours for dark surfaces -- the
       --*-text variants near the top of this file are tuned for white
       backgrounds and all fall under 3:1 here. */
    --dark-success-text: #4ADE9B;
    --dark-warning-text: #FFC46B;
    --dark-danger-text: #FF6B75;
}

/* ---- Sidebar: same component, darker palette ---- */
.sidebar {
    --navy: var(--navy-chrome);
    --navy-raised: var(--dark-raise-strong);
    --navy-border: var(--dark-border);
    --navy-text: #9FB0C7;
    --navy-text-muted: #7E90A8;
    border-right: 1px solid var(--dark-border);
}
.nav-item.is-active { color: var(--dark-text); }
.nav-item.is-active .nav-icon { color: var(--blue); }

/* ---- Top bar: dark on every page ---- */
.topbar {
    background: var(--navy-chrome);
    border-bottom: 1px solid var(--dark-border);
    color: var(--dark-text);
}
.topbar-menu-btn { color: var(--dark-text); }
.topbar-search {
    background: rgba(255, 255, 255, 0.04);
    border-color: var(--dark-border);
    border-radius: var(--radius-lg);
}
.topbar-search input { color: var(--dark-text); }
.topbar-search input::placeholder { color: var(--dark-text-secondary); }
.topbar-search-icon { color: var(--dark-text-secondary); }
/* The input clears its own outline, so the ring goes on the wrapper --
   without this, tabbing into search leaves no visible focus at all. */
.topbar-search:focus-within {
    outline: 2px solid var(--blue);
    outline-offset: 2px;
    border-color: transparent;
}
.topbar-search-kbd {
    background: rgba(255, 255, 255, 0.06);
    border-color: var(--dark-border);
    color: var(--dark-text-secondary);
}
.topbar-weather { color: var(--dark-text-secondary); }
.topbar-icon-btn { color: var(--dark-text-secondary); }
.topbar-icon-btn:hover:not(:disabled) { background: var(--dark-raise); color: var(--dark-text); }
.topbar-profile-name { color: var(--dark-text); }
.topbar-profile-btn { color: var(--dark-text-secondary); }
.topbar-profile-btn:hover { background: var(--dark-raise); }
.topbar .avatar {
    background: transparent;
    border: 1px solid var(--orange-bright);
    color: var(--orange-bright);
}
/* Chrome sits on dark, so the default orange focus ring loses contrast
   against the orange avatar and accents; blue is the selection colour
   throughout this palette. */
.topbar :focus-visible,
.sidebar :focus-visible { outline-color: var(--blue); }

/* ============================================================
   Dashboard canvas
   ============================================================ */
/* DORMANT. The dashboard was the only page that set body.theme-dark, and it
   is a light page now, so nothing below applies until some page sets the class
   again. Kept rather than deleted so the dark treatment can be restored in one
   move; do not add to it, and do not rely on it to style anything. */
body.theme-dark {
    --canvas: var(--navy-page);
    --surface: var(--navy-secondary);
    --text: var(--dark-text);
    --text-secondary: var(--dark-text-secondary);
    --border: var(--dark-border);
    --steel-light: var(--dark-raise);
    --muted-bg: var(--dark-raise);

    --orange: var(--orange-bright);
    --orange-bg: rgba(255, 116, 23, 0.12);
    --orange-dark: #FFAE70;
    --info: var(--blue);
    --info-bg: rgba(44, 140, 255, 0.12);
    --success-bg: rgba(22, 163, 106, 0.14);
    --danger-bg: rgba(255, 107, 117, 0.12);
    --warning-bg: rgba(255, 196, 107, 0.12);
    --success-text: var(--dark-success-text);
    --warning-text: var(--dark-warning-text);
    --danger-text: var(--dark-danger-text);

    background: var(--navy-page);
    color: var(--dark-text);
}
body.theme-dark :focus-visible { outline-color: var(--blue); }
/* Ink on the one dominant orange action. */
body.theme-dark .btn-primary { color: var(--on-orange); }
body.theme-dark .btn-primary:hover { background: #FF8A3D; }
body.theme-dark .btn-icon-square {
    background: transparent;
    border-color: var(--dark-border-strong);
    color: var(--dark-text-secondary);
}
body.theme-dark .btn-icon-square:hover { border-color: var(--blue); color: var(--dark-text); }
body.theme-dark .dropdown-menu {
    background: var(--navy-primary);
    border-color: var(--dark-border-strong);
}
body.theme-dark .dropdown-item:hover { background: var(--dark-raise-strong); }

/* ---- Heading + site context ---- */
.theme-dark .dash-greeting { font-size: 28px; letter-spacing: -0.02em; color: var(--dark-text); }
.dash-greeting { font-size: 28px; letter-spacing: -0.02em; }
.dash-context {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: 6px; margin: 6px 0 0;
    font-size: 13px; color: var(--text-secondary);
}
.dash-context-sep { color: var(--muted); }
.status-indicator { display: inline-flex; align-items: center; gap: 6px; }
.status-dot--success { background: var(--success); }
.status-dot--warning { background: var(--warning); }
.status-dot--danger { background: var(--danger); }

/* ---- Section label (QUICK ACTIONS) ---- */
.section-label {
    margin: 0 0 var(--space-3);
    font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--text-secondary);
}

/* ---- Quick actions ---- */
.quick-actions { margin-bottom: var(--space-5); }
.quick-actions-row {
    display: flex; align-items: center; flex-wrap: wrap;
    gap: 0 var(--space-2);
}
.quick-action {
    display: inline-flex; align-items: center; gap: 10px;
    padding: 8px var(--space-4) 8px 0;
    background: none; border: none; font-family: inherit;
    font-size: 14px; color: var(--text); text-decoration: none;
    cursor: pointer; border-radius: var(--radius-sm);
}
/* Divider between the actions rather than a border around each: three
   outlined cards read as three more panels competing with the summary. */
.quick-action + .quick-action { padding-left: var(--space-4); border-left: 1px solid var(--border); }
.quick-action-icon {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; flex-shrink: 0;
    border: none; border-radius: var(--radius-sm);
    color: var(--info); background: var(--info-bg);
}
.quick-action:hover { color: var(--orange-dark); }
.quick-action:hover .quick-action-icon { background: var(--orange-bg); color: var(--orange-dark); }
.quick-action:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

/* ---- Summary panel: one divided row, not four cards ---- */
.summary-panel {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: var(--shadow-raised);
    margin-bottom: var(--space-5);
}
.summary-panel .metric {
    display: flex; align-items: center; gap: var(--space-3);
    min-width: 0;
    padding: var(--space-4) var(--space-5);
    text-decoration: none; color: inherit;
    border-radius: 12px;
}
.summary-panel .metric + .metric { border-left: 1px solid var(--border); border-radius: 0; }
/* A recess, not a lift: a white wash on white does nothing. */
.summary-panel .metric:hover { background: var(--canvas); }
.summary-panel .metric:focus-visible { outline: 2px solid var(--orange); outline-offset: -2px; }
.summary-panel .metric-icon {
    width: 44px; height: 44px; flex-shrink: 0; margin-bottom: 0;
    border-radius: 10px; border: none;
    color: var(--info); background: var(--info-bg);
}
.summary-panel .metric-icon--orange {
    color: var(--orange-dark); background: var(--orange-bg);
}
.summary-panel .metric-icon--success {
    color: var(--success-text); background: var(--success-bg);
}
.summary-panel .metric-body { display: flex; flex-direction: column; min-width: 0; }
.summary-panel .metric-value {
    font-size: 30px; font-weight: 700; color: var(--text);
    letter-spacing: -0.02em; line-height: 1.12;
}
.summary-panel .metric-label { font-size: 13px; font-weight: 500; color: var(--text); margin-top: 1px; }
.summary-panel .metric-context {
    margin-top: 3px; font-size: 12px; color: var(--text-secondary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The one place orange is allowed outside the primary action: a real count
   of things needing attention. */
.summary-panel .metric-context--orange { color: var(--orange-dark); }

/* ---- Panels ----
   Elevation carries the hierarchy on light: a 1px contact edge under a
   two-layer shadow. The dark page ranked the primary panel with a LIGHTER
   fill; on white the only direction left is darker, which reads as sunken,
   so it is ranked by depth and a 2px rule instead. */
.dash-grid .panel, .panel--crew { box-shadow: var(--shadow-panel); }
.panel--primary {
    box-shadow: var(--shadow-raised);
    border-top: 2px solid var(--orange);
}
.dash-grid { gap: var(--space-5); }
.dash-col-main, .dash-col-side { gap: var(--space-5); }
.panel-link { color: var(--steel-text); }
.panel-link:hover { color: var(--orange-dark); }

/* ---- Panels ---- */
.theme-dark .panel {
    background: var(--navy-secondary);
    border-color: var(--dark-border);
    border-radius: 12px;
}
/* Today's priorities is the strongest panel on the page: a lighter surface
   is what ranks it above the two beside it. */
.theme-dark .panel--primary { background: var(--navy-primary); }
.theme-dark .panel--health { margin-top: var(--space-4); }
.theme-dark .panel-title { color: var(--dark-text-secondary); }
.theme-dark .panel-link { color: var(--blue); font-weight: 500; }
/* --blue clears 4.5:1 on the page and on the secondary panels, but the
   primary panel is a lighter surface and drops it to 4.2:1. One step
   lighter there rather than lightening the link colour everywhere. */
.theme-dark .panel--primary .panel-link { color: #57A4FF; }
.theme-dark .panel-link:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

/* ---- Priorities ---- */
.theme-dark .priority-row {
    background: var(--dark-raise);
    border: 1px solid var(--dark-border);
    border-left-width: 3px;
    border-radius: 10px;
    padding: 12px var(--space-3);
}
.theme-dark .priority-row:hover { background: var(--dark-raise-strong); }
.theme-dark .priority-row:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.theme-dark .priority-title { font-size: 14px; color: var(--dark-text); }
.theme-dark .priority-detail { color: var(--dark-text-secondary); margin-top: 1px; }
.theme-dark .priority-count {
    background: var(--dark-raise-strong); color: var(--dark-text);
    border: 1px solid var(--dark-border);
}
.theme-dark .priority-chevron { color: var(--dark-text-secondary); }

/* ---- Upcoming delivery ---- */
.theme-dark .delivery-row { border-radius: 10px; padding: 10px var(--space-2); }
.theme-dark .delivery-row:hover { background: var(--dark-raise); }
.theme-dark .delivery-row:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.theme-dark .delivery-date { background: transparent; border-color: var(--dark-border-strong); }
.theme-dark .delivery-date.is-today {
    border-color: var(--orange-bright); background: rgba(255, 116, 23, 0.10); color: var(--orange-dark);
}
.theme-dark .delivery-supplier { color: var(--dark-text); }

/* ---- Next drum code ---- */
.theme-dark .code-row { border-radius: 10px; }
.theme-dark .code-row:hover { background: var(--dark-raise); }
.theme-dark .code-row:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.theme-dark .code-room { color: var(--dark-text); }

/* ---- Equipment health ---- */
.theme-dark .health-bar { background: var(--dark-raise); border-radius: 999px; height: 10px; overflow: hidden; }
.theme-dark .health-seg + .health-seg { border-left-color: var(--navy-secondary); }
.theme-dark .legend-count { color: var(--dark-text); }
.theme-dark .legend-label { color: var(--dark-text-secondary); }
.theme-dark .empty-state-block { color: var(--dark-text-secondary); }
.theme-dark .flash-message {
    background: var(--navy-primary); border-color: var(--dark-border); color: var(--dark-text);
}

/* ============================================================
   Dashboard responsive
   ------------------------------------------------------------
   The summary panel is the one genuinely new layout risk: four cells in a
   single row cannot survive a phone, so it steps 4 -> 2 -> 1 and swaps its
   vertical dividers for horizontal ones on the way down.
   ============================================================ */
@media (max-width: 1100px) {
    .summary-panel { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .summary-panel .metric + .metric { border-left: none; }
    .summary-panel .metric:nth-child(even) { border-left: 1px solid var(--border); }
    .summary-panel .metric:nth-child(n + 3) { border-top: 1px solid var(--border); }
}
@media (max-width: 760px) {
    .dash-greeting { font-size: 24px; }
    .quick-action { padding-right: var(--space-3); }
    .quick-action + .quick-action { padding-left: var(--space-3); }
}
@media (max-width: 560px) {
    .summary-panel { grid-template-columns: minmax(0, 1fr); }
    .summary-panel .metric:nth-child(even) { border-left: none; }
    .summary-panel .metric + .metric { border-top: 1px solid var(--border); }
    .summary-panel .metric { padding: var(--space-3) var(--space-4); }
    .summary-panel .metric-value { font-size: 26px; }
    /* Stacked, each action takes its own line rather than sharing a rule. */
    .quick-actions-row { flex-direction: column; align-items: stretch; }
    .quick-action + .quick-action { padding-left: 0; border-left: none; border-top: 1px solid var(--border); }
}

/* ============================================================
   Bulk add equipment (/equipment/bulk-add) and stock (/stock/<id>/bulk-add)
   ------------------------------------------------------------
   Two cards (shared hire details, one row per machine) and a footer
   with the live count. Everything reads the shared tokens, so the
   dark theme's token remapping covers this page too.
   ============================================================ */
.bulk-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 18px 20px;
    margin-bottom: 16px;
    max-width: 900px;
}
.bulk-card-title { font-size: 15px; font-weight: 600; margin: 0 0 2px; }
.bulk-card-hint { font-size: 13px; color: var(--text-secondary); margin: 0 0 14px; }
.bulk-form-row { margin-bottom: 0; }
.bulk-grid-2 { display: grid; gap: 14px; grid-template-columns: minmax(220px, 1.4fr) minmax(200px, 1.2fr); }
.bulk-grid-3 {
    display: grid; gap: 14px; margin-top: 14px; align-items: end;
    grid-template-columns: repeat(2, minmax(150px, 1fr)) auto;
}
.bulk-check { padding-bottom: 10px; white-space: nowrap; }

.bulk-table { width: 100%; border-collapse: collapse; }
.bulk-table th {
    text-align: left; background: var(--canvas); padding: 8px 10px;
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase;
    color: var(--text); border-bottom: 1px solid var(--border);
}
.bulk-table td { padding: 5px 4px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.bulk-table input {
    width: 100%; box-sizing: border-box; height: 36px; padding: 0 10px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font-size: 13.5px; font-family: inherit; background: var(--surface); color: var(--text);
}
.bulk-table input.mono { font-family: 'IBM Plex Mono', 'Courier New', monospace; }
.bulk-col-num { width: 30px; }
.bulk-col-plant { width: 26%; }
.bulk-col-date { width: 20%; }
.bulk-col-x { width: 34px; }
/* The stock bulk add (/stock/<id>/bulk-add) carries more boxes per row than
   the equipment one, so its columns get their own widths — the item name
   takes whatever the fixed ones leave. */
.bulk-col-code { width: 15%; }
.bulk-col-qty { width: 12%; }
.bulk-col-unit { width: 13%; }
.bulk-col-shelf { width: 10%; }
.bulk-rownum {
    color: var(--muted); font-size: 12.5px; text-align: center;
    font-family: 'IBM Plex Mono', monospace;
}
.bulk-row-missing input[name="plant_number"] { border-color: var(--danger); }
.bulk-row-remove {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 30px; border: none; border-radius: var(--radius-sm);
    background: transparent; color: var(--muted); cursor: pointer;
}
.bulk-row-remove:hover { background: var(--danger-bg); color: var(--danger-text); }

.bulk-row-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.bulk-paste-panel {
    margin-top: 12px; padding: 14px; border: 1px dashed var(--border);
    border-radius: var(--radius-sm); background: var(--canvas);
}
.bulk-paste-panel label { display: block; font-size: 13px; color: var(--text-secondary); margin-bottom: 8px; }
.bulk-paste-panel textarea {
    width: 100%; box-sizing: border-box; padding: 8px 10px;
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    font-size: 13.5px; font-family: 'IBM Plex Mono', 'Courier New', monospace;
    background: var(--surface); color: var(--text); resize: vertical;
}
.bulk-paste-actions { display: flex; gap: 8px; margin-top: 10px; }

.bulk-footer {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    max-width: 900px; border-top: 1px solid var(--border); padding-top: 16px;
}
.bulk-count { font-size: 13.5px; color: var(--text-secondary); margin-right: auto; }

@media (max-width: 640px) {
    .bulk-grid-2, .bulk-grid-3 { grid-template-columns: 1fr; }
    .bulk-check { padding-bottom: 0; }
}

/* Flash variants: the default .flash-message stays the red style every
   existing flash() call already relies on; these apply only when a route
   passes a category, e.g. flash(msg, 'success'). */
.flash-success { background: var(--success-bg); color: var(--success-text); border-color: var(--success); }
.flash-warning { background: var(--warning-bg); color: var(--warning-text); border-color: var(--warning); }
.theme-dark .flash-success { background: var(--navy-primary); border-color: var(--success); color: var(--dark-text); }
.theme-dark .flash-warning { background: var(--navy-primary); border-color: var(--warning); color: var(--dark-text); }

/* ============================================================
   Fit-out (EC5 switchrooms)

   Supplying material into rooms being fitted out. The checklist is used
   on phones on site, so its controls are finger-sized; everything else
   reuses the house card/table/bar language.
   ============================================================ */

/* --- overview: room cards --- */
.fo-rooms {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: var(--space-3); margin: var(--space-5) 0 var(--space-6);
}
.fo-room {
    display: flex; flex-direction: column; gap: 10px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: var(--space-4);
    text-decoration: none; color: var(--text);
}
a.fo-room:hover { border-color: var(--text-secondary); box-shadow: var(--shadow-sm); }
.fo-room--empty {
    border-style: dashed; align-items: center; justify-content: center;
    text-align: center; color: var(--text-secondary); font-size: 13px; min-height: 130px;
}
.fo-room-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.fo-room-name { font-size: 14.5px; font-weight: 600; }
.fo-room-progress { display: flex; align-items: center; gap: 12px; }
.fo-room-progress .health-bar { flex: 1; }
.fo-room-pct { font-size: 24px; font-weight: 700; min-width: 58px; }
.fo-room-meta { font-size: 12.5px; color: var(--text-secondary); }
.fo-room-meta b { color: var(--text); font-size: 13.5px; }
.fo-open { font-size: 12.5px; font-weight: 600; color: var(--orange-dark); margin-top: auto; }

.fo-h2 { font-size: 15px; margin: var(--space-6) 0 var(--space-2); }
.fo-num { text-align: right; }
.data-table th.fo-num { text-align: right; }

/* --- status pills: dot + words, never colour alone --- */
.fo-pill {
    display: inline-flex; align-items: center; gap: 6px; padding: 2px 9px;
    border-radius: 20px; font-size: 11.5px; font-weight: 600; white-space: nowrap;
}
.fo-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.fo-pill--ok { background: var(--success-bg); color: var(--success-text); }
.fo-pill--part { background: var(--warning-bg); color: var(--warning-text); }
.fo-pill--none { background: var(--muted-bg); color: var(--text-secondary); }

/* --- room checklist --- */
.fo-checklist { max-width: 620px; }
.fo-progress-head {
    display: flex; align-items: center; gap: var(--space-4);
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 12px var(--space-4);
    margin-bottom: var(--space-3);
}
.fo-progress-body { flex: 1; display: flex; flex-direction: column; gap: 6px; }
.fo-progress-count { font-size: 12.5px; color: var(--text-secondary); }
.fo-progress-count b { color: var(--text); }

.fo-sec {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); margin-bottom: var(--space-3); overflow: hidden;
}
.fo-sec summary {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 12px var(--space-4); cursor: pointer; list-style: none;
}
.fo-sec summary::-webkit-details-marker { display: none; }
.fo-sec summary b {
    font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em;
}
.fo-sec-side { display: inline-flex; align-items: center; gap: 8px; }
.fo-sec-caret { color: var(--muted); display: inline-flex; transition: transform .15s ease; }
.fo-sec[open] .fo-sec-caret { transform: rotate(180deg); }
.fo-sec[open] summary { border-bottom: 1px solid var(--border); }
.fo-chip-count {
    font-family: 'IBM Plex Mono', 'Courier New', monospace; font-size: 11.5px; font-weight: 600;
    background: var(--muted-bg); border-radius: 20px; padding: 2px 9px; color: var(--text-secondary);
}
.fo-chip-count.is-done { background: var(--success-bg); color: var(--success-text); }

.fo-line { padding: 11px var(--space-4) 12px; }
.fo-line + .fo-line { border-top: 1px solid var(--steel-light); }
.fo-line-main { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.fo-line-name { font-size: 14px; font-weight: 500; }
.fo-line-qty { font-size: 12.5px; color: var(--text-secondary); white-space: nowrap; }
.fo-line-qty b { font-size: 13.5px; color: var(--text); font-weight: 600; }
.fo-line-bar {
    display: flex; height: 6px; border-radius: 20px; overflow: hidden;
    background: var(--steel-light); margin-top: 7px;
}
.fo-line-bar span { display: block; height: 100%; background: var(--warning); transition: width .25s ease; }
.fo-line.is-done .fo-line-bar span { background: var(--success); }
.fo-line.is-done .fo-line-name { color: var(--text-secondary); }
.fo-line.is-saving { opacity: .6; }
.fo-line-foot {
    display: flex; align-items: center; gap: 8px; margin-top: 8px; min-height: 26px;
}
.fo-line-stamp { font-size: 12px; color: var(--success-text); font-weight: 500; }
.fo-line-actions { display: flex; gap: 6px; margin-left: auto; }

/* Finger-sized chip buttons: the checklist is worked on a phone with
   gloves nearby, so these stay bigger than the desktop .btn-sm. */
.fo-chip {
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--border); background: var(--surface); color: var(--text);
    font-family: inherit; font-size: 13px; font-weight: 600;
    border-radius: 20px; padding: 6px 14px; cursor: pointer; min-height: 32px;
}
.fo-chip:hover { border-color: var(--text-secondary); }
.fo-chip--primary { background: var(--orange); border-color: var(--orange); color: var(--text); }
.fo-chip--primary:hover { background: var(--orange-hover); border-color: var(--orange-hover); }
.fo-chip--quiet { border-color: transparent; color: var(--text-secondary); padding: 4px 8px; min-height: 26px; font-size: 12px; }
.fo-chip--quiet:hover { color: var(--danger-text); border-color: transparent; }

.fo-addrow { display: flex; gap: 8px; margin-top: 9px; }
.fo-addrow[hidden] { display: none; }
.fo-addrow input {
    flex: 1; min-width: 0; min-height: 38px; border: 1px solid var(--border);
    border-radius: var(--radius-sm); padding: 0 10px; font-size: 14px;
    font-family: 'IBM Plex Mono', 'Courier New', monospace;
    background: var(--surface); color: var(--text);
}
.fo-note { margin: 6px 0 0; font-size: 12px; color: var(--warning-text); }

/* --- daily report --- */
.fo-daynav a { color: var(--orange-dark); text-decoration: none; }
.fo-daynav a:hover { text-decoration: underline; }
.fo-daynav-today { font-weight: 600; color: var(--text); }
.fo-dayroom { margin-top: var(--space-5); }
.fo-dayroom-head {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 10px; flex-wrap: wrap; margin-bottom: var(--space-2);
}
.fo-dayroom-head h2 { font-size: 15px; margin: 0; }
.fo-dayroom-head h2 a { color: var(--text); text-decoration: none; }
.fo-dayroom-head h2 a:hover { color: var(--orange-dark); }
.fo-dayroom-head > span { font-size: 12.5px; color: var(--text-secondary); }
.fo-dayroom-head > span a { color: var(--orange-dark); text-decoration: none; }

/* --- leader page --- */
.fo-leaderhead { display: flex; align-items: center; gap: 14px; margin: 12px 0 var(--space-4); }
.fo-avatar {
    width: 44px; height: 44px; border-radius: 50%; border: 2px solid var(--orange);
    color: var(--orange-dark); display: grid; place-items: center;
    font-weight: 700; font-size: 16px; flex-shrink: 0;
}

/* --- edit targets --- */
.fo-target-input { max-width: 110px; text-align: right; }
.fo-addline {
    display: grid; grid-template-columns: 1fr 1.4fr 0.7fr 0.7fr; gap: var(--space-3);
    max-width: 760px;
}
.fo-addline .form-row { margin-bottom: 0; }
@media (max-width: 700px) {
    .fo-addline { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 640px) {
    .fo-progress-head { padding: 10px 14px; }
    .fo-room-pct { font-size: 21px; min-width: 50px; }
}

/* ============================================================
   Dashboard, light: the crew band and the code card
   ============================================================ */

/* The health bar's segment colours come from domain.py as token names, and
   those tokens were tuned for a navy track. On a #EEF1F4 track the amber is
   the WEAKEST segment at 1.89:1 when it was the strongest on navy, so the
   bar and its legend get their own light fills. Words sit beside every
   count, so colour is never the only carrier. */
.panel--health .health-seg[style*="--warning"],
.legend-dot[style*="--warning"] { background: var(--warning-text) !important; }
.panel--health .health-seg[style*="--muted"],
.legend-dot[style*="--muted"] { background: var(--steel-text) !important; }

/* ---- On site now: a band, not a column ----
   Fifteen people across the page in five short rows. The same list down the
   narrow column runs ~900px and leaves a hole beside it. */
.panel--crew { margin-bottom: var(--space-5); }
.crew-stamp {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 12px; color: var(--text-secondary);
}
.crew-states { display: flex; gap: var(--space-3); margin-bottom: var(--space-4); flex-wrap: wrap; }
.crew-state {
    flex: 1 1 130px; padding: 10px var(--space-4);
    background: var(--canvas); border-radius: var(--radius-sm);
    border-left: 3px solid var(--border);
}
.crew-state-value {
    display: block; font-size: 24px; font-weight: 700;
    letter-spacing: -0.02em; line-height: 1.15; font-variant-numeric: tabular-nums;
}
.crew-state-label { display: block; font-size: 12px; color: var(--text-secondary); }
.crew-state--in { border-left-color: var(--success); }
.crew-state--in .crew-state-value { color: var(--success-text); }
.crew-state--out .crew-state-value { color: var(--text-secondary); }
.crew-state--flag { border-left-color: var(--warning); background: var(--warning-bg); }
.crew-state--flag .crew-state-value { color: var(--warning-text); }
.crew-state--clear { border-left-color: var(--success); }
.crew-state--clear .crew-state-value { color: var(--success-text); }

.crew-grid {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2);
}
.crew-chip {
    display: flex; align-items: center; gap: 10px; min-width: 0;
    padding: 9px var(--space-3);
    background: var(--canvas); border-radius: var(--radius-sm);
    border-left: 3px solid var(--success);
}
/* Flagged people sort to the front and wear the tint: someone on site who is
   not on the pre-start is the reason to look at this panel at all. */
.crew-chip--flag { border-left-color: var(--warning); background: var(--warning-bg); }
/* Been and gone: the same chip drained of the live green -- these people are
   accounted for, so the list reads as the day's memory, not status. */
.crew-chip--gone { border-left-color: var(--border-strong); }
.crew-chip--gone .crew-dot { background: var(--muted); }
.crew-chip--gone .crew-name { color: var(--text-secondary); }
/* The "Clocked out" tile becomes a link when there is a list to jump to. */
a.crew-state { display: block; text-decoration: none; color: inherit; }
a.crew-state:hover { background: var(--steel-light); }
.crew-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); flex: none; }
.crew-chip--flag .crew-dot { background: var(--warning-text); }
.crew-who { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.crew-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crew-name a { color: inherit; text-decoration: none; }
.crew-name a:hover { text-decoration: underline; }
.crew-meta { font-size: 12px; color: var(--text-secondary); }
.crew-chip--flag .crew-meta { color: var(--warning-text); font-weight: 500; }
.crew-since {
    flex: none; font-size: 12px; font-weight: 600;
    color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
@media (max-width: 1100px) { .crew-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) { .crew-grid { grid-template-columns: 1fr; } }

/* ---- Code card: last used and next free, together ---- */
.code-group {
    margin: var(--space-4) 0 var(--space-2);
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.06em; color: var(--muted);
}
.code-group:first-of-type { margin-top: 0; }
.code-row--static { cursor: default; }
.code-pair { display: inline-flex; align-items: baseline; gap: 5px; }
.code-was {
    font-family: 'IBM Plex Mono', monospace; font-size: 11.5px;
    color: var(--muted); text-decoration: line-through;
}
.code-arrow { color: var(--muted); font-size: 10px; }
.code-lbl {
    font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--muted);
}
.code-plain {
    font-family: 'IBM Plex Mono', monospace; font-size: 12.5px;
    font-weight: 600; color: var(--text);
}
.code-sub { display: block; font-size: 11.5px; color: var(--text-secondary); }
/* The one number free everywhere, given its own block: a room's own "last+1"
   is not necessarily safe, because product codes are unique system-wide. */
.code-next-free {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-3); margin-top: var(--space-2);
    padding: 10px var(--space-3);
    background: var(--orange-bg); border: 1px solid #FBCFAE;
    border-radius: var(--radius-sm);
}
.cnf-text { display: flex; flex-direction: column; font-size: 12.5px; font-weight: 600; }
.cnf-hint { font-size: 11px; font-weight: 400; color: var(--warning-text); }
.cnf-code {
    font-size: 19px; font-weight: 700; color: var(--orange-dark);
    font-variant-numeric: tabular-nums;
}

/* ============================================================
   Timesheets view (Day / Week / Month)
   ============================================================ */
.ts-toolbar {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    margin: 16px 0;
}
.view-seg {
    display: inline-flex; gap: 2px; padding: 3px;
    background: var(--steel-light); border-radius: var(--radius);
}
.view-seg a {
    padding: 6px 16px; border-radius: var(--radius-sm);
    font-size: 13px; font-weight: 600; color: var(--text-secondary);
    text-decoration: none;
}
.view-seg a:hover { color: var(--text); }
.view-seg a.is-active {
    background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm);
}
.ts-datenav { display: inline-flex; align-items: center; gap: 8px; }
.ts-arrow {
    width: 30px; height: 30px; border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong); background: var(--surface);
    color: var(--text-secondary); display: inline-flex;
    align-items: center; justify-content: center; text-decoration: none;
}
.ts-arrow:hover { color: var(--text); border-color: var(--steel); }
.ts-range { font-weight: 700; font-size: 14.5px; }
.ts-today {
    font-size: 12px; font-weight: 600; color: var(--text-secondary);
    border: 1px solid var(--border-strong); background: var(--surface);
    border-radius: 999px; padding: 4px 12px; text-decoration: none;
}
.ts-today:hover { color: var(--text); }
.card-of { font-size: 14px; font-weight: 600; color: var(--text-secondary); }

/* Status badges, in the app's badge idiom */
.badge-ts-ok { border-left-color: var(--success); background: var(--success-bg); color: var(--success-text); }
.badge-ts-ot { border-left-color: var(--orange); background: var(--orange-bg); color: var(--orange-dark); }
.badge-ts-missing { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger-text); }
.badge-ts-absent { border-left-color: var(--muted); background: var(--muted-bg); color: var(--steel-text); }
.badge-ts-excluded { border-left-color: var(--muted); background: var(--muted-bg); color: var(--steel-text); }

/* Week grid. The th needs its own rule (.data-table th outweighs a lone
   class) and a stronger tint than the tds, or the weekend band reads as
   starting one row down. */
.ts-wkend { background: var(--muted-bg); }
.data-table th.ts-wkend { background: var(--border); }
.ts-code { font-size: 11px; color: var(--text-secondary); margin-left: 4px; }
.ts-daylink { color: inherit; text-decoration: none; }
.ts-daylink:hover { color: var(--orange-dark); text-decoration: underline; }
.ot-dot {
    display: inline-block; width: 6px; height: 6px; border-radius: 50%;
    background: var(--orange); margin-left: 5px; vertical-align: 2px;
}
.edit-dot {
    display: inline-block; width: 6px; height: 6px; border-radius: 50%;
    background: var(--info); margin-left: 5px; vertical-align: 2px;
}
.badge-ts-edited { border-left-color: var(--info); background: var(--info-bg); color: var(--steel-text); }

/* Every week cell is a link to that person+day's edit page. Block-sized to
   swallow the td's padding so the whole cell is the tap target, not just
   the two-character label inside it. */
.ts-cellink {
    /* Margins mirror .data-table td's 9px 14px padding exactly. */
    display: block; margin: -9px -14px; padding: 9px 14px;
    color: inherit; text-decoration: none;
}
.ts-cellink:hover { background: var(--info-bg); }

/* The edit page's live sums line */
.ts-editcalc {
    background: var(--muted-bg); border-radius: var(--radius-sm);
    padding: 10px 14px; font-size: 13px; margin: 4px 0 16px;
}

/* Month grid: a square per person per day. Grid, not a table -- 31 columns
   of 16px squares, and the day-number header row shares the same track. */
.ts-monthwrap {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius-lg); box-shadow: var(--shadow-sm);
    padding: 16px 18px 12px; overflow-x: auto;
}
.ts-mrow { display: flex; align-items: center; gap: 14px; padding: 5px 0; }
/* Rows must take the scroll width, not the visible width: block children of
   an overflow-x container size to the viewport, so without this the row
   separators (and the legend's top border) stop mid-air once the grid
   scrolls sideways on a narrow screen. */
.ts-mrow, .ts-legend { min-width: max-content; }
.ts-mrow + .ts-mrow { border-top: 1px solid var(--steel-light); }
.ts-mrow--head { border-top: 0; }
.ts-mname { width: 190px; flex: none; font-size: 13px; line-height: 1.3; }
.ts-mname b { font-weight: 600; display: block; }
.ts-mgrid {
    /* --ts-days is set inline per month, so February gets 28 tracks
       rather than three phantom columns of dead space. */
    display: grid; grid-template-columns: repeat(var(--ts-days, 31), 16px);
    gap: 3px; flex: none;
}
.ts-mnum {
    font-size: 9px; color: var(--text-secondary); text-align: center;
    line-height: 16px; font-variant-numeric: tabular-nums;
}
.ts-mnum.is-weekend { color: var(--muted); }
.ts-mday { width: 16px; height: 16px; border-radius: 4px; display: block; }
.ts-mday--worked { background: var(--navy-raised); }
.ts-mday--ot { background: var(--orange); }
.ts-mday--missing { background: var(--danger-bg); border: 1px solid var(--danger); }
.ts-mday--absent { background: var(--muted-bg); border: 1px solid var(--border); }
.ts-mday--weekend { background: var(--steel-light); opacity: 0.55; }
.ts-mtotal {
    margin-left: auto; font-size: 12.5px; font-weight: 600;
    white-space: nowrap; font-variant-numeric: tabular-nums;
}
.ts-legend {
    display: flex; gap: 18px; flex-wrap: wrap; margin-top: 14px;
    padding-top: 12px; border-top: 1px solid var(--border);
}
.ts-legend span {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px; color: var(--text-secondary);
}
.ts-legend i { width: 13px; height: 13px; border-radius: 3.5px; display: inline-block; }
