/* ============================================================================
   boab-design.css — STAGE 3: the claim sheet's design language, app-wide.

   Owner's ruling: "the design in the claim sheet is great and we need to have
   that steer the entire app's design." Every colour / size here comes from the
   sheet tokens in css/sheet-tokens.css (the ONE mirror of SheetTheme.cs — 1
   sheet-pt = 0.1rem; see that file's header) or from the MudBlazor palette
   custom properties (--mud-palette-*, which BoabTheme.cs paints and which swap
   automatically in dark mode). NO literal colours or sheet dimensions may appear
   here except pure screen affordances — if you need a sheet value, add/alias it
   as a token first.

   TWO TIERS, one vocabulary:

   1. `.boab-sheet-*` — the PAPER-LITERAL classes, PROMOTED verbatim from
      Components/Shared/SectionLayoutEntry.razor.css (stage 2). These render a
      facsimile of the printed sheet (paper, ink, printed hairlines). They were
      once paper-fixed on screen too, but the owner overrode that (ruling
      2026-07-07: "have the boab sheet tier respect dark mode too … idc that it
      violates WYSIWYG") — so in dark mode their --sheet-* COLOUR tokens remap
      onto the Mud dark surface/ink/line family (see the `.boab-dark` sheet block
      below). PRINT / PDF stay paper: the @media print block forces the paper
      literals back, and the production PDF is drawn server-side by QuestPDF
      (never touches this CSS). Consumers: SectionLayoutEntry (the approved
      claim-entry surface — do not shift its LIGHT look) and EquipmentClaimGrid's
      "Who & when" sign-off band. The MudBlazor-internal
      capture chrome (the ::deep input re-skin) is NOT promoted: it stays scoped
      in SectionLayoutEntry.razor.css so it cannot leak into app-wide inputs and
      keeps its cascade edge over MudBlazor.min.css.

   2. `.boab-panel*` / `.boab-micro-label` / `.boab-stat*` / `.boab-tint` — the
      APP panel language: the sheet's GEOMETRY and TYPE verbatim (radius family,
      hairline stroke, tracked-caps caption band, micro-labels over values,
      restrained tint fills) but with colours routed through the --boab-panel-*
      indirection below, so light mode reads exactly like the sheet while dark
      mode maps onto the Mud dark palette instead of forcing paper-white panels.
      Consumers: every primary page surface (queue worklists, workspace panes,
      intake, outbox, queries, users, progress, home cards, AppDataGrid,
      MasterDetailView).

   DARK MODE HOOK: MainLayout puts `boab-dark` (+ bootstrap's data-bs-theme) on
   the MudLayout when the theme toggle is dark — MudBlazor itself swaps only its
   palette variable VALUES, so this class is the app's only selector-level hook.
   ============================================================================ */

/* ── Colour indirection for the APP tier ─────────────────────────────────────
   Light mode = the sheet's paper values (so the app IS the sheet); dark mode
   remaps to the Mud dark palette under `.boab-dark` below. */
:root {
    --boab-panel-bg: var(--mud-palette-surface, var(--sheet-page-bg));
    --boab-panel-border: var(--sheet-border);
    --boab-panel-ink: var(--mud-palette-text-primary, var(--sheet-ink));
    --boab-panel-label: var(--sheet-label-grey);
    --boab-panel-muted: var(--sheet-muted);
    --boab-panel-rule: var(--sheet-inner-rule);
    --boab-panel-tint: var(--sheet-field-tint);
}

.boab-dark {
    --boab-panel-border: var(--mud-palette-lines-default);
    --boab-panel-label: var(--mud-palette-text-secondary);
    --boab-panel-muted: var(--mud-palette-text-secondary);
    --boab-panel-rule: var(--mud-palette-lines-default);
    --boab-panel-tint: rgba(255, 255, 255, 0.05);
}

/* The app bar's hairline is powder-grey in light; soften it onto the dark bar. */
.boab-dark .boab-appbar {
    border-bottom-color: var(--mud-palette-lines-default);
}

/* ── Colour remap for the SHEET tier (TIER 1) — owner ruling 2026-07-07 ───────
   The `.boab-sheet-*` facsimile classes were originally paper-fixed even on
   screen (WYSIWYG: a sheet stayed paper-white in a dark viewer). The owner
   overrode that — "have the boab sheet tier respect dark mode too … idc that it
   violates WYSIWYG" — so here we remap the --sheet-* COLOUR tokens onto the same
   dark surface / ink / line family the panel tier uses (BoabTheme.PaletteDark).
   Readable dark sheets now win over paper fidelity ON SCREEN.

   ONLY colours move. Geometry / type tokens (--sheet-pt, fs-*, track-*, radii,
   the strokes-as-WIDTHS, capture dimensions, guide GEOMETRY) are untouched.
   --sheet-guide-image is NOT redeclared: it is built from var(--sheet-guide-grey)
   and re-resolves to the dark guide colour automatically (lazy custom-prop
   substitution on each consuming element under .boab-dark).

   NO DOUBLE-REMAP: every --boab-panel-* token that reads a --sheet-* colour in
   LIGHT mode is already re-pointed at the Mud dark palette in the .boab-dark
   block above — border/label/muted/rule/tint are overridden outright, and the
   --boab-panel-bg/-ink `var(mud, sheet-fallback)` fallbacks are dead in dark
   (their Mud values are defined). So the panel tier never re-reads these dark
   sheet values, and nothing inverts twice.

   PRINT / PDF STAY PAPER: the @media print block below forces the paper literals
   back (a Ctrl+P of a dark sheet prints white), and the production claim-sheet
   PDF is drawn server-side by QuestPDF (ClaimSheetDocument, colours straight from
   SheetTheme.cs) — it consumes no CSS and can never see .boab-dark. */
.boab-dark {
    /* surfaces + ink */
    --sheet-page-bg: var(--mud-palette-surface);           /* paper → dark card surface */
    --sheet-ink: var(--mud-palette-text-primary);          /* body / heading ink → light */
    --sheet-grey: var(--mud-palette-text-secondary);       /* secondary text → muted light */
    --sheet-label-grey: var(--mud-palette-text-secondary); /* tracked-caps labels → muted light */
    --sheet-muted: #8f918f;                                /* quietest micro type (~4.9:1 on surface) */
    /* rules + strokes — a 3-step ramp harmonised with --mud-palette-lines-default */
    --sheet-inner-rule: var(--mud-palette-lines-default);  /* in-panel rules → the Mud dark line */
    --sheet-hairline: var(--mud-palette-lines-default);
    --sheet-border: #4c504d;                               /* panel frame — a step above the line colour */
    --sheet-masthead-rule: #4c504d;
    --sheet-write-rule: #585c59;                           /* capture-box / tick chrome — brightest stroke */
    --sheet-guide-grey: #50544f;                           /* dashed baseline guides (feeds --sheet-guide-image) */
    /* the one fill — identical to --boab-panel-tint's dark value */
    --sheet-field-tint: rgba(255, 255, 255, 0.05);
}

/* PRINT / PDF-PREVIEW GUARD: force the paper literals back so a dark-mode sheet
   still prints on white, exactly like the QuestPDF page. These mirror the light
   :root values in css/sheet-tokens.css (the mirror-tested source of truth — move
   them together). Last in source + equal specificity ⇒ wins over .boab-dark
   under print media. */
