/* ═══════════════════════════════════════════════════════════════════
   site.css — Sundowners admin shell + shared components.
   Every colour, spacing and radius flows from tokens.css (no literals).
   Implements the .dc.html markup; responsive at 1440 / 768 / 375.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Base / rescale to the compact admin type scale the design uses ── */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html, body {
    height: 100%;
    font-family: var(--font-body);
    color: var(--so-text-1);
    font-size: 13px;            /* admin scale (design body) */
    line-height: 1.45;
    background: var(--so-app-bg);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.reservation-text-editor__insertions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}
h1, h2, h3, h4, h5, h6 { font-family: var(--font-display); color: var(--so-text-1); margin: 0; }
::selection { background: var(--so-coral-tint); }

/* design scrollbar */
.so-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
.so-scroll::-webkit-scrollbar-thumb { background: #CFCAC4; border: 3px solid var(--white); }
.so-scroll::-webkit-scrollbar-track { background: transparent; }
.so-scroll { scrollbar-width: thin; scrollbar-color: #CFCAC4 transparent; }

/* ══════════ APP SHELL ══════════ */

/* ── Work Packet 0.59 (a11y): skip-to-content link ──
   Visually hidden until focused by keyboard; jumps past the sidebar/topbar
   straight to #main. Token-only; no layout impact when idle.

   BH #210 — the first keyboard focus on every shell page must land here and the
   focused state must be fully visible within the viewport, above content and
   not clipped by the top bar or sidebar. `position: fixed` (not absolute) makes
   the link relative to the viewport itself, so neither the `.app` flex column
   nor any ancestor's `overflow: hidden` can push or clip it; the focused state
   sits at a concrete in-viewport offset (top: 8px) so its bounding box has
   `top >= 0` and `bottom <= viewport height`. Idle state is moved fully off the
   top edge via a clipped 1px box so it never flashes on paint. */
.skip-link {
    position: fixed;
    left: var(--space-8);
    top: var(--space-8);
    z-index: 100;
    /* Idle: collapse to a zero-footprint box off the top edge so there is no
       layout/scrollbar impact and no paint flash; the link is still in the DOM
       and first in tab order. */
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
    background: var(--so-card);
    color: var(--so-text-1);
    font-weight: 700;
    font-size: 13px;
    text-decoration: none;
}
.skip-link:focus,
.skip-link:focus-visible {
    /* Restored to a visible, in-viewport chip above all content. */
    width: auto;
    height: auto;
    margin: 0;
    padding: var(--space-8) var(--space-16);
    clip: auto;
    overflow: visible;
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 2px;
}

/* ── Work Packet 0.59 (a11y): visible keyboard focus on interactive elements ──
   A single token-driven :focus-visible ring so Tab navigation is visible in
   both themes. Component-specific :focus-visible rules below (sidebar toggle,
   theme seg, copy-btn, role-pick, kpi/report tiles) keep their own rings —
   higher specificity wins; this is the shared baseline for everything else
   (links, buttons, inputs, selects, textareas, nav items, tabs, row actions). */
a:focus-visible, button:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible,
[tabindex]:focus-visible,
.nav-item:focus-visible, .bk-tabs__tab:focus-visible, .pager__btn:focus-visible {
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 2px;
    border-radius: 0;
}

/* BugHerd #334 - the shell must occupy the space LEFT OVER below the demo banner, not the whole
   viewport. `.app` was `height: 100vh` while `#demoBanner` sits above it as an in-flow sibling, so
   every page in the app was exactly banner-height taller than the window: measured 941px against a
   900px viewport, i.e. 41px of blank space you could scroll the entire shell up into. The banner
   wraps at narrow widths, so its height is NOT a constant and no `calc(100vh - 41px)` would be
   correct - body becomes the flex column and the shell simply takes the remainder.
   `min-height: 0` is required because a flex item defaults to `min-height: auto`, which would
   refuse to shrink below its content and reinstate the overflow. `.app` is the ONLY place the
   viewport height enters the shell: `.sidebar` and `.app__main` are height:100% off it and
   `.content` is the flex-sized inner scroller, so they all follow automatically. Dropping the
   `100vh` also fixes the usual mobile-toolbar overshoot for free. */
body { display: flex; flex-direction: column; }

.app {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    overflow: hidden;
}

.app__scrim {
    display: none;
    position: fixed;
    inset: 0;
    background: var(--scrim-45);
    border: 0;
    padding: 0;
    cursor: default;
    z-index: 40;
}

/* ── Sidebar ── */
.sidebar {
    flex: none;
    width: var(--so-sidebar-width);
    background: var(--so-sidebar);
    color: var(--white);
    display: flex;
    flex-direction: column;
    height: 100%;
}
.sidebar__brand {
    padding: var(--space-16) var(--space-16) calc(var(--space-16) - 2px);
    border-bottom: var(--so-sidebar-rule) solid var(--so-sidebar-rule);
}
.sidebar__brand-name {
    display: block;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 16px;
    line-height: 1.15;
    letter-spacing: 0.01em;
}
.sidebar__brand-accent { color: var(--so-overland); }
.sidebar__brand-sub {
    display: block;
    font-size: 11px;
    color: var(--so-nav-sub);
    margin-top: 3px;
    letter-spacing: 0.03em;
}
.sidebar__nav {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--space-8) 0 var(--space-16);
}
.sidebar__footer {
    padding: var(--space-8) var(--space-16);
    border-top: var(--so-sidebar-rule) solid var(--so-sidebar-rule);
    font-size: 11px;
    color: var(--so-nav-footer);
    line-height: 1.5;
}

.nav-group { padding: var(--space-8) 0; }
.nav-group__label {
    padding: var(--space-8) var(--space-16) var(--space-4);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--so-nav-group);
}
.nav-group__items { list-style: none; margin: 0; padding: 0; }
.nav-item {
    display: flex;
    align-items: center;
    gap: var(--space-8);
    padding: 8px var(--space-16);
    color: #DDE3E4;
    text-decoration: none;
    font-size: 13px;
    line-height: 1.2;
    border-left: 3px solid transparent;
    transition: background-color .12s ease, color .12s ease;
}
.nav-item:hover { background: rgba(255,255,255,0.05); color: var(--white); }
.nav-item__icon {
    width: 18px; height: 18px; flex: none;
    display: flex; align-items: center; justify-content: center;
    color: currentColor; opacity: 0.9;
}
.nav-item__icon svg { width: 18px; height: 18px; }
.nav-item__label { flex: 1 1 auto; min-width: 0; }
.nav-item__badge {
    margin-left: auto;
    font-size: 10.5px; font-weight: 700;
    background: var(--so-nav-badge-bg);
    color: var(--so-nav-badge-fg);
    padding: 1px 6px; min-width: 18px; text-align: center;
}
.nav-item--active {
    background: var(--so-nav-active);
    color: var(--white);
    border-left-color: var(--so-coral);
    font-weight: 600;
}

/* ── Main column ── */
.app__main {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    height: 100%;
    min-width: 0;               /* lets content shrink + scroll instead of the page */
}

/* ── Top bar ── */
.topbar {
    height: var(--so-topbar-height);
    flex: none;
    background: var(--so-topbar);
    border-bottom: 1px solid var(--so-border);
    display: flex;
    align-items: center;
    gap: var(--space-16);
    padding: 0 var(--space-24);
}
.topbar__menu {
    display: none;
    align-items: center; justify-content: center;
    width: 36px; height: 36px;
    background: transparent;
    border: 1px solid var(--so-input-border);
    color: var(--so-text-2);
    cursor: pointer;
}
.topbar__search {
    position: relative;
    flex: 1 1 auto;
    max-width: 440px;
}
.topbar__search-icon {
    position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
    display: flex; color: #9A938C;
}
.topbar__search input {
    width: 100%;
    min-height: 44px;
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    padding: 0 var(--space-16) 0 34px;
    font-family: inherit;
    font-size: 13px;
    color: var(--so-text-1);
    outline: none;
    border-radius: var(--so-radius);
}
.topbar__search input:focus { border-color: var(--so-text-2); background: var(--so-card); }
.topbar__actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: var(--space-16);
}
.btn.topbar__mobile-search { display: none; }
.topbar__divider { width: 1px; height: 26px; background: var(--so-border); }

.user-chip {
    display: flex;
    align-items: center;
    gap: 9px;
    cursor: pointer;
    /* rendered as a <button> (Work Packet 0.12) — reset native chrome so it reads as a chip */
    border: 0;
    background: transparent;
    padding: 4px 6px;
    margin: -4px -6px;
    font: inherit;
    color: inherit;
    border-radius: var(--so-radius);
    transition: background-color .12s ease;
}
.user-chip:hover { background: var(--so-row-hover); }
.user-chip:focus-visible { outline: 2px solid var(--so-primary); outline-offset: 1px; }
.user-chip__avatar {
    width: 30px; height: 30px; flex: none;
    background: var(--so-brand);
    color: var(--white);
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 12px;
    position: relative; overflow: hidden;
}
/* Work Packet 1.06 / BH #27 — uploaded photo layered over the colour-initials badge (object-fit
   cover). The initials span stays behind it as the no-photo fallback + while the photo loads, so
   the badge is never blank. Square corners match the badge base (no radius token to mirror). */
.user-chip__avatar-img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; display: block;
}
.user-chip__meta { line-height: 1.15; }
.user-chip__name { display: block; font-weight: 600; font-size: 12.5px; }
.user-chip__role { display: block; font-size: 11px; color: var(--so-muted); }
.user-chip__chev { display: flex; color: var(--so-muted); }

/* ══════════ AVATAR COLOUR MODIFIERS (Work Packet 0.82 — BugHerd #10) ══════════
   Per-key background/fg applied alongside any avatar base class
   (.user-chip__avatar, .user-cell__avatar, .avatar-preview, .avatar-swatch).
   Tokens-only — see the --avatar-* pairs in tokens.css (+ dark overrides above) —
   so a single modifier set themes correctly in light + dark. */
.avatar--slate   { background: var(--avatar-slate-bg);   color: var(--avatar-slate-fg); }
.avatar--indigo  { background: var(--avatar-indigo-bg);  color: var(--avatar-indigo-fg); }
.avatar--teal    { background: var(--avatar-teal-bg);    color: var(--avatar-teal-fg); }
.avatar--green   { background: var(--avatar-green-bg);   color: var(--avatar-green-fg); }
.avatar--amber   { background: var(--avatar-amber-bg);   color: var(--avatar-amber-fg); }
.avatar--rose    { background: var(--avatar-rose-bg);    color: var(--avatar-rose-fg); }
.avatar--violet  { background: var(--avatar-violet-bg);  color: var(--avatar-violet-fg); }
.avatar--cyan    { background: var(--avatar-cyan-bg);    color: var(--avatar-cyan-fg); }

/* ── Content frame ── */
.content {
    flex: 1 1 auto;
    overflow-y: auto;
    overflow-x: hidden;
}

/* ══════════ BUTTONS ══════════ */
.btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-8);
    min-height: 44px;
    padding: 0 var(--space-16);
    border: 0;
    background: var(--so-primary);
    color: var(--white);
    font-family: inherit;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    border-radius: var(--so-radius);
    text-decoration: none;
}
.btn:hover { background: var(--so-primary-hover); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }
.btn__icon { display: flex; }
.btn--ghost {
    background: transparent;
    color: var(--so-primary);
    border: 1px solid var(--so-primary);
}
.btn--ghost:hover { background: var(--so-row-hover); }

/* ══════════ PAGE / PAGE HEADER ══════════ */
.page { padding: var(--space-24) var(--so-content-pad) 50px; }
.page--narrow { max-width: 820px; }
.page--form { max-width: 1040px; }

/* BugHerd #382 — Profile rides the shared 820px .page--narrow rail (the same class ~40 other pages
   use), so at 2560×1080 its left-aligned form left ~1493px of dead canvas beside it. It now opts
   into the SAME wide-canvas token the booking detail (BH #21), Analytics (BH #174) and now the
   dashboard (BH #355) use — --so-max-content-analytics, a deliberate maximum in the 1680–1760px
   band — and centres, with equal gutters either side. The shared .page--narrow class is NOT widened
   (every other narrow page keeps its 820px measure): the rule is scoped to Profile alone via :has()
   on the page's own post-back form (asp-controller="Account" asp-action="Profile" → action ends
   "/Account/Profile"), the only CSS-available handle since the markup carries no unique class.
   max-width (not width) keeps it fluid below 1680px, so narrower viewports never overflow. Tokens
   only; no new breakpoint. */
.page--narrow:has(form[action$="/Account/Profile"]) { max-width: var(--so-max-content-analytics); margin-inline: auto; }

/* BugHerd #382 — the Profile page keeps its accepted wide outer canvas, but the form content needs
   its own composition. The old body stacked every field across the full 1680px card, leaving the
   avatar controls as a small island at the top. A bounded two-column layout gives identity and
   account metadata a clear home beside readable editable fields. The existing form card, spacing
   tokens and field controls remain shared; this selector is scoped to Profile only. */
.profile-form__layout {
    display: grid;
    grid-template-columns: minmax(280px, 360px) minmax(0, 1fr);
    gap: var(--space-48);
    width: 100%;
    max-width: var(--so-max-content);
    margin-inline: auto;
    align-items: start;
}
.profile-page .form-card__body {
    padding: var(--space-24);
}
.profile-form__identity,
.profile-form__details {
    min-width: 0;
}
.profile-form__identity {
    display: flex;
    flex-direction: column;
    gap: var(--space-24);
}
.profile-form__identity-summary {
    display: flex;
    align-items: center;
    gap: var(--space-16);
    padding-bottom: var(--space-16);
    border-bottom: 1px solid var(--so-border-soft);
}
.profile-form__identity-summary .avatar-photo-pick__preview {
    width: 72px;
    height: 72px;
}
.profile-form__identity-summary .avatar-photo-pick__preview .avatar-preview {
    width: 72px;
    height: 72px;
    font-size: 22px;
}
.profile-form__identity-copy {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 3px;
}
.profile-form__identity-name {
    color: var(--so-text-1);
    font-family: var(--font-display);
    font-size: 18px;
    font-weight: 600;
    line-height: 1.2;
    overflow-wrap: anywhere;
}
.profile-form__identity-username {
    color: var(--so-text-2);
    font-size: 12px;
    overflow-wrap: anywhere;
}
.profile-form__identity-field {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}
.profile-form__hint {
    display: block;
    margin-top: var(--space-8);
    color: var(--so-text-2);
    font-size: 13px;
    line-height: 1.45;
}
.profile-form__metadata {
    display: grid;
    gap: var(--space-12);
    margin: 0;
    padding: var(--space-16) 0 0;
    border-top: 1px solid var(--so-border-soft);
}
.profile-form__metadata > div {
    display: grid;
    grid-template-columns: 90px minmax(0, 1fr);
    gap: var(--space-8);
}
.profile-form__metadata dt {
    color: var(--so-text-2);
    font-size: 11px;
}
.profile-form__metadata dd {
    min-width: 0;
    margin: 0;
    color: var(--so-text-2);
    font-size: 13px;
    overflow-wrap: anywhere;
}
.profile-form__identity .avatar-pick__grid {
    display: grid;
    grid-template-columns: repeat(4, 44px);
    gap: var(--space-8);
}
.profile-form__details {
    display: flex;
    flex-direction: column;
    gap: var(--space-24);
    width: 100%;
    max-width: 760px;
}
.profile-form__details .field__input {
    width: 100%;
    min-width: 0;
    max-width: 720px;
}
.profile-form__section-title {
    margin: 0;
    color: var(--so-text-1);
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
}
.profile-page .profile-form__hint {
    color: var(--so-text-2);
}
.profile-page .profile-form__bar {
    padding-inline: var(--space-24);
}
.profile-form__bar-inner {
    display: grid;
    grid-template-columns: minmax(280px, 360px) minmax(0, 1fr);
    gap: var(--space-48);
    width: 100%;
    max-width: var(--so-max-content);
    margin-inline: auto;
}
.profile-form__bar-actions {
    grid-column: 2;
    display: flex;
    align-items: center;
    gap: var(--space-8);
    min-width: 0;
    flex-wrap: wrap;
}
@media (max-width: 900px) {
    .profile-form__layout {
        grid-template-columns: 1fr;
        gap: var(--space-24);
    }
    .profile-form__details {
        max-width: none;
    }
    .profile-form__bar-inner {
        grid-template-columns: 1fr;
    }
    .profile-form__bar-actions {
        grid-column: 1;
    }
}

/* BH #164 — Product Edit/Create responsive desktop canvas. Both product views carry the shared
   page--product-form modifier in place of page--narrow. The wider bound is DESKTOP-ONLY (scoped
   inside a min-width: 992px media query): on wide screens the editable canvas widens to a
   deliberate readable measure (wider than the 820px narrow rail) and centres; below the desktop
   breakpoint the rule is inert, so the form keeps its natural single-column stack and the page
   wrapper imposes no max-width clamp — there is no horizontal overflow at 390px. The shared
   narrow shell is untouched: every other narrow page keeps its 820px measure. The fix is scoped
   below this modifier, never a global widening of page--narrow. See
   ProductEditCreateResponsiveCanvasContractTests. */
@media (min-width: 992px) {
    .page--product-form {
        max-width: 1100px;
        margin-inline: auto;
    }
}

.page-head { margin-bottom: var(--space-16); }
.page-head__eyebrow { font-size: 11.5px; color: var(--so-caption); margin-bottom: 7px; }
.page-head__bar { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-16); flex-wrap: wrap; }
.page-head__title { font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1.1; }
.page-head__actions { display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; }
.page-head__rule { width: 30px; height: 3px; background: var(--so-rule); margin-top: 11px; }

/* ══════════ CARDS ══════════ */
.card {
    background: var(--so-card);
    border: 1px solid var(--so-border);
    border-radius: var(--so-radius);
}
.card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-16);
    padding: 13px var(--space-16);
    border-bottom: 1px solid var(--so-border-soft);
}
.card__title { font-family: var(--font-display); font-weight: 600; font-size: 15px; }
.card__meta { font-size: 11.5px; color: var(--so-muted); }
.card__link { font-size: 11.5px; color: var(--so-primary); font-weight: 600; cursor: default; }
/* Work Packet 0.74 — a "View all" affordance in a card head: same muted size as card__meta, but a
   real link (primary token + underline-on-hover). Token-only so it dark-mode washes for free. */
.card__meta--link { color: var(--so-primary); font-weight: 600; text-decoration: none; }
.card__meta--link:hover { text-decoration: underline; text-decoration-thickness: 2px; }

/* ══════════ DASHBOARD ══════════ */
/* BugHerd #355 — at 2560×1080 the dashboard rode the shared 1180px --so-max-content cap, so its
   content stopped at ~1120px and more than half the ultra-wide canvas was dead. It now opts into
   the SAME wide-canvas token the booking detail (BH #21) and Analytics (BH #174) already use —
   --so-max-content-analytics, a deliberate maximum in the 1680–1760px band — and centres, so the
   page fills ~1680/2560 ≈ 66% of the canvas with equal gutters instead of leaving ~half empty.
   max-width (not width) keeps it fluid below 1680px, so narrower viewports never overflow. Tokens
   only; scoped to .page--dashboard, so every other 1180px page (settings/admin/lookups/bg-tasks)
   and the Analytics rule (owned by BH #174) are byte-for-byte unchanged. */
.page--dashboard { padding: var(--space-24) var(--so-content-pad) 60px; max-width: var(--so-max-content-analytics); margin-inline: auto; }
.dash-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-16); flex-wrap: wrap; }
.dash-head__date { font-size: 11px; color: var(--so-caption); letter-spacing: 0.02em; margin-bottom: 4px; }
.dash-head__greeting { font-family: var(--font-display); font-weight: 600; font-size: 23px; line-height: 1.1; }
.dash-head__brand { display: flex; align-items: center; gap: 9px; font-size: 12px; color: var(--so-muted); }
.dash-head__brand-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--so-primary); }
.dash-head__brand-name { font-weight: 600; color: var(--so-text-2); letter-spacing: 0.01em; }
.page-head__rule--dash { width: 34px; margin: 14px 0 var(--space-24); }

.banner {
    display: flex;
    /* BugHerd #330 — flex-start, NOT center. These banners carry multi-line guidance paragraphs, and
       align-items:center put the icon in the vertical middle of the whole block: measured 28px below
       the first line at 1440px and 128px below it at 390px, where the /Reservations notice is 296px
       tall. The icon floated in the middle of a wall of text instead of introducing its first
       sentence. flex-start is identical for the one-line flash banners (icon and line are both ~16px)
       and correct for the long ones. The two banners carrying a right-aligned link/close button now
       align that control to the first line too, which is also the wanted behaviour. */
    align-items: flex-start;
    gap: var(--space-8);
    padding: 11px var(--space-16);
    border: 1px solid var(--so-border);
    background: var(--so-card);
    font-size: 12.5px;
    color: var(--so-text-2);
    margin-bottom: var(--space-24);
    border-radius: var(--so-radius);
}
.banner--info { border-left: 3px solid var(--so-primary); }
/* BH #330 — 1px nudge so the 16px glyph optically centres on the first text line (padding-top
   11px + a ~18px line box puts that line's centre at ~20px; the icon top lands at 12px). */
.banner__icon { display: flex; color: var(--so-primary); margin-top: 1px; }
.banner__link { margin-left: auto; font-weight: 600; color: var(--so-primary); white-space: nowrap; }
.banner__link:hover { text-decoration: underline; }

/* BugHerd #357 — Reservations is a chase-and-confirm worklist. Its filters lead, followed by a
   compact operational snapshot and progressive help; the full workflow explanation no longer forms
   a permanent reading wall before the records. Native details/summary supplies announced state and
   keyboard behaviour without another JavaScript interaction model. */
.page--reservations .reservations-filterbar-row { margin-bottom: var(--space-16); }
.page--reservations .kpi-grid--reservations { margin-bottom: var(--space-16); }
.reservation-guidance { margin-bottom: var(--space-16); border: 1px solid var(--so-border); border-left: 3px solid var(--so-primary); background: var(--so-card); }
.reservation-guidance__summary { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-8) var(--space-12); min-height: 58px; padding: var(--space-12) var(--space-16); list-style: none; cursor: pointer; }
.reservation-guidance__summary::-webkit-details-marker { display: none; }
.reservation-guidance__summary:hover { background: var(--so-row-hover); }
.reservation-guidance__summary:focus-visible { outline: 2px solid var(--so-primary); outline-offset: 2px; }
.reservation-guidance__icon { display: flex; color: var(--so-primary); }
.reservation-guidance__summary-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.reservation-guidance__title { font-size: 12.5px; font-weight: 700; color: var(--so-text-1); }
.reservation-guidance__hint { font-size: 12px; line-height: 1.45; color: var(--so-muted); }
.reservation-guidance__action { display: inline-flex; align-items: center; gap: var(--space-8); font-size: 11px; font-weight: 700; color: var(--so-primary); white-space: nowrap; }
.reservation-guidance__action::after { content: ""; width: 7px; height: 7px; margin-bottom: 3px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); }
.reservation-guidance__action-close { display: none; }
.reservation-guidance[open] .reservation-guidance__summary { border-bottom: 1px solid var(--so-border-soft); }
.reservation-guidance[open] .reservation-guidance__action-open { display: none; }
.reservation-guidance[open] .reservation-guidance__action-close { display: inline; }
.reservation-guidance[open] .reservation-guidance__action::after { margin-bottom: -3px; transform: rotate(225deg); }
.reservation-guidance:not([open]) > .reservation-guidance__body { display: none; }
.reservation-guidance__body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-12) var(--space-24); padding: var(--space-16); }
.reservation-guidance__body p { margin: 0; font-size: 12px; line-height: 1.55; color: var(--so-text-2); }

/* KPI tiles
   BugHerd #133 — the grid adapts to its card count instead of a fixed 4-up. `auto-fit` collapses
   empty tracks, so the column count tracks the number of cards (no phantom blank columns and no
   orphan metric row at wide desktop widths); `minmax(0, 1fr)` keeps each card equal-width and fills
   the row without forcing page overflow (the min of 0 lets long values ellipsis/nowrap per .kpi__value
   rather than stretching the grid past its container). This is the shared KPI presentation — see
   KpiGridAdaptiveTests. Per-page inline `style="grid-template-columns:…"` overrides still win, and
   the ≤992px/≤480px breakpoints below keep the narrow collapse for legibility. */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    gap: 1px;
    background: var(--so-border);
    border: 1px solid var(--so-border);
    margin-bottom: 0;           /* the .kpi-grid__caption beneath carries the spacing (Work Packet 0.29) */
}
.kpi { background: var(--so-card); padding: var(--space-16) var(--space-16); }
.kpi__label { font-size: 11.5px; color: var(--so-muted); margin-bottom: var(--space-8); }
.kpi__value {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 26px;
    line-height: 1.15;          /* BH #133 r2 — usable line height now that text may wrap */
    color: var(--so-text-1);
    /* BH #133 r2 — allow meaningful text (e.g. "Multiple currencies", "See totals below") to wrap
       instead of clipping, while keeping numeric values intact. overflow-wrap (not word-break) breaks
       only an unbreakable run, so normal numbers never split; a single short word still reads on one
       line at ordinary desktop widths. Replaces the old white-space: nowrap that clipped at ~258px. */
    overflow-wrap: anywhere;
    font-variant-numeric: tabular-nums;
}
.kpi__note { font-size: 11px; color: var(--so-faint); margin-top: 6px; }

/* Work Packet 0.29 — straight "created this week" pill + clickable tiles + live-data caption.
   Tokens only (no hard-coded colours): the pill reuses the neutral chip vocabulary so it dark-mode
   washes for free; the tile hover/focus reuse the row-click affordance and primary focus ring. */
.kpi__week {
    display: inline-block;
    margin-top: 8px;
    padding: 2px 9px;
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    background: var(--chip-neutral-bg);
    color: var(--chip-neutral-fg);
    border-radius: var(--so-radius);
}
.kpi--link {
    display: block;
    text-decoration: none;
    color: inherit;             /* keep the tile's own text colours, not link blue */
    cursor: pointer;
}
.kpi--link:hover { background: var(--so-row-hover); }
.kpi--link:focus-visible { outline: 2px solid var(--so-primary); outline-offset: -2px; }
.kpi-grid__caption { margin: 6px 0 var(--space-24); font-size: 11px; color: var(--so-faint); }

/* two-column dashboard body */
.dash-cols {
    display: grid;
    grid-template-columns: 1.55fr 1fr;
    gap: var(--space-24);
    align-items: flex-start;
}
.dash-cols__main,
.dash-cols__side { display: flex; flex-direction: column; gap: var(--space-24); min-width: 0; width: 100%; }
.dash-cols .card { min-width: 0; width: 100%; }

/* generic row lists (follow-ups, activity, recent files) */
.rows { list-style: none; margin: 0; padding: 0; }
    .row { display: flex; align-items: center; gap: var(--space-16); padding: 11px var(--space-16); border-bottom: 1px solid var(--so-row-rule); }
.row:last-child { border-bottom: 0; }
.row__dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--so-primary); }
.row__main { flex: 1 1 auto; min-width: 0; }
.row__title { font-size: 13px; color: var(--so-text-1); }
.row__sub { font-size: 11px; color: var(--so-caption); margin-top: 1px;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row__due { font-size: 11.5px; font-weight: 600; color: var(--so-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.row__fileno { font-weight: 700; font-size: 12px; color: var(--so-primary); white-space: nowrap; }
.row__client { flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--so-text-2);
               overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row__when { font-size: 11px; color: var(--so-faint); white-space: nowrap; font-variant-numeric: tabular-nums; }

/* pipeline */
.pipeline { padding: var(--space-16); display: flex; flex-direction: column; gap: 13px; }
.pipeline__row { display: flex; align-items: center; gap: 14px; }
.pipeline__grade {
    width: 22px; height: 22px; flex: none;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 12px;
    background: var(--chip-neutral-bg); color: var(--chip-neutral-fg);
}
.pipeline__label { width: 96px; flex: none; font-size: 12px; color: var(--so-text-3); }
.pipeline__count { width: 34px; text-align: right; font-weight: 700; font-size: 13px; font-variant-numeric: tabular-nums; }
.pipeline__value { width: 92px; text-align: right; font-size: 12px; color: var(--so-muted); font-variant-numeric: tabular-nums; }

/* Work Packet 0.86 — proportional value bars between label and count. The fill sits inside the
   track (track = the muted rail; fill = the coloured bar, width:% driven by row value vs the
   pipeline max). Scoped under .pipeline__fill so the existing .pipeline__grade.conf--X badge
   colour rules (which set background via --conf-*-bg) are NOT touched. */
.pipeline__track { flex: 1; height: 14px; background: var(--pipe-track); position: relative; min-width: 40px; }
.pipeline__fill  { position: absolute; left: 0; top: 0; bottom: 0; width: 0; }
.pipeline__fill.conf--a { background: var(--pipe-a); }
.pipeline__fill.conf--b { background: var(--pipe-b); }
.pipeline__fill.conf--c { background: var(--pipe-c); }
.pipeline__fill.conf--d { background: var(--pipe-d); }

/* dashboard row affordances (Work Packet 0.21): in-row chips don't shrink; the file-no / title
   links reuse the primary token; a whole row that links gets a pointer + quiet hover wash. */
.row__chip { flex: none; }
.row__link { color: var(--so-primary); font-weight: 600; text-decoration: none; }
.row__link:hover { text-decoration: underline; text-decoration-thickness: 2px; }
.row.is-clickable { cursor: pointer; }
.row.is-clickable:hover { background: var(--chip-neutral-bg); }

/* ══════════ EMPTY STATE ══════════ */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
    padding: var(--space-32) var(--space-16);
    color: var(--so-muted);
}
.empty-state__icon {
    display: flex;
    color: var(--so-faint);
    margin-bottom: var(--space-4);
}
.empty-state__icon svg { width: 28px; height: 28px; }
.empty-state__message { margin: 0; font-size: 13px; font-weight: 600; color: var(--so-text-2); }
.empty-state__hint { margin: 0; font-size: 12px; color: var(--so-muted); max-width: 320px; }

/* ══════════ CHIPS ══════════ */
.chip {
    display: inline-block;
    font-size: 11px;
    font-weight: 700;
    padding: 2px 9px;
    white-space: nowrap;
    background: var(--chip-neutral-bg);
    color: var(--chip-neutral-fg);
    border-radius: var(--so-radius);
}
/* Booking-status lifecycle chips (tokens verbatim from the .dc.html chip() set). */
.chip--quote     { background: var(--chip-quote-bg);     color: var(--chip-quote-fg); }
.chip--option    { background: var(--chip-option-bg);    color: var(--chip-option-fg); }
.chip--booking   { background: var(--chip-booking-bg);   color: var(--chip-booking-fg); }
.chip--waitlist  { background: var(--chip-waitlist-bg);  color: var(--chip-waitlist-fg); }
.chip--cancelled { background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg); }
.chip--closed    { background: var(--chip-closed-bg);    color: var(--chip-closed-fg); } /* Work Packet 0.52 */

/* Catalogue / Agents status + rate-recency chips (Work Packet 0.9). Same token vocabulary —
   no new colours: success/option/info/cancelled reused per the .dc.html chip sets. */
.chip--active     { background: var(--chip-success-bg);   color: var(--chip-success-fg); }
.chip--retired    { background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg); }
.chip--suspended  { background: var(--chip-option-bg);    color: var(--chip-option-fg); }
.chip--info       { background: var(--chip-info-bg);      color: var(--chip-info-fg); }
.chip--current    { background: var(--chip-success-bg);   color: var(--chip-success-fg); }
.chip--scheduled  { background: var(--chip-info-bg);      color: var(--chip-info-fg); }
.chip--superseded { background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg); }

/* Booking-category confidence badge (A–D). 1/2/3 are hidden per screens.md. */
.conf {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px; height: 20px;
    font-weight: 700; font-size: 11px;
    border-radius: var(--so-radius);
}
.conf--a { background: var(--conf-a-bg); color: var(--conf-a-fg); }
.conf--b { background: var(--conf-b-bg); color: var(--conf-b-fg); }
.conf--c { background: var(--conf-c-bg); color: var(--conf-c-fg); }
.conf--d { background: var(--conf-d-bg); color: var(--conf-d-fg); }

/* ══════════ TABLES (shared base for later screens) ══════════ */
/* BugHerd #297 — `position: relative` is LOAD-BEARING, do not remove. An absolutely positioned
   descendant resolves against its nearest POSITIONED ancestor; without one it resolves against the
   initial containing block and is therefore NOT clipped by this scroller. The `.sr-only` span in a
   wide table's Actions header (Agents/Index.cshtml, Agents/Applications.cshtml) took its static
   position from inside the 636.9px table, landing at x=588.9 in DOCUMENT space. That 1px invisible
   span alone pushed document.documentElement.scrollWidth to 590 against a 390px viewport and let
   the whole page pan 200px sideways, even though body.scrollWidth was a correct 390 and every
   in-flow element was properly contained. Making this element positioned puts such descendants
   back inside the scroll container, where the overflow clips them. */
.table-wrap { position: relative; overflow-x: auto; border: 1px solid var(--so-border); background: var(--so-card); }
.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12.5px;
}
.table thead th {
    text-align: left;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--so-muted);
    padding: 10px var(--space-16);
    border-bottom: 1px solid var(--so-border);
    background: var(--so-table-head);
    white-space: nowrap;
}
.table tbody td { padding: 9px var(--space-16); border-bottom: 1px solid var(--so-row-rule); }
/* BH #125 — the cell padding above is scoped to `tbody td`, so a totals row in <tfoot> matched NO
   padding rule at all and fell back to the browser default of 1px, which is why the Costing totals read
   as compressed against their own 2px top rule. This is not local to Costing: 31 views render a <tfoot>,
   including the finance reports whose totals are the most-read rows on the page (Aged Debtors, Agent
   Statement, Bank Deposit, GST, Cheque Run, Close Bookings). Footer cells now take the same horizontal
   and vertical rhythm as body cells. The row rule is deliberately NOT repeated here: a totals row is
   the last row and already carries its own emphasis border, so a bottom rule would double it up. */
.table tfoot td, .table tfoot th { padding: 9px var(--space-16); }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--so-row-hover); }

/* BugHerd #377 — the five catalogue worklists share one explicit information architecture and
   advertise horizontal table scrolling only when the browser detects real overflow. */
.catalogue-section-nav {
    margin: 0 0 var(--space-16);
    border-bottom: 1px solid var(--so-border);
}
.catalogue-section-nav__heading {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 2px var(--space-8);
    color: var(--so-muted);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.catalogue-section-nav__cue { display: none; color: var(--so-primary); }
.catalogue-section-nav__cue[hidden] { display: none; }
.catalogue-section-nav__scroll {
    display: flex;
    gap: var(--space-8);
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scrollbar-width: thin;
}
.catalogue-section-nav__scroll:focus-visible {
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 2px;
}
.catalogue-section-nav__link {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 0 var(--space-12);
    border-bottom: 3px solid transparent;
    color: var(--so-text-2);
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
}
.catalogue-section-nav__link:hover { color: var(--so-text-1); background: var(--so-row-hover); }
.catalogue-section-nav__link.is-active {
    border-bottom-color: var(--so-primary);
    color: var(--so-primary);
}
.catalogue-table-cue {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 var(--space-8);
    color: var(--so-text-2);
    font-size: 12px;
    font-weight: 600;
}
.catalogue-table-cue[hidden] { display: none; }
.catalogue-table-wrap { scrollbar-gutter: stable; }
.catalogue-table-wrap:focus-visible {
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 2px;
}
.catalogue-row-actions {
    display: inline-block;
    width: 76px;
    color: var(--so-text-1);
    text-align: left;
    vertical-align: top;
}
.catalogue-row-actions[open] { width: 268px; }
.catalogue-row-actions__summary {
    display: flex;
    width: max-content;
    margin-left: auto;
    min-height: 30px;
    list-style: none;
    cursor: pointer;
}
.catalogue-row-actions__summary::-webkit-details-marker,
.catalogue-row-actions__confirm > summary::-webkit-details-marker { display: none; }
.catalogue-row-actions__summary::after {
    margin-left: 7px;
    content: "▾";
    color: var(--so-muted);
}
.catalogue-row-actions[open] > .catalogue-row-actions__summary::after { content: "▴"; }
.catalogue-row-actions__panel {
    display: grid;
    gap: var(--space-8);
    width: 268px;
    margin-top: 6px;
    padding: var(--space-12);
    border: 1px solid var(--so-border);
    background: var(--so-card);
    white-space: normal;
}
.catalogue-row-actions__edit {
    display: flex;
    align-items: center;
    min-height: 34px;
    padding: 0 var(--space-8);
    color: var(--so-primary);
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
}
.catalogue-row-actions__edit:hover { background: var(--so-row-hover); }
.catalogue-row-actions__lifecycle {
    padding-top: var(--space-8);
    border-top: 1px solid var(--so-border);
}
.catalogue-row-actions__label {
    display: block;
    margin: 0 var(--space-8) 6px;
    color: var(--so-muted);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.catalogue-row-actions__confirm > summary {
    display: flex;
    align-items: center;
    min-height: 34px;
    padding: 0 var(--space-8);
    color: var(--so-text-2);
    font-size: 12.5px;
    font-weight: 700;
    list-style: none;
    cursor: pointer;
}
.catalogue-row-actions__confirm > summary:hover { background: var(--so-row-hover); }
.catalogue-row-actions__review {
    display: grid;
    gap: var(--space-8);
    padding: var(--space-8);
    border-left: 3px solid var(--so-primary);
    background: var(--so-track);
}
.catalogue-row-actions__review p {
    margin: 0;
    color: var(--so-text-2);
    font-size: 12px;
    line-height: 1.5;
}
.catalogue-row-actions__review .btn { justify-self: start; }
.catalogue-row-actions__facts {
    display: grid;
    gap: 6px;
    margin: 0;
}
.catalogue-row-actions__facts > div {
    display: grid;
    grid-template-columns: minmax(82px, 0.8fr) minmax(110px, 1.2fr);
    gap: var(--space-8);
}
.catalogue-row-actions__facts dt {
    color: var(--so-muted);
    font-size: 10.5px;
    font-weight: 700;
}
.catalogue-row-actions__facts dd {
    margin: 0;
    color: var(--so-text-1);
    font-size: 11px;
    line-height: 1.4;
}
.catalogue-row-actions__review-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-8);
    align-items: center;
}
.catalogue-row-actions__review-actions .row-form { display: inline-flex; }

@media (max-width: 600px) {
    .catalogue-row-actions__summary,
    .catalogue-row-actions__edit,
    .catalogue-row-actions__confirm > summary { min-height: 44px; }
}

@media (max-width: 1024px) {
    .catalogue-section-nav__cue { display: inline; }
    .catalogue-table-wrap[data-overflow] .table--catalogue th:first-child,
    .catalogue-table-wrap[data-overflow] .table--catalogue td:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        box-shadow: 1px 0 0 var(--so-border);
        background: var(--so-card);
    }
    .catalogue-table-wrap[data-overflow] .table--catalogue thead th:first-child {
        z-index: 3;
        background: var(--so-table-head);
    }
    .catalogue-table-wrap[data-overflow] .table--catalogue tbody tr:hover td:first-child {
        background: var(--so-row-hover);
    }
}

/* ══════════ COMING SOON ══════════ */
.card--coming-soon {
    padding: var(--space-32) var(--space-24);
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-16);
    margin-top: var(--space-24);
}
.card__coming-icon {
    display: flex;
    width: 44px; height: 44px;
    align-items: center; justify-content: center;
    background: var(--chip-brand-bg);
    color: var(--so-primary);
}
.card__coming-icon svg { width: 22px; height: 22px; }
.card__coming-title { font-family: var(--font-display); font-weight: 600; font-size: 18px; }
.card__coming-desc { margin: 0; font-size: 13px; line-height: 1.6; color: var(--so-text-2); max-width: 620px; }
.card__coming-foot { margin: 0; font-size: 12px; color: var(--so-muted); }

.scope-list { width: 100%; }
.scope-list__label {
    display: block;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--so-muted);
    margin-bottom: var(--space-8);
}
.scope-list ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.scope-list li {
    font-size: 12.5px;
    color: var(--so-text-2);
    padding-left: var(--space-16);
    position: relative;
}
.scope-list li::before {
    content: "";
    position: absolute;
    left: 0; top: 8px;
    width: 5px; height: 5px;
    background: var(--so-overland);
    border-radius: 50%;
}

/* ══════════ BOOKINGS LIST ══════════ */
.page-head__count { font-size: 12px; color: var(--so-muted); }

/* filter bar — pill-style selects + search, all inside a GET form (idempotent). */
.filterbar {
    display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
    padding: 12px 14px; background: var(--so-card);
    border: 1px solid var(--so-border); margin-bottom: -1px;
}
/* Work Packet 3.02 — the GET filter form and the _SavedViews control (which emits its own POST
   forms) are SIBLINGS, not nested. This wrapper lays them out on one row so the saved-views chip
   stays visually in the same filter row as Export CSV / Clear filters. The GET form takes the
   remaining width; the saved-views control sits to its right. Shares the filterbar card surface +
   border so the row reads as a single bar (the form's own border is dropped here to avoid a
   double rule between the form and the chip). Tokens-only — light + dark unchanged. */
.filterbar-row {
    display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0;
    background: var(--so-card); border: 1px solid var(--so-border); margin-bottom: -1px;
}
.filterbar-row > .filterbar { flex: 1 1 320px; min-width: 0; border: 0; margin-bottom: 0; }
.filterbar-row > .saved-views {
    display: inline-flex; align-items: center; padding: 0 6px 0 2px; flex: 0 0 auto;
    /* BH #337 — the Views chip did not line up with Search / Export CSV. The chip is a SIBLING of the
       GET form (deliberately, see the note above: nesting it leaked POST fields into the GET URL), and
       the row is align-items: flex-start, so the chip aligned to the TOP of the row — level with the
       form's FIRST wrapped line of filter dropdowns, while Search / Export CSV / Clear filters sit on
       the form's LAST line. Measured on /Bookings before the fix: chip top 200, Search top 254 — a 54px
       offset, exactly the misalignment reported.

       Aligning the chip to the row's BOTTOM edge and insetting it by the form's own 12px vertical
       padding puts the chip's baseline on the form's last content line. This is derived from
       .filterbar's padding rather than a tuned magic number, so it stays correct whether the form wraps
       to two lines or fits on one (in the unwrapped case the last line IS the only line), and it is a
       no-op when the row itself wraps the chip onto its own line at narrow widths. */
    align-self: flex-end;
    padding-bottom: 12px;
}
.filterbar__pill {
    display: flex; align-items: center; gap: 7px; height: 32px;
    padding: 0 11px; border: 1px solid var(--so-input-border);
    background: var(--so-input-bg); white-space: nowrap;
}
.filterbar__pill-label { font-size: 12.5px; color: var(--so-caption); }
.filterbar__pill select {
    border: 0; background: transparent; font-family: inherit; font-size: 12.5px;
    color: var(--so-text-2); font-weight: 600; outline: none; cursor: pointer;
    max-width: 168px;
    /* Work Packet 0.81 (BH #12) — replace the UA dropdown arrow with a custom chevron and
       reserve room for it, so the selected text no longer renders under the native caret.
       appearance:none + a sized background image + padding-right is the cross-browser way to
       do this; the inline SVG uses a neutral grey (#888) that reads on both light and dark
       admin tokens, so no theme-keyed override is needed. */
    appearance: none; -webkit-appearance: none; -moz-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right center;
    padding-right: 18px;
}
.filterbar__pill input[type="date"] {
    border: 0; background: transparent; font-family: inherit; font-size: 12.5px;
    color: var(--so-text-2); font-weight: 600; outline: none; cursor: pointer;
    height: 100%;
}
.filterbar__search {
    display: flex; align-items: center; gap: 7px; height: 32px;
    padding: 0 11px; border: 1px solid var(--so-input-border); background: var(--so-input-bg);
    flex: 1 1 220px; min-width: 180px;
}
.filterbar__search input {
    border: 0; background: transparent; font-family: inherit; font-size: 12.5px;
    color: var(--so-text-1); outline: none; width: 100%;
}
.filterbar__search input::placeholder { color: var(--so-faint); }
.filterbar__search .btn { height: 26px; padding: 0 10px; font-size: 12px; }
.filterbar__clear {
    margin-left: auto; font-size: 12px; color: var(--so-primary);
    font-weight: 600; text-decoration: none; cursor: pointer;
    background: none; border: 0; font-family: inherit;
}
.filterbar__clear:disabled { color: var(--so-faint); cursor: not-allowed; }

/* BugHerd #348 — the Bookings page is a find-and-open worklist. Keyword, Status and Consultant
   therefore lead; specialist criteria sit behind one native disclosure with an always-visible
   applied count. Existing controls, query names and auto-submit behavior remain unchanged. */
.page--bookings .filterbar__search--primary { flex: 1 1 300px; }
.page--bookings .filterbar__pill--primary { flex: 0 1 auto; }
.filterbar__advanced { flex: 0 0 auto; min-width: 0; }
.filterbar__advanced-summary {
    display: flex;
    align-items: center;
    gap: var(--space-8);
    min-height: 32px;
    padding: 0 var(--space-12);
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    color: var(--so-text-1);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}
.filterbar__advanced-summary::-webkit-details-marker { display: none; }
.filterbar__advanced:not([open]) > .filterbar__advanced-fields { display: none; }
.filterbar__advanced-summary::after {
    width: 7px;
    height: 7px;
    margin: 0 2px 3px 0;
    border-right: 2px solid var(--so-muted);
    border-bottom: 2px solid var(--so-muted);
    content: "";
    transform: rotate(45deg);
}
.filterbar__advanced[open] { flex: 1 1 100%; }
.filterbar__advanced[open] .filterbar__advanced-summary::after {
    margin-bottom: -2px;
    transform: rotate(225deg);
}
.filterbar__advanced-summary:focus-visible {
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 2px;
}
.filterbar__advanced-count {
    margin-left: auto;
    color: var(--so-caption);
    font-size: 12px;
    font-weight: 600;
}
.filterbar__advanced-fields {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-8);
    padding-top: var(--space-8);
}
.filterbar__utilities {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    gap: var(--space-8);
}
.filterbar__utilities .filterbar__clear { margin-left: 0; }

/* BugHerd #337 — the Bookings action trio (Search, Export CSV and Views) shares one deliberate
   desktop control line. #348 keeps the common filters prominent before the specialist disclosure;
   the booking-only grid gives Search and the action group a clear first row, then places Status,
   Consultant and the Advanced summary on the second row. Saved Views stays outside the GET form
   (its own controls POST), but occupies the same outer row as the form actions. The wider breakpoint
   leaves the existing flex treatment intact at tablet widths, where #348's stacked hierarchy is
   the more useful composition. */
@media (min-width: 992px) {
    .page--bookings .filterbar__search--primary { height: 44px; }
    .page--bookings .filterbar__search--primary .btn,
    .page--bookings .filterbar__utilities .filterbar__export,
    .page--bookings .saved-views__chip { height: 44px; }
}

@media (min-width: 1360px) {
    .page--bookings .filterbar-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) max-content;
        align-items: start;
    }

    .page--bookings .filterbar-row > .filterbar {
        display: grid;
        grid-template-columns: minmax(220px, 1fr) max-content max-content;
        align-items: center;
        gap: 10px;
    }

    .page--bookings .filterbar__search--primary { grid-column: 1 / 3; grid-row: 1; }
    .page--bookings .filterbar__pill--status { grid-column: 1; grid-row: 2; }
    .page--bookings .filterbar__pill--consultant { grid-column: 2; grid-row: 2; }
    .page--bookings .filterbar__pill--status,
    .page--bookings .filterbar__pill--consultant { min-width: 0; }
    .page--bookings .filterbar__pill--status .dd,
    .page--bookings .filterbar__pill--consultant .dd { width: 100%; min-width: 0; }
    .page--bookings .filterbar__pill--status select,
    .page--bookings .filterbar__pill--consultant select { min-width: 0; max-width: 100%; }
    .page--bookings .filterbar__advanced { grid-column: 3; grid-row: 2; }
    .page--bookings .filterbar__advanced[open] { grid-column: 1 / -1; grid-row: 3; }
    .page--bookings .filterbar__utilities {
        grid-column: 3;
        grid-row: 1;
        min-width: max-content;
        justify-content: flex-end;
    }

    .page--bookings .filterbar-row > .saved-views {
        display: grid;
        grid-template-columns: minmax(0, 1fr) max-content;
        grid-template-rows: 44px auto;
        align-self: start;
        min-width: 0;
        justify-self: end;
        align-items: center;
        column-gap: var(--space-8);
        padding: 12px 6px 0 2px;
    }
    .page--bookings .saved-views__menu { grid-column: 2; grid-row: 1; }
    .page--bookings .saved-views__flash { grid-column: 1; grid-row: 1; }
    .page--bookings .saved-views__active { grid-column: 1; grid-row: 2; max-width: 100px; }
    .page--bookings .saved-views__clear { grid-column: 2; grid-row: 2; }
}

/* ══════════ WORK PACKET 1.00 (BH #25) — CUSTOM DROPDOWN (progressive-enhancement combobox) ══════════ */
/* The native <select> stays in the DOM (form value + no-JS fallback); dropdown.js visually hides
   it and renders this styled trigger + panel in its place. The open options list is therefore no
   longer the OS-native control. Selecting dispatches a real `change`, so onchange form-submits keep
   working. Tokens-only (light + dark); the only rgba is the shadow alpha (matches .user-menu__pop). */
.dd { position: relative; display: inline-block; min-width: 210px; }
.dd__btn {
    display: flex; align-items: center; gap: 8px; width: 100%; height: 32px;
    padding: 0 11px; border: 1px solid var(--so-input-border);
    background: var(--so-input-bg); font: inherit; font-size: 12.5px; font-weight: 600;
    color: var(--so-text-2); cursor: pointer; text-align: left;
}
.dd__btn-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd__chev { color: var(--so-muted); display: flex; transition: transform .15s ease; }
.dd[data-open="true"] .dd__chev { transform: rotate(180deg); }
.dd[data-open="true"] .dd__btn { border-color: var(--so-primary); }
.dd__btn:focus-visible { outline: 2px solid var(--so-primary); outline-offset: 1px; }
/* BH #211 — SR-only nodes that expose the current value as part of the trigger's
   accessible name (referenced via aria-labelledby) without changing the visual shape. */
.dd__btn-value-sr, .dd__btn-label--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;
}
/* Invalid state propagation (aria-invalid mirrored from the native select). */
.dd[data-dd-invalid="true"] .dd__btn { border-color: var(--error-02); }
.dd__panel {
    position: absolute; top: calc(100% + 3px); left: 0; right: 0; z-index: 20;
    background: var(--so-card); border: 1px solid var(--so-border);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    max-height: 260px; overflow-y: auto; padding: 4px;
}
.dd__opt {
    display: flex; align-items: center; gap: 8px; padding: 8px 10px;
    font-size: 12.5px; color: var(--so-text-2); cursor: pointer; white-space: nowrap;
}
.dd__opt:hover, .dd__opt[data-active="true"] { background: var(--so-tile-accent); }
.dd__opt[aria-selected="true"] { font-weight: 700; color: var(--so-text-1); }
.dd__opt-check { flex: 0 0 auto; display: flex; color: var(--so-primary); visibility: hidden; }
.dd__opt[aria-selected="true"] .dd__opt-check { visibility: visible; }
.dd__opt-text { flex: 1; overflow: hidden; text-overflow: ellipsis; }
.dd__search { padding: 4px 4px 6px; position: sticky; top: 0; background: var(--so-card); }
.dd__search input {
    width: 100%; height: 28px; border: 1px solid var(--so-input-border);
    background: var(--so-input-bg); padding: 0 9px; font: inherit; font-size: 12px;
    color: var(--so-text-1); outline: none;
}
.dd__search input:focus { border-color: var(--so-primary); }

/* Work Packet 0.68 — Export CSV sits beside the search pill, before the Clear-filters control
   (which keeps margin-left:auto so it stays rightmost). Matches the existing btn btn--ghost shape. */
.filterbar__export { height: 32px; padding: 0 11px; gap: 6px; font-size: 12.5px; white-space: nowrap; }

/* BH #367 — Mobile & touch viewport sizing for filter controls.
   At touch breakpoints (<= 600px), custom-dropdown buttons, date inputs, search and export actions
   expand to 44px min-height hit areas so that mobile users can tap reliably without missed taps.
   Date inputs fill their pill height (44px), dropdown triggers match 44px, and options provide comfortable
   touch padding without page overflow. */
@media (max-width: 600px) {
    .filterbar {
        gap: var(--space-8);
        padding: var(--space-12);
    }
    .filterbar__pill {
        min-height: 44px;
        height: 44px;
        flex: 1 1 100%;
    }
    .filterbar__pill input[type="date"] {
        height: 100%;
        min-height: 44px;
        flex: 1 1 auto;
        font-size: 13px;
    }
    .filterbar .dd {
        width: 100%;
        min-width: 0;
    }
    .filterbar .dd__btn {
        min-height: 44px;
        height: 44px;
        font-size: 13px;
    }
    .filterbar__search {
        min-height: 44px;
        height: 44px;
        flex: 1 1 100%;
        width: 100%;
    }
    .filterbar__search .btn {
        min-height: 36px;
        height: 36px;
    }
    .page--bookings .filterbar__search--primary .btn {
        min-height: 44px;
        height: 44px;
    }
    .filterbar .dd__opt {
        padding: 10px 12px;
        min-height: 40px;
        font-size: 13px;
    }
    .filterbar__export {
        min-height: 44px;
        height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    .filterbar__clear {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
    }
    .page--bookings .filterbar__search--primary,
    .page--bookings .filterbar__pill--primary,
    .page--bookings .filterbar__advanced,
    .page--bookings .filterbar__utilities {
        flex: 1 1 100%;
        width: 100%;
    }
    .filterbar__advanced-summary {
        min-height: 44px;
        padding: 0 var(--space-12);
        font-size: 13px;
    }
    .filterbar__advanced-fields > .filterbar__pill { flex-basis: 100%; }
    .filterbar__utilities {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--space-8);
    }
    .filterbar__utilities .filterbar__export { width: 100%; min-width: 0; }
    .filterbar__utilities .filterbar__clear {
        grid-column: 1 / -1;
        justify-content: flex-start;
    }
}

@media (max-width: 340px) {
    .page--reservations .reservations-filterbar-row .filterbar__pill { display: grid; grid-template-rows: auto 1fr; align-items: start; gap: 0; height: 52px; min-height: 52px; padding-block: var(--space-4); }
    .page--reservations .reservations-filterbar-row .filterbar__pill-label { font-size: 10px; line-height: 12px; }
    .page--reservations .reservations-filterbar-row .filterbar__pill select { width: 100%; min-width: 0; max-width: none; height: 24px; }
    .page--reservations .kpi-grid--reservations .kpi__note { display: none; }
    .reservation-guidance__summary { grid-template-columns: auto minmax(0, 1fr); align-items: start; }
    .reservation-guidance__summary-copy { grid-column: 2; grid-row: 1; }
    .reservation-guidance__action { grid-column: 2; grid-row: 2; justify-self: start; }
}

/* ══════════ WORK PACKET 0.79 — SAVED FILTER VIEWS (per-user, on the core lists) ══════════ */
/* The dropdown sits in the filterbar between Export CSV and Clear-filters. Mirrors the .user-menu
   position-relative + __pop pattern but is scoped per-chip (one per list). Themed light + dark via
   the existing --so-* tokens; no inline colour. */
.saved-views { display: inline-flex; align-items: center; }
.saved-views__menu { position: relative; }
.saved-views__chip { /* extends .btn .btn--ghost .filterbar__export */ }
.saved-views__pop {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 240px;
    background: var(--so-card);
    border: 1px solid var(--so-border);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);
    border-radius: var(--so-radius);
    z-index: 60;
    /* BH #16 — breathe: vertical + horizontal gutter so the head/list/save-form never touch
       the popup edge. Section rows carry their own padding on top of this. */
    padding: var(--space-8, 8px) 0;
}
.saved-views__head {
    padding: var(--space-12, 12px) var(--space-16, 16px);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--so-muted);
}
.saved-views__list { list-style: none; margin: 0; padding: 0; }
.saved-views__item {
    display: flex;
    align-items: center;
    gap: var(--space-4, 4px);
    padding: 0 var(--space-16, 16px);
}
.saved-views__apply {
    flex: 1 1 auto;
    padding: var(--space-10, 10px) 0;
    font-size: 13px;
    color: var(--so-text-1);
    text-decoration: none;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.saved-views__apply:hover { color: var(--so-primary); }
.saved-views__del-form { margin: 0; }
.saved-views__del {
    border: 0;
    background: transparent;
    color: var(--so-muted);
    font: inherit;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: var(--space-6, 6px) var(--space-8, 8px);
    border-radius: var(--so-radius);
}
.saved-views__del:hover { color: var(--error-02); background: var(--so-row-hover); }
.saved-views__empty {
    margin: 0;
    padding: var(--space-16, 16px) var(--space-16, 16px);
    font-size: 12.5px;
    color: var(--so-muted);
    font-style: italic;
}
.saved-views__save-form {
    margin: 0;
    padding: var(--space-12, 12px) var(--space-16, 16px);
    border-top: 1px solid var(--so-border-soft);
    display: flex;
    flex-direction: column;
    gap: var(--space-6, 6px);
}
.saved-views__save-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--so-muted);
}
.saved-views__save-row { display: flex; gap: var(--space-8, 8px); }
.saved-views__save-input {
    flex: 1 1 auto;
    height: 30px;
    padding: 0 var(--space-8, 8px);
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    color: var(--so-text-1);
    font: inherit;
    font-size: 12.5px;
    border-radius: var(--so-radius);
    outline: none;
}
.saved-views__save-input:focus { border-color: var(--so-primary); }
.saved-views__save-btn { height: 30px; padding: 0 var(--space-12, 12px); font-size: 12px; }
.saved-views__flash {
    font-size: 12px;
    font-weight: 600;
    margin-right: var(--space-8, 8px);
}
.saved-views__flash--success { color: var(--so-primary); }
.saved-views__flash--error { color: var(--error-02); }

/* ── BH #100/#101 — saved-view safety: active-state chip, clear-state link, confirm dialog ── */
/* The active-view name renders between the flash and the chip so a consultant can always tell which
   worklist is live; the adjacent "All <area>" link is the explicit clear-state affordance back to the
   bare /{Area} URL (same target as "Clear filters"). Mirrors the .filterbar__clear styling. */