@media print {
    :root,
    .boab-dark {
        --sheet-page-bg: #ffffff;
        --sheet-ink: #222524;
        --sheet-grey: #555555;
        --sheet-label-grey: #6b6b6b;
        --sheet-muted: #8c8c8c;
        --sheet-inner-rule: #d6d6d6;
        --sheet-hairline: #cfcfcf;
        --sheet-border: #9e9e9e;
        --sheet-masthead-rule: #b9b9b9;
        --sheet-write-rule: #a6a6a6;
        --sheet-guide-grey: #c6c6c6;
        --sheet-field-tint: #f6f6f6;
    }
}

/* ============================================================================
   TIER 2 — THE APP PANEL LANGUAGE (dark-aware)
   ============================================================================ */

/* The panel — the sheet's rounded hairline frame (Panel()), palette-routed.
   Apply to a plain div or a MudPaper (Elevation="0", WITHOUT Outlined — Mud's
   .mud-paper-outlined border would win the cascade tie over this rule). */
.boab-panel {
    background-color: var(--boab-panel-bg);
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-border);
    border-radius: var(--sheet-radius);
    overflow: hidden;              /* flush tables/PDF panes respect the corners */
    box-shadow: none;
}

/* Disposition-panel variant (ProcessingWorkspace's outcome panel): a left accent
   bar reads as "this is an out-of-band action" without the alarm of the old
   red/amber alert panels. The panel opens straight on ONE outcome, so the accent
   echoes the clicked button's colour family (theme tokens — never literals).
   GLOBAL on purpose: the classes sit on a MudPaper, whose root element never
   receives a component's CSS-isolation scope attribute — a scoped rule targeting
   it can never match (same reasoning as .boab-panel above). */
.boab-disposition {
    border-left: 4px solid var(--mud-palette-primary);
}

.boab-disposition--warning {
    border-left-color: var(--mud-palette-warning);
}

.boab-disposition--info {
    border-left-color: var(--mud-palette-info);
}

.boab-disposition--error {
    border-left-color: var(--mud-palette-error);
}

/* Caption band: tracked-caps label left, anything else (hint / count / actions)
   pushed right — the sheet's caption-plus-numeral band, generalised. */
.boab-panel-caption {
    display: flex;
    align-items: center;
    padding: var(--sheet-caption-pad-t) var(--sheet-panel-pad) var(--sheet-caption-pad-b);
}

.boab-panel-caption-label {
    flex: 1 1 auto;
    font-size: var(--sheet-fs-kicker);
    font-weight: 700;
    letter-spacing: var(--sheet-track-kicker);
    text-transform: uppercase;
    color: var(--boab-panel-ink);
    line-height: 1.3;
}

/* The inner rule under the caption — inset by the panel padding, like the sheet. */
.boab-panel-rule {
    border-top: var(--sheet-inner-rule-w) solid var(--boab-panel-rule);
    margin: 0 var(--sheet-panel-pad);
}

.boab-panel-body {
    padding: var(--sheet-panel-pad);
}

.boab-panel-body--flush {
    padding: 0;
}

/* Tracked-caps micro-label over a value — the sheet's FsLabelV5, palette-routed. */
.boab-micro-label {
    font-size: var(--sheet-fs-label);
    font-weight: 600;
    letter-spacing: var(--sheet-track-label);
    text-transform: uppercase;
    color: var(--boab-panel-label);
    line-height: 1.25;
}

/* The restrained fill — the sheet's write-area tint at the write-box radius
   (replaces bootstrap's bg-light + rounded). */
.boab-tint {
    background-color: var(--boab-panel-tint);
    border-radius: var(--sheet-write-radius);
}

/* ── Stat tiles (queue health strip) — micro-label over a printed value in a
   hairline tile; the ONLY colour is a thin semantic accent edge (restrained
   fills — no more solid bootstrap text-bg-* cards). ────────────────────────── */
.boab-stat-strip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sheet-block-gap);
}

.boab-stat {
    flex: 1 1 0;
    min-width: 7.5rem;
    background-color: var(--boab-panel-bg);
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-border);
    border-left: 3px solid var(--boab-stat-accent, var(--boab-panel-border));
    border-radius: var(--sheet-radius);
    padding: calc(var(--sheet-pt) * 5) var(--sheet-panel-pad) calc(var(--sheet-pt) * 4);
}

.boab-stat-value {
    padding-top: calc(var(--sheet-pt) * 2);
    font-size: var(--sheet-fs-identity);
    font-weight: 700;
    color: var(--boab-panel-ink);
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

/* Semantic accents via the Mud palette (dark-mode safe by construction). */
.boab-stat--warning { --boab-stat-accent: var(--mud-palette-warning); }
.boab-stat--info    { --boab-stat-accent: var(--mud-palette-info); }
.boab-stat--primary { --boab-stat-accent: var(--mud-palette-primary); }
.boab-stat--secondary { --boab-stat-accent: var(--mud-palette-secondary); }
.boab-stat--success { --boab-stat-accent: var(--mud-palette-success); }
.boab-stat--error   { --boab-stat-accent: var(--mud-palette-error); }
.boab-stat--neutral { --boab-stat-accent: var(--boab-panel-border); }

/* ── Brief / home cards + attention chips (PROMOTED 2026-08-31 from
   Components/Pages/Reporting.razor.css) ──────────────────────────────────────
   Authored on the Daily Brief — hence the `.boab-brief-*` prefix — but the Home
   strips (MyAreasStrip, NeedsALookStrip) render the SAME markup, and a SCOPED
   stylesheet only ever reaches its own component's elements. So the Home cards
   rendered as bare, unstyled divs. This vocabulary is app tier (the file header
   already lists "home cards" as a consumer), so it lives here, once, and the
   Brief keeps only its page-local classes (ribbon, empty state, project strip,
   suggestions). Geometry/type from the sheet tokens, colour through the
   --boab-panel-* indirection, so dark mode follows for free. ──────────────── */

/* ── attention chips ── */
.boab-brief-chip {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    padding: 0.6rem 0.75rem;
    margin-bottom: 0.5rem;
    min-height: 44px;
    border: max(1px, var(--sheet-stroke, 1px)) solid var(--boab-panel-border, var(--mud-palette-lines-default));
    border-left: 4px solid var(--mud-palette-warning);
    border-radius: var(--sheet-radius, 8px);
    text-decoration: none;
    color: var(--boab-panel-ink, inherit);
    background-color: color-mix(in srgb, var(--mud-palette-warning) 6%, transparent);
}

.boab-brief-chip:last-child { margin-bottom: 0; }

/* chip row = the tap-through chip + its snooze affordance side by side */
.boab-brief-chip-row {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-bottom: 0.5rem;
}

.boab-brief-chip-row:last-child { margin-bottom: 0; }

/* the chip inside a row carries no margin of its own (the row owns the spacing) and grows */
.boab-brief-chip-row .boab-brief-chip {
    flex: 1 1 auto;
    margin-bottom: 0;
    min-width: 0;
}

/* ── snoozed strip — never silently gone (§5 honesty) ── */
.boab-brief-snoozed-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-top: 0.6rem;
    padding: 0.25rem 0.4rem;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--boab-panel-muted, var(--mud-palette-text-secondary));
    font-size: 0.8rem;
    min-height: 32px;
}