.saved-views__active {
    display: inline-flex; align-items: center;
    height: 32px; padding: 0 var(--space-6, 6px) 0 var(--space-10, 10px);
    font-size: 12.5px; font-weight: 700;
    color: var(--so-text-1);
    background: var(--so-row-hover);
    border: 1px solid var(--so-border-soft);
    border-radius: var(--so-radius);
    max-width: 220px;
}
.saved-views__active-label {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.saved-views__clear {
    font-size: 12px; font-weight: 600;
    color: var(--so-primary); text-decoration: none;
    margin-right: var(--space-4, 4px);
    white-space: nowrap;
}
.saved-views__clear:hover { text-decoration: underline; }
.saved-views__item--active {
    background: var(--so-row-hover);
}
.saved-views__item--active .saved-views__apply {
    color: var(--so-primary);
}

/* The shared delete-confirmation dialog. Mirrors the .cmdk scrim + panel pattern (role=dialog +
   hidden); the scrim covers the page, the panel names the view, and Cancel/Delete are the only two
   focusable controls while open (saved-views.js traps Tab between them). */
.saved-views__confirm {
    position: fixed; inset: 0; z-index: 80;   /* above .saved-views__pop (60), below .cmdk (90) */
    background: var(--scrim-45);
    display: flex; align-items: center; justify-content: center;
    padding: var(--space-16, 16px);
}
.saved-views__confirm[hidden] { display: none; }
.saved-views__confirm-panel {
    width: 100%; max-width: 400px;
    background: var(--so-card);
    border: 1px solid var(--so-border);
    border-radius: var(--so-radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);   /* matches .saved-views__pop / .cmdk__panel */
    padding: var(--space-20, 20px);
    display: flex; flex-direction: column; gap: var(--space-12, 12px);
}
.saved-views__confirm-title {
    margin: 0; font-size: 15px; font-weight: 700; color: var(--so-text-1);
}
.saved-views__confirm-body {
    margin: 0; font-size: 13px; color: var(--so-text-2); line-height: 1.5;
}
.saved-views__confirm-name {
    font-weight: 700; color: var(--so-text-1);
}
.saved-views__confirm-actions {
    display: flex; justify-content: flex-end; gap: var(--space-8, 8px);
    margin-top: var(--space-4, 4px);
}
.saved-views__confirm-cancel { /* extends .btn .btn--ghost */ }
.saved-views__confirm-ok { /* extends .btn .btn--danger */ }

/* BugHerd #123 — shared consequential-action confirmation. Native <dialog> supplies top-layer
   modality; all presentation uses theme tokens and remains bounded at genuine phone widths. */
.app-confirm {
    width: min(520px, calc(100vw - 32px)); max-width: 520px; max-height: calc(100vh - 32px);
    padding: 0; border: 1px solid var(--so-border); border-radius: var(--so-radius);
    background: var(--so-card); color: var(--so-text-1); box-shadow: 0 18px 50px rgb(0 0 0 / 0.28);
}
.app-confirm::backdrop { background: rgb(15 23 29 / 0.68); backdrop-filter: blur(2px); }
.app-confirm__panel { display: flex; flex-direction: column; min-width: 0; }
.app-confirm__head { padding: var(--space-20); border-bottom: 1px solid var(--so-border-soft); }
.app-confirm__eyebrow { display: block; color: var(--so-caption); font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.app-confirm__title { margin: 5px 0 0; font-family: var(--font-display); font-size: 20px; line-height: 1.25; color: var(--so-text-1); }
.app-confirm__body { padding: var(--space-20); overflow: auto; }
.app-confirm__message { margin: 0; color: var(--so-text-2); font-size: 13.5px; line-height: 1.55; }
.app-confirm__details { display: grid; grid-template-columns: minmax(100px, .7fr) minmax(0, 1.3fr); margin: var(--space-16) 0 0; border: 1px solid var(--so-border-soft); }
.app-confirm__details[hidden] { display: none; }
.app-confirm__details dt, .app-confirm__details dd { margin: 0; padding: 9px 11px; border-bottom: 1px solid var(--so-border-soft); overflow-wrap: anywhere; }
.app-confirm__details dt { color: var(--so-caption); font-size: 11px; font-weight: 600; }
.app-confirm__details dd { color: var(--so-text-1); font-size: 12px; font-weight: 600; }
.app-confirm__status { min-height: 1.3em; margin: var(--space-12) 0 0; color: var(--so-caption); font-size: 12px; }
.app-confirm__actions { display: flex; justify-content: flex-end; gap: var(--space-8); padding: var(--space-16) var(--space-20); border-top: 1px solid var(--so-border-soft); background: var(--so-table-head); }
@media (max-width: 479px) {
    .app-confirm { width: calc(100vw - 24px); max-height: calc(100vh - 24px); }
    .app-confirm__head, .app-confirm__body { padding: var(--space-16); }
    .app-confirm__actions { padding: var(--space-12) var(--space-16); }
    .app-confirm__actions .btn { min-height: 44px; flex: 1 1 0; }
    .app-confirm__details { grid-template-columns: 1fr; }
    .app-confirm__details dt { padding-bottom: 2px; border-bottom: 0; }
    .app-confirm__details dd { padding-top: 2px; }
}

/* data table refinements for the bookings list */
.table--bookings thead th { position: sticky; top: 0; z-index: 1; }
.table th.is-sortable { cursor: pointer; }
.table th.is-sortable a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.table th.is-sorted { color: var(--so-primary); }
.table--bookings tbody tr,
.table--catalogue tbody tr,
.table--agents tbody tr { cursor: pointer; }
.t-fileno { font-weight: 700; color: var(--so-primary); white-space: nowrap; text-decoration: none; }
.t-num { font-variant-numeric: tabular-nums; }
.t-right { text-align: right; }
.t-center { text-align: center; }

/* BugHerd #302 - the numeric-alignment utilities were silently DEAD on table HEADERS.
   `.table thead th` and `.an-table thead th` each set `text-align: left` and score (0,1,2),
   which outranks the bare `.t-right` / `.t-center` utilities above at (0,1,0). So a
   `<th class="t-right">Total</th>` rendered LEFT-aligned while the figures beneath it were
   right-aligned: measured on /Finance the header text sat 155px from its own column's right
   edge. 177 `<th>` elements across 53 views carry these classes, and a few had already been
   hand-patched with inline `style="text-align:right"` - so the intent was never in doubt, the
   utility just never won the cascade.
   These two selectors score (0,2,1) - two classes beats one - which restores the utilities on
   headers (including tfoot) without touching `<td>`, where they always worked. Do not fold
   these into the bare `.t-right` / `.t-center` rules: the extra weight IS the fix. */
.table th.t-right, .an-table th.t-right { text-align: right; }
.table th.t-center, .an-table th.t-center { text-align: center; }
.t-muted { color: var(--so-caption); }
.t-strong { font-weight: 600; color: var(--so-text-1); }
.t-channel--direct { font-style: italic; color: var(--so-faint); }

/* ══════════ RESERVATIONS WORKLIST — inline status actions (0.27) ══════════ */
/* Tokens only. The note input reuses the field/input tokens; the action button is a compact .btn. */
/* BH #224 — row actions did not line up with each other. A reservations action cell holds inline-level
   SIBLINGS of very different heights: the .inline-action form is 44px (it contains a .btn, whose base
   min-height is 44px for the touch target) while each .inline-action__print link is about 17px. All of
   them defaulted to vertical-align: baseline, and the baseline of an inline-flex box is taken from its
   first flex item — so the tall form aligned on its note input's text baseline while the short links
   aligned on their own, leaving the pair visibly a couple of pixels out. Aligning every action in the
   group to `middle` makes them share the line box's centre, so they line up regardless of their internal
   heights and no matter which combination of actions a row's state renders (Save ref + History, or
   Email to supplier + Print request + History). */
.inline-action { display: inline-flex; align-items: center; gap: var(--space-8); justify-content: flex-end; vertical-align: middle; }
.inline-actions { display: inline-flex; align-items: center; gap: var(--space-8); justify-content: flex-end; flex-wrap: wrap; vertical-align: middle; }
.inline-action__note {
    height: 28px; width: 220px; max-width: 100%;
    padding: 0 var(--space-8);
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    color: var(--so-text-1);
    border-radius: var(--so-radius);
    font-family: inherit; font-size: 12px; outline: none;
}
.reservation-confirmation-cell { min-width: 310px; }
.inline-action__note::placeholder { color: var(--so-faint); }
.inline-action__note:focus { border-color: var(--so-primary); }
.inline-action .btn { height: 28px; padding: 0 var(--space-8); font-size: 12px; }
/* "Print request" link — opens the supplier reservation request document (0.41) in a new tab.
   Compact icon+text secondary action; tokens only. Sits below the status action when one exists,
   and is the sole action on a Confirmed row. */
.inline-action__print {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--so-text-3);
    text-decoration: none;
    font-size: 12px;
    font-weight: 600;
    /* BH #224 — see the note on .inline-action above. The comment block above describes this link as
       sitting BELOW the status action, and the margin-top: 4px it used to carry served that stacked
       layout. It does not stack: this is an inline-level box that flows on the SAME line as the action
       form, so that margin only pushed the link 4px off the shared line and was a direct contributor to
       the reported misalignment. Dropped, and aligned to the line's centre instead. This class is used
       only by the two Reservations worklist links (Print request / History), so nothing else relied on
       the old offset. */
    vertical-align: middle;
}
.inline-action__print:hover { color: var(--so-primary); text-decoration: underline; text-underline-offset: 2px; }
.t-value-txn { font-weight: 700; color: var(--so-text-1); }
.t-value-aud { font-size: 11px; color: var(--so-faint); }

/* pagination */
.pager {
    display: flex; align-items: center; justify-content: space-between;
    padding: 13px 2px; font-size: 12px; color: var(--so-muted); flex-wrap: wrap; gap: 10px;
}
.pager__pages { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.pager__btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 28px; height: 28px; padding: 0 8px;
    border: 1px solid var(--so-input-border); background: var(--so-card);
    color: var(--so-text-2); font-size: 12px; font-weight: 600;
    text-decoration: none; cursor: pointer; font-family: inherit;
}
.pager__btn[disabled] { color: var(--so-faint); cursor: not-allowed; opacity: 0.7; }
.pager__btn--active { border-color: var(--so-primary); background: var(--so-primary); color: var(--white); }
.pager__gap { padding: 0 4px; color: var(--so-faint); }

/* ══════════ BOOKING DETAIL ══════════ */
/* BugHerd #148 — the Financials tab is the wide operational canvas whose 2560px evidence left a
   72.16% booking rail and a large unlabelled void. Keep the established #21 centred 1680px detail
   rail for Notes and the other tabs; only the Financials composition opts into the available work
   area. The page wrapper still supplies shared content gutters, and the rule stays fluid below the
   wide breakpoint. */
.bk-detail { max-width: var(--so-max-content-analytics); margin-inline: auto; }
.bk-detail--financials { max-width: none; margin-inline: 0; }

/* BugHerd #125 — Costing's six-column summary is useful as a table at desktop measures, but its
   481px intrinsic width hid Sell and Margin inside the 356px phone card. The mobile treatment below
   uses each cell's explicit data label to preserve the same information hierarchy while making every
   value visible in a compact two-column scan card. It is opt-in to the Costing table only; engine
   preview and finance enquiry tables retain their own table/scroll contracts. */
@media (max-width: 600px) {
    .bk-costing-table-wrap {
        overflow-x: visible;
        border: 0;
    }

    .bk-costing-table {
        display: block;
        width: 100%;
    }

    .bk-costing-table thead {
        /* Keep the real column headers in the accessibility tree while taking them
           out of the visual card flow. Cell data-labels provide the phone layout's
           visible labels; the semantic thead remains available to assistive tech. */
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }

    .bk-costing-table tbody,
    .bk-costing-table tfoot {
        display: block;
    }

    .bk-costing-table tbody tr,
    .bk-costing-table tfoot tr {
        display: block;
        margin: 0 0 var(--space-8);
        border: 1px solid var(--so-border-soft);
        background: var(--so-card);
    }

    .bk-costing-table tbody tr:last-child,
    .bk-costing-table tfoot tr:last-child {
        margin-bottom: 0;
    }

    .bk-costing-table tbody td,
    .bk-costing-table tfoot td {
        display: grid;
        grid-template-columns: minmax(88px, 35%) minmax(0, 1fr);
        align-items: start;
        gap: var(--space-8);
        min-width: 0;
        padding: var(--space-8) var(--space-12);
        border-bottom: 1px solid var(--so-border-soft);
        text-align: left;
        overflow-wrap: anywhere;
    }

    .bk-costing-table tbody td::before,
    .bk-costing-table tfoot td::before {
        content: attr(data-label);
        color: var(--so-muted);
        font-size: 10.5px;
        font-weight: 700;
        letter-spacing: 0.02em;
    }

    .bk-costing-table tbody td:last-child,
    .bk-costing-table tfoot td:last-child {
        border-bottom: 0;
    }

    .bk-costing-table tfoot tr {
        border-top: 2px solid var(--so-brand);
        background: var(--so-input-bg);
    }

    .bk-costing-table tfoot td {
        border-top: 0 !important;
    }

    .bk-costing-table tfoot td[data-label=""] {
        display: none;
    }

    .bk-costing-table .t-right,
    .bk-costing-table .t-center {
        text-align: left;
    }
}
.breadcrumb { display: flex; align-items: center; gap: 7px; font-size: 11.5px; color: var(--so-caption); flex-wrap: wrap; }
.breadcrumb a { color: var(--so-primary); text-decoration: none; }
.breadcrumb__sep { display: flex; color: var(--so-faint); }
.breadcrumb__current { color: var(--so-text-3); }

/* Work Packet 1.00 (BH #26) — extends the breadcrumb rules above. A leading home icon link,
   bolder ancestor links, and an optional right-aligned Back chip. Light + dark via tokens. */
.breadcrumb a { font-weight: 600; }
.breadcrumb__home { display: inline-flex; align-items: center; color: var(--so-muted); }
.breadcrumb__home:hover { color: var(--so-primary); }
.breadcrumb__sep { color: var(--so-faint); }
.breadcrumb__back {
    margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
    font-size: 11.5px; font-weight: 600; color: var(--so-primary); text-decoration: none;
    border: 1px solid var(--so-input-border); background: var(--so-input-bg);
    height: 26px; padding: 0 9px;
}
.breadcrumb__back:hover { border-color: var(--so-primary); }

/* header band */
.bk-head {
    background: var(--so-card); border: 1px solid var(--so-border);
    margin-top: 14px;
}
.bk-head__top { padding: 18px 22px; display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.bk-head__lead { min-width: 280px; }
.bk-head__title-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.bk-head__fileno { font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1.1; }
.bk-head__party { font-family: var(--font-display); font-size: 16px; font-weight: 500; margin-top: 10px; color: var(--so-text-1); }
.bk-head__sub { font-size: 12.5px; color: var(--so-text-3); margin-top: 6px; line-height: 1.7; }
.bk-head__sub strong { color: var(--so-text-1); }
.bk-head__totals { display: flex; gap: 28px; align-items: flex-start; }
.bk-head__total { text-align: right; }
.bk-head__total-label { font-size: 11px; color: var(--so-caption); margin-bottom: 3px; }
.bk-head__total-value { font-family: var(--font-display); font-weight: 600; font-size: 24px; line-height: 1.1; }
.bk-head__total-aud { font-size: 12px; color: var(--so-muted); font-variant-numeric: tabular-nums; }
.bk-head__balance { font-size: 12px; color: var(--so-text-3); margin-top: 9px; font-variant-numeric: tabular-nums; }
.bk-head__balance strong { color: var(--so-primary); }

/* meta strip */
.bk-meta { display: flex; flex-wrap: wrap; border-top: 1px solid var(--so-border-soft); }
.bk-meta__cell { padding: 11px 22px; border-right: 1px solid var(--so-row-rule); }
.bk-meta__k { font-size: 10.5px; color: var(--so-faint); letter-spacing: 0.02em; margin-bottom: 2px; }
.bk-meta__v { font-size: 12.5px; font-weight: 600; color: var(--so-text-1); font-variant-numeric: tabular-nums; }
.bk-meta__v--good { color: var(--chip-booking-fg); }
.bk-meta__v--danger { color: var(--error-02); }

/* tabs */
/* BH #307 — a stray scrollbar appeared on the booking tab strip. Two CSS behaviours combined:
   (1) `overflow-x: auto` alone does not leave the other axis alone — per spec a `visible` overflow-y
       computes to `auto` when overflow-x is not visible, so this strip was scrollable VERTICALLY too;
   (2) .bk-tabs__tab carries `margin-bottom: -1px` so the active tab's 2px underline overlaps this
       container's 1px bottom rule, and inside a scroll container that negative margin is 1px of real
       scrollable overflow. Measured on /Bookings/Details/94: scrollHeight 47 vs clientHeight 46, with
       computed overflow-y "auto" — a vertical scrollbar over a single pixel, exactly as reported.
   `padding-bottom: 1px` gives that pixel back so there is no overflow to scroll, which means the
   overflow-y guard below clips NOTHING — the active tab's underline stays intact. Hiding overflow-y
   alone would have removed the scrollbar by clipping the very 1px the underline overlap needs.
   overflow-y: hidden is kept as a guard so a future tweak cannot reintroduce the scrollbar, and
   overflow-x: auto still lets the strip scroll horizontally at narrow widths. */
.bk-tabs { display: flex; border-bottom: 1px solid var(--so-border); padding: 0 6px 1px; overflow-x: auto; overflow-y: hidden; }
.bk-tabs__tab {
    padding: 13px 16px; font-size: 13px; font-weight: 600; color: var(--so-muted);
    cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
    text-decoration: none; white-space: nowrap;
}
.bk-tabs__tab:hover { color: var(--so-text-2); }
.bk-tabs__tab--active { color: var(--so-primary); border-bottom-color: var(--so-primary); }

/* BH-376: Finance mobile navigation picker */
.fin-tabs__mobile-picker { display: none; }

@media (max-width: 768px) {
    .fin-tabs { display: none; }
    .fin-tabs__mobile-picker {
        display: flex;
        flex-direction: column;
        gap: 6px;
        margin-bottom: var(--space-16);
        background: var(--so-card);
        border: 1px solid var(--so-border);
        padding: var(--space-12) var(--space-16);
    }
    .fin-tabs__mobile-label {
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        color: var(--so-muted);
    }
    .fin-tabs__mobile-select-wrap {
        position: relative;
        display: flex;
        align-items: center;
    }
    .fin-tabs__mobile-select {
        width: 100%;
        height: 44px;
        min-height: 44px;
        padding: 0 36px 0 12px;
        border: 1px solid var(--so-input-border);
        background-color: var(--so-input-bg);
        color: var(--so-text-1);
        font-family: inherit;
        font-size: 13px;
        font-weight: 600;
        outline: none;
        border-radius: 0;
        cursor: pointer;
        appearance: none;
        -webkit-appearance: none;
        -moz-appearance: none;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 12px center;
    }
    .fin-tabs__mobile-select:focus-visible {
        outline: 2px solid var(--so-primary);
        outline-offset: -2px;
        border-color: var(--so-primary);
    }
}

/* detail body grid (content + side panel on wide; stacks on narrow) */
.bk-body { display: grid; grid-template-columns: 1fr 312px; gap: 20px; padding: 18px 0 50px; align-items: start; }
.bk-body__main { background: var(--so-card); border: 1px solid var(--so-border); min-width: 0; }
.bk-body__side { background: var(--so-card); border: 1px solid var(--so-border); align-self: start; }
.bk-body__side .empty-state { padding: var(--space-24) var(--space-16); }

/* key-value grid (overview + meta) */
.kv-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--so-border); border: 1px solid var(--so-border); }
.kv { background: var(--so-card); padding: 13px 16px; }
.kv__k { font-size: 10.5px; font-weight: 700; letter-spacing: 0.03em; color: var(--so-muted); margin-bottom: 4px; text-transform: uppercase; }
.kv__v { font-size: 13px; font-weight: 600; color: var(--so-text-1); font-variant-numeric: tabular-nums; }
.kv__v--muted { color: var(--so-text-3); font-weight: 500; }

/* section label inside a tab */
.tab-section-label { font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; color: var(--so-muted); padding: 13px 22px 7px; text-transform: uppercase; }

/* itinerary / lines timeline */
.lines { padding: 6px 0; }
.lines__row { display: flex; gap: 14px; padding: 12px 22px; border-bottom: 1px solid var(--so-border-soft); align-items: flex-start; }
.lines__date { width: 76px; flex: none; text-align: right; padding-top: 1px; }
.lines__date-main { font-weight: 700; font-size: 12px; color: var(--so-text-1); font-variant-numeric: tabular-nums; }
.lines__date-sub { font-size: 10.5px; color: var(--so-faint); margin-top: 2px; }
.lines__type { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--so-text-3); }
.lines__product { font-family: var(--font-display); font-weight: 500; font-size: 14px; color: var(--so-text-1); margin-top: 1px; }
.lines__detail { font-size: 12px; color: var(--so-text-4); margin-top: 2px; }
.lines__main { flex: 1; min-width: 0; }
.lines__qty { width: 64px; flex: none; text-align: center; padding-top: 2px; font-size: 12px; color: var(--so-muted); }
.lines__price { width: 130px; flex: none; text-align: right; padding-top: 1px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.lines__price-main { font-weight: 700; font-size: 12.5px; color: var(--so-text-1); }
.lines__price-sub { font-size: 10.5px; color: var(--so-faint); }
.lines__subtotal { display: flex; justify-content: flex-end; gap: 40px; padding: 14px 22px; background: var(--so-input-bg); border-top: 1px solid var(--so-border-soft); }

/* summary cards (costing / financials) */
.summary-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--so-border); border-top: 1px solid var(--so-border); }
.summary-card { background: var(--so-card); padding: 18px 22px; }
.summary-card__label { font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; color: var(--so-muted); margin-bottom: 14px; }
.summary-line { display: flex; align-items: baseline; justify-content: space-between; padding: 7px 0; border-bottom: 1px solid var(--so-border-soft); }
.summary-line__label { font-size: 12.5px; color: var(--so-text-2); }
.summary-line__note { font-size: 11px; color: var(--so-faint); margin-left: 7px; }
.summary-line__amt { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* passenger cards */
.pax-card { padding: 16px 22px; border-bottom: 1px solid var(--so-border-soft); }
.pax-card__head { display: flex; align-items: center; gap: 13px; margin-bottom: 14px; flex-wrap: wrap; }
.pax-avatar { width: 40px; height: 40px; flex: none; background: #EDE7DF; color: #7A6A57; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 14px; }
.pax-card__name { font-family: var(--font-display); font-weight: 500; font-size: 15px; display: flex; align-items: center; gap: 8px; }
.pax-card__role { font-size: 12px; color: var(--so-muted); margin-top: 2px; }
.pax-lead-tag { font-size: 10px; font-weight: 700; color: var(--so-primary); border: 1px solid var(--so-coral-tint); padding: 1px 6px; }
.pax-flag { font-size: 11px; font-weight: 700; padding: 3px 10px; white-space: nowrap; flex: none; }
.pax-price { text-align: right; padding-left: 8px; flex: none; }
.pax-price__label { font-size: 10.5px; color: var(--so-faint); }
.pax-price__v { font-weight: 700; font-size: 13px; color: var(--so-primary); font-variant-numeric: tabular-nums; }
.pax-fields { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--so-border-soft); border: 1px solid var(--so-border-soft); }

/* financials summary strip */
.fin-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--so-border); border-bottom: 1px solid var(--so-border); }
.fin-strip__cell { background: var(--so-card); padding: 15px 22px; }
.fin-strip__label { font-size: 11px; color: var(--so-muted); margin-bottom: 7px; }
.fin-strip__txn { font-family: var(--font-display); font-weight: 600; font-size: 20px; line-height: 1; font-variant-numeric: tabular-nums; }
.fin-strip__txn--paid { color: #3F7A2E; }   /* paid-to-date green (light); dark override below */
.fin-strip__aud { font-size: 11.5px; color: var(--so-faint); margin-top: 4px; font-variant-numeric: tabular-nums; }

/* payment rows */
.pay-row { display: flex; align-items: center; padding: 11px 22px; border-bottom: 1px solid var(--so-border-soft); gap: 12px; }
.pay-row__icon { width: 28px; height: 28px; flex: none; background: #E4F0DA; color: #3F7A2E; display: flex; align-items: center; justify-content: center; }
.pay-row__icon svg { width: 16px; height: 16px; }
.pay-row__main { flex: 1; min-width: 0; }
.pay-row__title { font-size: 13px; font-weight: 600; color: var(--so-text-1); }
.pay-row__meta { font-size: 11px; color: var(--so-faint); }
.pay-row__amt { width: 150px; text-align: right; font-variant-numeric: tabular-nums; }
.pay-row__amt-main { font-weight: 700; font-size: 13px; color: #3F7A2E; }
.pay-row__amt-sub { font-size: 11px; color: var(--so-faint); }

/* Work Packet 0.20 — booking Activity feed + Admin audit log rows. Tokens only. */
.activity-row { display: flex; align-items: flex-start; padding: 11px 22px; border-bottom: 1px solid var(--so-border-soft); gap: 12px; }
.activity-row__icon { width: 28px; height: 28px; flex: none; background: var(--chip-info-bg); color: var(--chip-info-fg); display: flex; align-items: center; justify-content: center; }
.activity-row__icon svg { width: 15px; height: 15px; }
.activity-row__main { flex: 1; min-width: 0; }
.activity-row__summary { font-size: 13px; font-weight: 600; color: var(--so-text-1); line-height: 1.35; }
.activity-row__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 4px; font-size: 11.5px; color: var(--so-faint); }
.activity-row__actor { color: var(--so-text-3); font-weight: 600; }

/* Work Packet 0.58 — pinned booking notes use the brand accent on the icon + a small pinned tag. Tokens only. */
.activity-row--pinned { background: var(--so-tile-accent); }
.activity-row--pinned .activity-row__icon { background: var(--chip-brand-bg); color: var(--chip-brand-fg); }
.pinned-tag { display: inline-flex; align-items: center; font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--so-primary); margin-right: 6px; }

/* documents list */
.doc-row { display: flex; align-items: center; gap: 13px; padding: 13px 22px; border-bottom: 1px solid var(--so-border-soft); }
.doc-row__icon { width: 32px; height: 32px; flex: none; background: var(--so-table-head); color: var(--so-text-4); display: flex; align-items: center; justify-content: center; }
.doc-row__icon svg { width: 18px; height: 18px; }
.doc-row__main { flex: 1; min-width: 0; }
.doc-row__name { font-size: 13px; font-weight: 600; color: var(--so-text-2); }
.doc-row__meta { font-size: 11px; color: var(--so-faint); }

/* BH-144 — booking Documents responsive workspace card grid & layout */
.doc-cards-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 16px;
    padding: 20px;
    background: var(--so-tile-accent);
    border-bottom: 1px solid var(--so-border-soft);
}

.doc-summary-card {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 18px 20px;
    background: var(--so-card);
    border: 1px solid var(--so-border-soft);
    border-radius: var(--so-radius, 4px);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.doc-summary-card:hover {
    border-color: var(--so-border);
}

.doc-summary-card__head {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 14px;
}

.doc-summary-card__icon {
    width: 40px;
    height: 40px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--so-tile-accent);
    color: var(--so-primary);
    border: 1px solid var(--so-border);
    border-radius: var(--so-radius, 4px);
}

.doc-summary-card__main {
    flex: 1;
    min-width: 0;
}

.doc-summary-card__title {
    font-size: 13.5px;
    font-weight: 700;
    color: var(--so-text-1);
    line-height: 1.3;
}

.doc-summary-card__meta {
    font-size: 11.5px;
    color: var(--so-text-3);
    margin-top: 4px;
    line-height: 1.45;
    word-break: break-word;
    overflow-wrap: anywhere;
}

.doc-summary-card__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: auto;
    padding-top: 14px;
    border-top: 1px solid var(--so-border-soft);
}

.doc-summary-card__email-form {
    display: inline-flex;
    margin: 0;
}

.doc-summary-card .btn {
    flex: 0 0 auto;
    min-height: 38px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* BugHerd #40 — the prerequisite/hint shown in place of the View/print + Email actions when a
   document is not issuable for the booking's current status (e.g. the travel voucher for a
   Quote/Option/WaitList/Cancelled booking). Reuses the warning token vocabulary — no new colour. */
.doc-summary-card__meta--hint {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-style: italic;
    font-size: 11.5px;
    color: var(--so-text-3);
    padding: 6px 10px;
    background: var(--so-tile-accent);
    border-radius: var(--so-radius, 4px);
    width: 100%;
}

@media (max-width: 600px) {
    .doc-cards-grid {
        grid-template-columns: 1fr;
        padding: 12px;
        gap: 12px;
    }

    .doc-summary-card {
        padding: 14px 16px;
    }

    .doc-summary-card__head {
        gap: 12px;
        margin-bottom: 12px;
    }

    .doc-summary-card__actions {
        flex-direction: flex-row;
        flex-wrap: wrap;
        align-items: stretch;
        gap: 8px;
    }

    .doc-summary-card__email-form {
        display: flex;
        flex: 1 1 auto;
    }

    .doc-summary-card__email-form .btn {
        width: 100%;
    }

    .doc-summary-card .btn {
        flex: 1 1 auto;
        min-height: 44px; /* usable touch target */
    }
}

/* margin dot */
.margin-dot { display: inline-flex; align-items: center; gap: 5px; justify-content: flex-end; }
.margin-dot__d { width: 5px; height: 5px; border-radius: 50%; background: var(--chip-booking-fg); }
.margin-dot--thin .margin-dot__d { background: var(--chip-option-fg); }

/* ══════════ CATALOGUE + AGENTS (Work Packet 0.9) ══════════ */
.page-head__link { color: var(--so-primary); text-decoration: none; font-weight: 600; }
.page-sub { font-size: 12px; color: var(--so-muted); margin: 0 0 var(--space-16); max-width: 820px; }

/* clickable-row table variant uses the shared .table base; only the cursor differs (above). */

/* product detail: cost-rate grouping per sell currency */
.rate-group { border-bottom: 1px solid var(--so-border-soft); }
.rate-group:last-child { border-bottom: 0; }
.rate-group__head {
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--so-muted); padding: 12px 22px 8px;
}
.rate-letter {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 4px;
    font-size: 10.5px; font-weight: 700; color: var(--so-text-3);
    background: var(--so-table-head); border-radius: var(--so-radius);
}

/* agency detail: stacked sections in the main column */
.ag-detail {
    /* BH-365 — at 2560px the unbounded page produced a 1936px operational column beside a fixed
       312px terms rail. Use the established 1680px dossier canvas and centre it, keeping records
       scannable without changing the fluid tablet/mobile page. */
    max-width: var(--so-max-content-analytics);
    margin-inline: auto;
}
.ag-detail .bk-body {
    /* Commercial terms grows deliberately from its existing 312px baseline to at most 400px,
       while the operational ledger receives the remaining bounded width. The shared booking-detail
       grid is untouched; the existing <=992px rule still stacks this route. */
    grid-template-columns: minmax(0, 1fr) clamp(312px, 24vw, 400px);
}
.bk-body__main-col { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.detail-section { background: var(--so-card); border: 1px solid var(--so-border); }
.detail-section__head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 13px 18px; border-bottom: 1px solid var(--so-border-soft);
}
.detail-section__title { font-family: var(--font-display); font-weight: 600; font-size: 15px; margin: 0; }
.detail-section__title--sm { font-size: 14px; }
.detail-section__link { font-size: 11.5px; color: var(--so-primary); font-weight: 600; text-decoration: none; }

/* consultant rows */
.con-row { display: flex; align-items: center; gap: 13px; padding: 12px 18px; border-bottom: 1px solid var(--so-border-soft); }
.con-row:last-child { border-bottom: 0; }
.con-row__avatar {
    width: 34px; min-height: 44px; flex: none; background: var(--chip-neutral-bg); color: var(--so-text-3);
    display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px;
}
.con-row__main { flex: 1; min-width: 0; }
.con-row__identity { display: flex; align-items: baseline; gap: var(--space-8); flex-wrap: wrap; }
.con-row__name { font-size: 13px; font-weight: 600; color: var(--so-text-1); }
.con-row__email { font-size: 11.5px; color: var(--so-muted); }
.con-row__role { font-size: 11.5px; color: var(--so-muted); white-space: nowrap; }

/* commission rate-book table */
.spec-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--space-8);
    white-space: nowrap;
}
.spec-cell .spec-badge,
.comm-table .spec-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    font-size: 10.5px;
    font-weight: 700;
    background: var(--so-table-head);
    color: var(--so-muted);
    border-radius: var(--so-radius);
    flex-shrink: 0;
}
.spec-cell .spec-label {
    font-weight: 600;
    font-size: 12.5px;
    color: var(--so-text-1);
}

/* commercial-terms side panel */
.terms { padding: 4px 0; }
.terms__row { display: flex; justify-content: space-between; gap: 12px; padding: 9px 18px; border-bottom: 1px solid var(--so-border-soft); }
.terms__row:last-child { border-bottom: 0; }
.terms__k { font-size: 12px; color: var(--so-muted); }
.terms__v { font-size: 12px; font-weight: 600; color: var(--so-text-1); text-align: right; font-variant-numeric: tabular-nums; }

/* web-active dot on the agencies list */
.web-dot { color: var(--chip-booking-fg); font-size: 10px; line-height: 1; }

/* ══════════ RESERVATIONS + CUSTOMERS + REPORTS (Work Packet 0.11) ══════════ */

/* customer detail: avatar + contact fact grid + opt-ins side panel */
.cust-avatar {
    width: 46px; height: 46px; flex: none;
    background: var(--so-brand); color: var(--white);
    display: flex; align-items: center; justify-content: center;
    font-family: var(--font-display); font-weight: 600; font-size: 16px;
}
.fact-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--so-border-soft); }
.fact { background: var(--so-card); padding: 13px 20px; }
.fact__k { font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em; color: var(--so-faint); margin-bottom: 4px; text-transform: uppercase; }
.fact__v { font-size: 13px; font-weight: 600; color: var(--so-text-1); word-break: break-word; }
.optins { padding: 4px 0; }
.optins__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 18px; border-bottom: 1px solid var(--so-border-soft); }
.optins__row:last-child { border-bottom: 0; }
.optins__k { font-size: 12.5px; color: var(--so-text-2); }

/* reports hub: grouped launcher grid + side note */
.reports-launcher { background: var(--so-card); border: 1px solid var(--so-border); }
.reports-launcher__title { margin: 2px 0 0; font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--so-text-1); }
.reports-launcher__hint { font-size: 11px; color: var(--so-muted); }
.reports-launcher--secondary { margin-top: var(--space-24); }
.reports-launcher__summary { list-style: none; cursor: pointer; padding: 15px 18px; }
.reports-launcher__summary::-webkit-details-marker { display: none; }
.reports-launcher__summary:hover { background: var(--so-row-hover); }
.reports-launcher__summary:focus-visible { outline: 2px solid var(--so-primary); outline-offset: 2px; }
.reports-launcher__summary-heading { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 3px 18px; }
.reports-launcher__summary .reports-launcher__title { grid-column: 1; grid-row: 1; margin: 0; }
.reports-launcher__summary .reports-launcher__hint { grid-column: 1; grid-row: 2; }
.reports-launcher__summary-action { grid-column: 2; grid-row: 1 / span 2; display: inline-flex; align-items: center; gap: var(--space-8); font-size: 11px; font-weight: 700; color: var(--so-primary); }
.reports-launcher__summary-action::after { content: ""; width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); transition: transform 140ms ease; }
.reports-launcher__summary-action-close { display: none; }
.reports-launcher[open] .reports-launcher__summary { border-bottom: 1px solid var(--so-border-soft); }
.reports-launcher[open] .reports-launcher__summary-action-open { display: none; }
.reports-launcher[open] .reports-launcher__summary-action-close { display: inline; }
.reports-launcher[open] .reports-launcher__summary-action::after { transform: rotate(225deg); }
.reports-launcher:not([open]) > .reports-launcher__body { display: none; }
.reports-launcher__body { display: grid; grid-template-columns: minmax(220px, 0.85fr) minmax(360px, 1.45fr); gap: 12px; padding: 12px; }
.reports-launcher__categories, .reports-launcher__reports { display: flex; flex-direction: column; min-width: 0; }
.reports-launcher__categories { border: 1px solid var(--so-border); padding: 10px; }
.reports-launcher__reports { border: 1px solid var(--so-border); padding: 10px; }
.reports-launcher__categories label, .reports-launcher__reports label { margin-bottom: 6px; font-size: 11px; font-weight: 700; color: var(--so-text-2); }
.reports-launcher__categories select, .reports-launcher__reports select { width: 100%; min-height: 214px; border: 1px solid var(--so-input-border); background: var(--so-input-bg); color: var(--so-text-1); font: inherit; font-size: 12px; padding: 2px; }
.reports-launcher__categories select:focus-visible, .reports-launcher__reports select:focus-visible { outline: 2px solid var(--so-primary); outline-offset: 1px; }
.reports-launcher__description, .reports-launcher__empty { margin: 8px 0 0; font-size: 11px; line-height: 1.45; color: var(--so-muted); }
.reports-launcher__empty { min-height: 214px; padding: 14px; border: 1px dashed var(--so-border); }
.reports-launcher__actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
.reports-launcher__notice { margin-bottom: 12px; padding: 10px 14px; border: 1px solid var(--so-primary); color: var(--so-text-2); background: var(--so-card); font-size: 12px; }
.reports-library-heading { display: flex; align-items: baseline; gap: 12px; margin: 0 0 8px; }
.reports-library-heading__title { flex: 0 0 auto; margin: 0; font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--so-text-1); }
.reports-library-heading p { margin: 0; font-size: 12px; color: var(--so-muted); }
.report-grid { display: grid; grid-template-columns: 1fr 322px; gap: 24px; align-items: start; }
.report-groups { background: var(--so-card); border: 1px solid var(--so-border); }
.report-group { border-bottom: 1px solid var(--so-border-soft); }
.report-group:last-child { border-bottom: 0; }
.report-group__label { padding: 12px 18px 4px; font-size: 10px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--so-muted); }
.report-tile {
    display: flex; align-items: center; gap: 13px; padding: 12px 18px;
    border-top: 1px solid var(--so-border-soft); opacity: 0.7; cursor: not-allowed;
}
.report-group__label + .report-tile { border-top: 0; }
.report-tile__icon { width: 32px; height: 32px; flex: none; background: var(--so-table-head); color: var(--so-text-4); display: flex; align-items: center; justify-content: center; }
.report-tile__icon svg { width: 18px; height: 18px; }
.report-tile__main { flex: 1; min-width: 0; }
.report-tile__name { font-size: 13px; font-weight: 600; color: var(--so-text-2); }
.report-tile__desc { font-size: 11px; color: var(--so-faint); margin-top: 1px; }
.report-tile__fmt { font-size: 10px; font-weight: 700; color: var(--so-muted); border: 1px solid var(--so-border); padding: 1px 7px; flex: none; }
/* Visible "Coming soon" badge on disabled tiles — so grayed launchers read as pending, not broken. */
.report-tile__badge { font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--so-muted); background: var(--so-table-head); padding: 2px 8px; border-radius: 999px; flex: none; }