.boab-brief-snoozed-toggle:hover { text-decoration: underline; }

.boab-brief-chip--snoozed {
    opacity: 0.72;
    border-left-color: var(--mud-palette-lines-default);
    background-color: color-mix(in srgb, var(--mud-palette-text-secondary) 5%, transparent);
    margin-top: 0.4rem;
}

.boab-brief-chip--snoozed .boab-brief-chip-action a {
    color: var(--mud-palette-primary);
    text-decoration: none;
}

.boab-brief-chip:hover {
    text-decoration: none;
    background-color: color-mix(in srgb, var(--mud-palette-warning) 12%, transparent);
}

.boab-brief-chip--applause {
    border-left-color: var(--mud-palette-success);
    background-color: color-mix(in srgb, var(--mud-palette-success) 7%, transparent);
}

.boab-brief-chip--applause:hover {
    background-color: color-mix(in srgb, var(--mud-palette-success) 13%, transparent);
}

.boab-brief-chip-text {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.boab-brief-chip-head {
    font-weight: 600;
    overflow-wrap: anywhere;
}

.boab-brief-chip-action {
    font-size: 0.8rem;
    color: var(--boab-panel-muted, var(--mud-palette-text-secondary));
}

.boab-brief-chip-go {
    color: var(--mud-palette-primary);
    font-weight: 600;
    white-space: nowrap;
}

.boab-brief-chip-icon { margin-top: 0.1rem; }

.boab-brief-allquiet,
.boab-brief-applause-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--boab-panel-muted, var(--mud-palette-text-secondary));
}

.boab-brief-applause-head { margin: 0.75rem 0 0.4rem; }

/* ── area cards ── */
.boab-brief-cards {
    display: grid;
    grid-template-columns: 1fr;              /* phone-first: single column, stacked */
    gap: 0.75rem;
}

@media (min-width: 40rem) {
    .boab-brief-cards {
        grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));   /* PC: comfortable multi-column */
    }
}

.boab-brief-card {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.7rem 0.85rem;
    border: max(1px, var(--sheet-stroke, 1px)) solid var(--boab-panel-border, var(--mud-palette-lines-default));
    border-radius: var(--sheet-radius, 8px);
}

.boab-brief-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.boab-brief-card-title {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
    overflow-wrap: anywhere;
}

.boab-brief-card-title:hover { text-decoration: underline; }

.boab-brief-card-line {
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 0.4rem;
    align-items: baseline;
}

/* e/s unit-tags: shorthand-as-UNIT, visually distinct from the digits so it can't read
   as notation (owner ruling 2026-07-04). Lives INSIDE the number's <strong> so the pair
   never wraps apart; the tooltips/sparkline teach the convention in words. */
.boab-unit-tag {
    font-size: 0.72em;
    color: var(--mud-palette-text-secondary);
    font-weight: 500;
    margin-left: 1px;
}

.boab-brief-bar {
    height: 8px;
    border-radius: 4px;
    background-color: var(--boab-panel-tint, rgba(0, 0, 0, 0.06));
    overflow: hidden;
}

.boab-brief-bar-fill {
    height: 100%;
    /* Flipping primary (the pinned gum-green first arg was defined, so the intended fallback
       never ran and the fill was near-black on the dark track). Light: primary == gum-green. */
    background-color: var(--mud-palette-primary);
    transition: width 0.2s ease;
}

.boab-brief-runrate {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
}

.boab-brief-card-actions {
    display: flex;
    gap: 0.25rem;
    margin-top: 0.1rem;
}

/* ── Table dressing inside panels/grids: column headers become the sheet's
   tracked-caps micro-labels (works for bootstrap .table AND Mud tables). ───── */
.boab-panel thead th,
.boab-data-grid thead th {
    font-size: var(--sheet-fs-label);
    font-weight: 600;
    letter-spacing: var(--sheet-track-label);
    text-transform: uppercase;
    color: var(--boab-panel-label);
}

/* AppDataGrid (Components/Shared) — the shared grid carries the panel chrome on
   ALL its states (skeleton / empty / grid), keyed off the one class it already sets. */
.boab-data-grid {
    background-color: var(--boab-panel-bg);
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-border);
    border-radius: var(--sheet-radius);
    overflow: hidden;
}

/* StatusBadge — the one status pill (Components/Shared/StatusBadge.razor). Set in the
   sheet's tracked-caps micro type (kicker size + label tracking) so a column of statuses
   reads like the sheet's printed captions, not as loud chips. Lives here (not the web's
   app.css) so BOTH heads that render the shared component style it identically. */
.boab-status-badge {
    font-weight: 600;
    height: 22px;
    min-width: 0;
}
.boab-status-badge .mud-chip-content {
    padding: 0 8px;
    font-size: var(--sheet-fs-kicker);
    letter-spacing: var(--sheet-track-label);
    text-transform: uppercase;
}

/* ── Scroll-pan affordance (A3/B5) — a CROSS-PAGE idiom used by the reporting ledger AND the
   Performance pivot (both wrap their wide tables in .boab-rpt-scroll). GLOBAL on purpose: the class
   is shared across two components' scoped stylesheets, so the shadow lives once here, not duplicated.
   The classic background-attachment:local scroll shadow — edge shadows that appear ONLY when the
   content overflows and fade out as you pan to each end:
     • the two 'cover' layers are the SOLID panel background, pinned local (they scroll WITH the
       content, masking the shadow when the reader is already at that edge);
     • the two 'shadow' layers are a translucent ink, pinned scroll (fixed to the box, so they show
       whenever there is more content that way).
   Palette-routed: the cover is --boab-panel-bg (opaque — the shadow trick needs a solid backdrop);
   the shadow is ink at low alpha, which reads as a soft dark edge in light mode and degrades to a
   gentle light edge-glow in dark mode (--boab-panel-ink flips light under .boab-dark) — a graceful
   pan cue either way. Scoped .boab-rpt-scroll rules only set overflow/height, never background, so
   this is never overridden. Strength tuned per the #213 senior review: 16%/0.85rem was
   imperceptible at 1x zoom — an affordance you squint for is not an affordance; 28%/1.2rem reads
   at a glance while still fading softly (cover scaled to 3rem so the mask stays ahead of it). */
.boab-rpt-scroll {
    overflow-x: auto;
    background-color: var(--boab-panel-bg);
    background-image:
        linear-gradient(to right, var(--boab-panel-bg) 30%, transparent),
        linear-gradient(to left, var(--boab-panel-bg) 30%, transparent),
        radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--boab-panel-ink) 28%, transparent), transparent),
        radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--boab-panel-ink) 28%, transparent), transparent);
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size: 3rem 100%, 3rem 100%, 1.2rem 100%, 1.2rem 100%;
    background-attachment: local, local, scroll, scroll;
}

/* ============================================================================
   TIER 1 — PROMOTED PAPER-LITERAL SHEET CLASSES
   Moved verbatim from SectionLayoutEntry.razor.css (stage 2); that scoped file
   now keeps ONLY the MudBlazor-internal capture chrome (::deep input re-skin).
   These are a facsimile of the printed sheet. They read as PAPER in light mode;
   in dark mode their --sheet-* COLOUR tokens remap (owner ruling 2026-07-07 —
   see the `.boab-dark` sheet block up top), while @media print + the QuestPDF
   PDF path keep paper. Everything below references --sheet-* tokens, so both
   modes fall out of the token values — do not hard-code colours here.
   ============================================================================ */

/* ── The panel — ClaimSheetDocument.Panel(): rounded hairline frame ─────────── */
.boab-sheet-panel {
    background: var(--sheet-page-bg);
    border: max(1px, var(--sheet-stroke)) solid var(--sheet-border);
    border-radius: var(--sheet-radius);
    margin-bottom: var(--sheet-block-gap);
}

/* Caption band: tracked-caps label left, section numeral right (01, 02 …). */
.boab-sheet-caption {
    display: flex;
    align-items: center;
    padding: var(--sheet-caption-pad-t) var(--sheet-panel-pad) var(--sheet-caption-pad-b);
}

.boab-sheet-caption-label {
    flex: 1 1 auto;
    font-size: var(--sheet-fs-kicker);
    font-weight: 700;
    letter-spacing: var(--sheet-track-kicker);
    text-transform: uppercase;
    color: var(--sheet-ink);
    line-height: 1.3;
}

.boab-sheet-caption-index {
    font-size: var(--sheet-fs-kicker);
    font-weight: 600;
    letter-spacing: var(--sheet-track-kicker);
    color: var(--sheet-muted);
    line-height: 1.3;
}

/* The inner rule under the caption — inset by the panel padding, like the sheet. */
.boab-sheet-rule {
    border-top: var(--sheet-inner-rule-w) solid var(--sheet-inner-rule);
    margin: 0 var(--sheet-panel-pad);
}

.boab-sheet-body {
    padding: var(--sheet-panel-pad);
}

/* ── Tracked-caps micro-label (FsLabelV5) — shared by every printed label ──── */
.boab-mini-label {
    font-size: var(--sheet-fs-label);
    font-weight: 600;
    letter-spacing: var(--sheet-track-label);
    text-transform: uppercase;
    color: var(--sheet-label-grey);
    line-height: 1.25;
}

/* ── IDENTIFICATION strip — big ids over vertical hairline separators ───────── */
.boab-sheet-identity {
    display: flex;
    flex-wrap: wrap;
}

.boab-sheet-identity-cell {
    flex: 1 1 0;
    min-width: 8rem;             /* screen affordance: wrap instead of crushing */
}

.boab-sheet-identity-cell + .boab-sheet-identity-cell {
    border-left: var(--sheet-inner-rule-w) solid var(--sheet-inner-rule);
    padding-left: calc(var(--sheet-pt) * 14);
}

.boab-sheet-identity-value {
    padding-top: calc(var(--sheet-pt) * 2);
    font-size: var(--sheet-fs-identity);
    font-weight: 700;
    color: var(--sheet-ink);
    overflow-wrap: anywhere;
}

/* ── SCHEDULED DETAILS grid — 2 columns, hairline-banded rows, printed values ─ */
.boab-sheet-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.boab-sheet-grid-cell {
    padding: var(--sheet-grid-row-pad-v) calc(var(--sheet-pt) * 12) var(--sheet-grid-row-pad-v) 0;
    border-bottom: var(--sheet-inner-rule-w) solid var(--sheet-inner-rule);
    min-width: 0;
}

/* The last band loses its rule (the sheet's lastBand logic): the last cell always;
   the second-last too when it starts the final band (it sits in the LEFT column). */
.boab-sheet-grid-cell:last-child,
.boab-sheet-grid-cell:nth-last-child(2):nth-child(odd) {
    border-bottom: none;
}

.boab-sheet-grid-value {
    padding-top: calc(var(--sheet-pt) * 2);
    padding-bottom: calc(var(--sheet-pt) * 1);
    font-size: var(--sheet-fs-value);
    color: var(--sheet-ink);
    overflow-wrap: anywhere;
}

/* ── Entry rows — the spec's row structure (Start | End side by side, etc.) ─── */
.boab-sheet-rows {
    display: flex;
    flex-direction: column;
    gap: var(--sheet-block-gap);
}

.boab-sheet-row {
    display: flex;
    flex-wrap: wrap;             /* screen affordance for narrow panes */
    gap: calc(var(--sheet-pt) * 12);
}

.boab-sheet-row > .boab-field {
    flex: 1 1 12rem;
    min-width: 0;
}

.boab-field {
    min-width: 0;
}

.boab-field--comment {
    width: 100%;
}

/* ── Checklist — the sheet's printed table: ITEM | ✓ | ✗ | N/A | COMMENTS ───── */
.boab-sheet-checklist {
    display: grid;
    grid-template-columns:
        minmax(0, 5fr)
        calc(var(--sheet-pt) * 30)
        calc(var(--sheet-pt) * 30)
        calc(var(--sheet-pt) * 30)
        minmax(0, 3fr);
}

.boab-sheet-check-h {
    display: flex;
    align-items: flex-end;                    /* labels sit ON the shared rule */
    padding: 0 calc(var(--sheet-pt) * 2) calc(var(--sheet-pt) * 4);
    border-bottom: var(--sheet-inner-rule-w) solid var(--sheet-inner-rule);
}

.boab-sheet-check-h--tick {
    justify-content: center;
}

.boab-sheet-check-h--comments {
    padding-left: calc(var(--sheet-pt) * 8);
}

.boab-sheet-check-yes,
.boab-sheet-check-no {
    font-size: var(--sheet-fs-tick);
    font-weight: 700;
    line-height: 1;
}

.boab-sheet-check-yes { color: var(--sheet-ink); }
.boab-sheet-check-no  { color: var(--sheet-label-grey); }

.boab-sheet-check-c {
    display: flex;
    align-items: center;
    min-height: calc(var(--sheet-checklist-row) + var(--sheet-pt) * 2);
    padding: calc(var(--sheet-pt) * 3) calc(var(--sheet-pt) * 2);
    border-bottom: var(--sheet-inner-rule-w) solid var(--sheet-inner-rule);
    min-width: 0;
}

.boab-sheet-check-c--last {
    border-bottom: none;
}

.boab-sheet-check-c--tick {
    justify-content: center;
}

.boab-sheet-check-c--comments {
    padding-left: calc(var(--sheet-pt) * 8);
}

.boab-sheet-check-item {
    font-size: var(--sheet-fs-item);
    color: var(--sheet-ink);
}

/* The discrete rounded tick-square (SvgPanel at TickBoxSize/WriteStroke). */
.boab-sheet-tick {
    flex: none;
    width: var(--sheet-tick-box);
    height: var(--sheet-tick-box);
    border: max(1px, var(--sheet-write-stroke)) solid var(--sheet-write-rule);
    border-radius: var(--sheet-tick-radius);
}

/* The trailing tinted capture cell (SvgWriteBox, guides: 0). */
.boab-sheet-check-write {
    flex: 1 1 auto;
    min-height: var(--sheet-checklist-row);
    background-color: var(--sheet-field-tint);
    border: max(1px, var(--sheet-write-stroke)) solid var(--sheet-write-rule);
    border-radius: var(--sheet-write-radius);
}