/* Work Packet 0.62 — global search results (tokens only). */
.search-note { padding: 16px 18px; font-size: 13px; color: var(--so-faint); background: var(--so-card); border: 1px solid var(--so-border); }

/* BH #313 — contain long Search query echoes. An unbroken ~600-char /Search query echoed in the
   Results heading (.page-head__title) and the no-match card (.search-note) overflowed its content
   container and clipped at the right edge. `overflow-wrap: anywhere` lets an unbroken run wrap
   inside the existing container so neither echoed line is clipped — no truncation, no hidden
   overflow, no fixed height, no horizontal scroll, and no change to page/header/card widths.
   Scoped to the Search page only (.page--search) so the shared page-head/typography rules used
   elsewhere are untouched (no generic word-break/overflow rule is introduced). */
.page--search {
    max-width: var(--so-max-content-analytics);
    margin-inline: auto;
}
.page--search .page-head__title,
.page--search .search-note {
    overflow-wrap: anywhere;
}

.search-groups { display: flex; flex-direction: column; gap: var(--space-16); }
.search-group { background: var(--so-card); border: 1px solid var(--so-border); }
.search-group__head {
    display: flex;
    align-items: baseline;
    gap: var(--space-8);
    padding: 11px var(--space-16);
    border-bottom: 1px solid var(--so-border-soft);
}
.search-group__label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--so-muted);
    margin: 0;
}
.search-group__count {
    font-size: 11px;
    color: var(--so-faint);
    font-weight: 500;
}
.search-list { list-style: none; margin: 0; padding: 0; }
.search-result {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    padding: 11px var(--space-16);
    border-top: 1px solid var(--so-border-soft);
    text-decoration: none;
    color: inherit;
}
.search-list li:first-child .search-result { border-top: 0; }
.search-result:hover { background: var(--so-row-hover); }
.search-result:focus-visible { outline: 2px solid var(--so-primary); outline-offset: -2px; }
.search-result__icon { color: var(--so-muted); flex: none; display: flex; }
.search-result__main { min-width: 0; display: flex; flex-direction: column; overflow-wrap: anywhere; }
.search-result__primary { font-size: 13px; font-weight: 600; color: var(--so-text-2); }
.search-result__secondary { font-size: 11.5px; color: var(--so-faint); }
.search-result__context { font-size: 11.5px; color: var(--so-faint); opacity: 0.85; }

/* Work Packet 0.64 — email log + detail viewer (tokens only). */
.email-log__override { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 12px 16px; margin-bottom: 14px; background: var(--so-card); border: 1px solid var(--so-border); }
.email-log__override-form { display: flex; align-items: center; gap: 8px; }
.email-log__override-hint { font-size: 11.5px; color: var(--so-faint); }
.email-log__redirected { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--so-muted); }
.email-log__err { font-size: 11.5px; color: var(--error-02); }
.email-detail__head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.email-detail__subject { font-size: 16px; font-weight: 600; color: var(--so-text-1); }
.email-detail__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px 24px; padding: 14px 16px; background: var(--so-card); border: 1px solid var(--so-border); margin-bottom: 14px; }
.email-detail__meta { display: flex; flex-direction: column; gap: 2px; font-size: 12.5px; }
.email-detail__meta > span:first-child { font-size: 10px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--so-muted); }
.email-detail__actions { display: flex; gap: 8px; margin-bottom: 14px; }
.email-detail__actions--fresh-invite { flex-wrap: wrap; align-items: flex-start; }
.email-detail__actions--fresh-invite > p { flex: 0 0 100%; margin: 0; overflow-wrap: anywhere; }
.email-detail__body { background: var(--so-card); border: 1px solid var(--so-border); }
.email-detail__body-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 16px; border-bottom: 1px solid var(--so-border-soft); }
.email-detail__body-tabs { display: flex; gap: 6px; }
/* BH #214 — the format tabs use the roving-tabindex ARIA pattern; only the active
   tab is in the page Tab order, so every tab needs a visible focus ring when it
   receives keyboard focus (arrow navigation moves focus between them). */
.email-detail__body-tabs .tab:focus-visible {
    outline: 2px solid var(--so-primary); outline-offset: 2px;
    border-radius: 3px;
}
/* The email preview renders the message's own HTML on white — like a real mail client / the print
   documents — so it must NOT inherit the app's dark theme. Intentional fixed light surface. */
.email-detail__iframe { width: 100%; min-height: 420px; border: 0; background: #ffffff; display: block; }
.email-detail__text { white-space: pre-wrap; font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 12px; color: var(--so-text-3); padding: 14px 16px; margin: 0; }
/* The one live tile (0.42 — departure manifest): an <a> shaped like a tile. Overrides the disabled
   base (opacity/cursor) so it reads as a real link; every placeholder tile keeps the disabled look. */
.report-tile--link { opacity: 1; cursor: pointer; text-decoration: none; color: inherit; }
.report-tile--link:hover { background: var(--so-row-hover); }
.report-tile--link:hover .report-tile__name { color: var(--so-text-1); }
.report-tile--link:focus-visible { outline: 2px solid var(--so-primary); outline-offset: -2px; }
.report-side { background: var(--so-card); border: 1px solid var(--so-border); padding: 16px 18px; }
.report-side__title { font-family: var(--font-display); font-weight: 600; font-size: 15px; margin: 0; }
.report-side__sub { font-size: 11.5px; color: var(--so-muted); margin-top: 3px; }
.report-side__body { font-size: 12.5px; color: var(--so-text-3); line-height: 1.6; margin-top: 12px; }

/* Tour roster capacity fill (Work Packet 0.43) — the in-shell "how full is each departure" bar.
   Tokens only (no literals): track reuses the same --so-track trough the finance forward-bars use,
   fill is the app primary. The data-driven width is inline in the view (the % is the datum, not a
   colour literal) — mirrors the forward-bar width convention (see .forward-bar__fill). The print
   surface reuses summary.css and renders the fill as a "60%" figure instead, since site.css is not
   loaded there and a bar would not translate to paper reliably. */
.roster-fill { display: flex; align-items: center; gap: 10px; min-width: 140px; }
.roster-fill__track { flex: 1; height: 8px; background: var(--so-track); position: relative; }
.roster-fill__bar { position: absolute; left: 0; top: 0; bottom: 0; background: var(--so-primary); }
.roster-fill__label { font-size: 11px; color: var(--so-text-3); width: 36px; text-align: right; font-variant-numeric: tabular-nums; }

/* ═══════════════════════════════════════════════════════════════════
    RESPONSIVE — desktop 1440 / tablet 768 / mobile 375
   Nav collapses to a drawer below the nav breakpoint; tables scroll in
   their own overflow region; no horizontal page scroll on mobile.
   ═══════════════════════════════════════════════════════════════════ */

/* ≤ tablet — KPI grid 2-wide, dashboard stacks, detail body stacks */
@media (max-width: 992px) {
    .topbar__menu { display: inline-flex; }
    .topbar__search { max-width: none; }

    /* sidebar becomes an off-canvas drawer */
    .sidebar {
        position: fixed;
        top: 0; left: 0; bottom: 0;
        z-index: 50;
        transform: translateX(-100%);
        transition: transform .2s ease;
        box-shadow: 0 0 40px rgba(0,0,0,0.25);
    }
    .app.nav-open .sidebar { transform: translateX(0); }
    .app.nav-open .app__scrim { display: block; }
    .app.nav-open .topbar__menu {
        position: relative;
        z-index: 60;
    }

    /* BH #126 — restore the adaptive auto-fit grid here too, instead of a hard repeat(2, 1fr).
       A fixed two-column grid left an empty cell whenever the card count was odd (the Departures
       board's three cards → a 2x2 with a phantom fourth cell), and because .kpi-grid paints the
       border colour behind the 1px gap while only .kpi children paint the card colour, that empty
       cell rendered as a full-size grey tile. The gap/colour relationship is the design, not the
       bug — the bug is a cell with no card — so the clean fix is to never produce an empty cell:
       auto-fit makes the column count == the card count at EVERY width in this band, robustly for
       two/four/any-card boards too (a different fixed count would just move the empty cell). Chosen
       over neutralising the empty-cell painting because that would require either dropping the
       1px-gap border/card treatment (the design) or padding the grid to an even card count (not
       robust). The ≤480px single-column collapse below still wins on the very narrowest widths. */
    .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); }
    .dash-cols { grid-template-columns: 1fr; }
    .page, .page--dashboard { padding: var(--space-24) var(--so-content-pad-narrow) 50px; }

    /* booking detail: side panel drops below the main column */
    .bk-body { grid-template-columns: 1fr; }
    /* BH-365 — match the specificity of the route-scoped desktop dossier grid so Agency detail
       retains the shared tablet/mobile stacked treatment. */
    .ag-detail .bk-body { grid-template-columns: 1fr; }
    .kv-grid, .fin-strip, .summary-grid { grid-template-columns: repeat(2, 1fr); }
    .pax-fields { grid-template-columns: repeat(2, 1fr); }
    .lines__price, .lines__qty { display: none; }
    .report-grid { grid-template-columns: 1fr; }
}

/* ≤ small tablet — collapse the dashboard two-column into one earlier if cramped */
@media (max-width: 768px) {
    .topbar { padding: 0 var(--space-16); gap: 10px; }
    .topbar__actions { gap: 10px; }
    .user-chip__meta { display: none; }     /* avatar-only on narrow */
    .dash-head__greeting { font-size: 20px; }
    .page-head__title { font-size: 20px; }

    /* BH #349 — the previous-system report picker is a two-step task, so preserve that sequence
       vertically when the desktop two-column canvas no longer fits. Both labelled listboxes and the
       actions now use the content width instead of overflowing into an unreachable second column. */
    .reports-launcher__body { grid-template-columns: minmax(0, 1fr); }
    .reports-launcher__categories,
    .reports-launcher__reports { width: 100%; min-width: 0; }
    .reports-launcher__actions { flex-wrap: wrap; }
}

/* ≤ mobile — single-column KPIs on the very narrowest, tighter gutters */
@media (max-width: 480px) {
    .kpi-grid { grid-template-columns: 1fr; }
    .page--reservations .kpi-grid--reservations { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .page--reservations .kpi-grid--reservations .kpi { min-width: 0; padding: var(--space-12); }
    .page--reservations .kpi-grid--reservations .kpi__label { margin-bottom: var(--space-4); }
    .page--reservations .kpi-grid--reservations .kpi__value { font-size: 22px; }
    .page--reservations .reservations-filterbar-row > .filterbar { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .page--reservations .reservations-filterbar-row .filterbar__pill { min-width: 0; width: 100%; }
    .page--reservations .reservations-filterbar-row .filterbar__pill select { min-width: 0; max-width: 100%; }
    .page--reservations .reservations-filterbar-row .filterbar__search { grid-column: 1 / -1; min-width: 0; }
    .page--reservations .reservations-filterbar-row .filterbar__export { width: 100%; min-width: 0; }
    .page--reservations .reservations-filterbar-row .filterbar__clear { width: 100%; margin-left: 0; justify-content: flex-start; }
    .page--reservations .reservations-filterbar-row > .saved-views { width: 100%; padding: 0 var(--space-12) var(--space-12); }
    .reservation-guidance__body { grid-template-columns: minmax(0, 1fr); }
    /* BH #46 — the selected direct/parent route is operational evidence, not a clipped desktop
       amount. Give the label and value honest shrinkable tracks and allow the principal identity to
       wrap without colliding with the label at phone/200%-zoom widths. */
    .reservation-composer__summary .summary-line {
        display: grid;
        grid-template-columns: minmax(0, 96px) minmax(0, 1fr);
        align-items: start;
        gap: var(--space-12);
    }
    .reservation-composer__summary .summary-line__amt {
        min-width: 0;
        white-space: normal;
        overflow-wrap: anywhere;
        text-align: right;
    }
    .reports-library-heading { align-items: flex-start; flex-direction: column; gap: var(--space-4); }
    .reports-launcher__summary-heading { grid-template-columns: minmax(0, 1fr); }
    .reports-launcher__summary-action { grid-column: 1; grid-row: 3; margin-top: var(--space-4); }
    .btn span:not(.btn__icon) { display: none; }   /* icon-only primary button on mobile */
    .topbar__search { display: none; }              /* search affordance deferred to a sheet later */
    /* BH #360 — touch entry into the existing accessible command/search palette. The palette owns
       Escape, backdrop close and focus return; this control only restores the missing phone trigger. */
    .btn.topbar__mobile-search {
        display: inline-flex;
        width: 44px;
        min-width: 44px;
        height: 44px;
        min-height: 44px;
        padding: 0;
    }
    /* BH #354 — the lower dashboard is an operational sequence, not a clipped desktop canvas.
       Keep identity/status on the first line, put secondary dates and values on deliberate lower
       lines, and let every row shrink inside its card instead of exporting desktop min-content. */
    .dash-cols .row {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        align-items: start;
        gap: var(--space-8);
        min-width: 0;
    }
    .dash-cols .row__title,
    .dash-cols .row__client { min-width: 0; overflow: visible; overflow-wrap: anywhere; white-space: normal; }
    .row--followup .row__due { grid-column: 2; justify-self: start; }
    .row--departure .row__main,
    .row--departure .row__due { grid-column: 1 / -1; }
    .row--file .row__chip { grid-column: 1; grid-row: 2; }
    .row--file .row__when { grid-column: 2; grid-row: 2; justify-self: end; }
    .pipeline__row {
        display: grid;
        grid-template-columns: 22px minmax(0, 1fr) auto;
        gap: 6px var(--space-8);
        min-width: 0;
    }
    .pipeline__label,
    .pipeline__count,
    .pipeline__value { width: auto; min-width: 0; }
    .pipeline__track { grid-column: 1 / -1; grid-row: 2; min-width: 0; }
    .pipeline__value { grid-column: 1 / -1; grid-row: 3; justify-self: end; }
    .row__sub { white-space: normal; }
    .kv-grid, .fin-strip, .summary-grid, .pax-fields { grid-template-columns: 1fr; }
    .fact-grid { grid-template-columns: 1fr; }
    .bk-head__totals { width: 100%; justify-content: flex-end; }
    .filterbar__pill select { max-width: 128px; }
    .acct-row { align-items: flex-start; }
}

/* BugHerd #338 — mobile card-head composition (the shared .card__head, site-wide). The desktop
   side-by-side title/metadata row is kept at every width, so at the 390px acceptance viewport a
   328.7px header left the H2 a 59–105px sliver beside a long scope string: titles broke into
   stacked word fragments ('Daily' over 'activity') 96px tall inside a 122.7px header, and the
   meta wrapped into dense 3–4 line blocks. Below the mobile breakpoint (the --bp-mobile 480px
   band, which the redesign brief's 390px acceptance viewport sits inside) the head recomposes
   per the brief's mobile contract instead: title FIRST at full card width, scope metadata BELOW
   it, normal phrase wrapping, no forced nowrap, no truncation. The 8px gap is the brief's
   heading-to-description step; the 16px horizontal inset is preserved by the base padding above.
   .card__head/.card__title are shared classes, so every card in the app gets this composition —
   checked in the #338 package evidence on the Dashboard (a genuine shared-class consumer: five
   heads, all stack cleanly) and on /Bookings and /Catalogue/CostAll, which render no .card__head
   at all (form-card/table pages) and are untouched by the rule. */
@media (max-width: 480px) {
    .card__head {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-8);
    }
    /* The base .card__title sets font-size 15px but no line-height, so the 48px line box of the
       tokens.css h2 default rides through and a stacked head would carry a 48px title line —
       taller than the 96px fragment stack the ticket reports. The brief's mobile card-title
       contract is 16/24, so the stacked title takes the documented 24px line (font-size itself
       stays with the typography workstream). */
    .card__title { line-height: 24px; }
}

/* ══════════ BH #221 — mobile containment for filterbars reused as data-entry forms ══════════ */
/* The shared .filterbar is a pill filter bar (inline label+control pills at a fixed 32px height,
   white-space:nowrap, no min-width:0). The Finance Refund and GST compilation views REUSE it as a
   write form. Below ~480px the long-labelled pills (Reference (gateway / cheque), GST reference
   (optional)) can neither wrap nor shrink, so a pill extends past the padded form to the viewport
   edge and the page gains horizontal overflow.

   Scope is deliberately narrow: this modifier is OPT-IN, applied only to the two entry forms, so the
   shared .filterbar / .filterbar__pill desktop rule (and every other filter bar across the app) is
   provably untouched — the desktop rendering is identical. The treatment generalises the intent the
   Refund form already hand-patched onto its Reason pill (inline flex:1 1 100%; min-width:240px) into
   the component for every field at mobile: each pill drops onto its own line, the label stacks above
   the control (readable, never clipped), the fixed height relaxes to content, and the input is capped
   to the pill width so it cannot push past the form's padded boundary. */
@media (max-width: 480px) {
    .filterbar--entry .filterbar__pill {
        /* full-width on its own line so no pill can run wide; min-width:0 lets the flex input shrink;
           height relaxes off the fixed 32px so the stacked label+control fit; wrap+normal let the
           label break instead of forcing the pill past the boundary. */
        flex: 1 1 100%;
        min-width: 0;
        height: auto;
        flex-wrap: wrap;
        white-space: normal;
        align-items: flex-start;
    }
    /* stack the label on its own line above the control */
    .filterbar--entry .filterbar__pill-label { width: 100%; }
    /* constrain the control to the pill's content width so its right edge stays inside the form */
    .filterbar--entry .filterbar__pill input,
    .filterbar--entry .filterbar__pill select {
        width: 100%;
        max-width: 100%;
    }
}

/* ══════════ BH #272 — Banking account balances unreachable at 390px ══════════ */
/* Measured on the local render of the captured UAT markup (390x844, 26 Aug 2026): the page is
   correctly constrained (document clientWidth and scrollWidth both 390; .fin-cols 330px) and
   does NOT scroll, but below 992px .fin-cols is a single 1fr track whose grid items keep
   min-width:auto, so the track is sized to its largest item's min-content. The carrier is NOT
   the account row (its identity cell already has min-width:0 and its text wraps) — it is the
   enquiry .table inside .fin-cols__main: .table thead th and the .t-fileno refs are nowrap, a
   ~665px min-content. Everything stretched to the blown track (.fin-cols__stack, .acct-list,
   .acct-row measured 665.5 / 665.5 / 663.5, balances at x=602–678), and because .app and
   main.content clip overflow-x, content past x=390 was unreachable rather than scrollable. A
   first attempt that restyled only the row (27deadd) failed for exactly this reason: setting
   min-width:0 on .fin-cols__stack alone measurably changes nothing; setting it on .fin-cols__main
   collapses the track 665.5 → 330. The tables then fall back to their own .table-wrap
   overflow-x:auto scroller (the app's established pattern), and no money is hidden, truncated,
   ellipsized or font-shrunk — the row recomposes identity-first with the balances stacked below
   in their existing labelled lines (currency code first, A$ equivalent second), right-aligned as
   on desktop. Both grid items get the rule so a future wide child of either pane cannot reopen
   the blowout. Scoped to the ≤480px mobile band: above it nothing changes (verified
   byte-identically at 1440px in bh-drain-272-verification.spec.ts). */
@media (max-width: 480px) {
    .fin-cols__stack, .fin-cols__main { min-width: 0; }
    .acct-row { flex-direction: column; align-items: flex-start; gap: 6px; }
    .acct-row__right { align-self: stretch; }
}

/* ═══════════════════════════════════════════════════════════════════
   Work Packet 0.12 — auth (branded login) + form fields + user menu.
   Reuses tokens only (no literals). The login page uses _AuthLayout,
   so it is rendered standalone (no app sidebar/topbar).
   ═══════════════════════════════════════════════════════════════════ */

/* ── Full-width (block) button modifier ── */
.btn--block { display: flex; width: 100%; justify-content: center; }

/* ── Form fields (shared — login first, reusable later) ── */
.field {
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.field__label {
    font-size: 12px;
    font-weight: 700;
    color: var(--so-text-2);
}
.field__input {
    height: 38px;
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    padding: 0 var(--space-12, 12px);
    font-family: inherit;
    font-size: 14px;
    color: var(--so-text-1);
    outline: none;
    border-radius: var(--so-radius);
}
.field__input:focus { border-color: var(--so-text-2); background: var(--so-card); }
.field__error {
    font-size: 12px;
    color: var(--error-02);
    min-height: 0;
}
.field--check {
    flex-direction: row;
    align-items: center;
    gap: var(--space-8);
    font-size: 13px;
    color: var(--so-text-2);
}
.field__check { width: 16px; height: 16px; accent-color: var(--so-primary); }

/* BH-74 — the locked Active control and its reason are two related lines, not competing columns.
   Keep this scoped to Users/Edit so shared checkbox rows retain their established inline layout. */
.user-access-guard { flex-direction: column; align-items: flex-start; }
.user-access-guard > label { display: flex; align-items: center; gap: var(--space-8); }

/* validation summary (clean single error line) */
.auth-form__error {
    margin: 0;
    padding: 0;
    list-style: none;
}
.auth-form__error ul { margin: 0; padding-left: 0; list-style: none; }
.auth-form__error li {
    color: var(--error-02);
    background: var(--error-01);
    padding: var(--space-8) var(--space-12, 12px);
    font-size: 13px;
    font-weight: 600;
    margin-bottom: var(--space-8);
}

/* ── Auth shell (standalone) ── */
.auth-body { background: var(--so-app-bg); }
.auth-shell {
    min-height: 100vh;
    display: flex;
}
.auth-shell__brand {
    flex: 1 1 55%;
    background: var(--so-brand);
    color: var(--white);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-64);
    position: relative;
}
.auth-shell__brand-inner { max-width: 420px; }
.auth-shell__wordmark {
    display: block;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 30px;
    line-height: 1.1;
    letter-spacing: 0.01em;
}
.auth-shell__accent { color: var(--so-overland); }
.auth-shell__tag {
    display: block;
    font-size: 13px;
    color: var(--so-nav-sub);
    margin-top: 6px;
    letter-spacing: 0.03em;
}
.auth-shell__quote {
    margin: var(--space-48) 0 0;
    font-family: var(--font-display);
    font-style: italic;
    font-size: 18px;
    line-height: 1.5;
    color: rgba(255,255,255,0.78);
    max-width: 340px;
}
.auth-shell__card {
    flex: 1 1 45%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-48) var(--space-24);
}
.auth-card {
    width: 100%;
    max-width: 360px;
}
.auth-card__head { margin-bottom: var(--space-24); }
.auth-card__wordmark {
    display: block;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 18px;
    color: var(--so-brand);
    margin-bottom: var(--space-24);
}
.auth-card__accent { color: var(--so-overland); }
.auth-card__title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 24px;
    line-height: 1.15;
}
.auth-card__sub {
    margin: 4px 0 0;
    font-size: 13px;
    color: var(--so-muted);
}
.auth-form { display: flex; flex-direction: column; gap: var(--space-16); }

/* ── User menu dropdown (top bar) ── */
.user-menu { position: relative; }
.user-menu__pop {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 200px;
    background: var(--so-card);
    border: 1px solid var(--so-border);
    box-shadow: 0 8px 24px rgba(0,0,0,0.10);
    z-index: 60;
}
.user-menu__head {
    padding: var(--space-12, 12px) var(--space-16);
    border-bottom: 1px solid var(--so-border-soft);
}
.user-menu__name { display: block; font-weight: 600; font-size: 13px; }
.user-menu__role { display: block; font-size: 11px; color: var(--so-muted); }
/* BH #15 — "My profile" link mirrors the .user-menu__signout affordance (full-width row, icon
   gutter, hover state) so the menu reads as one consistent list of actions. */
.user-menu__link {
    display: flex;
    align-items: center;
    gap: var(--space-8);
    padding: var(--space-12, 12px) var(--space-16);
    font-size: 13px;
    color: var(--so-text-1);
    text-decoration: none;
    border-bottom: 1px solid var(--so-border-soft);
    cursor: pointer;
    transition: background-color .12s ease;
}
.user-menu__link:hover { background: var(--so-row-hover); }
.user-menu__link:focus-visible { outline: 2px solid var(--so-primary); outline-offset: -2px; }
.user-menu__link-icon { display: flex; color: var(--so-muted); }
.user-menu__form { margin: 0; }
.user-menu__signout {
    display: flex;
    align-items: center;
    gap: var(--space-8);
    width: 100%;
    border: 0;
    background: transparent;
    padding: var(--space-12, 12px) var(--space-16);
    font: inherit;
    font-size: 13px;
    color: var(--so-text-1);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease;
}
.user-menu__signout:hover { background: var(--so-row-hover); }
.user-menu__signout-icon { display: flex; color: var(--so-muted); }

/* ── Auth responsive ── */
@media (max-width: 768px) {
    .auth-shell__brand { display: none; }       /* card-only on tablet/mobile */
    .auth-shell__card { flex-basis: 100%; }
}

/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.13 — Finance (F1–F4). Read-only screens over the
    seeded ledger. Tokens only (no literals); reuses .table/.chip/.kpi-grid/
    .summary-grid/.banner/.filterbar/.bk-tabs where the design maps directly.
    ═══════════════════════════════════════════════════════════════════ */

/* The F1–F4 frames open with a flush area-tab strip (white, bottom rule),
   then the page title + body. .page--finance clears the default page padding
   (the tab strip is flush to the top edge); .fin-head / .fin-body restore the
   content gutter, matching the .dc.html. */
.page--finance { padding: 0; }
.page--finance-batches .fin-head,
.page--finance-batches .fin-body { max-width: var(--so-max-content-analytics); margin-inline: auto; }
.fin-tabs { padding: 0 var(--so-content-pad); background: var(--so-card); }
.fin-head {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: var(--space-16); flex-wrap: wrap;
    padding: 22px var(--so-content-pad) 12px;
}
.fin-head__lead { min-width: 0; }
.fin-head__title { font-family: var(--font-display); font-weight: 600; font-size: 22px; line-height: 1.1; margin: 0; }
.fin-head__sub { font-size: 12px; color: var(--so-muted); margin-top: 6px; }
.fin-head__rule { width: 30px; height: 3px; background: var(--so-rule); margin-top: 11px; }
.fin-head__actions { display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; }
.fin-body { padding: 0 var(--so-content-pad) 50px; }

/* BugHerd #130 — Close bookings is a three-stage reconciliation workflow, not a filter strip.
   The numbered structure encodes the real operator sequence (candidate population → settlement →
   read-only preview), while the established field/button tokens preserve the application's visual
   language. All interactive rows expose a 44px target and every grid track can shrink to zero, so
   320/390px and 200% zoom keep context without whole-page horizontal panning. */
.close-workflow {
    max-width: 1180px;
    margin: var(--space-16) var(--so-content-pad) 0;
    color: var(--so-text-1);
}
.close-workflow__head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-24);
    padding: var(--space-16) var(--space-20, 20px);
    border: 1px solid var(--so-border);
    background: var(--so-card);
}
.close-workflow__eyebrow {
    color: var(--so-primary);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
}
.close-workflow__title {
    margin: 4px 0 0;
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 600;
    line-height: 1.25;
}
.close-workflow__intro {
    max-width: 570px;
    margin: 0;
    color: var(--so-muted);
    font-size: 12px;
    line-height: 1.55;
}
.close-workflow__form {
    display: grid;
    gap: var(--space-16);
    min-width: 0;
    padding: var(--space-20, 20px);
    border: 1px solid var(--so-border);
    border-top: 0;
    background: var(--so-card);
}
.close-workflow__stage {
    min-inline-size: 0;
    margin: 0;
    padding: var(--space-16);
    border: 1px solid var(--so-border-soft);
    background: var(--so-input-bg);
}
.close-workflow__legend {
    display: flex;
    max-width: 100%;
    align-items: center;
    gap: var(--space-12);
    padding: 0 var(--space-8);
    color: var(--so-text-1);
}
.close-workflow__legend > span:last-child,
.close-workflow__action-copy > span:last-child {
    display: flex;
    min-width: 0;
    flex-direction: column;
    gap: 2px;
}
.close-workflow__legend strong,
.close-workflow__action-copy strong {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.25;
}
.close-workflow__legend small,
.close-workflow__action-copy small {
    color: var(--so-muted);
    font-size: 11.5px;
    font-weight: 400;
    line-height: 1.4;
}
.close-workflow__step {
    display: inline-flex;
    width: 30px;
    height: 30px;
    flex: 0 0 30px;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--so-primary);
    background: var(--so-card);
    color: var(--so-primary);
    font-size: 12px;
    font-weight: 700;
}
.close-workflow__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
    gap: var(--space-16);
    min-width: 0;
    padding-top: var(--space-12);
}
.close-workflow__grid--selection { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.close-workflow__grid--settlement { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.close-workflow .field { min-width: 0; }
.close-workflow .field__input {
    width: 100%;
    min-width: 0;
    height: 44px;
    min-height: 44px;
    box-sizing: border-box;
}
.close-workflow .dd { width: 100%; min-width: 0; }
.close-workflow .dd__btn { width: 100%; height: 44px; min-height: 44px; }
.close-workflow__options {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-12);
    margin-top: var(--space-16);
}
.close-workflow__check {
    display: flex;
    min-width: 0;
    min-height: 56px;
    align-items: center;
    gap: var(--space-12);
    padding: var(--space-8) var(--space-12);
    border: 1px solid var(--so-input-border);
    background: var(--so-card);
    color: var(--so-text-1);
    cursor: pointer;
}
.close-workflow__check .field__check { width: 18px; height: 18px; flex: 0 0 18px; }
.close-workflow__check > span { display: flex; min-width: 0; flex-direction: column; gap: 2px; }
.close-workflow__check strong { font-size: 12.5px; }
.close-workflow__check small { color: var(--so-muted); font-size: 11px; line-height: 1.35; }
.close-workflow__check:has(input:focus-visible) {
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 2px;
}
.close-workflow__action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-20, 20px);
    padding: var(--space-16);
    border-left: 3px solid var(--so-primary);
    background: var(--so-tile-accent);
}
.close-workflow__action-copy { display: flex; min-width: 0; align-items: center; gap: var(--space-12); }
.close-workflow__actions { display: flex; flex: 0 0 auto; align-items: center; gap: var(--space-8); }
.close-workflow__actions .btn { min-height: 44px; }

/* BugHerd #131 — an exclusion reason is corrective evidence, not a low-priority table column.
   At zoom/mobile widths, keep the complete record visible as one labelled card instead of
   requiring horizontal discovery of currency, calculation basis and reason. */
@media (max-width: 768px) {
    .finance-exclusions,
    .finance-exclusions tbody,
    .finance-exclusions tr,
    .finance-exclusions td { display: block; width: 100%; }
    .finance-exclusions thead {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }
    .finance-exclusions tbody { display: grid; gap: var(--space-12); }
    .finance-exclusions tbody tr {
        padding: var(--space-8) var(--space-12);
        border: 1px solid var(--so-border);
        background: var(--so-card);
    }
    .finance-exclusions tbody td {
        display: grid;
        grid-template-columns: minmax(88px, .7fr) minmax(0, 1.3fr);
        gap: var(--space-8);
        align-items: start;
        padding: 6px 0;
        border: 0;
        text-align: left;
        white-space: normal;
        overflow-wrap: anywhere;
    }
    .finance-exclusions tbody td::before {
        content: attr(data-label);
        color: var(--so-muted);
        font-size: 10px;
        font-weight: 700;
        letter-spacing: .04em;
        text-transform: uppercase;
    }
}

@media (max-width: 992px) {
    .close-workflow__grid--selection,
    .close-workflow__grid--settlement { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 768px) {
    .close-workflow__head,
    .close-workflow__action { align-items: stretch; flex-direction: column; }
    .close-workflow__grid--selection,
    .close-workflow__grid--settlement,
    .close-workflow__options { grid-template-columns: minmax(0, 1fr); }
    .close-workflow__actions { flex-wrap: wrap; }
}
@media (max-width: 480px) {
    .close-workflow { margin-inline: var(--space-16); }
    .close-workflow__head,
    .close-workflow__form { padding: var(--space-16); }
    .close-workflow__stage { padding: var(--space-12); }
    .close-workflow__legend { align-items: flex-start; padding-inline: var(--space-4); }
    .close-workflow__actions { display: grid; grid-template-columns: 1fr; }
    .close-workflow__actions .btn { width: 100%; justify-content: center; }
}

/* money-direction + trust utility colours */
.t-in     { color: var(--so-money-in); }
.t-out    { color: var(--so-money-out); }
.t-trust  { color: var(--so-trust); }

/* tiles (F3/F4) — kpi-grid reused; accent + direction variants */
.kpi--accent           { background: var(--so-tile-accent); }
.kpi__value--in        { color: var(--so-money-in); }
.kpi__value--out       { color: var(--so-money-out); }
.kpi__value--accent    { color: var(--so-primary); }

/* chart of accounts (F2) */
.acct-list { background: var(--so-card); border: 1px solid var(--so-border); }
.acct-list__head {
    padding: 11px 16px; border-bottom: 1px solid var(--so-border-soft);
    font-size: 10px; font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--so-muted);
}
.acct-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 12px 16px; border-bottom: 1px solid var(--so-row-rule); cursor: pointer;
    border-left: 3px solid transparent; background: var(--so-card);
    text-decoration: none; color: inherit;
}
.acct-row > div:first-child { min-width: 0; flex: 1 1 auto; }
.acct-row:last-child { border-bottom: 0; }
.acct-row:hover { background: var(--so-row-hover); }
.acct-row--trust { background: var(--so-trust-tint); border-left-color: var(--so-trust); }
.acct-row--selected { background: var(--so-row-hover); border-left-color: var(--so-primary); }
.acct-row__name { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--so-text-1); flex-wrap: wrap; }
.acct-row__name span { word-break: break-word; }
.acct-row__name--trust { color: var(--so-trust); }
.acct-row__sub { font-size: 11px; color: var(--so-caption); margin-top: 2px; font-variant-numeric: tabular-nums; }
.acct-row__right { text-align: right; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.acct-row__bal-ccy { font-size: 12.5px; font-weight: 700; color: var(--so-text-1); }
/* .acct-row__bal-aud removed by BH-387 - see Views/Finance/Banking.cshtml */
.acct-trust-note {
    display: flex; align-items: center; gap: 9px; padding: 10px 16px;
    background: var(--so-trust-tint); border-top: 1px solid var(--so-border-soft);
    color: var(--so-trust); font-size: 11px; line-height: 1.5;
}

/* tender split (F1 detail) — mirrors the .dc.html 5-cell strip */
.tender-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--so-border); border: 1px solid var(--so-border); }
.tender-cell { background: var(--so-card); padding: 13px 16px; }
.tender-cell--total { background: var(--so-tile-accent); }
.tender-cell__k { font-size: 10.5px; color: var(--so-muted); }
.tender-cell__v { font-size: 16px; font-weight: 600; color: var(--so-text-1); margin-top: 5px; font-variant-numeric: tabular-nums; }
.tender-cell__v--total { font-weight: 700; color: var(--so-primary); }

/* reconcile panel (F1 detail) */
.recon { padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }
.recon__row { display: flex; align-items: center; justify-content: space-between; }
.recon__k { font-size: 12.5px; color: var(--so-text-2); }
.recon__k--strong { font-weight: 600; color: var(--so-text-1); }
.recon__v { font-size: 14px; font-weight: 700; color: var(--so-text-1); font-variant-numeric: tabular-nums; }
.recon__rule { height: 1px; background: var(--so-border-soft); }
.recon__ok {
    display: flex; align-items: center; gap: 9px; background: var(--so-ok-bg);
    border: 1px solid var(--so-ok-border); padding: 10px 12px;
    color: var(--chip-success-fg); font-size: 11.5px; font-weight: 600;
}
.recon__ok-dot { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; background: var(--chip-success-fg); color: var(--white); flex: none; }
.recon__note { font-size: 11px; color: var(--so-muted); line-height: 1.6; }

/* balanced footer (journal entry, F2) */
.balanced-foot {
    display: flex; align-items: center; justify-content: space-between;
    padding: 11px 18px; background: var(--so-ok-bg); border-top: 1px solid var(--so-ok-border);
}
.balanced-foot__tag { display: flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 600; color: var(--chip-success-fg); }
.balanced-foot__dot { display: flex; align-items: center; justify-content: center; width: 18px; height: 18px; background: var(--chip-success-fg); color: var(--white); }
.balanced-foot__amt { font-size: 12px; color: var(--chip-success-fg); font-variant-numeric: tabular-nums; }

/* inter-currency transfer panel (F2) */
.xfer { padding: 16px 18px; }
.xfer__leg { border: 1px solid var(--so-border); padding: 11px 13px; }
.xfer__leg--to { border-color: var(--so-primary); background: var(--so-row-hover); }
.xfer__leg-k { font-size: 10px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--so-muted); }
.xfer__leg-k--to { color: var(--so-primary); }
.xfer__leg-row { display: flex; align-items: center; justify-content: space-between; margin-top: 5px; }
.xfer__leg-acct { font-size: 13px; font-weight: 600; color: var(--so-text-1); }
.xfer__leg-amt { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }
.xfer__mid { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 8px 0; color: var(--so-faint); font-size: 11px; }

/* forward cash flow bars (F3) */
.forward-row { display: grid; grid-template-columns: 150px 1fr 110px; gap: 16px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--so-row-rule); }
.forward-row:last-child { border-bottom: 0; }
.forward-row__week { font-size: 12.5px; font-weight: 600; color: var(--so-text-1); }
.forward-bars { display: flex; flex-direction: column; gap: 5px; }
.forward-bar { display: flex; align-items: center; gap: 9px; }
.forward-bar__track { flex: 1; height: 13px; background: var(--so-track); position: relative; max-width: 520px; }
.forward-bar__fill { position: absolute; left: 0; top: 0; bottom: 0; }
.forward-bar__fill--in { background: var(--so-money-in-bar); }
.forward-bar__fill--out { background: var(--so-money-out-bar); }
.forward-bar__amt { font-size: 11px; color: var(--so-text-4); width: 64px; text-align: right; font-variant-numeric: tabular-nums; }
.forward-row__net { text-align: right; font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* legend (F3) */
.legend { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.legend__item { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--so-text-3); }
.legend__swatch { width: 11px; height: 11px; }
.legend__swatch--in { background: var(--so-money-in-bar); }
.legend__swatch--out { background: var(--so-money-out-bar); }

/* two-pane finance body (F2 chart + detail) */
.fin-cols { display: grid; grid-template-columns: 340px 1fr; gap: var(--space-24); align-items: start; }
.fin-cols__stack { display: flex; flex-direction: column; gap: var(--space-24); }
.fin-cols__main { display: flex; flex-direction: column; gap: var(--space-24); }

/* F4 two-column (breakdown+writeoffs | refunds+bas) */
.fin-cols--gst { grid-template-columns: 1fr 360px; }

/* Finance responsive — stack the two-pane layouts + collapse strips */
@media (max-width: 992px) {
    .fin-cols, .fin-cols--gst { grid-template-columns: 1fr; }
    .fin-cols--batch { grid-template-columns: 1fr !important; }
    .fin-cols--half { grid-template-columns: 1fr !important; }
}
@media (max-width: 768px) {
    .tender-grid { grid-template-columns: repeat(2, 1fr); }
    .forward-row { grid-template-columns: 1fr; gap: 6px; }
    .forward-row__net { text-align: left; }
}

/* ═══════════════════════════════════════════════════════════════════
   Work Packet 0.14 — user management (AD2). Reuses tokens only.
   Success/error banners (the existing .banner only had --info), the
   Admin role brand chip, and an in-shell form layout shared by the
   create / edit / reset-password views.
   ═══════════════════════════════════════════════════════════════════ */

/* role chip — terracotta brand token flags elevated (Admin) access */
.chip--brand { background: var(--chip-brand-bg); color: var(--chip-brand-fg); }

/* success / error banner variants */
.banner--success { border-left: 3px solid var(--success-02); }
.banner--success .banner__icon { color: var(--success-02); }
.banner--error { border-left: 3px solid var(--error-02); background: var(--error-01); }
.banner--error .banner__icon { color: var(--error-02); }
.banner__close {
    margin-left: auto; border: 0; background: none; cursor: pointer;
    color: inherit; display: flex; opacity: 0.7; font-family: inherit;
}
.banner__close:hover { opacity: 1; }

/* the users table leans on the shared .table (used by customers/agents) —
   rows are not clickable (actions live in a column), so override the pointer. */
.table--users tbody tr { cursor: default; }
.table--users .user-cell { display: flex; align-items: center; gap: 11px; }
.table--users .user-cell__avatar {
    width: 30px; height: 30px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: var(--so-brand); color: var(--white);
    font-weight: 700; font-size: 11px;
}
.table--users .user-cell__name { font-weight: 600; color: var(--so-text-1); }
.table--users .user-cell__email { font-size: 11px; color: var(--so-caption); }
.table--users .row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.table--users .row-actions .btn { height: 26px; padding: 0 10px; font-size: 12px; }
.page--users { max-width: var(--so-max-content-analytics); margin-inline: auto; }
.page--audit { max-width: var(--so-max-content-analytics); margin-inline: auto; }

/* in-shell form card (create / edit / reset-password) */
.form-card { background: var(--so-card); border: 1px solid var(--so-border); }
.form-card__head { padding: 13px var(--space-16); border-bottom: 1px solid var(--so-border-soft); }
.form-card__title { font-family: var(--font-display); font-weight: 600; font-size: 15px; }
.form-card__body { padding: var(--space-20, 20px) var(--space-16); display: flex; flex-direction: column; gap: var(--space-16); }
.form-card__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-16); }
.form-card__row > .field--span-2 { grid-column: span 2; }
.form-card__row > .field--span-all { grid-column: 1 / -1; }

/* BH #390 — a long Product option gave the grid item an intrinsic width wider than the 390px
   Departure Edit card. The page suppresses document overflow, so the select's right border and
   chevron were clipped rather than scrollable. Keep this containment local to the affected form:
   the field may shrink below its content width and its controls fill, but never exceed, that track. */
.page--departure-edit .form-card__row > .field { min-width: 0; }
.page--departure-edit .field__input { width: 100%; min-width: 0; max-width: 100%; }

@media (max-width: 600px) {
    .form-card__row > .field--span-2,
    .form-card__row > .field--span-all { grid-column: auto; }
}
.form-card__readonly { font-size: 13px; color: var(--so-text-2); }
.form-card__readonly- label { font-size: 12px; font-weight: 700; color: var(--so-text-2); display: block; margin-bottom: 5px; }
.form-card__actions { display: flex; gap: var(--space-8); align-items: center; flex-wrap: wrap; margin-top: var(--space-4); }

/* role pick — segmented control built from radio inputs (no JS) */
.role-pick { display: flex; border: 1px solid var(--so-input-border); }
.role-pick__opt { flex: 1; position: relative; }
.role-pick__opt input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.role-pick__opt label {
    display: block; text-align: center; padding: 9px 14px; cursor: pointer;
    font-size: 13px; font-weight: 600; color: var(--so-text-2); background: var(--so-input-bg);
}
.role-pick__opt input:checked + label { background: var(--so-primary); color: var(--white); }
.role-pick__opt input:focus-visible + label { outline: 2px solid var(--so-text-2); outline-offset: -2px; }

/* ══════════ AVATAR PICKER + PREVIEW (Work Packet 0.82 — BugHerd #10) ══════════
   Mirrors the .role-pick skeleton (hidden radio + visible label, :checked +
   :focus-visible sibling selectors, tokens-only) but the label IS the colour
   swatch. The .avatar--{key} modifier on the swatch fills it; :checked draws a
   ring + shows the check icon to mark the selection. The live preview badge uses
   the same modifier set as the chip + list so WYSIWYG across the shell. */
.avatar-pick { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-12); }
.avatar-pick__preview { display: inline-flex; flex-shrink: 0; }
.avatar-pick__grid { display: flex; flex-wrap: wrap; gap: var(--space-8); align-items: center; }
.avatar-preview {
    width: 36px; height: 36px; flex: none;
    display: flex; align-items: center; justify-content: center;
    font-weight: 700; font-size: 13px;
    border: 1px solid var(--so-border);
    position: relative; overflow: hidden;
}
/* Work Packet 1.06 / BH #27 — uploaded photo layered over the colour-initials badge on the Profile
   preview (object-fit cover). Mirrors .user-chip__avatar-img: the initials stay behind as the
   no-photo fallback + while loading. */
.avatar-preview__img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover; display: block;
}

/* Work Packet 1.06 / BH #27 — the Profile page "Profile photo" picker: a larger preview alongside
   the upload/remove buttons. Tokens-only — reuses the existing form-card + btn vocabulary so it
   themes correctly in light + dark with no new colour. */
.avatar-photo-pick { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.avatar-photo-pick__preview {
    display: inline-flex;
    /* Larger preview than the colour picker (48px) so an uploaded photo reads clearly. */
    width: 48px; height: 48px; flex: none;
}
.avatar-photo-pick__preview .avatar-preview { width: 48px; height: 48px; font-size: 16px; }
.avatar-photo-pick__controls { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Hide the native file input — the wrapping <label class="btn"> is the clickable surface, but the
   input stays in the DOM so the browser still submits the selected file. Visually-hidden (not
   display:none) so the field remains accessible to assistive tech + the file picker still opens. */
.avatar-photo-pick__file {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.avatar-pick__opt {
    position: relative;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.avatar-pick__opt input { position: absolute; opacity: 0; inset: 0; cursor: pointer; z-index: 1; }
.avatar-pick__opt .avatar-swatch {
    display: flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; cursor: pointer;
    border-radius: var(--radius-sm);
    color: var(--white); /* check icon legible on a mid-tone swatch in light mode */
}
.avatar-pick__opt .avatar-swatch icon { opacity: 0; } /* hidden until selected */
.avatar-pick__opt input:checked + .avatar-swatch { outline: 2px solid var(--so-text-1); outline-offset: 2px; }
.avatar-pick__opt input:checked + .avatar-swatch icon { opacity: 1; }
.avatar-pick__opt input:focus-visible + .avatar-swatch { outline: 2px solid var(--so-primary); outline-offset: 2px; }

@media (max-width: 480px) {
    .avatar-pick__grid {
        display: grid;
        grid-template-columns: repeat(4, 44px);
        gap: var(--space-8);
    }
}

@media (max-width: 600px) {
    .form-card__row { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.15 — polish + premium UI.
    (1) Collapsible sidebar (icon rail, persisted, no flash),
    (2) 3-way theme toggle + dark-mode token overrides,
    (3) copy-to-clipboard buttons, (4) sticky form action bar.
    Tokens only (no literals); dark variants are token overrides, not
    per-element hacks. The teal sidebar stays teal in both themes by
    design (it is the constant brand surface).
    ═══════════════════════════════════════════════════════════════════ */

/* ── Sidebar brand row + collapse toggle ── */
.sidebar__brand { display: flex; align-items: center; gap: var(--space-8); }
.sidebar__brand-text { min-width: 0; flex: 1 1 auto; }
.sidebar__toggle {
    flex: none;
    width: 26px; height: 26px;
    display: grid; place-items: center;
    border: 0;
    background: var(--so-nav-badge-bg);
    color: #DDE3E4;
    cursor: pointer;
    border-radius: var(--so-radius);
    transition: background-color .15s ease, color .15s ease, transform .22s ease;
}
.sidebar__toggle:hover { background: rgba(255,255,255,0.20); color: var(--white); }
.sidebar__toggle:focus-visible { outline: 2px solid var(--white); outline-offset: 1px; }
.sidebar__toggle--collapsed { transform: rotate(180deg); }
.sidebar__toggle svg { width: 16px; height: 16px; }

/* Collapsed state — only on desktop (the sidebar is a drawer below 993px). */
@media (min-width: 993px) {
    html[data-sidebar="collapsed"] .sidebar { width: var(--so-sidebar-mini); }
    html[data-sidebar="collapsed"] .sidebar__brand {
        padding: var(--space-16) var(--space-8);
        justify-content: center;
    }
    html[data-sidebar="collapsed"] .sidebar__brand-text,
    html[data-sidebar="collapsed"] .nav-item__label,
    html[data-sidebar="collapsed"] .nav-item__badge,
    html[data-sidebar="collapsed"] .nav-group__label,
    html[data-sidebar="collapsed"] .sidebar__footer-text { display: none; }
    html[data-sidebar="collapsed"] .nav-item {
        justify-content: center;
        padding: 9px 0;
        border-left: 0;                 /* the active coral bar is meaningless without the label */
    }
    html[data-sidebar="collapsed"] .nav-item--active { border-left: 0; }
    html[data-sidebar="collapsed"] .nav-group { padding: var(--space-8) 0; }
    html[data-sidebar="collapsed"] .sidebar__footer {
        padding: var(--space-8) 0;
        border-top: var(--so-sidebar-rule) solid var(--so-sidebar-rule);
    }
}
/* The toggle is irrelevant inside the mobile drawer — keep the drawer fully labelled. */
@media (max-width: 992px) {
    .sidebar__toggle { display: none; }
}

/* ── Theme segmented control (sidebar footer) ── */
.theme-seg {
    display: flex;
    gap: 2px;
    background: var(--so-nav-badge-bg);
    padding: 3px;
    margin-bottom: var(--space-8);
}
.theme-seg__btn {
    flex: 1;
    display: grid; place-items: center;
    border: 0;
    background: transparent;
    color: var(--so-nav-sub);
    cursor: pointer;
    padding: 6px 0;
    font: inherit;
    border-radius: var(--so-radius);
    transition: background-color .12s ease, color .12s ease;
}
.theme-seg__btn svg { width: 15px; height: 15px; }
.theme-seg__btn:hover { color: var(--white); }
.theme-seg__btn[aria-pressed="true"] { background: rgba(255,255,255,0.18); color: var(--white); }
.theme-seg__btn:focus-visible { outline: 2px solid var(--white); outline-offset: 1px; }
html[data-sidebar="collapsed"] .theme-seg { display: none; }   /* no room in the icon rail */

/* ── Copy-to-clipboard ── */
.copyable { display: inline-flex; align-items: center; gap: 4px; }
.copy-btn {
    display: inline-grid; place-items: center;
    width: 20px; height: 20px;
    flex: none;
    border: 0;
    background: transparent;
    color: var(--so-faint);
    cursor: pointer;
    padding: 0;
    border-radius: var(--so-radius);
    transition: color .12s ease, background-color .12s ease;
}
.copy-btn:hover { color: var(--so-primary); background: var(--so-row-hover); }
.copy-btn:focus-visible { outline: 2px solid var(--so-primary); outline-offset: 1px; }
.copy-btn svg { width: 13px; height: 13px; pointer-events: none; }
.copy-btn--done { color: var(--chip-booking-fg); }          /* green check */
.copy-btn--done:hover { color: var(--chip-booking-fg); background: var(--chip-booking-bg); }
/* Inside a teal sidebar/header the ghost needs a light tint — not currently used there. */

/* ── Sticky form action bar (user-management create/edit/reset-password) ── */
/* Pinned to the bottom of the scroll region so Save/Cancel are always reachable. It is the
   card's last child, so when the form is short it just sits at the foot normally. */
.form-bar {
    position: sticky;
    bottom: 0;
    z-index: 5;
    display: flex;
    gap: var(--space-8);
    align-items: center;
    flex-wrap: wrap;
    padding: var(--space-12, 12px) var(--space-16);
    background: var(--so-card);
    border-top: 1px solid var(--so-border-soft);
}
.form-bar[hidden] { display: none; }

/* ═══════════════════════════════════════════════════════════════════
    DARK THEME — :root[data-theme="dark"] overrides of the admin tokens.
    Surfaces invert (app bg darkest, cards one step up), text inverts,
    borders/chips darken their soft fills and lift their fg for AA.
    The teal sidebar (--so-sidebar) intentionally keeps its brand hue —
    it already reads as a distinct dark panel. colour-scheme flips the
    UA chrome (scrollbars / form controls).
    ═══════════════════════════════════════════════════════════════════ */
:root[data-theme="dark"] {
    color-scheme: dark;

    /* Work Packet 0.59 (a11y) — the thin accent rule rides --so-brand
       (#2A3E43), which is near-invisible on the dark card (#1F2528, ~1.4:1).
       Lift just the rule token to a lighter teal (#5E8290 ≈ 3.75:1 on the
       card) so the page/fin head rules meet the 3:1 non-text minimum. The
       filled teal sidebar still uses --so-brand (--so-sidebar) unchanged. */
    --so-rule:          #5E8290;

    --so-app-bg:      #161A1C;
    --so-topbar:      #1B2022;
    --so-card:        #1F2528;
    --so-border:      #2D3438;
    --so-border-soft: #282E31;
    --so-table-head:  #1B2022;
    --so-row-rule:    #262C2F;
    --so-row-hover:   #262D30;
    --so-track:       #1B2022;
    --so-input-bg:    #161A1C;
    --so-input-border:#394247;

    /* warm-neutral text scale inverted (adjusted for WCAG AA >= 4.5:1 on dark cards) */
    --so-text-1:  #ECEEF0;
    --so-text-2:  #D2D7DA;
    --so-text-3:  #ABB1B5;
    --so-text-4:  #949A9F;
    --so-muted:   #9AA1A6;
    --so-caption: #949A9F;
    /* BugHerd #339 — was #767D82, the exact value the ticket measured at 3.71:1 on the dark card
       (--so-card #1F2528). That is the ticket's own headline failure, and it is still reachable on
       Analytics through .kpi__note. #8A9196 is 4.85:1 on the card and 5.48:1 on the app background,
       clearing AA with margin while staying visibly BELOW --so-caption (5.45:1) so the
       caption → faint hierarchy the ticket asks to preserve is not collapsed. */
    --so-faint:   #8A9196;

    /* the terracotta primary lifts slightly for contrast on dark surfaces */
    --so-primary:       #C8632E;
    --so-primary-hover: #A8542A;
    --so-coral-tint:    #4A3328;

    /* BugHerd #339 — the 11.5px selected-period scope cue fails AA in dark. Measured on the
       deployed build: #C8632E on the dark CARD (--so-card #1F2528, which is the surface it actually
       sits on — not the app background) is 3.90:1, against the 4.5:1 small-text requirement.
       #D67740 is 4.86:1 there, keeping a real margin while still reading as terracotta.
       Deliberately a separate token, NOT a change to --so-primary: the primary is correct at button
       size and would have to go to roughly #DE854F to clear AA on every dark surface including
       borders and row-hover, which this cue never sits on. */
    --so-scope-cue:     #D67740;

    /* status chips — darken soft fills, lift fg (AA) */
    --chip-success-bg:  #1E3A22;  --chip-success-fg:  #8BD36A;
    --chip-info-bg:     #203039;  --chip-info-fg:     #9CC4D2;
    --chip-neutral-bg:  #2A2F32;  --chip-neutral-fg:  #B6BCC0;
    --chip-warn-bg:     #3A3017;  --chip-warn-fg:     #E5C162;
    --chip-error-bg:    #3E1F1E;  --chip-error-fg:    #F08A85;
    --chip-brand-bg:    #3D2417;  --chip-brand-fg:    #E08A5C;

    /* booking lifecycle + category chips share the semantic ramp */
    --chip-quote-bg:     #203039; --chip-quote-fg:     #9CC4D2;
    --chip-option-bg:    #3A3017; --chip-option-fg:    #E5C162;
    --chip-booking-bg:   #1E3A22; --chip-booking-fg:   #8BD36A;
    --chip-waitlist-bg:  #34301F; --chip-waitlist-fg:  #D3C28A;
    --chip-cancelled-bg: #2A2F32; --chip-cancelled-fg: #9A9FA3;
    --chip-closed-bg:    #243038; --chip-closed-fg:    #A8C2CE;  /* Work Packet 0.52 — lifted slate */

    --conf-a-bg: #2C5A2A; --conf-a-fg: #D6F0BD;
    --conf-b-bg: #1E3A22; --conf-b-fg: #8BD36A;
    --conf-c-bg: #3A3017; --conf-c-fg: #E5C162;
    --conf-d-bg: #2A2F32; --conf-d-fg: #9A9FA3;

    /* Work Packet 0.86 — dashboard pipeline value bars: vivid fills on a dark track. */
    --pipe-track: #2A2F32;
    --pipe-a: #6DA84A;
    --pipe-b: #8BD36A;
    --pipe-c: #E5C162;
    --pipe-d: #6E7377;

    /* finance direction + trust accents lift for dark */
    --so-money-in:      #8BD36A;
    --so-money-out:     #E27A6A;
    --so-trust:         #7FB0C0;
    --so-trust-tint:    #1A2326;
    --so-tile-accent:   #232A2D;
    --so-ok-bg:         #1C3320;
    --so-ok-border:     #2C4A30;

    /* feedback soft fills — darken so error/success/warning banners + the
       auth validation summary don't glare (mirror the chip dark washes).
       The -02 strong tokens stay vivid: they back the danger button + void
       borders, where a saturated red still reads on dark. */
    --error-01:         #3E1F1E;
    --success-01:       #1E3A22;
    --warning-01:       #3A3017;

    /* avatar palette (Work Packet 0.82) — lift each fill ~1–2 steps lighter so the
       initials badge keeps AA contrast on the dark card / top bar. fg stays white. */
    --avatar-slate-bg:   #94A3B8; --avatar-slate-fg:   #0F172A;
    --avatar-indigo-bg:  #818CF8; --avatar-indigo-fg:  #0F172A;
    --avatar-teal-bg:    #5EEAD4; --avatar-teal-fg:    #042F2E;
    --avatar-green-bg:   #86EFAC; --avatar-green-fg:   #052E16;
    --avatar-amber-bg:   #FCD34D; --avatar-amber-fg:   #1C1917;
    --avatar-rose-bg:    #FB7185; --avatar-rose-fg:    #1C1917;
    --avatar-violet-bg:  #C4B5FD; --avatar-violet-fg:  #1E1B4B;
    --avatar-cyan-bg:    #67E8F9; --avatar-cyan-fg:    #083344;
}

/* Stragglers: a few base rules baked literal whites/greys that need a dark hand-off so
   nothing glares. The surface-card stragglers were retired once the base rules moved to
   var(--so-card); the scrollbar + payment/passenger literals below are still tokenised here. */
:root[data-theme="dark"] .so-scroll::-webkit-scrollbar-thumb { background: #3A4146; border: 3px solid var(--so-app-bg); }
:root[data-theme="dark"] .so-scroll { scrollbar-color: #3A4146 transparent; }
/* the pay-row / pax-avatar greens are literal in light mode — retokenise for dark */
:root[data-theme="dark"] .pay-row__icon { background: var(--chip-success-bg); color: var(--chip-success-fg); }
:root[data-theme="dark"] .pay-row__amt-main { color: var(--so-money-in); }
:root[data-theme="dark"] .pax-avatar { background: var(--chip-neutral-bg); color: var(--so-text-2); }
/* error text rides the strong --error-02 red, which drops below AA on dark surfaces —
   lift it to the chip error fg. (The -02 red still backs .btn--danger / void borders.) */
:root[data-theme="dark"] .field__error,
:root[data-theme="dark"] .field__warn,
:root[data-theme="dark"] .bk-meta__v--danger,
:root[data-theme="dark"] .auth-form__error li,
:root[data-theme="dark"] .banner--error .banner__icon { color: var(--chip-error-fg); }
/* paid-to-date green needs lifting on dark surfaces (the light #3F7A2E falls below AA). */
:root[data-theme="dark"] .fin-strip__txn--paid { color: #7BC47F; }

/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.16 — booking create/edit (B1 write flow).
    Tokens only (no literals). Reuses .form-card / .field / .role-pick /
    .banner / .btn from earlier packets; adds a line + passenger editor
    and a status-transitions block.
    ═══════════════════════════════════════════════════════════════════ */

/* the editor stacks multiple cards vertically with a tight gap */
.bk-editor { display: flex; flex-direction: column; gap: var(--space-16); }
.bk-editor > .form-card { max-width: none; }   /* deprecated override, retained for safety */
.bk-editor__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-12); flex-wrap: wrap;
    padding: 0 0 var(--space-4) 0;
}
.bk-editor__total { font-variant-numeric: tabular-nums; font-weight: 600; }

/* 3-column variant of the form-card row (Brand/Brochure/Trip etc.) */
.form-card__row--3 { /* deprecated, auto-fit handles this now, retained for safety */ }
@media (max-width: 800px) {
    .form-card__row--3 { grid-template-columns: 1fr; }
}

.is-hidden { display: none !important; }

/* ── Itinerary line editor ── */
.bk-line {
    border: 1px solid var(--so-border-soft);
    background: var(--so-input-bg);
    padding: var(--space-12, 12px) var(--space-12, 12px);
    margin-bottom: var(--space-12);
}
.bk-line__head {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-8); margin-bottom: var(--space-8);
}
.bk-line__title {
    font-family: var(--font-display); font-weight: 600; font-size: 13.5px;
    color: var(--so-text-1); flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bk-line__remove { height: 26px; padding: 0 10px; font-size: 12px; }
.bk-line__grid {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-8) var(--space-12);
}
.bk-line__grid .field--check { grid-column: 1 / -1; }

/* ── Passenger editor (same shape, slightly different grid) ── */
.bk-pax {
    border: 1px solid var(--so-border-soft);
    background: var(--so-input-bg);
    padding: var(--space-16, 16px);
    margin-bottom: var(--space-12);
}
/* BugHerd #4: give the Lead / title / remove row room so it doesn't read as cramped. */
.bk-pax__head {
    display: flex; align-items: center; gap: var(--space-16, 16px);
    margin-bottom: var(--space-12);
    padding-bottom: var(--space-8);
    border-bottom: 1px solid var(--so-border-soft);
}
.bk-pax__title {
    font-family: var(--font-display); font-weight: 600; font-size: 13.5px;
    color: var(--so-text-1); flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bk-pax__remove { height: 26px; padding: 0 10px; font-size: 12px; }
/* BugHerd #3: a touch more room between fields (esp. Sex / Age / Child). */
.bk-pax__grid {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-12) var(--space-16, 16px);
}
.bk-pax__grid .field--check { align-self: end; }

/* a row flagged for removal */
.bk-line.is-removed, .bk-pax.is-removed {
    opacity: 0.55;
    border-left: 3px solid var(--chip-cancelled-fg);
}

/* responsive — collapse the 4-col grid to 2 then 1 */
@media (max-width: 900px) {
    .bk-line__grid, .bk-pax__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 540px) {
    .bk-line__grid, .bk-pax__grid { grid-template-columns: 1fr; }
}

/* ── Status transitions block ── */
.bk-transitions {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: var(--space-12); margin-top: var(--space-12);
}
.bk-transition {
    display: flex; flex-direction: column; gap: var(--space-8);
    padding: var(--space-12); border: 1px solid var(--so-border-soft);
    background: var(--so-input-bg);
}
.bk-transition__btn {
    text-align: left; height: auto; padding: var(--space-8) var(--space-12);
    align-items: flex-start;
}
.bk-transition__btn:hover { background: var(--so-row-hover); }

/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.18 — booking payments (Financials tab + add/edit/void forms).
    Tokens only (no literals). Reuses .form-card / .field / .banner / .btn /
    .form-bar from earlier packets; adds a voided-row state, a payment action
    row, field hint/warn lines, a danger button and the void block.
    ═══════════════════════════════════════════════════════════════════ */

/* field hint (muted helper) + warn (PAN guard — hidden until JS reveals it) */
.field__hint { font-size: 11px; color: var(--so-faint); }
.field__warn { font-size: 11.5px; color: var(--error-02); min-height: 0; }
.field__warn:empty { display: none; }

/* danger button — the only destructive action in the write flows (void) */
.btn--danger {
    background: var(--error-02);
    color: var(--white);
}
.btn--danger:hover { background: var(--so-money-out); }

/* a "voided" chip — mirrors the cancelled semantic ramp */
.chip--void { background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg); }

/* the payment form stacks a single card + sticky bar, like the booking editor */
.pay-editor { display: flex; flex-direction: column; gap: var(--space-16); }
.pay-editor > .form-card { max-width: none; }

/* void block — sits below the edit form, danger-tinted, confirms on submit */
.pay-void {
    margin-top: var(--space-16);
    border: 1px solid var(--error-02);
    background: var(--error-01);
}
.pay-void__body {
    display: flex; align-items: center; gap: var(--space-12);
    padding: var(--space-16); flex-wrap: wrap;
}
.pay-void__icon {
    width: 30px; height: 30px; flex: none;
    display: flex; align-items: center; justify-content: center;
    background: var(--error-02); color: var(--white);
}
.pay-void__text { flex: 1; min-width: 200px; }
.pay-void__title { font-family: var(--font-display); font-weight: 600; font-size: 14px; color: var(--so-text-1); }
.pay-void__hint { font-size: 12px; color: var(--so-text-3); margin-top: 3px; }

/* ── Financials tab: action row + voided rows + edit link ── */
.fin-enquiry-nav,
.fin-enquiry-toolbar,
.fin-enquiry-filters {
    display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap;
}
.fin-enquiry-nav {
    padding: var(--space-12) var(--space-20);
    border-bottom: 1px solid var(--so-border-soft);
    background: var(--so-row-hover);
}
.fin-enquiry-toolbar {
    justify-content: space-between;
    padding: var(--space-16) var(--space-20) 0;
}
.fin-enquiry-nav .btn,
.fin-enquiry-toolbar .btn { min-height: 34px; }
.fin-enquiry-facts { border-top: 1px solid var(--so-border-soft); }
.fin-enquiry-facts .kv { min-width: 0; }
.fin-enquiry-facts .kv__sub { margin-top: 4px; font-size: 11px; color: var(--so-faint); }
.fin-enquiry-boundary { margin: var(--space-16) var(--space-20); }
.fin-enquiry-table th,
.fin-enquiry-table td { white-space: nowrap; }
.fin-enquiry-table td:nth-child(7) { white-space: normal; min-width: 180px; }

.fin-actions {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-12); flex-wrap: wrap;
    padding: var(--space-16) var(--space-20);
    border-bottom: 1px solid var(--so-border-soft);
}
.fin-actions__hint { font-size: 11.5px; color: var(--so-faint); }
.fin-actions__btns { display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap; }
.fin-actions .btn { height: 30px; padding: 0 var(--space-12); font-size: 12.5px; }

.pay-row__actions { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.pay-row__edit {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 11px; font-weight: 700; color: var(--so-text-3);
    text-decoration: none; padding: 3px 6px;
}
.pay-row__edit:hover { color: var(--so-primary); background: var(--so-row-hover); }
.pay-row__edit svg { width: 12px; height: 12px; }

/* voided receipt — dimmed + struck amount; the row stays (audit-not-delete) */
.pay-row--voided { opacity: 0.6; }
.pay-row--voided .pay-row__amt-main {
    text-decoration: line-through;
    color: var(--so-text-3);
}
.pay-row--voided .pay-row__icon { background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg); }
.pay-row__void-chip {
    font-size: 10px; font-weight: 700;
    background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg);
    padding: 1px 7px; text-transform: uppercase; letter-spacing: 0.04em;
}

@media (max-width: 600px) {
    .pay-row__amt { width: auto; }
    .fin-actions { flex-direction: column; align-items: flex-start; }
    .fin-enquiry-nav .btn,
    .fin-enquiry-filters .btn { flex: 1 1 auto; justify-content: center; }
    .fin-enquiry-toolbar { align-items: stretch; }
}

/* dark hand-off for the new payment surfaces (tokens-only) */
:root[data-theme="dark"] .pay-row--voided .pay-row__icon { background: var(--chip-cancelled-bg); color: var(--chip-cancelled-fg); }
:root[data-theme="dark"] .pay-void { background: var(--so-ok-bg); }
:root[data-theme="dark"] .pay-void__title { color: var(--so-text-1); }

/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.17 — user invitations. Reuses tokens only.
    Pending-invite list metadata, inline POST forms in the row actions /
    sticky form bar, the copyable invite-link box on the confirmation
    page, and the accept-invite greeting. No new colours.
    ═══════════════════════════════════════════════════════════════════ */

/* pending-invite metadata under the status chip on the users list */
.user-status__meta {
    font-size: 11px; line-height: 16px; color: var(--so-caption);
    margin-top: 3px;
}

/* an inline POST form (anti-forgery button) that should lay out as if its
   button were a direct child of the surrounding flex container. */
.row-form { display: contents; margin: 0; }

/* copyable one-time invite link on the InvitationSent page */
.invite-link { display: flex; gap: var(--space-8); align-items: flex-start; }
.invite-link__input {
    flex: 1; min-width: 0;
    font-family: var(--font-body); font-size: 13px;
    padding: 8px 10px;
    background: var(--so-input-bg);
    border: 1px solid var(--so-input-border);
    color: var(--so-text-2);
    border-radius: var(--so-radius);
}
.invite-link .btn { flex: none; }
.field__hint { display: block; font-size: 12px; color: var(--so-caption); margin-top: 6px; }

/* accept-invite greeting paragraph (sits in the .auth-form stack) */
.auth-form__intro {
    margin: 0 0 var(--space-16) 0;
    font-size: 14px; line-height: 22px; color: var(--so-text-2);
}
.auth-form__intro strong { color: var(--so-text-1); }

@media (max-width: 600px) {
    .invite-link { flex-direction: column; }
}

/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.23 — Analytics dashboard. Read-only KPI cards + inline
    SVG / CSS charts. Tokens only — every fill/colour flows from the chip
    + surface tokens, so the whole screen inverts correctly in dark mode
    (no literal colours, no dark-theme overrides needed here). No external
    chart library (strict CSP). Vanilla; accessible (SVG title/desc + a
    companion data table / aria labels on bars).
    ═══════════════════════════════════════════════════════════════════ */

/* visually hidden but available to assistive tech (companion data tables) */
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); clip-path: inset(50%);
    white-space: nowrap; border: 0;
}

.page--analytics {
    padding: var(--space-32) var(--space-32) var(--space-64);
    max-width: var(--so-max-content-analytics);
    margin-inline: auto;
}

/* BugHerd #340/#341/#342 (A01/A02/A04) — Analytics is an operations control desk. Its page,
   section and card levels follow the committed redesign scale instead of inheriting the compact
   generic dashboard chrome. This remains page-scoped: neighbouring cards and typography keep the
   shared defaults. */
.page--analytics .page-head { margin-bottom: var(--space-32); }
.page--analytics .page-head__eyebrow {
    margin-bottom: var(--space-8);
    font-size: 12px;
    line-height: 18px;
}
.page--analytics .page-head__title {
    font-size: 28px;
    line-height: 34px;
}
.page--analytics .page-head__count {
    font-size: 12px;
    line-height: 18px;
}
.page--analytics .page-head__rule { margin-top: var(--space-12); }

/* BugHerd #346 (A08) — Analytics colour-role contract. Measured on the deployed build, Overland
   orange (--so-primary / --so-overland) carried FOUR unrelated jobs at once (structural head border,
   selected-range chip, active-range button AND magnitude-chart fill), so emphasis carried no
   learnable meaning. Per the redesign brief's colour-role table, orange is reserved here for brand
   accent and active range/selection ONLY, and every magnitude series reads through this page-scoped
   NEUTRAL series token instead. Added page-scope (not in tokens.css) deliberately: tokens.css is the
   shared site-wide scale and this role is Analytics-only.
   HUE CHOICE, corrected after measuring the deployed build: a slate-blue neutral does NOT work here.
   "Bookings by status" and "Value by brand" render side by side at the same y, and slate sits at hue
   209deg against Quote 197deg and Closed 199deg - a 10-12deg separation, i.e. the same colour family
   meaning two different things in adjacent cards. That is the conflation this ticket exists to remove,
   merely repainted. The violet below sits at 256deg: its WORST separation from any status hue is
   57deg (Closed), against 122deg from the reserved orange and clear of the negative money red. Keep
   any future neutral at least 40deg from every status hue AND from the orange.
   Themes switch via the data-theme ATTRIBUTE on <html>, never prefers-color-scheme, so the dark
   hand-off below is attribute-scoped too. */
.page--analytics {
    --an-series:        #553C9A;   /* neutral data-series fill (bars), light - 8.40:1 on white */
    --an-series-strong: #45307E;   /* emphasis/hover variant of the same series */
}
[data-theme="dark"] .page--analytics,
:root[data-theme="dark"] .page--analytics {
    --an-series:        #A99BE0;   /* lifted violet stays visible on the dark card - 6.24:1 */
    --an-series-strong: #C0B5EC;
}

/* KPI values are data, not headings: Open Sans keeps figures distinct from Poppins headings and
   tabular numerals align money, counts and percentages. */
.page--analytics .kpi__value {
    font-family: var(--font-body);
    font-size: 30px;
    font-weight: 700;
    line-height: 36px;
    font-variant-numeric: tabular-nums;
}

/* layout: stacked cards, with a two-up pair for status × brand */
.an-grid { display: flex; flex-direction: column; gap: var(--space-24); }
.an-grid__pair { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-24); align-items: start; }
.an-card__body { padding: var(--space-20) var(--space-24) var(--space-24); }