.boab-sheet-check-note {
    margin-top: calc(var(--sheet-pt) * 4);
    font-size: var(--sheet-fs-kicker);
    font-style: italic;
    color: var(--sheet-grey);
}

/* ── Checklist — capture-by-exception interactive tri-state (ITR Phase 6, Ruling 3) ──
   Each ✓/✗/N-A tick-square becomes a selectable button on the SAME sheet chrome. At rest it
   is the empty tick-square; selected fills it (Pass=ink, Fail=error, N/A=label grey). Screen
   affordances (cursor/hover/focus) are free — the printed sheet is untouched. */
.boab-sheet-tick--btn {
    cursor: pointer;
    padding: 0;
    background-color: transparent;
    transition: background-color 0.08s ease, border-color 0.08s ease;
}

.boab-sheet-tick--btn:hover:not(:disabled) {
    border-color: var(--sheet-ink);
}

.boab-sheet-tick--btn:disabled {
    cursor: default;
    opacity: 0.55;
}

.boab-sheet-tick--btn:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.boab-sheet-tick--on {
    border-color: var(--sheet-ink);
    background-color: var(--sheet-ink);
}

.boab-sheet-tick--f.boab-sheet-tick--on {
    border-color: var(--mud-palette-error);
    background-color: var(--mud-palette-error);
}

.boab-sheet-tick--na.boab-sheet-tick--on {
    border-color: var(--sheet-label-grey);
    background-color: var(--sheet-label-grey);
}

/* ── SIGN-OFF band layout: Installer | Supervisor | Date (date cell = the
   sheet's narrow 88 pt constant cell). The --lines INPUT re-skin stays scoped
   in SectionLayoutEntry.razor.css (MudBlazor internals). ───────────────────── */
.boab-sheet-signoff {
    display: flex;
    flex-wrap: wrap;                          /* screen affordance for narrow panes */
    align-items: flex-start;
    gap: calc(var(--sheet-pt) * 12);
}

.boab-sheet-signoff-cell {
    flex: 1 1 14rem;
    min-width: 0;
}

.boab-sheet-signoff-cell--date {
    flex: 0 1 calc(var(--sheet-pt) * 88);
    min-width: calc(var(--sheet-pt) * 88);
}

/* The sheet's micro-hint under each signature line (FsFootV5 − 0.5, TrackLabel). */
.boab-sheet-sign-hint {
    padding-top: calc(var(--sheet-pt) * 2.5);
    font-size: var(--sheet-fs-sign-hint);
    letter-spacing: var(--sheet-track-label);
    text-transform: uppercase;
    color: var(--sheet-muted);
}

/* ── Narrow panes (screen affordance only — print layout never sees this) ───── */
@media (max-width: 40rem) {
    .boab-sheet-grid {
        grid-template-columns: 1fr;
    }

    /* Single column ⇒ every cell but the true last keeps its band rule. */
    .boab-sheet-grid-cell:nth-last-child(2):nth-child(odd) {
        border-bottom: var(--sheet-inner-rule-w) solid var(--sheet-inner-rule);
    }

    .boab-sheet-grid-cell:last-child {
        border-bottom: none;
    }
}

/* ============================================================================
   TO-GO COMMODITY TRACKERS (reporting-suite-plan.md §8) — shared by the
   /reporting/togo index + /reporting/togo/{slug} pages. GLOBAL (not scoped)
   because both pages use the same idiom and Blazor scoped CSS never crosses a
   component boundary. Phone-first field surface: ≥44px targets, full rows are
   targets, no horizontal page scroll; palette-routed for dark mode.
   ============================================================================ */

/* freshness ribbon (mirrors the Brief's, shareable across the two togo pages) */
.boab-togo-ribbon {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.55rem 0.85rem;
    border-radius: var(--sheet-radius);
    color: var(--boab-panel-ink);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    min-height: 44px;
}

.boab-togo-ribbon:hover {
    text-decoration: none;
    outline: 1px solid var(--boab-panel-rule);
}

/* index: card grid — single column on phone, comfortable multi-column on PC */
.boab-togo-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.75rem;
}

@media (min-width: 40rem) {
    .boab-togo-cards {
        grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
    }
}

.boab-togo-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.75rem 0.9rem;
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-border);
    border-radius: var(--sheet-radius);
    text-decoration: none;
    color: var(--boab-panel-ink);
    min-height: 44px;
}

.boab-togo-card:hover {
    text-decoration: none;
    outline: 1px solid var(--boab-panel-rule);
}

.boab-togo-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.boab-togo-card-title {
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--mud-palette-primary);
    overflow-wrap: anywhere;
}

/* headline metric row: to-go / done / total */
.boab-togo-headline {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.5rem;
    align-items: baseline;
}

.boab-togo-headline--lg {
    gap: 0.6rem 2.25rem;
    margin-bottom: 0.35rem;
}

.boab-togo-metric {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
}

.boab-togo-metric-value {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.15;
}

.boab-togo-headline--lg .boab-togo-metric-value {
    font-size: 1.55rem;
}

.boab-togo-metric--togo .boab-togo-metric-value {
    color: var(--mud-palette-primary);
}

.boab-togo-card-sub,
.boab-togo-hours {
    font-size: 0.85rem;
    color: var(--boab-panel-muted);
    font-variant-numeric: tabular-nums;
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 0.75rem;
    align-items: baseline;
}

.boab-togo-hours { margin-top: 0.25rem; }

.boab-togo-mixed {
    color: var(--mud-palette-warning);
    font-weight: 600;
}

/* tracker page: run-rate line + headline ledger link */
.boab-togo-runrate {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.55rem;
    font-size: 0.9rem;
    font-variant-numeric: tabular-nums;
    flex-wrap: wrap;
}

.boab-togo-headlink {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
    font-weight: 600;
    font-size: 0.9rem;
    min-height: 44px;
}

.boab-togo-headlink:hover { text-decoration: underline; }

.boab-togo-copybtn { margin-left: auto; }

/* tracker page: cascade AREA FILTER (Section → WBS → WorkPack) — chips + one next-tier picker.
   Phone-first: chips wrap, the picker + buttons are ≥44px touch targets, nothing hover-dependent. */
.boab-togo-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.75rem;
    margin-bottom: 0.7rem;
}

.boab-togo-filter-label { align-self: center; }

.boab-togo-filter-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.2rem;
}

/* Enlarge the chip + its ✕ so they clear the field-touch minimum on a phone. */
.boab-togo-filter-chips .mud-chip {
    min-height: 40px;
    font-size: 0.9rem;
}

.boab-togo-filter-chips .mud-chip .mud-chip-close-button {
    min-width: 32px;
    min-height: 32px;
}

.boab-togo-filter-pick {
    min-height: 44px;
    max-width: 100%;
    flex: 1 1 15rem;
}

.boab-togo-filter-clear { min-height: 44px; }

.boab-togo-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.boab-togo-modes .mud-button { min-height: 44px; }