.page--analytics .card__head {
    align-items: flex-start;
    gap: var(--space-8) var(--space-16);
    padding: var(--space-24) var(--space-24) 0;
    border-bottom: 0;
    flex-wrap: wrap;
}
.page--analytics .card__title {
    font-size: 16px;
    line-height: 24px;
}
.page--analytics .card__meta {
    font-size: 12px;
    line-height: 18px;
    padding-top: 3px;
}

/* ── monthly bar chart (CSS bars — responsive, tokens-only) ── */
.an-chart { width: 100%; }
.an-bars {
    display: flex; align-items: flex-end; gap: 3px;
    height: 160px; border-bottom: 1px solid var(--so-border);
}
.an-bar-col {
    flex: 1 1 0; min-width: 0; height: 100%;
    display: flex; align-items: flex-end; justify-content: center; cursor: help;
}
.an-bar-col__bar {
    width: 64%; max-width: 28px; min-height: 2px;
    /* A08/#346 — monthly magnitude series reads neutral; orange is selection/brand only */
    background: var(--an-series); border-radius: 2px 2px 0 0;
}
.an-bar-col__bar--zero { background: var(--so-track); }
.an-axis { display: flex; gap: 3px; padding-top: 6px; }
.an-axis__label {
    flex: 1 1 0; min-width: 0; text-align: center;
    font-size: 10.5px; color: var(--so-caption);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── companion data table (also the accessible fallback) ── */
.an-table { width: 100%; border-collapse: collapse; margin-top: var(--space-16); font-size: 12px; }
.an-table thead th {
    font-size: 10px; text-transform: uppercase; letter-spacing: .06em;
    color: var(--so-muted); font-weight: 700; text-align: left; padding: 6px 8px;
    border-bottom: 1px solid var(--so-border-soft);
}
.an-table tbody th, .an-table tbody td { padding: 6px 8px; border-bottom: 1px solid var(--so-row-rule); color: var(--so-text-2); font-variant-numeric: tabular-nums; }
.an-table tbody tr:last-child td, .an-table tbody tr:last-child th { border-bottom: 0; }
.an-table tbody th { font-weight: 600; color: var(--so-text-3); }
.an-table td:nth-child(2), .an-table td:nth-child(3) { text-align: right; }

/* ── horizontal CSS bar rows (status / brand / agency) ── */
.an-rows { display: flex; flex-direction: column; gap: 11px; }
.an-row { display: flex; align-items: center; gap: 12px; }
.an-row__label { width: 78px; flex: none; font-size: 12px; color: var(--so-text-3); }
.an-row__track {
    flex: 1 1 auto; min-width: 0; height: 18px;
    background: var(--so-track); border-radius: 2px; overflow: hidden;
}
.an-bar { display: block; height: 100%; min-width: 2px; border-radius: 2px; }
.an-row__value { width: 70px; flex: none; text-align: right; font-size: 12px; font-weight: 700; color: var(--so-text-2); font-variant-numeric: tabular-nums; }

/* status bar fills — the saturated chip -fg tokens (read as solid bars, invert in dark) */
.an-bar--quote     { background: var(--chip-quote-fg); }
.an-bar--option    { background: var(--chip-option-fg); }
.an-bar--booking   { background: var(--chip-booking-fg); }
.an-bar--waitlist  { background: var(--chip-waitlist-fg); }
.an-bar--cancelled { background: var(--chip-cancelled-fg); }
.an-bar--closed    { background: var(--chip-closed-fg); } /* Work Packet 0.52 */
/* single-series breakdowns — A08/#346: these plot MAGNITUDE (value by brand /
   agency), not brand identity, so they read through the neutral series token.
   Overland orange stays reserved for the brand accent and active range only. */
.an-bar--brand  { background: var(--an-series); }
.an-bar--agency { background: var(--an-series); }

/* agency rows — wider label + a two-line value (amount + commission) */
.an-row--agency { }
.an-row__label--agency { width: 130px; }
.an-row__value--agency { width: 130px; display: flex; flex-direction: column; align-items: flex-end; }
.an-row__amt { font-weight: 700; font-size: 12px; color: var(--so-text-2); font-variant-numeric: tabular-nums; }
.an-row__sub { font-size: 10.5px; color: var(--so-caption); font-variant-numeric: tabular-nums; }

/* ── method & caveat notes ── */
.an-notes { background: var(--so-card); border: 1px solid var(--so-border); padding: var(--space-24); margin-top: var(--space-32); }
.an-notes__title { font-family: var(--font-display); font-weight: 600; font-size: 16px; line-height: 24px; margin: 0 0 var(--space-8); color: var(--so-muted); }
.an-notes__list { margin: 0; padding-left: var(--space-20); }
.an-notes__list li { font-size: 12px; color: var(--so-text-3); line-height: 18px; margin-bottom: var(--space-4); }

@media (max-width: 992px) {
    .an-grid__pair { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
    .an-row__label--agency { width: 88px; }
    .an-row__value--agency { width: 100px; }
}

/* ════════════════════════════════════════════════════════════════════
   Work Packet 0.65 — Analytics count layer (sits ALONGSIDE the money
   charts above; nothing there is changed). Adds: a date-range segmented
   control, count-KPI tiles with prior-period trend, an inline-SVG
   daily-activity bar chart, and a pipeline funnel. (The range-summary
   card this packet originally added was removed again by A07/BH #345.)
   Tokens only; no external chart library (strict CSP — inline SVG only).
   ════════════════════════════════════════════════════════════════════ */

/* ── date-range segmented control ── */
.an-range {
    background: var(--so-card);
    border: 1px solid var(--so-border);
    padding: var(--space-16) var(--space-20);
    margin-bottom: var(--space-16);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-12) var(--space-16);
}
.an-range__presets {
    display: flex;
    border: 1px solid var(--so-input-border);
}
.an-range__opt {
    display: block;
    padding: 7px 14px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--so-text-2);
    background: var(--so-input-bg);
    text-decoration: none;
    border-right: 1px solid var(--so-input-border);
}
.an-range__opt:last-child { border-right: 0; }
.an-range__opt:hover { background: var(--so-row-hover); color: var(--so-text-1); }
.an-range__opt--active,
.an-range__opt--active:hover { background: var(--so-primary); color: var(--white); }
.an-range__opt:focus-visible { outline: 2px solid var(--so-focus-ring); outline-offset: -2px; }

.an-range__custom { display: flex; align-items: flex-end; gap: var(--space-8); }
.an-range__field { display: flex; flex-direction: column; gap: 3px; font-size: 12px; line-height: 18px; color: var(--so-muted); }
.an-range__field input {
    font: inherit; font-size: 12.5px;
    padding: 5px 7px;
    background: var(--so-input-bg);
    border: 1px solid var(--so-input-border);
    border-radius: var(--so-radius);
    color: var(--so-text-1);
}
.an-range__apply {
    font: inherit; font-size: 12.5px; font-weight: 600;
    padding: 6px 14px;
    background: var(--so-primary); color: var(--white);
    border: 0; border-radius: var(--so-radius);
    cursor: pointer;
}
.an-range__apply:hover { background: var(--so-primary-hover); }
.an-range__apply:focus-visible { outline: 2px solid var(--so-focus-ring); outline-offset: 1px; }

.an-range__caption {
    margin: 0 0 0 auto;
    font-size: 12px;
    line-height: 18px;
    color: var(--so-caption);
    font-variant-numeric: tabular-nums;
}

/* BugHerd #57 — inline message shown when a Custom range was requested but the bounds were missing
   or reversed (the service fell back to Last 30 days). Sits alongside the form so the operator sees
   why their dates didn't apply. */
.an-range__note {
    margin: 0;
    font-size: 12px;
    line-height: 18px;
    color: var(--so-money-out);
    font-variant-numeric: tabular-nums;
}

/* ── count-KPI tiles (alongside the money KPIs; trend indicator) ── */
.page--analytics .kpi-grid--counts {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: var(--space-16);
    margin-top: 0;
    background: transparent;
    border: 0;
}
.page--analytics .kpi-grid--counts .kpi {
    grid-column: span 1;
    padding: var(--space-24);
    border: 1px solid var(--so-border);
}
/* Booking volume and active sales work are the two operator outcomes. Supporting agency/catalogue
   changes retain full fidelity but take one track each, producing the brief's 2:2:1:1 priority. */
.page--analytics .kpi-grid--counts .kpi:nth-child(1),
.page--analytics .kpi-grid--counts .kpi:nth-child(2) { grid-column: span 2; }
.page--analytics .kpi-grid--counts .kpi:nth-child(1) { border-top: 3px solid var(--so-primary); }
.page--analytics .kpi--count .kpi__label {
    margin-bottom: var(--space-8);
    font-size: 12px;
    line-height: 18px;
}
.page--analytics .kpi--count .kpi__value { font-size: 30px; line-height: 36px; }
.page--analytics .kpi-grid--counts .kpi:first-child .kpi__value { font-size: 34px; line-height: 40px; }
.kpi--count .kpi__trend {
    display: flex; align-items: baseline; gap: 5px;
    margin-top: var(--space-8);
    font-variant-numeric: tabular-nums;
}
.kpi--count .kpi__trend-arrow { font-size: 13px; line-height: 1; }
.kpi--count .kpi__trend-delta { font-size: 12.5px; font-weight: 700; }
.kpi--count .kpi__trend-note { font-size: 12px; line-height: 18px; color: var(--so-faint); margin-left: auto; }
.kpi__trend--up   { color: var(--so-money-in); }    /* green */
.kpi__trend--down { color: var(--so-money-out); }   /* red */
.kpi__trend--flat { color: var(--so-muted); }       /* neutral */

@media (max-width: 992px) {
    .an-range__caption { margin: 0; flex-basis: 100%; }
    .page--analytics .kpi-grid--counts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .page--analytics .kpi-grid--counts .kpi,
    .page--analytics .kpi-grid--counts .kpi:nth-child(1),
    .page--analytics .kpi-grid--counts .kpi:nth-child(2) { grid-column: span 1; }
}
@media (max-width: 768px) {
    .an-range { flex-direction: column; align-items: flex-start; }
    .an-range__presets { width: 100%; }
    .an-range__opt { flex: 1 1 0; text-align: center; }
    .an-range__custom { flex-wrap: wrap; }
}

/* ── count-charts grid (separate stack so the money an-grid stays intact) ── */
.an-grid--counts { margin-bottom: var(--space-24); }

/* BugHerd #174 + A07 (BugHerd #345) — wide-desktop control-desk layout (≥1600px). The redesign brief
   (docs/handoff/ANALYTICS-VISUAL-REDESIGN-BRIEF-2026-08-12.md) calls for a centred bounded grid with
   no dead zone beside compressed cards. An earlier layout nested the pipeline + summary pair as
   equal halves inside ONE narrow right column — on a 2560px canvas those cards were squeezed to
   ~290px each and their titles wrapped into fragments, and the squeeze IS that nesting. BH #174
   flattened the pair onto the top level; A07 then deleted the redundant range-summary card outright,
   so .an-grid--counts now holds its TWO cards as direct children and the squeeze is structurally
   impossible: there is no .an-grid__pair wrapper left in this grid to nest anything inside. The two
   tracks take the brief's 12-column contract split for these cards (Daily activity 8 cols,
   journey/pipeline 4) so Daily keeps the clear lead while both remaining cards are wider than in
   the three-track interim it replaces. Tokens only; scoped to the analytics page so nothing else
   shifts, and the 1600px breakpoint leaves 1440×900 (the Playwright default) on the standard stack.
   (.an-grid__pair itself still serves the all-time section and the standard-width stack.) */
@media (min-width: 1600px) {
    .page--analytics .an-grid--counts {
        display: grid;
        grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
        gap: var(--space-24);
        align-items: start;
    }
}

/* BugHerd #174 — Analytics card titles never wrap into one-word fragments (the visible symptom the
   tester reported at wide desktop: a 290px column let the flex card head shrink the title until it
   broke across 2–3 lines). Scoped to the analytics page so no other consumer of .card__title shifts;
   the card__head flex row lets the secondary .card__meta wrap in the remaining space while the title
   holds one line. BugHerd #338 narrows the guard to ABOVE the mobile breakpoint only: at ≤480px the
   card head recomposes into the stacked title-over-meta column (see the .card__head mobile rule in
   the CARDS section) and the title must phrase-wrap normally at full card width — the mobile
   contract forbids forced nowrap — so the one-line guard sits inside min-width: 481px. */
@media (min-width: 481px) {
    .page--analytics .card__title { white-space: nowrap; }
}

/* ── daily-activity inline-SVG bar chart ── */
/* BugHerd #343 (A05) — count magnitude without hovering, sparse states that look deliberate.
   The plot adapts to the range instead of holding a fixed 180px box: the view writes
   --an-daily-units (bucket count + 4, capped at 22), one unit is --space-8, and --space-64 is the
   floor so even a one-bucket Custom range keeps a readable labelled stage (~64px) rather than a
   lone column floating in an empty frame; 22 units ≈ the previous 176px presence for dense ranges.
   Everything scale-related (gridlines, tick values, peak callout) is HTML layered AROUND the SVG:
   the chart is viewBox="0 0 100 40" stretched with preserveAspectRatio="none", so text or strokes
   inside it would distort non-uniformly as the card resizes — these layers measure real screen
   pixels on both axes regardless of viewport width. */
.an-daily {
    width: 100%;
    --an-daily-units: 22;
    --an-daily-plot-h: max(var(--space-64), calc(var(--an-daily-units) * var(--space-8)));
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
}
.an-daily__yaxis {
    position: relative;
    height: var(--an-daily-plot-h);
    padding-right: var(--space-4);
    min-width: 0;
    max-width: 100%;
}
.an-daily__tick {
    position: absolute;
    right: 0;
    transform: translateY(50%);
    font-size: 10.5px;
    color: var(--so-caption);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.an-daily__stage {
    position: relative;
    height: var(--an-daily-plot-h);
    min-width: 0;
    max-width: 100%;
}
.an-daily__gline {
    position: absolute;
    left: 0;
    right: 0;
    border-top: 1px solid var(--so-border);
    pointer-events: none;                 /* never intercept a bar's tooltip */
}
.an-daily__chart {
    display: block;
    width: 100%;
    height: var(--an-daily-plot-h);
    border-bottom: 1px solid var(--so-border);   /* baseline (the 0 gridline) */
}
/* A08/#346 — decision recorded: the page's primary chart goes neutral too. The brief's binding rule
   is "orange must not be a data-series fill anywhere on the page" and this IS one (booking counts per
   day); its lead role comes from layout (widest card, first chart) not from competing with the
   active-range/selection accent, which would recreate the conflation this ticket fixes. */
.an-daily__bar { fill: var(--an-series); }
.an-daily__bar:hover { fill: var(--an-series-strong); }
.an-daily__bar--zero { fill: var(--so-track); }
.an-daily__peak {
    position: absolute;
    transform: translate(-50%, calc(-100% - var(--space-4)));   /* centred on the bar, just above its tip */
    padding: 0 var(--space-4);
    background: var(--so-card);           /* stay legible over neighbouring bars */
    font-size: 10.5px;
    color: var(--so-caption);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    pointer-events: none;
}
/* BugHerd #343 — keep the callout inside the plot near either end. Centring it on the bar pushes it
   past the stage (and the card) when the peak is the first or last bucket: measured 23.6px past the
   stage and 6.6px past the card at 390px, where the label is ~29% of the stage width against ~10% on
   a wide canvas. Shifting the anchor instead of clipping keeps the whole label readable. */
.an-daily__peak--start { transform: translate(0, calc(-100% - var(--space-4))); }
.an-daily__peak--end   { transform: translate(-100%, calc(-100% - var(--space-4))); }
.an-daily__axis {
    grid-column: 2;                       /* align under the bars, clear of the tick gutter */
    display: flex; justify-content: space-between;
    padding-top: 6px;
    font-size: 10.5px; color: var(--so-caption);
    font-variant-numeric: tabular-nums;
}

/* ── pipeline funnel → A06 booking journey strip (BugHerd #344) ──
   The generic bar-list rows are replaced by a travel route: Quote, Option,
   Booking and Closed are labelled STOPS on one rail at desktop and a vertical
   route at mobile. Occupancy is shown by each stop's cumulative count AND
   percentage together; the rail never narrows, points downward or colours a
   gap as failure.
   BugHerd #59 — the between-stops remainder is NOT lost records (the model
   carries no status-transition audit): it is the count still CURRENTLY at the
   prior stage, rendered as a positive interval annotation under the route in
   neutral colour, wording and weight, with drill-through to the exact
   contributing bookings. Explicit IsLostOpportunity records stay in their own
   strictly-separate disclosure below the route so they are never merged into
   the open-quote population. */
.an-journey {
    --an-journey-gutter: calc(var(--space-20) + var(--space-12));
}

/* ── the route (desktop: horizontal strip) ── */
.an-journey__route {
    list-style: none;
    margin: 0 0 var(--space-8);
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
.an-journey__stop {
    position: relative;
    text-align: center;
    padding-top: 30px;                        /* clears the rail band above */
}

/* One continuous rail: every stop draws a full-width segment at the same
   height; the outermost stops trim to the marker so the line starts and ends
   ON a stop. Identical weight for every segment — the gap between stops never
   looks different when a remainder exists. */
.an-journey__stop::before {
    content: "";
    position: absolute;
    top: 14px;                                /* centres on the 14px marker */
    left: 0; right: 0;
    height: 2px;
    background: var(--so-border);
}
.an-journey__stop:first-child::before { left: 50%; }
.an-journey__stop:last-child::before  { right: 50%; }

.an-journey__marker {
    position: absolute;
    top: 7px;
    left: 50%;
    transform: translateX(-50%);
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--so-primary);
    box-shadow: 0 0 0 3px var(--so-card);     /* lifts the dot off the rail */
}
/* stage fills reuse EXACTLY the former bar tokens (.an-bar--quote etc.) — no
   new colour semantics here (A08/#346 owns the colour contract) */
.an-journey__stop--quote .an-journey__marker   { background: var(--chip-quote-fg); }
.an-journey__stop--option .an-journey__marker  { background: var(--chip-option-fg); }
.an-journey__stop--booking .an-journey__marker { background: var(--chip-booking-fg); }
.an-journey__stop--closed .an-journey__marker  { background: var(--chip-closed-fg); }

.an-journey__stop-body { display: block; }
.an-journey__stage {
    display: block;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--so-text-2);
}
/* count and percentage together, always (chart contract) */
.an-journey__figures {
    display: flex;
    justify-content: center;
    align-items: baseline;
    gap: 6px;
    margin-top: 2px;
    font-variant-numeric: tabular-nums;
}
.an-journey__count { font-size: 16px; font-weight: 700; color: var(--so-text-1); }
.an-journey__pct   { font-size: 11px; color: var(--so-text-3); }

/* ── interval annotations (current occupancy BETWEEN stops) — stacked BELOW
      the route, full width, neutral in every respect ── */
.an-journey__intervals {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--so-border-soft);
}
.an-journey__interval { padding: var(--space-8) 0 0; }
.an-journey__remainder {
    font-size: 11.5px;
    color: var(--so-text-3);                  /* neutral — a current-state count, not a loss */
    font-variant-numeric: tabular-nums;
}
.an-journey__interval-term { font-weight: 600; color: var(--so-muted); }

/* drill-through disclosure for a stage remainder / the explicit-lost list */
.an-journey__disclosure {
    margin: 4px 0 0;
    font-size: 11.5px;
}
.an-journey__disclosure > summary {
    cursor: pointer;
    color: var(--so-text-link, var(--so-primary));
    font-weight: 600;
    list-style: none;                         /* custom marker below */
}
.an-journey__disclosure > summary::-webkit-details-marker { display: none; }
.an-journey__disclosure > summary::before {
    content: "\25B6";                         /* right-pointing triangle; rotates when open */
    display: inline-block;
    margin-right: 6px;
    font-size: 9px;
}
@media (prefers-reduced-motion: no-preference) {
    .an-journey__disclosure > summary::before { transition: transform 0.12s ease; }
}
.an-journey__disclosure[open] > summary::before { transform: rotate(90deg); }
.an-journey__disclosure > summary:focus-visible { outline: 2px solid var(--so-focus-ring); outline-offset: 2px; }

.an-journey__list {
    list-style: none;
    margin: var(--space-8) 0 0;
    padding: 0;
    display: flex; flex-direction: column;
    gap: 4px;
    max-height: 260px;                        /* keep the disclosure compact; scroll if long */
    overflow-y: auto;
}
.an-journey__list-item { margin: 0; }
.an-journey__link {
    display: flex; align-items: baseline; gap: 10px;
    padding: 5px var(--space-8);
    text-decoration: none;
    border-radius: var(--so-radius);
    background: var(--so-row-hover);
    color: var(--so-text-2);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}
.an-journey__link:hover { background: var(--so-primary); color: var(--white); }
.an-journey__link:focus-visible { outline: 2px solid var(--so-focus-ring); outline-offset: 1px; }
.an-journey__fileno { font-weight: 700; color: var(--so-text-1); min-width: 56px; }
.an-journey__link:hover .an-journey__fileno { color: var(--white); }
.an-journey__party { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.an-journey__status {
    flex: none;
    font-size: 10.5px; font-weight: 600;
    color: var(--so-muted);
    text-transform: capitalize;
}
.an-journey__link:hover .an-journey__status { color: var(--white); }

/* explicit-lost disclosure — visually DISTINCT from the route (it IS a loss)
   via a full-width rule beneath the whole strip, but still token-driven and
   dark-mode safe. Its meaning and wording are the BugHerd #59 contract. The
   selector deliberately matches even when the route is absent (a period with
   no pipeline stages but with lost records), where the disclosure renders
   WITHOUT the .an-journey wrapper. */
.an-journey__disclosure--lost {
    margin-top: var(--space-12);
    padding-top: var(--space-12);
    border-top: 1px solid var(--so-border);
}
.an-journey__disclosure--lost > summary { color: var(--so-money-out); }
.an-journey__lost-note {
    margin: 6px 0 var(--space-8);
    font-size: 11px; line-height: 1.5;
    color: var(--so-text-3);
}
/* BH #58 acceptance — the all-time availability note wraps its prose in a child <p>. The global
   typography rule in tokens.css gives every bare paragraph a fixed light-theme ink colour, size and
   line-height; without an explicit reset that child becomes ~1.07:1 in dark mode even though the
   token-safe wrapper is correct. Keep the override Analytics-scoped and let the paragraph inherit
   the summary note's theme-aware text contract. */
.page--analytics .an-journey__lost-note--summary {
    margin-top: var(--space-8);
    color: var(--so-text-2);
    font-size: 12.5px;
    line-height: 1.55;
}
.page--analytics .an-journey__lost-note--summary > strong {
    display: block;
    margin-bottom: var(--space-4);
    color: var(--so-text-1);
}
.page--analytics .an-journey__lost-note--summary > p {
    margin: 0;
    color: inherit;
    font: inherit;
}
.an-journey__lost-note code {
    font: inherit;
    background: var(--so-track);
    padding: 1px 4px;
    border-radius: 2px;
}

/* ── A06 mobile: a VERTICAL ROUTE, not the strip squeezed. The rail turns
      down the left edge, each stop becomes a full-width row, the figures
      right-align along the row like ledger columns, and the interval
      annotations indent to the route's content column. No label is reduced
      to a narrow column and no information drops out. ── */
@media (max-width: 768px) {
    .an-journey__route { display: block; }
    .an-journey__stop {
        text-align: left;
        padding: 0 0 var(--space-16) var(--an-journey-gutter);
    }
    .an-journey__route .an-journey__stop::before {
        top: 0; bottom: 0; left: 10px; right: auto;
        width: 2px; height: auto;
    }
    .an-journey__route .an-journey__stop:first-child::before { top: 14px; }
    .an-journey__route .an-journey__stop:last-child::before  { top: 0; bottom: auto; height: 15px; }
    .an-journey__marker {
        top: 7px; left: 4px; transform: none;
    }
    .an-journey__stop-body {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--space-12);
    }
    .an-journey__figures { justify-content: flex-end; }

    .an-journey__intervals { margin-left: var(--an-journey-gutter); }
}

/* ════════════════════════════════════════════════════════════════════
   BugHerd #58 — Analytics page-level scope contract. Two named section
   landmarks split the page so an operator can tell BEFORE the first KPI
   whether a figure describes selected-period activity (scoped to the
   resolved CreatedAtUtc window) or fixed all-time/not-range-scoped position.
   Each landmark carries a heading + a small scope tag, and every card
   inside repeats its own scope cue so the bottom "Method & caveats" note
   is no longer the only signal. Tokens only — no literals, no dark-theme
   override needed (every colour flows from the existing surface tokens).
   ════════════════════════════════════════════════════════════════════ */
.an-scope {
    margin-bottom: var(--space-48);
    padding: 0;
}
.an-scope--alltime { margin-top: 0; }

/* BugHerd #347 / A09 — keep the all-time ledger available without letting more than a page of
   historical detail overpower the operational story. Native details/summary provides its own
   expanded state and keyboard behaviour; these styles establish the quieter visual hierarchy. */
.an-alltime-disclosure {
    margin: 0;
}
.an-alltime-disclosure__summary {
    padding: var(--space-20) var(--space-24);
    border: 1px solid var(--so-border);
    border-left: 3px solid var(--so-caption);
    border-radius: var(--radius-md);
    background: var(--so-card);
    color: var(--so-text-1);
    cursor: pointer;
    list-style: none;
}
.an-alltime-disclosure__summary::-webkit-details-marker { display: none; }
.an-alltime-disclosure:not([open]) > :not(.an-alltime-disclosure__summary) { display: none; }
.an-alltime-disclosure__summary:hover { background: var(--so-row-hover); }
.an-alltime-disclosure__summary:focus-visible {
    outline: 3px solid var(--so-focus-ring);
    outline-offset: 3px;
}
.an-alltime-disclosure__heading {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 2px var(--space-24);
    align-items: center;
    margin: 0;
}
.an-alltime-disclosure__title {
    font-family: var(--font-display);
    font-size: 20px;
    font-weight: 600;
    line-height: 28px;
}
.an-alltime-disclosure__description {
    grid-column: 1;
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 400;
    line-height: 20px;
    color: var(--so-text-2);
}
.an-alltime-disclosure__action {
    grid-column: 2;
    grid-row: 1 / span 2;
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    line-height: 20px;
    color: var(--so-text-2);
}
.an-alltime-disclosure__action::after {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin: 0 3px 3px var(--space-8);
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    content: "";
    transform: rotate(45deg);
}
.an-alltime-disclosure__action--hide { display: none; }
.an-alltime-disclosure[open] > .an-alltime-disclosure__summary {
    margin-bottom: var(--space-24);
}
.an-alltime-disclosure[open] .an-alltime-disclosure__action--show { display: none; }
.an-alltime-disclosure[open] .an-alltime-disclosure__action--hide { display: block; }
.an-alltime-disclosure[open] .an-alltime-disclosure__action--hide::after {
    margin-bottom: -1px;
    transform: rotate(225deg);
}
.an-alltime-disclosure > .an-scope--alltime { margin-bottom: var(--space-32); }
.an-alltime-disclosure > .an-notes { margin-top: 0; }

.an-scope__head {
    margin-bottom: var(--space-24);
    padding: 0 0 0 var(--space-20);
    border-left: 3px solid var(--so-border);
    border-bottom: 0;
}
.an-scope--period .an-scope__head { border-left-color: var(--so-primary); }
.an-scope--alltime .an-scope__head { border-left-color: var(--so-caption); }
.an-scope__title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 20px;
    line-height: 28px;
    margin: 0 0 var(--space-8);
    color: var(--so-text-1);
}
.an-scope__cue {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-8);
    margin: 0 0 var(--space-8);
}
.an-scope__tag {
    display: inline-block;
    padding: 3px var(--space-8);
    border-radius: 12px;
    font-size: 12px;
    line-height: 18px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    background: var(--so-primary);
    color: var(--white);
}
.an-scope__tag--alltime {
    background: var(--so-caption);
    color: var(--white);
}
.an-scope__window {
    font-size: 13px;
    line-height: 20px;
    color: var(--so-text-2);
    font-variant-numeric: tabular-nums;
}
.an-scope__blurb {
    margin: 0;
    font-size: 12px;
    color: var(--so-caption);
    line-height: 18px;
    max-width: 80ch;
}

/* Per-card scope cues repeat the period/all-time tag inline in the card meta
   so a figure is never read in isolation. The accent border mirrors the
   landmark it belongs to (primary = selected period, caption = all-time). */
.card__meta--scope-period { color: var(--so-scope-cue); font-weight: 600; }
.card__meta--scope-alltime { color: var(--so-caption); font-weight: 600; }

/* Count-KPI tiles carry their own scope line beneath the value so the
   selected-period population is obvious on every tile, not just the section. */
.kpi--count .kpi__scope {
    margin-top: 0;
    font-size: 12px;
    line-height: 18px;
    color: var(--so-caption);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 768px) {
    .page--analytics {
        padding: var(--space-24) var(--space-16) var(--space-48);
    }
    .page--analytics .page-head { margin-bottom: var(--space-24); }
    .page--analytics .page-head__title { font-size: 24px; line-height: 30px; }
    .page--analytics .page-head__bar { align-items: flex-start; }
    .page--analytics .page-head__actions { flex-basis: 100%; }
    .an-scope { margin-bottom: var(--space-40); }
    .an-scope--alltime { margin-top: 0; }
    .an-scope__head { padding-left: var(--space-16); }
    .an-scope__title { font-size: 18px; line-height: 26px; }
    .an-alltime-disclosure__summary { padding: var(--space-16) var(--space-20); }
    .an-alltime-disclosure__title { font-size: 18px; line-height: 26px; }
    /* Keep the scope tag + window on one line where possible; wrap cleanly on phone. */
    .an-scope__cue { gap: 6px; }
    .page--analytics .card__head { padding: var(--space-20) var(--space-20) 0; }
    .page--analytics .an-card__body { padding: var(--space-16) var(--space-20) var(--space-20); }
    .page--analytics .kpi-grid--counts .kpi { padding: var(--space-20); }
    .page--analytics .kpi-grid--counts { gap: var(--space-16); }
}

/* The range selector lives INSIDE the selected-period landmark (BugHerd #58). Drop its own card
   chrome there so it reads as part of the landmark, not a nested box; keep it when rendered alone. */
.an-scope--period .an-range {
    background: transparent;
    border: 0;
    padding: 0;
    margin-bottom: var(--space-24);
}

@media (max-width: 480px) {
    .an-scope { margin-bottom: var(--space-32); }
    .an-scope--alltime { margin-top: 0; }
    .an-alltime-disclosure__heading { gap: 2px var(--space-12); }
    .an-alltime-disclosure__summary { padding: var(--space-16); }
    .an-alltime-disclosure__action { font-size: 12px; }
    .page--analytics .card__head { padding: var(--space-16) var(--space-16) 0; }
    .page--analytics .an-card__body { padding: var(--space-16); }
    .page--analytics .kpi-grid--counts { grid-template-columns: minmax(0, 1fr); }
    .page--analytics .kpi-grid--counts .kpi,
    .page--analytics .kpi-grid--counts .kpi:nth-child(1),
    .page--analytics .kpi-grid--counts .kpi:nth-child(2) { grid-column: span 1; padding: var(--space-16); }
    .page--analytics .kpi--count .kpi__value,
    .page--analytics .kpi-grid--counts .kpi:first-child .kpi__value { font-size: 28px; line-height: 34px; }
}


/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.24 — Admin Settings screen (/Settings). A single form
    that lists SystemSetting rows grouped by category into cards, with
    type-appropriate controls (text/number/Yes-No/date) and a sticky
    Save/Reload bar. Tokens only — every colour flows from the surface +
    chip tokens so the screen inverts correctly in dark mode (no literal
    colours, no dark-theme overrides needed). Mirrors the design's
    "System parameters · grouped by area" two-up card grid.
    ═══════════════════════════════════════════════════════════════════ */

/* BH-369 — Settings is a policy ledger rather than a narrow form. At 2560px the old shared 1180px
   cap stopped at x=1412 and left 1148px of dead canvas on the right. Reuse the established bounded
   wide-canvas token and centre the page within the authenticated work area. max-width keeps the page
   fluid at ordinary desktop/tablet/mobile widths; no setting, form or neighbouring route changes. */
.page--settings {
    padding: var(--space-24) var(--so-content-pad) 60px;
    max-width: var(--so-max-content-analytics);
    margin-inline: auto;
}

/* search box (client-side row filter) */
.settings-search { position: relative; max-width: 320px; margin-bottom: var(--space-20); }
.settings-search__icon {
    position: absolute; left: 10px; top: 18px; transform: translateY(-50%);
    display: flex; color: var(--so-faint); pointer-events: none;
}
.settings-search__input {
    width: 100%; height: 36px;
    border: 1px solid var(--so-input-border, var(--so-border));
    background: var(--so-app-bg); color: var(--so-text-1);
    padding: 0 32px 0 34px;
    font-family: inherit; font-size: 13px; outline: none; border-radius: var(--so-radius);
}
.settings-search__input:focus { border-color: var(--so-text-2); background: var(--so-card); }
.settings-search__clear-btn {
    position: absolute; right: 8px; top: 18px; transform: translateY(-50%);
    background: transparent; border: 0; padding: 4px; cursor: pointer; color: var(--so-muted);
    display: flex; align-items: center; justify-content: center;
}
.settings-search__clear-btn:hover { color: var(--so-text-1); }
.settings-search__clear-btn[hidden] { display: none; }
.settings-search__status {
    font-size: 11.5px; color: var(--so-caption); margin-top: 6px; font-variant-numeric: tabular-nums;
}
.settings-search__status[hidden] { display: none; }

/* BH-370 — empty state when search matches 0 editable settings */
.settings-empty {
    display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
    padding: var(--space-32) var(--space-20);
    background: var(--so-card); border: 1px solid var(--so-border);
    gap: var(--space-8);
}
.settings-empty[hidden] { display: none; }
.settings-empty__icon { color: var(--so-faint); margin-bottom: 4px; }
.settings-empty__title { font-family: var(--font-display); font-size: 15px; font-weight: 600; color: var(--so-text-1); margin: 0; }
.settings-empty__hint { font-size: 12.5px; color: var(--so-caption); margin: 0; max-width: 420px; line-height: 1.4; }
.settings-empty__clear { min-height: 44px; padding: 0 var(--space-16); margin-top: var(--space-8); }

.settings-form { display: flex; flex-direction: column; gap: var(--space-20); }
/* the asp-validation-summary placeholder stays in the DOM when valid (it carries the
   validation-summary-valid marker); hide that state so no empty error banner shows. */
.settings-form__error.validation-summary-valid { display: none; }

/* two-up card grid */
/* BugHerd #31 (Work Packet 3.02) — align-items: stretch + .settings-card as a flex column whose
   body grows, so the two columns in each row reach equal height and the white space under a
   short card no longer looks uneven beside a tall one. Responsive 992px collapse preserved. */
.settings-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-20); align-items: flex-start; }
.settings-grid--single { grid-template-columns: minmax(0, 1fr); }
.settings-grid[hidden] { display: none; }
.settings-card { background: var(--so-card); border: 1px solid var(--so-border); display: flex; flex-direction: column; }
.settings-card__head { padding: 12px var(--space-16); border-bottom: 1px solid var(--so-border-soft); }
.settings-card__title {
    font-family: var(--font-display); font-weight: 600; font-size: 15px; line-height: 1.3;
    margin: 0; color: var(--so-text-1);
}
.settings-card__body { display: flex; flex-direction: column; flex: 1 1 auto; }

/* one setting row */
.settings-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-16); padding: 13px var(--space-16);
    border-bottom: 1px solid var(--so-row-rule);
}
.settings-row:last-child { border-bottom: 0; }
.settings-row__text { flex: 1 1 auto; min-width: 0; }
.settings-row__label { font-size: 13.5px; font-weight: 600; color: var(--so-text-1); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.settings-row__help { font-size: 12.5px; color: var(--so-caption); margin-top: 3px; line-height: 1.5; }
.settings-row__key { font-size: 10.5px; color: var(--so-faint); margin-top: 4px; font-variant-numeric: tabular-nums; }
.settings-row__lock { display: inline-flex; align-items: center; gap: 3px; font-size: 10px; font-weight: 600; }

.settings-row__control { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.settings-row__input { width: 200px; height: 30px; text-align: right; font-variant-numeric: tabular-nums; }
.settings-row--locked .settings-row__control { align-items: flex-end; }
.settings-row__error { text-align: right; }

/* Yes/No toggle (bool) — reuses the .field--check control */
.settings-toggle { flex-direction: row; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; color: var(--so-text-2); white-space: nowrap; }

.settings-row[hidden] { display: none; }
.settings-card[hidden] { display: none; }

@media (max-width: 992px) {
    .settings-grid { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
    .settings-search { max-width: 100%; }
    .settings-search__input { height: 44px; font-size: 14px; }
    .settings-search__icon { top: 22px; }
    .settings-search__clear-btn { top: 22px; }
    .settings-row { flex-direction: column; align-items: flex-start; }
    .settings-row__control { align-items: flex-start; }
    .settings-row__input { width: 100%; text-align: left; }
    .settings-row__error { text-align: left; }
}

/* ── Work Packet 3.09a — read-only settings registry section (outside the POST form) ──
   Reuses the settings-card/settings-row look so it reads as part of the same screen, but the
   rows are display-only: no input control, and a status chip + monospaced reference default. */
.settings-registry { display: flex; flex-direction: column; gap: var(--space-12); margin-top: var(--space-24); }
.settings-registry__head { display: flex; flex-direction: column; gap: 4px; }
.settings-registry__title {
    font-family: var(--font-display); font-weight: 600; font-size: 18px; line-height: 1.25;
    margin: 0; color: var(--so-text-1);
}
.settings-registry__hint { font-size: 13px; color: var(--so-caption); margin: 0; line-height: 1.5; max-width: 78ch; }
/* registry rows are always display-only (reuse settings-row--locked so the right side aligns) */
.settings-registry__status { display: inline-flex; align-items: center; font-size: 10px; font-weight: 600; }
.settings-registry__default { font-size: 12.5px; font-weight: 600; color: var(--so-text-2); text-align: right; font-variant-numeric: tabular-nums; }


/* ── Demo-environment banner (Work Packet 0.55, deviation-audit §6) — env-gated, tokens-only ── */
.demo-banner {
    display: flex; align-items: center; gap: var(--space-16);
    padding: 8px var(--space-16);
    background: var(--chip-warn-bg); color: var(--chip-warn-fg);
    border-bottom: 1px solid var(--so-border);
    font-size: 13px; line-height: 1.35;
}
.demo-banner__text { flex: 1 1 auto; }
.demo-banner__dismiss {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; padding: 0;
    background: transparent; border: 0; color: inherit; cursor: pointer; border-radius: 4px;
}
.demo-banner__dismiss:hover { background: rgba(0,0,0,0.08); }


/* ═══════════════════════════════════════════════════════════════════
    Work Packet 0.60 — Admin hub + Lookups (reference-code maintenance).
    Tokens only — every colour flows from the surface + chip tokens so
    both screens invert correctly in dark mode (no literal colours, no
    dark-theme overrides needed). The Admin hub mirrors the Reports hub
    visual family (.report-grid / tile look); the Lookups screen is a
    two-column left-rail + right-table layout.
    ═══════════════════════════════════════════════════════════════════ */

/* ── Admin hub (/Admin) — launcher-card grid ── */
.page--admin { padding: var(--space-24) var(--so-content-pad) 60px; max-width: var(--so-max-content); }

.admin-hub {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--space-16);
}
.admin-hub__card {
    display: flex; align-items: flex-start; gap: var(--space-12);
    padding: var(--space-16);
    background: var(--so-card);
    border: 1px solid var(--so-border);
    min-height: 92px;
}
.admin-hub__card--link {
    cursor: pointer; text-decoration: none; color: inherit;
    transition: background 0.12s ease;
}
.admin-hub__card--link:hover { background: var(--so-row-hover); }
.admin-hub__card--link:hover .admin-hub__name { color: var(--so-text-1); }
.admin-hub__card--link:focus-visible { outline: 2px solid var(--so-primary); outline-offset: -2px; }
.admin-hub__card--planned { opacity: 0.72; }

.admin-hub__icon {
    width: 32px; height: 32px; flex: none;
    background: var(--so-table-head); color: var(--so-text-4);
    display: flex; align-items: center; justify-content: center;
    /* BugHerd #30 (Work Packet 3.02) — add a token-based gutter so the icon reads as a distinct
       tile rather than crowding the heading/description. Keeps the card's existing flex layout
       and light/dark surfaces (the fill is already a token); only the right margin is new. */
    margin-right: var(--space-8, 8px);
}
.admin-hub__icon svg { width: 18px; height: 18px; }
.admin-hub__main { flex: 1; min-width: 0; }
.admin-hub__name { font-family: var(--font-display); font-size: 14px; font-weight: 600; color: var(--so-text-2); }
.admin-hub__desc { font-size: 11.5px; color: var(--so-faint); margin-top: 4px; line-height: 1.45; }
.admin-hub__meta { font-size: 11px; font-weight: 700; color: var(--so-muted); margin-top: 8px; }
.admin-hub__badge {
    font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--so-muted); background: var(--so-table-head);
    padding: 2px 8px; border-radius: 999px; flex: none;
}
.admin-hub__chev { flex: none; color: var(--so-faint); display: flex; align-items: center; align-self: center; }
.admin-hub__card--planned .admin-hub__chev { display: none; }

@media (max-width: 600px) {
    .admin-hub { grid-template-columns: 1fr; }
}


/* ── Lookups (/Admin/Lookups) — left rail + right table ── */
.page--lookups { padding: var(--space-24) var(--so-content-pad) 60px; max-width: var(--so-max-content); }

.lookups {
    display: grid;
    grid-template-columns: 248px 1fr;
    gap: var(--space-24);
    align-items: start;
}

.lookups__mobile-picker { display: none; }

/* left rail */
.lookups__rail {
    background: var(--so-card);
    border: 1px solid var(--so-border);
    position: sticky; top: var(--space-16);
}
.lookups__rail-group { border-bottom: 1px solid var(--so-border-soft); }
.lookups__rail-group:last-child { border-bottom: 0; }
.lookups__rail-label {
    padding: 12px 14px 4px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--so-muted);
}
.lookups__rail-item {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 14px;
    text-decoration: none; color: var(--so-text-3);
    font-size: 12.5px; line-height: 1.3;
    border-left: 3px solid transparent;
}
.lookups__rail-item:hover { background: var(--so-row-hover); color: var(--so-text-1); }
.lookups__rail-item.is-active {
    background: var(--so-row-hover);
    color: var(--so-text-1); font-weight: 600;
    border-left-color: var(--so-primary);
}
.lookups__rail-name { flex: 1; min-width: 0; }
.lookups__rail-tag {
    font-size: 9px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--so-faint); border: 1px solid var(--so-border);
    padding: 1px 5px; border-radius: 3px; flex: none;
}
.lookups__rail-count {
    flex: none; font-size: 11px; color: var(--so-muted);
    font-variant-numeric: tabular-nums; min-width: 22px; text-align: right;
}

/* right panel */
.lookups__panel { min-width: 0; }
.lookups__panel-head { margin-bottom: var(--space-16); }
.lookups__panel-title { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--so-text-1); margin: 0; }
.lookups__panel-sub { font-size: 12px; color: var(--so-caption); margin: 4px 0 0; }
.lookups__readonly-note {
    display: flex; align-items: center; gap: 6px;
    font-size: 11.5px; color: var(--so-muted);
    background: var(--so-card); border: 1px solid var(--so-border-soft);
    padding: 8px 12px; margin: 0 0 var(--space-16);
}

/* right-hand table */
.table--lookups { }
.table--lookups tr.is-retired td { color: var(--so-faint); }
.table--lookups tr.is-retired .t-fileno { text-decoration: line-through; text-decoration-color: var(--so-faint); }
.table--lookups .row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; align-items: center; }
.table--lookups .row-actions .btn { height: 26px; padding: 0 10px; font-size: 12px; }

/* BH #371 — on mobile / narrow viewports (<=900px), collapse the 18-item 703px left rail
   and replace it with a compact, accessible 44px dropdown selector near the page heading,
   keeping the chosen lookup table immediately discoverable without scrolling past the full list. */
@media (max-width: 900px) {
    .lookups { grid-template-columns: 1fr; gap: var(--space-12); }
    .lookups__rail { display: none; }
    .lookups__mobile-picker {
        display: flex;
        flex-direction: column;
        gap: 6px;
        margin-bottom: 0;
        background: var(--so-card);
        border: 1px solid var(--so-border);
        padding: var(--space-12) var(--space-16);
    }
    .lookups__mobile-label {
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        color: var(--so-muted);
    }
    .lookups__mobile-select-wrap {
        position: relative;
        display: flex;
        align-items: center;
    }
    .lookups__mobile-select {
        width: 100%;
        height: 44px;
        min-height: 44px;
        padding: 0 36px 0 12px;
        border: 1px solid var(--so-input-border);
        background-color: var(--so-input-bg);
        color: var(--so-text-1);
        font-family: inherit;
        font-size: 13px;
        font-weight: 600;
        outline: none;
        border-radius: 0;
        cursor: pointer;
        appearance: none;
        -webkit-appearance: none;
        -moz-appearance: none;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 12px center;
    }
    .lookups__mobile-select:focus-visible {
        outline: 2px solid var(--so-primary);
        outline-offset: -2px;
        border-color: var(--so-primary);
    }
}


/* ═════════════════════════════════════════════════════════════════
   Work Packet 0.63 — Background tasks (/Admin/BackgroundTasks).

   One table of registered jobs (schedule + last-run + status + row
   actions), mirroring the Lookups right-panel pattern. Tokens only —
   no new colours. The Edit-schedule disclosure is an inline form-card
   folded under each row.
   ═════════════════════════════════════════════════════════════════ */

.page--bg-tasks { padding: var(--space-24) var(--so-content-pad) 60px; max-width: var(--so-max-content); }

/* BH-385 — compact operator filters and paging for the run-history ledger. The grid keeps the
   four evidence controls scannable as one unit; on narrow screens it collapses without changing
   the shared form-field vocabulary. */
.page--bg-tasks .filter-bar {
    margin-bottom: var(--space-16);
    padding: var(--space-16);
    background: var(--so-card);
    border: 1px solid var(--so-border-soft);
    border-radius: var(--so-radius);
}
.page--bg-tasks .filter-bar__fields {
    display: grid;
    grid-template-columns: repeat(4, minmax(150px, 1fr));
    gap: var(--space-12);
}
.page--bg-tasks .filter-bar__actions {
    display: flex;
    gap: var(--space-8);
    margin-top: var(--space-12);
}
.page--bg-tasks .pagination {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-12);
    margin-top: var(--space-16);
}
.page--bg-tasks .pagination .is-disabled {
    pointer-events: none;
    opacity: .5;
}
@media (max-width: 800px) {
    .page--bg-tasks .filter-bar__fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
    .page--bg-tasks .filter-bar__fields { grid-template-columns: 1fr; }
    .page--bg-tasks .pagination { justify-content: space-between; }
}

.page-head__flag {
    font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: var(--so-warning-fg, var(--chip-option-fg));
    background: var(--chip-option-bg);
    padding: 3px 10px; border-radius: 999px;
    margin-left: 8px;
}

/* job name + key stack */
.bg-tasks__name { font-family: var(--font-display); font-size: 13px; font-weight: 600; color: var(--so-text-1); }
.bg-tasks__key { font-size: 11px; color: var(--so-muted); margin-top: 2px; font-family: var(--font-mono, var(--font-display)); }

/* error strap (last-run detail) */
.bg-tasks__err {
    font-size: 11px; color: var(--chip-cancelled-fg);
    margin-top: 4px; max-width: 320px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* disabled row visually dims but stays readable */
.table--bg-tasks tr.is-disabled td { color: var(--so-faint); }
.table--bg-tasks tr.is-disabled .bg-tasks__name { color: var(--so-text-3); }

/* row actions inherit the lookups row-actions sizing */
.table--bg-tasks .row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; align-items: center; }
.table--bg-tasks .row-actions .btn { height: 26px; padding: 0 10px; font-size: 12px; }

/* BH-388: below ~700px this table scrolls horizontally to reach the Actions column, which scrolls the
   JOB NAME out of view - so an operator can be pressing "Run now" on a row they can no longer identify.
   Anchor the identity column so it stays beside the actions. Scoped to .table--bg-tasks only; the
   opaque background is required or scrolled cells show through the sticky one. NOTE: this is a 700px
   query, deliberately NOT the 480px block KpiGridAdaptiveTests asserts .kpi-grid lives in. */
@media (max-width: 700px) {
    .table--bg-tasks th:first-child,
    .table--bg-tasks td:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        background: var(--so-card);
        box-shadow: 1px 0 0 var(--so-border-soft);
    }
}

/* inline schedule editor (disclosed under each row) */
.bg-tasks__edit { margin-top: 6px; }
.bg-tasks__edit > summary {
    list-style: none; cursor: pointer;
    display: inline-flex; align-items: center; gap: 4px;
}
.bg-tasks__edit > summary::-webkit-details-marker { display: none; }
.bg-tasks__edit[open] > summary { margin-bottom: 8px; }
.bg-tasks__edit-form {
    display: flex; flex-wrap: wrap; gap: var(--space-12);
    align-items: flex-end;
    padding: var(--space-12);
    background: var(--so-card);
    border: 1px solid var(--so-border-soft);
    border-radius: var(--so-radius);
}
.field--inline { flex: 1; min-width: 160px; }
.field--inline .field__input { margin-top: 4px; }
.field__input--mono { font-family: var(--font-mono, var(--font-display)); font-size: 12.5px; }

/* Work Packet 1.00 (BH #21) — textarea variant of .field__input. The base rule pins height:38px
   (right for single-line inputs) which a multi-line textarea must override to honour its rows.
   Auto vertical resize only, full width, sensible cap so the field reads as a deliberate text
   area and not a cramped box. Tokens-only (no colour override — it inherits the input tokens). */
.field__input--area {
    height: auto;
    width: 100%;
    max-width: 720px;
    min-height: 96px;
    padding: var(--space-8) var(--space-12);
    line-height: 1.5;
    resize: vertical;
}
/* ══════════ BOOKING NOTES TAB COMPOSITION (BugHerd #21) ══════════
   Layout-only pass over the booking detail Notes tab. The tab was never given a deliberate
   composition, so on the now-wide card four things read as "unfinished": (1) the add-note
   textarea rode the shared .field__input--area 720px cap and stopped ~300px short of its card's
   right edge; (2) the Audience/Area/Pin/Chase row rode the empty .form-card__row--3 vestige
   (auto-fit) so the LP-046 additions were never composed; (3) the empty-state hint sat in the
   global .empty-state__hint 320px measure, centred in the wide card, and wrapped mid-sentence as
   "…for this" / "booking."; (4) the summary strip's .fin-actions space-between left a dead gap
   between the running-commentary hint and the Search notes control. Each fix below is scoped to a
   Notes-tab hook (.bk-note-form / .bk-notes__empty / .fin-actions--search) so the shared
   .field__input--area, .empty-state, .fin-actions and .form-card__row--3 components every other
   tab and page relies on are byte-for-byte unchanged. No note behaviour changes. */

/* The note field stays full-width (it was previously crammed into a 2-col row). */
.bk-note-field { max-width: 100%; }

/* (1) The note body fills its card's content width. The shared .field__input--area caps textareas
   at 720px (right for ordinary comment fields in narrow cards); the Notes add-note form opts out so
   the textarea spans the whole card instead of stopping short. Scoped to .bk-note-form so the
   sibling Follow-ups / Amendments comment fields (which also reuse .bk-note-field) are untouched. */
.bk-note-form .bk-note-field .field__input--area { max-width: 100%; }

/* (2) Audience / Area / Pin / Chase-Up composed as ONE deliberate control row beneath the note
   field: two flexible inputs (Audience select, Area code) then two compact checkboxes, instead of
   the auto-fit vestige that left the LP-046 additions to fall wherever. minmax(0,…) inputs can
   shrink; auto-width checkboxes stay tight; the row wraps to a single column on narrow viewports
   (below). Replaces the empty .form-card__row--3 modifier ON THIS ROW ONLY (the global vestige is
   retained — dozens of other forms still carry the class). */
.bk-note-form .form-card__row--note-controls {
    grid-template-columns: minmax(180px, 1fr) minmax(140px, 1fr) auto auto;
    align-items: start;
}
@media (max-width: 600px) {
    /* Single column at narrow widths so none of the four controls is squeezed; matches the shared
       .form-card__row mobile collapse. */
    .bk-note-form .form-card__row--note-controls { grid-template-columns: 1fr; }
}

/* (3) The Notes empty-state hint reads as complete line(s) at a sensible measure instead of
   wrapping mid-sentence in the global 320px column, and the block stays compact in the wide card.
       "Add a note below to start a running commentary for this booking." is ~64 chars (~430px at
   12px), so a 520px measure holds it on one line at every desktop width, and the parent card caps
   it on narrow viewports. The modest padding reduction keeps the empty block proportional to the
       surrounding rows instead of dominating the tab. Scoped to .bk-notes__empty so every other
   empty state (whose 320px measure is right for narrow columns) is unchanged. */
.bk-notes__empty .empty-state { padding: var(--space-24) var(--space-16); }
.bk-notes__empty .empty-state__hint { max-width: 520px; }

/* (4) The Notes summary strip reads as ONE composed toolbar instead of hint-hard-left /
   search-hard-right with a dead gap between: the running-commentary hint and the Search notes
   control sit together at the start of the row. The hint stays at its content width; the search
   field is bounded and can shrink (min-width:0) so it never forces horizontal overflow. Scoped to
   the opt-in .fin-actions--search modifier so every other .fin-actions (Follow-ups, Amendments,
   finance — all space-between) keeps its layout. */
.fin-actions--search { justify-content: flex-start; column-gap: var(--space-20); }
.fin-actions--search .fin-actions__hint { flex: 0 1 auto; }
.fin-actions--search .field { flex: 0 1 320px; min-width: 0; }
.btn--small { height: 28px; padding: 0 12px; font-size: 12px; }

@media (max-width: 700px) {
    .bg-tasks__edit-form { flex-direction: column; align-items: flex-start; }
    .field--inline { min-width: 0; }
}

/* ════════════════════════════════════════════════════════════════════
   Work Packet 0.78 — Costing tab provisional engine-pricing preview.
   Tokens only (no literals). Reuses the amber chip vocabulary
   (--chip-option-bg/-fg) for the warning banner + the matches/differs/
   n/a chips so the section reads consistently light + dark. The stored
   costing figures above remain authoritative; this preview is flagged
   provisional (best-effort D12, not golden-validated).
   ════════════════════════════════════════════════════════════════════ */

/* The prominent provisional banner — amber left rule + amber icon, mirroring
   .banner--info/--error so it slots into the existing banner vocabulary. */
.banner--warning { border-left: 3px solid var(--chip-option-fg); background: var(--chip-option-bg); }
.banner--warning .banner__icon { color: var(--chip-option-fg); }
.banner--warning strong { color: var(--chip-option-fg); }

/* BugHerd #185 — the passport-readiness banner's trailing next-step clause. Rendered inline so the
   reason and its correction path read as one sentence, with a soft separator and the muted text
   tone the rest of the banner body uses. */
.bk-readiness__next { color: var(--so-text-4); }
.bk-readiness__next::before { content: " — "; }

.engine-preview { margin-top: var(--space-16); }
.engine-preview__head {
    display: flex; align-items: center; gap: var(--space-8);
    font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--so-text-3);
    margin: 0 0 var(--space-8) 2px;
}
/* The "provisional" flag on the engine-preview head + the apply trigger. Amber option chip,
   mirroring the differs chip vocabulary so "provisional" reads consistently across the section. */