/* copy list box (the readonly-textarea reveal — reliable, no external libs) */
.boab-togo-copybox {
    margin-bottom: 0.85rem;
    padding: 0.6rem;
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-border);
    border-radius: var(--sheet-write-radius);
    background-color: var(--boab-panel-tint);
}

.boab-togo-copystatus {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.85rem;
    margin-bottom: 0.4rem;
    color: var(--boab-panel-muted);
}

.boab-togo-copytext {
    width: 100%;
    resize: vertical;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.82rem;
    line-height: 1.4;
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-border);
    border-radius: var(--sheet-write-radius);
    padding: 0.5rem;
    background-color: var(--boab-panel-bg);
    color: var(--boab-panel-ink);
}

/* the grouped named list — the point (§8) */
.boab-togo-group { margin-bottom: 1rem; }
.boab-togo-group:last-child { margin-bottom: 0; }

.boab-togo-group-head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.4rem 0.15rem;
    text-decoration: none;
    color: var(--boab-panel-ink);
    border-bottom: var(--sheet-inner-rule-w) solid var(--boab-panel-rule);
    min-height: 44px;
}

.boab-togo-group-head:hover { text-decoration: none; }
.boab-togo-group-head:hover .boab-togo-group-title { text-decoration: underline; }

.boab-togo-group-title {
    font-weight: 700;
    color: var(--mud-palette-primary);
    overflow-wrap: anywhere;
}

.boab-togo-group-count {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    color: var(--boab-panel-muted);
    font-weight: 600;
}

/* Pivot-style CLICK-THROUGH drill (owner ruling 2026-07-07): a group header now DESCENDS into that
   group (URL updates, breadcrumb climbs back) instead of expanding in place. A drillable header reads
   as a button; a static header (a drill leaf, or a residual "(no area)" / "(no work code)" bucket that
   can't descend) keeps the layout but does not masquerade as a link. */
.boab-togo-group-head.boab-togo-drillhead { cursor: pointer; }
.boab-togo-group-head.boab-togo-group-static { cursor: default; }
.boab-togo-group-static .boab-togo-group-title { color: var(--boab-panel-ink); font-weight: 600; }
.boab-togo-group-static:hover .boab-togo-group-title { text-decoration: none; }

/* The secondary "open in Performance" cross-link on a drill card — subtle, and it stops the click
   from also triggering the descend (pivot cross-links keep working, plan §3). */
.boab-togo-group-pivot {
    display: inline-flex;
    align-items: center;
    color: var(--boab-panel-muted);
    margin-left: 0.15rem;
}
.boab-togo-group-pivot:hover { color: var(--mud-palette-primary); }

/* C3 / C1: coarse-pointer touch floor for the tracker leaf surface. The drill head is already ≥44px
   (.boab-togo-group-head). Give the small "open in Performance" icon link a centred 44px hit area so
   it is a real target sitting inside the head (it already stops propagation), and float every leaf
   action button up to 44px. Pseudo-element hit-expansion — no layout shift, no markup change. */
@media (pointer: coarse) {
    .boab-togo-group-pivot { position: relative; }

    .boab-togo-group-pivot::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        width: 44px;
        height: 44px;
        transform: translate(-50%, -50%);
        z-index: 1;
    }

    .boab-togo-rowwrap .btn,
    .boab-togo-rowwrap button {
        min-height: 44px;
    }
}

/* Per-work-code sections inside an area group — the plan picker's collapsible heading, reused so a
   long works-remaining area breaks into per-work-code sections (owner ruling 2026-07-07). The heading
   is a BUTTON (toggles expand in place, never navigates — unlike the area <a> above it): reset the
   native chrome and indent it a shade under its area. A subtler, non-link title keeps the blue area
   header the one that reads as a link. */
.boab-togo-subgroup { margin-top: 0.15rem; }

.boab-togo-subhead {
    width: 100%;
    background: none;
    border: 0;
    border-bottom: var(--sheet-inner-rule-w) solid var(--boab-panel-rule);
    cursor: pointer;
    text-align: left;
    padding-left: 0.5rem;
    background-color: color-mix(in srgb, var(--boab-panel-tint) 40%, transparent);
}

.boab-togo-subhead .boab-togo-group-title {
    color: var(--boab-panel-ink);
    font-weight: 600;
}

.boab-togo-subhead:hover .boab-togo-group-title { text-decoration: underline; }

.boab-togo-rows {
    display: flex;
    flex-direction: column;
}

/* Each row is a flex LINE: the clickable asset link (grows) + an always-visible Claim button
   (Lane C). The separator + hover tint sit on the wrapper so they span the whole line; on a
   narrow phone the button drops below the link (flex-wrap) while staying a ≥44px touch target. */
.boab-togo-rowwrap {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.5rem;
    border-bottom: max(1px, var(--sheet-stroke)) solid var(--boab-panel-tint);
}

.boab-togo-rowwrap:hover { background-color: var(--boab-panel-tint); }

.boab-togo-row {
    display: flex;
    flex: 1 1 12rem;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.3rem;
    padding: 0.5rem 0.15rem;
    text-decoration: none;
    color: var(--boab-panel-ink);
    min-height: 44px;
}

.boab-togo-row:hover { text-decoration: none; }

/* Always-visible, phone-first (≥44px) inline Claim CTA — no hover dependence. */
.boab-togo-row-claim {
    flex: 0 0 auto;
    min-height: 44px;
    white-space: nowrap;
    align-self: center;
}

/* C1: the host's leaf actions grouped into one flex line (web: add-to-plan + inline Claim; field:
   the Capture deep-link). At ≥40rem it sits inline after the row link; on a phone the whole rowwrap
   goes two-line (media query below) and this becomes the right-aligned second line. */
.boab-togo-rowactions {
    display: flex;
    flex: 0 0 auto;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.5rem;
}

/* C1: phone (<40rem) — restructure a leaf row to two lines: identity + hours on line 1 (the row link
   stretches full width), the actions right-aligned on line 2. Pure CSS on .boab-togo-rowwrap — the
   LeafAction markup contract is unchanged. Reset the row's row-axis 12rem basis so, as a column-flex
   item, it takes natural height instead of growing to a 12rem-tall block. Also covers the
   AssetRemainingPanel rows, which share .boab-togo-rowwrap with an unwrapped action child. */
@media (max-width: 40rem) {
    .boab-togo-rowwrap {
        flex-direction: column;
        align-items: stretch;
        gap: 0.15rem;
    }

    .boab-togo-rowwrap > .boab-togo-row {
        flex: 0 0 auto;
        width: 100%;
    }

    .boab-togo-rowwrap > :not(.boab-togo-row) {
        align-self: flex-end;
        padding-bottom: 0.35rem;
    }

    .boab-togo-rowactions {
        justify-content: flex-end;
    }
}

.boab-togo-row-primary {
    font-weight: 600;
    color: var(--mud-palette-primary);
    overflow-wrap: anywhere;
}

/* C2: long asset ids (MCC4101BTB001 / TV4102_ET2) wrap instead of shattering the row layout. */
.boab-togo-row-part { color: var(--boab-panel-ink); overflow-wrap: anywhere; }
.boab-togo-sep { color: var(--boab-panel-muted); }

.boab-togo-row-hrs {
    margin-left: auto;
    font-size: 0.82rem;
    color: var(--boab-panel-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* new-tracker form: a compact single-column stack (no dialog hop) */
.boab-togo-form {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 34rem;
}

.boab-togo-form-actions {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

/* ===========================================================================
   S2 SCOPE PAGES (spinup-scope-plan §4) — the variation register, the asset
   browser detail, and the reworked asset timeline. Palette-routed (mud tokens +
   the --boab-panel-* indirection) so light/dark both read as one system.
   GLOBAL on purpose: these classes sit on MudPaper roots / the shared
   ScopeTimeline component, where a scoped .razor.css attribute never matches
   (same reasoning as .boab-panel above).
   =========================================================================== */

/* Clickable master-detail rows (variation register + asset list). */
.boab-clickable:hover { background-color: var(--boab-panel-tint); }

/* Detail-pane empty state (mirrors ReportingAreas' — kept here since that one is
   scoped to its page and can never match a scope page's markup). */
.boab-scope-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 1.75rem 1rem;
    color: var(--mud-palette-text-secondary);
}

/* Inline checkbox label (by-others flags, installed-by-others). */
.boab-check {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    cursor: pointer;
    user-select: none;
}
.boab-check input { accent-color: var(--mud-palette-primary); }

/* Variation picker + scope forms — quiet grouping. */
.boab-varpick .boab-micro-label { display: block; margin-bottom: 0.25rem; }
.boab-varpick-select { max-width: 26rem; }
.boab-varpick-new { background-color: var(--boab-panel-tint); }
.boab-scope-form { background-color: var(--boab-panel-bg); }

/* Guarded destructive (Cancel scope) panel — a red left accent, no alarm fill. */
.boab-danger-panel { border-left: 4px solid var(--mud-palette-error); }

/* Resolved current-design grid — chunked label/value cells. */
.boab-design-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0.5rem 1.25rem;
}
.boab-design-cell { min-width: 0; }
.boab-design-label {
    font-size: var(--sheet-fs-label);
    font-weight: 600;
    letter-spacing: var(--sheet-track-label);
    text-transform: uppercase;
    color: var(--boab-panel-label);
    line-height: 1.2;
}
.boab-design-value {
    color: var(--boab-panel-ink);
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
   ScopeTimeline — a chunked, scannable vertical stream with a kind-coloured
   icon rail. Reused by /scope/assets and /assets/{id}.
   --------------------------------------------------------------------------- */
.boab-timeline { display: flex; flex-direction: column; }

.boab-timeline-item { display: flex; gap: 0.75rem; }

/* The rail: a centred connector line behind the dot. */
.boab-timeline-rail {
    position: relative;
    flex: 0 0 1.75rem;
    display: flex;
    justify-content: center;
}
.boab-timeline-rail::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--boab-panel-rule);
}
.boab-timeline-item:first-child .boab-timeline-rail::before { top: 0.9rem; }
.boab-timeline-item:last-child .boab-timeline-rail::before { bottom: calc(100% - 1.6rem); }

.boab-timeline-dot {
    position: relative;
    z-index: 1;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    background: var(--mud-palette-primary);
    margin-top: 0.15rem;
}
.boab-timeline-dot .mud-icon-root { font-size: 1rem; }
.boab-timeline-dot--primary   { background: var(--mud-palette-primary); }
.boab-timeline-dot--info      { background: var(--mud-palette-info); }
.boab-timeline-dot--warning   { background: var(--mud-palette-warning); }
.boab-timeline-dot--success   { background: var(--mud-palette-success); }
.boab-timeline-dot--secondary { background: var(--mud-palette-secondary); }
.boab-timeline-dot--note      { background: var(--mud-palette-tertiary); }
.boab-timeline-dot--default   { background: var(--boab-powder); color: var(--boab-ink); }

.boab-timeline-card {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.35rem 0 0.85rem;
}
.boab-timeline-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.boab-timeline-title { font-weight: 600; color: var(--boab-panel-ink); }
.boab-timeline-date {
    margin-left: auto;
    font-size: 0.8rem;
    color: var(--boab-panel-label);
    white-space: nowrap;
}
.boab-timeline-detail {
    margin-top: 0.15rem;
    color: var(--boab-panel-ink);
    overflow-wrap: anywhere;
}
.boab-timeline-meta {
    margin-top: 0.25rem;
    display: flex;
    align-items: center;
    gap: 0.9rem;
    flex-wrap: wrap;
    font-size: 0.82rem;
}
.boab-timeline-actor {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--boab-panel-label);
}
.boab-timeline-actor .mud-icon-root { font-size: 0.95rem; }
.boab-timeline-doc {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--mud-palette-primary);
    text-decoration: none;
}
.boab-timeline-doc:hover { text-decoration: underline; }
.boab-timeline-doc .mud-icon-root { font-size: 0.95rem; }

/* Claim-photo thumbnail strip on a Submission event — chunked + scannable; each chip opens the
   full image in a new tab (the InternalOnly attachment endpoint 302s to a read-only SAS). */