.engine-preview__prov {
    font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
    padding: 2px 7px; border-radius: 999px;
    background: var(--chip-option-bg); color: var(--chip-option-fg);
}
/* Each computed-vs-stored cell stacks the stored figure (muted) over the engine figure. */
.engine-preview .table td { vertical-align: top; }
.engine-preview__row--differs { background: var(--chip-option-bg); }
/* Matches/differs/n/a indicator chips — reuse the success/option/neutral chip vocabulary. */
.engine-preview__chip {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 10.5px; font-weight: 600; white-space: nowrap;
    padding: 3px 8px; border-radius: 999px;
}
.engine-preview__chip--matches  { background: var(--chip-success-bg); color: var(--chip-success-fg); }
.engine-preview__chip--differs  { background: var(--chip-option-bg);  color: var(--chip-option-fg); }
.engine-preview__chip--na       { background: var(--chip-neutral-bg);  color: var(--chip-neutral-fg); }

/* ── Work Packet 2.01 — "Apply engine pricing" confirm panel + trigger. Tokens only; the
   panel reuses the card + border + warning-banner vocabulary so it themes for free. ── */
.engine-apply {
    margin-top: var(--space-16);
    border: 1px solid var(--so-border);
    background: var(--so-card);
    padding: var(--space-16);
}
.engine-apply__prov { margin-bottom: var(--space-12); }
.engine-apply__head {
    font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--so-text-3);
    margin: 0 0 var(--space-8) 2px;
}
.engine-apply__actions {
    display: flex; align-items: center; gap: var(--space-8);
    margin-top: var(--space-12);
}
.engine-apply__trigger {
    display: flex; align-items: center; gap: var(--space-12);
    margin-top: var(--space-12);
}


/* ═══════════════════════════════════════════════════════════════════
   Work Packet 0.85 — Ctrl+K command palette. Tokens only (no literals),
   square corners (--so-radius is 0), themes for free via the dark block.
   Backdrop is a translucent ink overlay; the panel reuses the card +
   border tokens and the existing popover shadow vocabulary. The active
   row rides the terracotta primary (lifted in dark) with a left accent
   bar so it reads clearly in both themes.
   ═══════════════════════════════════════════════════════════════════ */

.cmdk {
    position: fixed;
    inset: 0;
    z-index: 90;                              /* above .user-menu__pop (60) + sidebar drawer */
    background: var(--scrim-45);              /* translucent ink overlay (existing token) */
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 15vh var(--space-16) var(--space-16);
}
.cmdk[hidden] { display: none; }

.cmdk__panel {
    width: 100%;
    max-width: 560px;
    background: var(--so-card);
    border: 1px solid var(--so-border);
    border-radius: var(--so-radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.10);   /* matches .user-menu__pop / .saved-views__pop */
    display: flex;
    flex-direction: column;
    max-height: 70vh;
    overflow: hidden;
}

.cmdk__input {
    width: 100%;
    border: 0;
    border-bottom: 1px solid var(--so-border-soft);
    background: transparent;
    padding: var(--space-16) var(--space-16);
    font-family: inherit;
    font-size: 15px;
    color: var(--so-text-1);
    outline: none;
    border-radius: 0;
}
.cmdk__input::placeholder { color: var(--so-muted); }
.cmdk__input:focus { background: var(--so-row-hover); }

.cmdk__list {
    list-style: none;
    margin: 0;
    padding: var(--space-4) 0;
    overflow-y: auto;
    flex: 1 1 auto;
}

/* Group heading — non-selectable (role=presentation). */
.cmdk__group {
    padding: var(--space-8) var(--space-16) var(--space-4);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--so-muted);
}

.cmdk__opt {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-16);
    padding: var(--space-8) var(--space-16);
    cursor: pointer;
    color: var(--so-text-1);
    border-left: 3px solid transparent;        /* room for the active accent bar */
}
.cmdk__opt-primary { font-size: 14px; font-weight: 600; }
.cmdk__opt-secondary {
    font-size: 12px;
    color: var(--so-muted);
    text-align: right;
    white-space: nowrap;
}
/* BH #118 — left column wraps primary + optional match-context line so secondary stays right-aligned. */
.cmdk__opt-main { display: flex; flex-direction: column; min-width: 0; }
.cmdk__opt-context { font-size: 12px; color: var(--so-muted); opacity: 0.85; }

/* Active row — accent-tinted background + left accent bar. Reads in light + dark:
   --so-coral-tint is the warm selection wash (lifted to #4A3328 in dark); the bar
   rides --so-primary (terracotta, lifted to #C8632E in dark). */
.cmdk__opt--active,
.cmdk__opt:hover {
    background: var(--so-coral-tint);
    border-left-color: var(--so-primary);
}
.cmdk__opt--active .cmdk__opt-primary { color: var(--so-text-1); }

/* Hint rows (searching… / no matches) — muted, non-selectable. */
.cmdk__row {
    padding: var(--space-8) var(--space-16);
    font-size: 13px;
    color: var(--so-muted);
    font-style: italic;
}

.cmdk__footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-16);
    padding: var(--space-8) var(--space-16);
    border-top: 1px solid var(--so-border-soft);
    background: var(--so-table-head);
}
.cmdk__hint {
    font-size: 11px;
    color: var(--so-muted);
}
.cmdk__brand {
    font-size: 11px;
    font-weight: 700;
    color: var(--so-faint);
    letter-spacing: .04em;
}

/* Topbar Ctrl+K hint chip — token-styled, hidden on narrow screens. */
.topbar__cmdk {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--so-border);
    background: var(--so-card);
    color: var(--so-muted);
    padding: 2px 6px;
    font: inherit;
    font-size: 11px;
    line-height: 1;
    cursor: pointer;
    border-radius: var(--so-radius);
}
.topbar__cmdk:hover { color: var(--so-text-2); border-color: var(--so-text-2); }
.topbar__cmdk-kbd {
    font-family: var(--font-meta);
    font-size: 10.5px;
    letter-spacing: .02em;
}

@media (max-width: 992px) {
    .cmdk { padding-top: 10vh; }
    .cmdk__panel { max-height: 80vh; }
}
@media (max-width: 480px) {
    .topbar__cmdk { display: none; }           /* hint hidden on phone; Ctrl+K still works on desktop */
}

/* Agent Applications Responsive overrides (BH-176) */
.agent-apps-grid,
.d-mobile-only { display: none; }
@media (max-width: 900px) {
    .agent-apps-grid.d-mobile-only { display: grid; gap: 16px; margin-bottom: 16px; }
    .table-wrap.d-desktop-only { display: none; }
}
.agent-app-card__body { padding: 16px; }
.agent-app-card__row { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 13px; }
.agent-app-card__row:last-child { margin-bottom: 0; }
.agent-app-card__label { color: var(--so-text-2); font-weight: 600; padding-right: 16px; flex: none; }
.agent-app-card__value { color: var(--so-text-1); text-align: right; word-break: break-word; min-width: 0; flex: 1 1 auto; }
.agent-app-card__actions { padding: 12px 16px; border-top: 1px solid var(--so-border-soft); display: flex; gap: 8px; }
.agent-app-card__actions form { flex: 1; }
.agent-app-card__actions .btn { width: 100%; min-height: 44px; justify-content: center; /* keep touch target */  }

/* ══════════ BH #275 — Customers / Agencies responsive operator folios ══════════ */
/* These two record worklists carry identity, status, secondary fields and a safe Edit route. Their
   nine/eight-column desktop tables are useful at wide measures but force status/actions behind an
   undiscoverable inner scroll on phones and small tablets. Keep one data hierarchy: table above
   768px, labelled scan-first cards at and below it. Existing WinTrav surface/type/status tokens do
   all visual work; no parallel palette or decorative card system is introduced. */
.mobile-worklist { display: none; }

@media (max-width: 768px) {
    .page--customers .filterbar-row,
    .page--agents .filterbar-row {
        display: block;
    }

    .page--customers .filterbar,
    .page--agents .filterbar {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--space-8);
        padding: var(--space-12);
    }

    .page--customers .filterbar__pill,
    .page--agents .filterbar__pill {
        width: 100%;
        min-width: 0;
        min-height: 44px;
        height: 44px;
    }

    .page--customers .filterbar__pill select,
    .page--agents .filterbar__pill select {
        flex: 1 1 auto;
        min-width: 0;
        max-width: none;
    }

    .page--customers .filterbar .dd,
    .page--agents .filterbar .dd {
        width: 100%;
        min-width: 0;
    }

    .page--customers .filterbar .dd__btn,
    .page--agents .filterbar .dd__btn,
    .page--customers .filterbar__search,
    .page--agents .filterbar__search {
        min-height: 44px;
        height: 44px;
    }

    .page--customers .filterbar__search,
    .page--agents .filterbar__search {
        grid-column: 1 / -1;
        width: 100%;
        min-width: 0;
    }

    .page--customers .filterbar__search .btn,
    .page--agents .filterbar__search .btn {
        min-height: 44px;
        height: 44px;
    }

    .page--customers .filterbar__search input,
    .page--agents .filterbar__search input {
        height: 100%;
    }

    .page--customers .filterbar__export,
    .page--agents .filterbar__export,
    .page--customers .filterbar__clear,
    .page--agents .filterbar__clear,
    .page--customers .saved-views__chip,
    .page--agents .saved-views__chip {
        min-height: 44px;
    }

    .page--customers .filterbar__clear,
    .page--agents .filterbar__clear {
        margin-left: 0;
        display: inline-flex;
        align-items: center;
    }

    .page--customers .filterbar-row > .saved-views,
    .page--agents .filterbar-row > .saved-views {
        width: 100%;
        padding: 0 var(--space-12) var(--space-12);
        align-self: auto;
    }

    .mobile-worklist {
        display: grid;
        gap: var(--space-12);
    }

    .mobile-worklist__desktop {
        display: none;
    }

    .mobile-worklist-card {
        min-width: 0;
        background: var(--so-card);
        border: 1px solid var(--so-border);
        border-left: 3px solid var(--so-overland);
    }

    .mobile-worklist-card--retired {
        border-left-color: var(--so-muted);
    }

    .mobile-worklist-card__identity {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: var(--space-12);
        padding: var(--space-16);
        border-bottom: 1px solid var(--so-row-rule);
    }

    .mobile-worklist-card__identity-copy {
        min-width: 0;
        display: grid;
        gap: 4px;
    }

    .mobile-worklist-card__title {
        color: var(--so-text-1);
        font-family: var(--font-display);
        font-size: 15px;
        font-weight: 650;
        line-height: 1.3;
        overflow-wrap: anywhere;
        text-decoration-color: var(--so-primary);
        text-underline-offset: 3px;
    }

    .mobile-worklist-card__subtitle {
        min-width: 0;
        color: var(--so-muted);
        font-size: 12px;
        line-height: 1.4;
        overflow-wrap: anywhere;
    }

    .mobile-worklist-card__data {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: var(--space-12) var(--space-16);
        margin: 0;
        padding: var(--space-16);
    }

    .mobile-worklist-card__data > div {
        min-width: 0;
    }

    .mobile-worklist-card__data dt {
        margin: 0 0 3px;
        color: var(--so-caption);
        font-size: 10.5px;
        font-weight: 700;
        letter-spacing: .04em;
        text-transform: uppercase;
    }

    .mobile-worklist-card__data dd {
        min-width: 0;
        margin: 0;
        color: var(--so-text-2);
        font-size: 12.5px;
        line-height: 1.4;
        overflow-wrap: anywhere;
    }

    .mobile-worklist-card__actions {
        display: flex;
        padding: 0 var(--space-16) var(--space-16);
    }

    .mobile-worklist-card__actions .btn {
        width: 100%;
        min-height: 44px;
        justify-content: center;
    }

    .user-mobile-card__identity {
        display: grid;
        grid-template-columns: auto minmax(0, 1fr);
        justify-content: initial;
    }

    .user-mobile-card__chips {
        grid-column: 2;
        display: flex;
        flex-wrap: wrap;
        gap: var(--space-8);
    }

    .user-mobile-card__invite-note {
        grid-column: 1 / -1;
    }

    .user-mobile-card__actions {
        gap: var(--space-8);
    }

    .user-mobile-card__actions form {
        display: flex;
        flex: 1 1 0;
        margin: 0;
    }

    .audit-mobile-card__head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: var(--space-12);
        padding: var(--space-16);
        border-bottom: 1px solid var(--so-row-rule);
    }

    .audit-mobile-card__time {
        min-width: 0;
        color: var(--so-text-1);
        font-variant-numeric: tabular-nums;
        font-weight: 650;
        line-height: 1.4;
        white-space: nowrap;
    }

    .audit-mobile-card__head .chip {
        flex: 0 1 auto;
        text-align: right;
    }

    .audit-mobile-card__entity-label {
        display: block;
        margin-top: 3px;
        color: var(--so-muted);
    }

    .audit-mobile-card__change {
        grid-column: 1 / -1;
    }

    .audit-mobile-card__actions {
        gap: var(--space-8);
    }

    .finance-batch-mobile-card__head {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        gap: var(--space-12);
        padding: var(--space-16);
        border-bottom: 1px solid var(--so-row-rule);
    }

    .finance-batch-mobile-card__chips {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: var(--space-8);
    }

    .finance-batch-mobile-card__data dd {
        font-variant-numeric: tabular-nums;
    }

    .finance-batch-mobile-card__provisional {
        display: inline-flex;
        margin-left: 4px;
        font-size: 9.5px;
        padding: 1px 5px;
    }
}

@media (max-width: 480px) {
    .page--customers .filterbar,
    .page--agents .filterbar,
    .mobile-worklist-card__data {
        grid-template-columns: minmax(0, 1fr);
    }

    .page--customers .filterbar__search,
    .page--agents .filterbar__search {
        grid-column: 1;
    }

    /* BH-276: keep a full active email visible beside the native search clear control.
       The button takes a separate, padded row instead of consuming the input width. */
    .page--customers .filterbar__search {
        display: grid;
        grid-template-columns: 16px minmax(0, 1fr);
        grid-template-rows: 44px 44px;
        gap: var(--space-8);
        height: auto;
        padding: var(--space-8) var(--space-12);
    }

    .page--customers .filterbar__search input { min-width: 0; }
    .page--customers .filterbar__search .btn { grid-column: 1 / -1; }
}

/* ═════════════════════════════════════════════════════════════════
   BH-183 — readable catalogue detail grid (Product/Principal/Package)
   The three catalogue detail routes previously stretched their metadata
   edge-to-edge across a 2300px canvas, leaving labels, values and actions
   spread thin and hard to scan. The fix is desktop-bounded only and reuses
   the existing kv-grid/kv detail structure + surface/border tokens — no new
   data, cards, tabs or interaction design. Scoped to the cat-detail--readable
   modifier so no other route is touched. Mobile (< 480px) keeps the existing
   compact single-column stack inherited from the base kv-grid rules.
   ═════════════════════════════════════════════════════════════════ */

/* Desktop-only: bound the catalogue detail page to a readable centred
   measure so the header, tabs and detail body line up in a single column
   of roughly 1300px instead of spanning the full app width. Engages at the
   >= 1200px desktop breakpoint (AC #2). */
@media (min-width: 1200px) {
    .page.cat-detail--readable {
        max-width: 1300px;
        margin-inline: auto;
    }
}

/* LP-027 — actionable quote / option / wait-list enquiry worklist. */
.quote-enquiry-page__intro {
    margin: 12px 0 18px;
    max-width: 920px;
}

.quote-enquiry-score,
.quote-enquiry-detail {
    margin-top: var(--space-16);
}

.quote-enquiry-section-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--space-16);
    margin-bottom: var(--space-12);
}

.quote-enquiry-score__table {
    max-width: 620px;
}

.quote-enquiry-score__total td {
    font-weight: 700;
    border-top: 2px solid var(--so-border);
}

.quote-enquiry-kpis {
    margin-top: var(--space-16);
}

.quote-enquiry-worklist {
    margin-top: var(--space-16);
}

.quote-enquiry-worklist tr.is-selected td {
    /* BH #267 (same undeclared-token class) — was var(--so-accent), which is not declared, so the
       whole background declaration was invalid and the selected row rendered identically to an
       unselected one. --so-primary is the declared brand accent this tint was written against. */
    background: color-mix(in srgb, var(--so-primary) 10%, var(--so-card));
}

.quote-enquiry-sub {
    display: block;
    margin-top: 3px;
    /* BH #267 (same undeclared-token class) — was var(--so-text-muted), never declared, so this label
       silently inherited its parent's body colour instead of the caption ramp. --so-muted is the
       declared "labels / captions" token these uppercase micro-labels use elsewhere (.kv__k). */
    color: var(--so-muted);
    font-size: 11px;
}

.quote-enquiry-comment {
    min-width: 180px;
    max-width: 320px;
    white-space: normal;
}

.quote-enquiry-detail__facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1px;
    overflow: hidden;
    border: 1px solid var(--so-border-soft);
    border-radius: var(--radius-md);
    background: var(--so-border-soft);
}

.quote-enquiry-detail__facts > div {
    display: grid;
    gap: 5px;
    min-width: 0;
    padding: var(--space-12);
    background: var(--so-card);
}

.quote-enquiry-detail__facts span {
    /* BH #267 (same undeclared-token class) — was var(--so-text-muted), never declared, so this label
       silently inherited its parent's body colour instead of the caption ramp. --so-muted is the
       declared "labels / captions" token these uppercase micro-labels use elsewhere (.kv__k). */
    color: var(--so-muted);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.quote-enquiry-detail__facts strong {
    overflow-wrap: anywhere;
}

.quote-enquiry-detail__wide {
    grid-column: 1 / -1;
}

.quote-enquiry-actions {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(260px, 1fr);
    gap: var(--space-16);
    margin-top: var(--space-16);
}

.quote-enquiry-action {
    display: grid;
    gap: var(--space-12);
    padding: var(--space-16);
    border: 1px solid var(--so-border-soft);
    border-radius: var(--radius-md);
    /* BH #267 (same undeclared-token class) — was var(--so-surface-soft), never declared, so this card
       had no background and showed the page wash through its own border. --so-card is the declared
       surface every other card/panel in the admin uses, so these action cards now match the system. */
    background: var(--so-card);
}

.quote-enquiry-action h3 {
    margin: 0;
    font-size: 18px;
    line-height: 1.25;
}

.quote-enquiry-action--danger {
    /* BH #267 (same undeclared-token class) — was var(--so-danger), never declared, so the destructive
       card kept the ordinary soft border and lost its only visual warning. --error-02 is the declared
       danger token (also behind .btn--danger), so danger now reads consistently across the admin. */
    border-color: color-mix(in srgb, var(--error-02) 35%, var(--so-border-soft));
}

.quote-enquiry-action__buttons {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-8);
    align-items: center;
}

@media (max-width: 900px) {
    .quote-enquiry-detail__facts {
        grid-template-columns: 1fr 1fr;
    }

    .quote-enquiry-actions {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 560px) {
    .quote-enquiry-section-head {
        align-items: stretch;
        flex-direction: column;
    }

    .quote-enquiry-detail__facts {
        grid-template-columns: 1fr;
    }

    .quote-enquiry-detail__wide {
        grid-column: auto;
    }
}

/* Desktop-only: render the detail metadata as a responsive grid with
   sensible minimum columns (~260–280px) and an intentional gap, rather than
   the fixed 3-up grid that left cells either crammed or stretched. Padded
   value cells read comfortably; surface + border come from the existing
   tokens so the screen inverts correctly in dark mode (AC #3). The page
   already pins an explicit grid-template-columns via inline style on
   .bk-body (1fr), so the kv-grid reformats inside the bounded main column. */
@media (min-width: 1200px) {
    .cat-detail--readable .kv-grid {
        grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
        gap: var(--space-8);
        background: transparent;           /* base rule paints the hairline via 1px gaps; reset it so
                                              the wider 8px gap does not bleed the border colour through. */
        border: 0;
    }
    .cat-detail--readable .kv {
        padding: var(--space-16);
        background: var(--so-card);
        border: 1px solid var(--so-border-soft);
    }
}
/* LP-059: legacy-shaped single-value accounts comment dialog. */
.account-comment-card {
    max-width: 42rem;
}

.account-comment-form {
    display: grid;
    gap: .65rem;
    max-width: 34rem;
}

.account-comment-form input[type="text"],
.account-comment-form input:not([type]) {
    width: 100%;
}

.account-comment-delete {
    margin-top: 1rem;
}

/* BH-156: scoped Settings and Profile draft-loss dialogs. */
#settingsDirtyBadge[hidden] { display: none; }
#profileDirtyBadge[hidden] { display: none; }

dialog.settings-unsaved-dialog {
    padding: 0;
    border: none;
    background: transparent;
    border-radius: var(--so-radius);
    max-width: 480px;
    width: calc(100% - 32px);
}
dialog.settings-unsaved-dialog .form-card {
    color: var(--so-text-1);
}
dialog.settings-unsaved-dialog #settings-dialog-desc,
dialog.settings-unsaved-dialog #profile-dialog-desc {
    color: var(--so-text-1);
}
dialog.settings-unsaved-dialog::backdrop {
    background: var(--scrim-45);
    backdrop-filter: blur(2px);
}

/* BH-66: keep the template editor readable and contained at genuine mobile widths. */
.page--email-template-edit,
.page--email-template-edit .form-card,
.page--email-template-edit fieldset,
.page--email-template-edit .field,
.page--email-template-edit .email-templates__token-help {
    min-width: 0;
    max-width: 100%;
}
.page--email-template-edit .page__lede { color: var(--so-text-1); }
.page--email-template-edit .form-card { padding: var(--space-16); }
.page--email-template-edit fieldset {
    margin: 0;
    padding: var(--space-12);
    border: 1px solid var(--so-border);
}
.page--email-template-edit .field__input {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
}
.page--email-template-edit .field__hint { overflow-wrap: anywhere; }
.page--email-template-edit .email-templates__token-help { overflow-x: auto; }

/* BH #374 — staged, touch-safe setup and immutable review for advance commission. */
.advance-setup,
.advance-review {
    margin-top: var(--space-16);
    overflow: visible;
}
.advance-setup__head,
.advance-review__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-24);
    padding: var(--space-20) var(--space-24);
    border-bottom: 1px solid var(--so-border);
}
.advance-setup__head p,
.advance-review__head > .muted {
    max-width: 520px;
    margin: 2px 0 0;
    color: var(--so-text-2);
    font-size: 12.5px;
    line-height: 1.55;
    text-align: right;
}
.advance-step {
    display: block;
    margin-bottom: 5px;
    color: var(--so-primary);
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
}
.advance-setup__form {
    display: grid;
    gap: var(--space-20);
    padding: var(--space-24);
}
.advance-setup__group {
    min-width: 0;
    margin: 0;
    padding: var(--space-20);
    border: 1px solid var(--so-border-soft);
    background: var(--so-track);
}
.advance-setup__group legend {
    display: flex;
    align-items: center;
    gap: var(--space-8);
    padding: 0 var(--space-8) 0 0;
    color: var(--so-text-1);
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 700;
}
.advance-setup__group legend > span {
    display: inline-flex;
    width: 24px;
    height: 24px;
    align-items: center;
    justify-content: center;
    background: var(--so-primary);
    color: var(--white);
    font-family: var(--font-body);
    font-size: 11px;
}
.advance-setup__hint {
    margin: 0 0 var(--space-16);
    color: var(--so-muted);
    font-size: 12px;
    line-height: 1.5;
}
.advance-setup__grid {
    display: grid;
    gap: var(--space-16);
    align-items: start;
}
.advance-setup__grid--population { grid-template-columns: 1.2fr 1.2fr 1fr 1fr 1.35fr; }
.advance-setup__grid--allocation { grid-template-columns: 1.25fr .85fr 1fr 1.4fr; }
.advance-setup__grid--posting { grid-template-columns: 1.4fr 1.4fr .7fr .85fr .9fr; }
.advance-field {
    display: grid;
    min-width: 0;
    gap: 7px;
    color: var(--so-text-2);
    font-size: 11.5px;
    font-weight: 700;
}
.advance-field > span {
    min-height: 17px;
    letter-spacing: .01em;
}
.advance-field small {
    color: var(--so-muted);
    font-size: 10.5px;
    font-weight: 500;
}
.advance-field > input,
.advance-field > select {
    width: 100%;
    min-width: 0;
    min-height: 44px;
    padding: 0 var(--space-12);
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    color: var(--so-text-1);
    font: inherit;
    font-size: 13px;
}
.advance-field > input:focus-visible,
.advance-field > select:focus-visible {
    outline: 2px solid var(--so-focus-ring);
    outline-offset: 1px;
}
.advance-field > [aria-invalid="true"] { border-color: var(--error-02); }
.advance-field > small { margin-top: -2px; }
.advance-field .dd {
    display: block;
    width: 100%;
    min-width: 0;
}
.advance-field .dd__btn {
    height: 44px;
    min-height: 44px;
    font-size: 13px;
}
.advance-check {
    display: flex;
    min-width: 0;
    min-height: 68px;
    align-items: center;
    gap: var(--space-12);
    padding: var(--space-12);
    border: 1px solid var(--so-input-border);
    background: var(--so-input-bg);
    color: var(--so-text-1);
    cursor: pointer;
}
.advance-check input {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    accent-color: var(--so-primary);
}
.advance-check > span { display: grid; gap: 3px; }
.advance-check strong { font-size: 12px; }
.advance-check small { color: var(--so-muted); font-size: 11px; line-height: 1.35; }
.advance-setup__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-24);
    padding-top: var(--space-20);
    border-top: 1px solid var(--so-border);
}
.advance-setup__actions > div { display: grid; gap: 3px; }
.advance-setup__actions strong { color: var(--so-text-1); font-size: 13px; }
.advance-setup__actions span { color: var(--so-muted); font-size: 11.5px; }
.advance-setup__help {
    border-top: 1px solid var(--so-border);
}
.advance-setup__help > summary {
    display: flex;
    min-height: 44px;
    align-items: center;
    padding: 0 var(--space-24);
    color: var(--so-primary);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
}
.advance-setup__help > div {
    display: grid;
    gap: var(--space-8);
    max-width: 920px;
    padding: 0 var(--space-24) var(--space-20);
}
.advance-setup__help p { margin: 0; color: var(--so-text-2); font-size: 12px; line-height: 1.55; }
.advance-review__notice {
    margin: var(--space-20) var(--space-24) 0;
    padding: var(--space-12) var(--space-16);
    border-left: 3px solid var(--so-primary);
    background: var(--so-track);
    color: var(--so-text-2);
    font-size: 12px;
    line-height: 1.5;
}
.advance-review__notice strong { color: var(--so-text-1); }
.advance-review__facts {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    margin: var(--space-16) var(--space-24) var(--space-20);
    background: var(--so-border-soft);
    border: 1px solid var(--so-border-soft);
}
.advance-review__facts > div {
    min-width: 0;
    padding: var(--space-12);
    background: var(--so-card);
}
.advance-review__facts dt {
    margin-bottom: 5px;
    color: var(--so-muted);
    font-size: 10px;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
}
.advance-review__facts dd {
    margin: 0;
    overflow-wrap: anywhere;
    color: var(--so-text-1);
    font-size: 11.5px;
    line-height: 1.45;
}

@media (max-width: 1100px) {
    .advance-setup__grid--population,
    .advance-setup__grid--posting { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .advance-setup__grid--allocation { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .advance-review__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
    .advance-setup__head,
    .advance-review__head {
        display: grid;
        gap: var(--space-8);
        padding: var(--space-16);
    }
    .advance-setup__head p,
    .advance-review__head > .muted { margin: 0; text-align: left; }
    .advance-setup__form { gap: var(--space-16); padding: var(--space-16); }
    .advance-setup__group { padding: var(--space-16); }
    .advance-setup__grid--population,
    .advance-setup__grid--allocation,
    .advance-setup__grid--posting,
    .advance-review__facts { grid-template-columns: minmax(0, 1fr); }
    .advance-field > input,
    .advance-field > select,
    .advance-field .dd__btn { font-size: 16px; }
    .advance-check { min-height: 56px; }
    .advance-setup__actions { display: grid; gap: var(--space-16); }
    .advance-setup__actions .btn { width: 100%; justify-content: center; }
    .advance-setup__help > summary { padding: 0 var(--space-16); }
    .advance-setup__help > div { padding: 0 var(--space-16) var(--space-16); }
    .advance-review__notice { margin: var(--space-16) var(--space-16) 0; }
    .advance-review__facts { margin: var(--space-12) var(--space-16) var(--space-16); }
}
/* BH #117 — the authenticated field guide. Scoped to Help so it does not alter shared tokens. */
.help-guide__intro { display:flex; gap:2rem; justify-content:space-between; align-items:end; padding:1.5rem; border:1px solid var(--so-border); border-left:4px solid var(--so-rule); background:var(--so-card); }
.help-guide__kicker { margin:0 0 .35rem; color:var(--so-text-2); font-size:.78rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; }
.help-guide__intro h2 { margin:0; font-size:1.45rem; }
.help-guide__intro p:last-child { margin:.4rem 0 0; max-width:44rem; color:var(--so-text-2); }
.help-guide__search { min-width:min(100%, 25rem); }
.help-guide__search label { display:block; margin-bottom:.35rem; font-weight:700; }
.help-guide__search > div { display:flex; gap:.5rem; }
.help-guide__search input { min-width:0; flex:1; }
.help-guide__search p { margin:.45rem 0 0; color:var(--so-text-2); font-size:.88rem; }
.help-guide__layout { display:grid; grid-template-columns:minmax(14rem, 18rem) minmax(0, 1fr); gap:2rem; align-items:start; margin-top:2rem; }
.help-guide__contents { position:sticky; top:1rem; max-height:calc(100vh - 2rem); overflow:auto; padding:1.1rem; border:1px solid var(--so-border); background:var(--so-card); }
.help-guide__contents h2 { margin:0 0 .75rem; font-size:1rem; }
.help-guide__contents ol { margin:0; padding:0; list-style:none; }
.help-guide__contents-item { margin:.35rem 0; font-size:.9rem; line-height:1.35; }
.help-guide__contents-item--level-3 { margin-left:.8rem; font-size:.84rem; }
.help-guide__contents a { color:var(--so-text-2); text-decoration:none; }
.help-guide__contents a:hover, .help-guide__contents a:focus-visible { color:var(--so-text-1); text-decoration:underline; }
.help-guide__article { min-width:0; padding:clamp(1rem, 3vw, 2.5rem); border:1px solid var(--so-border); background:var(--so-card); color:var(--so-text-2); }
.help-guide__article > :first-child { margin-top:0; }
.help-guide__article p, .help-guide__article li, .help-guide__article td { color:var(--so-text-2); }
.help-guide__article strong, .help-guide__article th { color:var(--so-text-1); }
.help-guide__article a { color:var(--so-trust); text-decoration-thickness:.08em; text-underline-offset:.14em; }
.help-guide__article a:hover, .help-guide__article a:focus-visible { color:var(--so-text-1); }
.help-guide__article h1 { font-size:clamp(1.7rem, 3vw, 2.35rem); }
.help-guide__article h2 { margin-top:2.8rem; padding-top:.75rem; border-top:1px solid var(--so-border); font-size:1.35rem; scroll-margin-top:1rem; }
.help-guide__article h3, .help-guide__article h4 { margin-top:1.75rem; scroll-margin-top:1rem; }
.help-guide__article img { display:block; max-width:100%; height:auto; margin:1rem 0 1.5rem; border:1px solid var(--so-border); }
.help-guide__article table { display:block; max-width:100%; overflow-x:auto; border-collapse:collapse; }
.help-guide__article th, .help-guide__article td { padding:.55rem .7rem; border:1px solid var(--so-border); text-align:left; vertical-align:top; }
.help-guide__article code { overflow-wrap:anywhere; }
.help-guide__search-hit { padding:0 .08em; background:color-mix(in srgb, var(--so-brand) 30%, transparent); color:inherit; }
@media (max-width: 760px) { .help-guide__intro { display:block; } .help-guide__search { margin-top:1.25rem; } .help-guide__layout { display:block; } .help-guide__contents { position:static; max-height:none; margin-bottom:1rem; } }
@media print { .sidebar, .topbar, .help-guide__contents, .help-guide__intro, .page-head { display:none !important; } .app__main, .page, .help-guide__article { display:block; margin:0; padding:0; border:0; } .help-guide__article a { color:#000; text-decoration:underline; } }