.boab-timeline-photos {
    margin-top: 0.4rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.boab-timeline-photo {
    display: block;
    width: 3.25rem;
    height: 3.25rem;
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--boab-hairline, rgba(0, 0, 0, 0.12));
    background: var(--boab-powder, #eef2f6);
    line-height: 0;
}
.boab-timeline-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.boab-timeline-photo:hover { border-color: var(--mud-palette-primary); }

/* ===========================================================================
   MOBILE FIELD HARDENING (feat/mobile-field-hardening) — the supervisor field
   loop on a phone: /plan, the de novo claim dialog, and the claim photo attach.
   Doctrine: gloved-thumb targets ≥44px, ≥16px input text (kills iOS focus-zoom),
   no hover dependence, nothing here restyles the wider app.
   =========================================================================== */

/* ── Bootstrap alignment SHIM for the field head (no Bootstrap loaded there) ───
   The shared RCL views (DailyPlanView etc.) are authored with Bootstrap utility
   class names. MudBlazor supplies most of them (d-flex, gap-*, flex-wrap, m*-*,
   ms-auto, align-center, justify-space-between), so those resolve on BOTH heads —
   but NOT Bootstrap's `align-items-*` / `justify-content-*` spellings, which the
   field head (MudBlazor + this file only; index.html loads no Bootstrap) lacks.
   That silently no-ops the /plan day-bar centering, so the date text between the
   prev/next steppers sat ABOVE the buttons' centerline on the device. Alias the
   two alignment names the shared views use. On the WEB these merely duplicate
   Bootstrap's own identical (and !important) declarations — Bootstrap wins, so the
   computed layout is unchanged. */
.align-items-center { align-items: center; }
.justify-content-between { justify-content: space-between; }

/* ── Required-field red star, SHARED by both heads (owner: standardise the star) ─
   The web marks a required field with a red CSS star via a COMPONENT-SCOPED rule
   (SectionLayoutEntry.razor.css: `.boab-field.boab-required ::deep
   .mud-input-label::after`) that never reaches the field head. This is the shared
   equivalent both heads load: a `.boab-required` ancestor stars its Mud input's
   floating label, and `.boab-req-star` colours a plain (non-Mud) literal `*`. The
   star is CSS, NEVER a literal " *" folded into a Mud label string. No double-star
   on the web: `::after` is ONE pseudo-element per label, so a web field matching
   BOTH the scoped rule and this one still paints a single star (identical content
   + colour). */
.boab-required .mud-input-label::after {
    content: " *";
    color: var(--mud-palette-error);
}

.boab-req-star {
    color: var(--mud-palette-error);
}

/* ── /plan — the whole page rides inside .boab-plan ────────────────────────── */

/* Sticky day bar: pinned under the fixed DENSE app bar (MudBlazor dense toolbar
   height = --mud-appbar-height − ¼, i.e. 0.75 × the themed 64px). The canvas
   token backs it so the tick list scrolls away cleanly in light AND dark. */
.boab-plan-daybar {
    position: sticky;
    top: calc(var(--mud-appbar-height, 64px) * 0.75);
    z-index: 10;
    background-color: var(--boab-canvas);
    padding: 0.35rem 0;
}

/* Field touch targets: every Mud button/icon-button on the plan page clears 44px
   (day stepper chevrons, "today", copy list, carry-over, untick ✕, All areas).
   Chip close buttons are excluded — 44px would balloon the breadcrumb chips
   (they keep the 32px tracker-chip minimum set on .boab-togo-filter-chips). */
.boab-plan .mud-icon-button:not(.mud-chip-close-button) {
    min-width: 44px;
    min-height: 44px;
}

.boab-plan .mud-button {
    min-height: 44px;
}

/* Sunlight-legible tick list: the row identity reads at 1rem (16px) on the plan
   page — outdoors trumps density here (the shared tracker keeps its own scale). */
.boab-plan .boab-togo-row-primary,
.boab-plan .boab-togo-row-part {
    font-size: 1rem;
}

.boab-plan .boab-togo-row-hrs {
    font-size: 0.9rem;
}

/* ── /plan dense rows (plan redesign 2026-07-06) ─────────────────────────────
   The owner's review: "huge amount of space under each list item … no indication
   of hover". Root cause: the shared .boab-togo-row carries `flex: 1 1 12rem`
   (a WIDTH basis for the row-flex .boab-togo-rowwrap context) — /plan rendered
   drill/tick rows as DIRECT children of the COLUMN-flex .boab-togo-rows, where
   that basis becomes ~192px of HEIGHT per row. These classes replace that usage
   on /plan only (the tracker pages wrap rows correctly and are untouched):
   44px-min rows (PR #140 gloved-thumb floor), hairline rules, hover + active
   tint on the whole line, tabular numerals right-aligned. */
.boab-plan-rows {
    display: flex;
    flex-direction: column;
}

/* one visual line: the row control (grows) + an optional "+ all N" button */
.boab-plan-rowwrap {
    display: flex;
    align-items: center;
    gap: 0.3rem 0.5rem;
    border-bottom: max(1px, var(--sheet-stroke)) solid var(--boab-panel-tint);
}

.boab-plan-rowwrap:hover { background-color: var(--boab-panel-tint); }

/* the release row to the whole project — visually set off from the pinned areas */
.boab-plan-rowwrap--else {
    margin-top: 0.35rem;
    border-top: var(--sheet-inner-rule-w) solid var(--boab-panel-rule);
}

/* the row itself — an <a> (drill) or a <button> (tick / group head); the button
   reset keeps both reading identically */
.boab-plan-row {
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem;
    min-height: 44px;
    padding: 0.15rem 0.25rem;
    border: 0;
    background: transparent;
    text-align: left;
    text-decoration: none;
    color: var(--boab-panel-ink);
    font-size: 1rem;             /* sunlight floor (PR #140) — density comes from height, not type */
    cursor: pointer;
}

.boab-plan-row:hover,
.boab-plan-row:focus-visible { text-decoration: none; background-color: var(--boab-panel-tint); }
.boab-plan-row:active { background-color: var(--boab-panel-tint); }

/* a bare tick row (not inside a rowwrap) still needs its own hairline */
.boab-plan-row--tick { border-bottom: max(1px, var(--sheet-stroke)) solid var(--boab-panel-tint); }
.boab-plan-row--tick.is-on .boab-plan-row-primary { color: var(--mud-palette-primary); }

.boab-plan-row-primary {
    font-weight: 600;
    color: var(--mud-palette-primary);
    overflow-wrap: anywhere;
}

.boab-plan-row-part { color: var(--boab-panel-ink); }
.boab-plan-sep { color: var(--boab-panel-muted); }
.boab-plan-drillic { color: var(--boab-panel-muted); }

/* right-hand measures: count + to-go hours, tabular, never wrapping */
.boab-plan-row-meta {
    margin-left: auto;
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.boab-plan-row-count {
    font-size: 0.82rem;
    color: var(--boab-panel-muted);
}

.boab-plan-row-hrs {
    font-size: 0.9rem;
    color: var(--boab-panel-muted);
}

/* "+ all N" — the node-grain add; a thumbable inline button that never triggers the drill */
.boab-plan-addall {
    flex: 0 0 auto;
    min-height: 44px;
    white-space: nowrap;
    align-self: center;
}

/* the quiet everything-here-is-planned mark (replaces the button, not a control) */
.boab-plan-allon {
    flex: 0 0 auto;
    align-self: center;
    font-size: 0.82rem;
    color: var(--boab-panel-muted);
    white-space: nowrap;
    padding: 0 0.4rem;
}

/* group heads sit a shade above their leaf rows */
.boab-plan-grouphead { background-color: color-mix(in srgb, var(--boab-panel-tint) 45%, transparent); }

/* the quick filter over the terminal lists — ≥16px kills the iOS focus-zoom */
.boab-plan-filter {
    width: 100%;
    min-height: 44px;
    font-size: 1rem;
    padding: 0.25rem 0.6rem;
    margin-bottom: 0.35rem;
    border: max(1px, var(--sheet-stroke)) solid var(--boab-panel-rule);
    border-radius: 0.35rem;
    background-color: var(--boab-panel-bg);
    color: var(--boab-panel-ink);
}

/* the background-save whisper in the plan caption — informative, never alarming */
.boab-plan-saving {
    font-size: 0.8rem;
    color: var(--boab-panel-muted);
    font-style: italic;
    margin-left: 0.25rem;
}

/* ── De novo claim dialog (.boab-denovo on the MudDialog) ──────────────────── */

/* The asset search: ≥44px tall and ≥16px type — below 16px, iOS Safari auto-zooms
   the page on focus and the supervisor has to pinch back out after every search. */
.boab-denovo .boab-denovo-search {
    min-height: 44px;
    font-size: 1rem;
}

/* Result rows + the prefilled-chip "change" affordance: full touch height. */
.boab-denovo .list-group-item {
    min-height: 44px;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.boab-denovo .boab-denovo-change {
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
}

/* Cancel / Start claim: thumb-size on the fullscreen phone dialog. */
.boab-denovo .mud-dialog-actions .mud-button-root {
    min-height: 44px;
}

/* ── Claim photo attach (ClaimEntryForm) ───────────────────────────────────── */

/* "Take photo" / "Add photos" + each row's remove affordance clear 44px. */
.boab-photo-actions .mud-button-root {
    min-height: 44px;
}

.boab-photo-remove {
    min-height: 44px;
    min-width: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
