﻿/* Phone-first records surface, on paper. Deliberately small — this client shares nothing with the
   manager console's design system.

   COLOUR RULE: every colour in this sheet resolves through a custom property declared once below.
   There is ONE palette — the app is pinned to a single light theme (HQU-280) — so a colour literal
   in a rule outside the palette block is a value that can never be re-pointed. Don't add one. */

/* ── Webfonts ──────────────────────────────────────────────────────────────
   Public Sans (body) and Archivo (display), self-hosted beside this sheet at
   _content/Hque.Aspire.Records.UI/fonts/. Declared HERE rather than left to the
   host page because this RCL is rendered by two apps: the standalone records
   PWA, which loads nothing but this stylesheet, and the portal, which has its
   own identical copy. Same family names, so in the portal the browser matches
   one @font-face and downloads one file — the duplicate declaration costs
   bytes on disk, not on the wire.

   Both are VARIABLE fonts: one file per family per subset covers 400–700. */
@font-face {
    font-family: 'Archivo';
    font-style: normal; font-weight: 400 700; font-display: swap;
    src: url('../fonts/archivo-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Archivo';
    font-style: normal; font-weight: 400 700; font-display: swap;
    src: url('../fonts/archivo-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Public Sans';
    font-style: normal; font-weight: 400 700; font-display: swap;
    src: url('../fonts/publicsans-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Public Sans';
    font-style: normal; font-weight: 400 700; font-display: swap;
    src: url('../fonts/publicsans-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    /* Surfaces */
    /* Warm paper, a shade off the portal's green --canvas-authoring: the records surface has its
       own ground so it is told apart from authoring at a glance. Matches --canvas-records in the
       portal's hque-tokens.css — the PWA loads no other sheet, so the value is repeated here.
       NOTE the standalone PWA does NOT yet take the per-organisation override (HQU-749): it boots
       on a device/PIN staff session rather than the portal's org claim, so there is no org to read
       colours from at paint time. The portal's own records surface does honour it. */
    --rec-bg: #f5f3ee;
    --rec-surface: #fff;
    --rec-raised: #f7f9f7;          /* run rows, pick entries, tiles */
    --rec-sunken: #e9edea;          /* statements, notes */
    --rec-hover: #e9edea;
    --rec-row-hover: #e9edea;
    --rec-shadow: rgba(22, 33, 29, 0.10);

    /* Ink */
    --rec-text: #16211d;
    --rec-body: #33443c;
    --rec-muted: #47574f;
    /* One step darker than the portal's --fg-subtle (#627268, HQU-1394): that value clears 4.5:1 on
       white and paper but measures 4.31 on the row-hover / sunken grey and 4.2 on --rec-accent-soft —
       the segmented filter's counts, hovered rows, a highlighted picker option. #5b6b61 measures 4.78
       and 4.64 there (5.65 on white) and stays a tier lighter than --rec-muted. */
    --rec-faint: #5b6b61;

    /* Lines */
    --rec-border: #d3dad5;
    --rec-border-soft: #e4e9e5;
    --rec-edge: #bcc7c0;            /* the 4px left edge on a card row */

    /* Accents */
    --rec-accent: #16211d;
    --rec-accent-hover: #0b120f;    /* the ink primary button, pressed */
    --rec-accent-soft: #e5eae7;
    --rec-accent-dim: #e4e9e5;
    --rec-link: #2563eb;
    --rec-danger: #a31212;
    --rec-danger-edge: #a31212;
    --rec-danger-surface: #fbe4e2;
    --rec-danger-border: #eec3bf;

    /* Run-status pills (RecordRunTone → tone-*) — the RECORD-lifecycle axis.
       Earth-and-safety, and deliberately NOT blue: blue belongs to the screen-mode
       axis below, and a glance at the colour has to say which of the two questions
       you are looking at the answer to (HQU-296). "Active" was #1d4ed8 blue, which
       put a lifecycle state in mode's colour; it is now the mockup's amber. */
    --rec-tone-neutral-bg: #e5eae7;  --rec-tone-neutral-fg: #55665f;
    --rec-tone-active-bg: #fce9dd;   --rec-tone-active-fg: #a93b08;
    --rec-tone-positive-bg: #dcebe1; --rec-tone-positive-fg: #12603b;
    --rec-tone-warning-bg: #fbe4e2;  --rec-tone-warning-fg: #a31212;
    --rec-tone-muted-bg: #e9edea;    --rec-tone-muted-fg: #5b6b61;

    /* Verdict banner (StatusTone → tone-*) */
    --rec-v-success-bg: #dcebe1; --rec-v-success-bd: #bcd6c6; --rec-v-success-fg: #12603b;
    --rec-v-danger-bg: #fbe4e2;  --rec-v-danger-bd: #eec3bf;  --rec-v-danger-fg: #a31212;
    --rec-v-warning-bg: #fff6de; --rec-v-warning-bd: #e8d08a; --rec-v-warning-fg: #6b4a00;
    --rec-v-neutral-bg: #f1f4f1; --rec-v-neutral-bd: #e4e9e5; --rec-v-neutral-fg: #47574f;

    /* Status dots (StatusTone → tone-*) — also the record axis, so Info moves off
       blue for the same reason the Active pill did. Teal, not slate: it still has
       to separate from the neutral dot beside it. */
    --rec-dot-success: #12603b;
    --rec-dot-danger: #a31212;
    --rec-dot-warning: #a93b08;
    --rec-dot-info: #0e5a66;
    --rec-dot-neutral: #627268;

    /* ── Screen mode — the SECOND axis (HQU-296) ────────────────────────────────
       What YOU are doing: View → Edit → Saving → Saved → View. Ink blue, and no
       status, tone, pill, dot or verdict may borrow it — that exclusivity is the
       whole mechanism, because it lets the colour alone report the mode without
       the reader hunting for a label.

       Not to be confused with --rec-accent/--rec-link, which are chrome and links
       rather than either axis. Those stay where they are; the wider repalette of
       this surface against the shell mockups belongs to the parent epic. */
    --rec-mode: #27348f;             /* Edit — band, save-bar rule, primary button */
    --rec-mode-strong: #1b2668;      /* Saving — one step deeper, so the step reads */
    --rec-mode-soft: #e5e8f6;        /* tinted field backgrounds while editing */
    --rec-mode-on: #fff;
    /* Saved resolves green rather than ink blue. It is the one deliberate exception
       and it comes from the spec screen: a confirmation that reads as anything but
       "done" gets misread, and the band is gone moments later either way. */
    --rec-mode-saved: #12603b;
    --rec-mode-saved-soft: #dcebe1;

    /* Type. Same pairing as the portal: Public Sans for running text,
       Archivo for the few pieces of display type. The fallbacks matter more
       here than in the portal — this surface is used on a phone in the field,
       where the font may not have arrived yet. */
    --rec-font-body: 'Public Sans', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --rec-font-display: 'Archivo', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

    /* Minimum tap target. Declared here because the PWA loads no other stylesheet; in the portal the
       identical --tap-min already exists and the two agree. */
    --rec-tap: 46px;
}

html, body {
    margin: 0;
    font-family: var(--rec-font-body);
    background: var(--rec-bg);
    min-height: 100vh;
}

/* The PWA shell. COLUMN, not row: a screen is free to emit more than one top-level
   element (the run wizard emits its stepper AND the step's card) and they must STACK.
   As a row they became sibling flex items sitting side by side, which squeezed the
   stepper into a narrow column beside the run card — the Portal, whose own layout
   wraps pages in a normal block, never showed the fault. */
.record-shell {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: center;
    min-height: 100vh;
    padding: 24px 16px;
}

/* Focus mode: the capture screen IS the shell. Drop the centring gutter and the padding so
   the sticky header and foot sit on the viewport edges, exactly as they do on the portal. */
.record-shell--focus {
    align-items: stretch;
    padding: 0;
}

/* ── The tile, and the page ─────────────────────────────────────────────────
   .record-card is the centered single-message TILE, and now nothing else: the name/PIN sign-in, the
   session splash, enrolment, device management, the one-time PIN reveal — a message that owns an
   otherwise empty screen, in the PWA only.

   It is deliberately NOT what a screen renders on. A page-sized rounded white slab behind the whole
   screen is a shape the shell mockups do not have (mockups/venuehq-shell run-detail-view.html): a
   screen there is a head, then sections, and each SECTION carries the surface. HQU-428 moved four
   screens onto that paper; the rest followed, so no page-sized card is left on this surface in
   either host. The rules below give the screens on paper the box the page card used to provide:
   .record-page .record-state for the non-list outcomes, .record-page .record-panel for the titled
   sections that hang off a body. */

.record-card {
    width: 100%;
    max-width: 420px;
    background: var(--rec-surface);
    border-radius: 16px;
    box-shadow: 0 2px 16px var(--rec-shadow);
    padding: 32px 24px;
    margin-top: 8vh;
    text-align: center;
}

/* The screen on paper. Same column as .record-screen, and for the same reason: the portal host
   widened .rec-page to --page-max (1200px) so records share the authoring surface's working area,
   while the PWA's .record-shell is a centred flex column that caps nothing. So the cap lives on the
   screen and follows the host: --page-max in the portal, the 940px fallback where that token isn't
   defined (the Staff PWA), which on a phone never bites anyway.

   The two names are now the same thing wearing two words — .record-page is what a screen wraps
   itself in, .record-screen what RecordScreenHead's own screens carried — and collapsing them is a
   tidy-up for whoever touches this next, not a change of shape. */
.record-page {
    width: 100%;
    max-width: var(--page-max, 940px);
    text-align: left;
}

/* The TILE's heading, and the headline of a state block — centred, because both of those are
   centred things. A SCREEN's title is not one of them: it is .record-head-title, left-aligned on
   paper, and RecordScreenHead is the only thing that draws it. */
.record-title {
    font-family: var(--rec-font-display);
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: -0.012em;
    margin: 8px 0 12px;
    text-align: center;
    color: var(--rec-text);
}

/* The icon-only twin of .record-btn: same border, same surface, same tap height, square rather
   than label-wide. A back affordance is a CONTROL like every other one on this surface, so it wears
   the surface's control shape — a bare glyph at Size.Small read as a stray icon beside a page title
   rather than as the button it is. Worn by RecordScreenHead's optional back button, which is the
   surface's one remaining back affordance now that every screen is on paper. */
.record-icon-btn.mud-icon-button {
    width: var(--rec-tap);
    height: var(--rec-tap);
    padding: 0;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    color: var(--rec-text);
}

.record-icon-btn.mud-icon-button:hover { background: var(--rec-hover); }

/* The favourite star after a record's title (HQU-839, HQU-1452). A secondary thing, so a small bare
   glyph rather than the bordered .record-icon-btn: faint until pointed at; starred it takes the amber
   verdict family — the same "attention" amber the management surface's star wears. */
.record-star-btn.mud-icon-button {
    width: 32px;
    height: 32px;
    padding: 0;
    border-radius: 6px;
    color: var(--rec-faint);
}
.record-star-btn.mud-icon-button:hover { background: var(--rec-hover); color: var(--rec-text); }
.record-star-btn.mud-icon-button .mud-icon-root { font-size: 20px; width: 20px; height: 20px; }
.record-star-btn.is-starred.mud-icon-button,
.record-star-btn.is-starred.mud-icon-button:hover { color: var(--rec-v-warning-fg); }

/* A screen head's actions as one split control (RecordActionButton, HQU-1419): the main action is
   an icon in the .record-icon-btn square, and a caret beside it opens the rest. One bordered box for
   both halves, so it reads as one control beside the star and the QR rather than two more buttons.
   Alone (no caret) it is exactly the .record-icon-btn square. */
.record-split {
    position: relative;
    display: inline-flex;
    align-items: stretch;
    box-sizing: border-box;
    height: var(--rec-tap);
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
}

.record-split-main,
.record-split-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--rec-text);
    font: inherit;
    text-decoration: none;
    cursor: pointer;
}

.record-split-main {
    width: calc(var(--rec-tap) - 2px);
    border-radius: 5px;
}

.record-split.has-more .record-split-main { border-radius: 5px 0 0 5px; }

.record-split-more {
    width: 26px;
    border-left: 1px solid var(--rec-border);
    border-radius: 0 5px 5px 0;
    color: var(--rec-muted);
}

.record-split-main:hover,
.record-split-more:hover,
.record-split-more[aria-expanded="true"] { background: var(--rec-hover); text-decoration: none; }

.record-split-main:focus-visible,
.record-split-more:focus-visible {
    outline: 2px solid var(--rec-accent);
    outline-offset: -2px;
}

.record-split-main .mud-icon-root { width: 24px; height: 24px; font-size: 24px; }
.record-split-more .mud-icon-root { width: 20px; height: 20px; font-size: 20px; }

/* The menu — the breadcrumb's workspace menu (.crumb-select-menu in the portal's components.css)
   in this sheet's tokens, so the PWA, which loads no portal CSS, gets the same thing. Anchored to the
   control's RIGHT edge (it sits at the head's trailing edge) and dropped downward, inside the clipped
   shell. */
.record-split-scrim {
    position: fixed;
    inset: 0;
    z-index: 1290;
    background: transparent;
}

.record-split-menu {
    position: absolute;
    z-index: 1300;
    top: calc(100% + 6px);
    right: -1px;
    min-width: 220px;
    max-width: min(320px, calc(100vw - 32px));
    padding: 6px;
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    background: var(--rec-surface);
    box-shadow: 0 6px 18px var(--rec-shadow);
}

.record-split-item {
    display: flex;
    align-items: center;
    /* A UA centres a flex <button>'s content; the rows are left-aligned like the crumb menu's. */
    justify-content: flex-start;
    gap: 10px;
    box-sizing: border-box;
    width: 100%;
    min-height: 38px;
    padding: 8px 10px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--rec-text);
    font-family: var(--rec-font-body);
    font-size: 14px;
    line-height: 1.3;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.record-split-item:hover { background: var(--rec-hover); text-decoration: none; }
.record-split-item:focus-visible { outline: 2px solid var(--rec-accent); outline-offset: -2px; }
.record-split-item.is-main { font-weight: 600; }
.record-split-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.record-split-item .record-split-item-icon {
    width: 18px;
    height: 18px;
    font-size: 18px;
    flex: 0 0 auto;
    color: var(--rec-muted);
}

.record-split-sep {
    height: 1px;
    margin: 5px 6px;
    background: var(--rec-border);
}

/* Filters that outlive the body's loading + error states. */
.record-page-toolbar {
    margin-top: 4px;
    margin-bottom: 8px;
}

/* Loading / error / empty / not-found — every non-list outcome, centered in the card. */
.record-state {
    text-align: center;
    padding: 16px 4px 8px;
}

.record-muted {
    color: var(--rec-muted);
}

.record-hero-icon {
    font-size: 56px !important;
    width: 56px;
    height: 56px;
    color: var(--rec-muted);
}

/* NOTE: .record-pin-reveal is gone. Nothing displays a PIN any more — the staff member
   chooses their own at enrolment and changes it themselves (HQU-742/751), so there is no
   server-generated value to reveal once. Don't reintroduce the rule without reintroducing
   the flow it belonged to. */

/* On-device enrolment at the empty-device gate. Every control is at least the shared
   phone tap target; the camera handoff is prose, not a competing action. */
.record-enrol-entry {
    margin-top: 20px;
    text-align: left;
}

/* Manage device's "Add someone to this device" (HQU-1457) — a sub-section under the list of names. */
.record-device-add-head {
    margin: 24px 0 4px;
    font: 600 16px var(--rec-font-body);
    color: var(--rec-text);
}

.record-enrol-action.mud-button-root {
    min-height: var(--rec-tap);
}

.record-enrol-camera {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-top: 20px;
    padding: 14px;
    border-radius: 10px;
    background: var(--rec-sunken);
    color: var(--rec-body);
    font-size: 0.88rem;
    line-height: 1.5;
    text-align: left;
}

.record-enrol-camera .mud-icon-root {
    flex: none;
    margin-top: 1px;
}

/* Tile grid: tap your name, then enter your PIN. */
.record-tile-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    margin-top: 8px;
}

.record-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 18px 8px;
    border: 1px solid var(--rec-border);
    border-radius: 12px;
    background: var(--rec-raised);
    font: inherit;
    font-weight: 600;
    color: var(--rec-text);
    cursor: pointer;
}

.record-tile:hover {
    background: var(--rec-hover);
    border-color: var(--rec-edge);
}

.record-tile .mud-icon-root {
    font-size: 34px;
    color: var(--rec-muted);
}

/* The commit pad's "Sign as …" (HQU-1432): the signed-in person first, everyone else under a caption. */
.record-tile-you { overflow-wrap: anywhere; }
.record-tile-others {
    margin: 18px 0 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--rec-muted);
}

/* Authenticated chrome: the signed-in top bar (name + sign-out). Rendered only for a
   signed-in principal — the anonymous tile screen has no chrome. */
.record-topbar {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px 8px 16px;
    background: var(--rec-surface);
    border-bottom: 1px solid var(--rec-border);
}

/* A procedure removes every navigation escape, but not its location context. */
.record-topbar--context {
    justify-content: flex-start;
    min-height: 48px;
}

/* Left cluster: the always-available Home affordance, then who's signed in. */
.record-topbar-left {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    flex: 1 1 auto;
}

.record-topbar-home { color: var(--rec-muted); }
.record-topbar-home:hover { color: var(--rec-accent); }

/* Who is signed in. The org's name used to stack under it (HQU-746, removed HQU-1453). */
.record-topbar-who {
    display: inline-flex;
    flex-direction: column;
    min-width: 0;
    flex: 0 1 auto;
    overflow: hidden;
    /* A 50-character name gives way first (HQU-1384): capped, it ellipsises inside rather than
       pushing Sign out off the edge or squeezing the venue chip to one letter. */
    max-width: clamp(96px, 30vw, 320px);
}

.record-topbar-who .record-topbar-name { overflow: hidden; text-overflow: ellipsis; }

.record-topbar-name {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-weight: 600;
    color: var(--rec-text);
    white-space: nowrap;
}

.record-topbar-name > .mud-icon-root { flex: 0 0 auto; }

/* The active-location chip (HQU-1128): always ONE line — a long venue name ("Harbour Bridge Climb —
   North Pylon") truncates with an ellipsis instead of wrapping the bar and overlapping the person. */
.record-topbar-loc {
    display: inline-flex;
    min-width: 72px;                /* keeps a few characters of the venue, never just "Q…" (HQU-1384) */
    max-width: 40vw;
}

.record-topbar-loc .mud-menu,
.record-topbar-loc .mud-menu-activator { min-width: 0; max-width: 100%; }

.record-topbar-loc-btn { min-width: 0; max-width: 100%; text-transform: none; }
.record-topbar-loc-btn .mud-button-label { min-width: 0; white-space: nowrap; }

/* The chip's menu (HQU-1388). Unbounded, the popover sized to its longest venue name and, pinned to
   the chip's left edge, ran off a phone's right edge and made the page scroll sideways. Cap it to the
   screen and let a long name wrap; on a phone pin it to the screen's gutters (MudBlazor positions the
   popover with an inline `left`, hence !important). */
.mud-popover.record-loc-menu, .mud-popover.record-ws-menu {
    max-width: min(420px, calc(100vw - 32px));
    overflow-x: hidden;
}

.record-loc-menu .mud-menu-item, .record-ws-menu .mud-menu-item {
    white-space: normal;
    overflow-wrap: anywhere;
}

/* The workspace menu also opens from the Menu drawer (z-index 1201), over MudBlazor's popover layer
   (1200) — lift it above the drawer or the list opens behind it (HQU-1454). */
.mud-popover.record-ws-menu { z-index: 1210 !important; }

@media (max-width: 720px) {
    .mud-popover.record-loc-menu, .mud-popover.record-ws-menu {
        left: 16px !important;
        width: calc(100vw - 32px);
        max-width: none;
    }
}

.record-topbar-loc-label,
.record-topbar-name-text {
    overflow: hidden;
    min-width: 0;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Enrolled, nobody signed (HQU-757). Deliberately quieter than a name: it is a statement of
   absence, not an identity, and it must not read as "you are signed in as Not signed". */
.record-topbar-name--unsigned {
    font-weight: 500;
    color: var(--rec-muted);
}

/* ── Worklist count pill ──────────────────────────────────────────────────────
   Rides beside a landing-page button's label to show there is work waiting.
   Rendered ONLY for a non-zero count — an empty worklist shows no pill at all. */
.record-count-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    margin-left: 8px;
    border-radius: 999px;
    background: var(--rec-accent);
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

/* Anything overdue turns the pill urgent — same count, louder. */
.record-count-pill.is-overdue { background: var(--rec-v-danger-fg); }

/* ── "Add to home screen" (InstallAppPrompt) ──────────────────────────────────
   Sits under the setup-path content on the enrol and tile screens, ruled off so it
   reads as an aside rather than a step. Absent entirely once the app is installed. */
.record-install {
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--rec-border);
}

.record-install-steps {
    margin: 12px 0 0;
    padding-left: 22px;
    text-align: left;
    font-size: 0.85rem;
    line-height: 1.6;
    color: var(--rec-body);
}

.record-install-note {
    margin: 8px 0 0;
    font-size: 0.8rem;
    color: var(--rec-muted);
}

/* Manage-device row: name + remove control. Its own name: as .record-manage-row it shared the record
   side panel's row class, and its space-between pushed the panel links' labels away from their
   icons (HQU-1395) — and its flex-wrap dropped the ✕ under a long name (HQU-1385). A long name now
   wraps beside its ✕. */
.record-device-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: nowrap;
    gap: 8px;
    width: 100%;
}

.record-device-name { flex: 1 1 0; min-width: 0; overflow-wrap: anywhere; }
.record-device-row > .mud-icon-button { flex: 0 0 auto; }

/* ── Worklist run rows (Scheduled + Requested) ────────────────────────────
   ONE card of rows, per mockups/venuehq-shell runs.html — not a stack of cards. The list owns the
   border box; a run owns only its content and, past due, its left edge. The child selector rather
   than .record-run + .record-run because Scheduled wraps each run in .record-run-item to carry the
   decline editor below it, and both hosts' lists have to divide the same way. */

.record-run-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--rec-surface);
}

.record-run-list > * + * {
    border-top: 1px solid var(--rec-border-soft);
}

.record-run {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 68px;
    padding: 12px 16px;
    /* Reserved rather than drawn: a 4px edge on every row would be noise, but a row that gains one
       when it falls overdue would also shift its text 4px sideways. */
    border-left: 4px solid transparent;
    background: var(--rec-surface);
}

/* Past-due runs get a warm edge so the list scans at a glance. */
.record-run.is-overdue {
    border-left-color: var(--rec-danger-edge);
    background: var(--rec-danger-surface);
}

/* Due soon is deliberately distinct from overdue: a calm accent, never the danger surface. */
.record-run.is-due-soon {
    border-left-color: var(--rec-tone-active-fg);
}

.record-run-body {
    min-width: 0; /* let long names ellipsize instead of pushing the meta column */
    flex: 1 1 auto;
}

/* The body is a tap target (opens a run of this procedure, carrying the instance ref). Reset the
   <button> chrome so it reads as the card body, not a button; subtle hover cue on the title. */
.record-run-open {
    appearance: none;
    border: none;
    background: none;
    margin: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    display: block;
    width: 100%;
}
.record-run-open:hover .record-run-procedure {
    text-decoration: underline;
}

.record-run-procedure {
    font-weight: 600;
    color: var(--rec-text);
    line-height: 1.3;
}

.record-run-subjects {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.record-run-subject {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--rec-hover);
    color: var(--rec-body);
    font-size: 0.8rem;
    font-weight: 500;
}

.record-run-subject.is-empty {
    background: var(--rec-sunken);
    color: var(--rec-body);
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    letter-spacing: 0.02em;
}

.record-run-context {
    margin-top: 7px;
    font-size: 0.78rem;
    color: var(--rec-muted);
}

/* Requested runs only: who asked + their note. Both sit in the body column so the note
   wraps to the body width rather than blowing out the card. */
.record-run-requester {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 8px;
    font-size: 0.8rem;
    color: var(--rec-muted);
}

.record-run-requester-icon {
    font-size: 16px !important;
    width: 16px;
    height: 16px;
}

.record-run-note {
    margin-top: 6px;
    padding: 8px 10px;
    border-radius: 8px;
    background: var(--rec-sunken);
    color: var(--rec-body);
    font-size: 0.82rem;
    line-height: 1.4;
    /* Unknown length, user-authored: preserve the author's newlines, wrap, and break
       even an unbroken string so a long note never overflows the card horizontally. */
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* One line, not a stacked column: on a card of rows the meta reads across the end of its row the way
   the mockup's pill does, and a stack of three made every run three times taller than it needed to
   be. Wraps rather than squeezing when the row is narrow. */
.record-run-meta {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 4px 10px;
    flex: 0 0 auto;
    text-align: right;
}

.record-run-status {
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
}

/* Status tones — semantic, mapped from RecordRunPresentation.RecordRunTone via RecordTone.Class. */
.record-run-status.tone-neutral  { background: var(--rec-tone-neutral-bg);  color: var(--rec-tone-neutral-fg); }
.record-run-status.tone-active   { background: var(--rec-tone-active-bg);   color: var(--rec-tone-active-fg); }
.record-run-status.tone-positive { background: var(--rec-tone-positive-bg); color: var(--rec-tone-positive-fg); }
.record-run-status.tone-warning  { background: var(--rec-tone-warning-bg);  color: var(--rec-tone-warning-fg); }
.record-run-status.tone-muted    { background: var(--rec-tone-muted-bg);    color: var(--rec-tone-muted-fg); }

/* A phone has no room for the meta beside the title: on one line it squeezes the run's NAME down to
   two words to keep a date whole. Stack it back into a column there — the row grows taller, which is
   the cheaper of the two costs. Phone layouts proper are HQU-299. */
@media (max-width: 600px) {
    .record-run {
        align-items: flex-start;
        gap: 10px;
    }
    .record-run-meta {
        flex-direction: column;
        align-items: flex-end;
        gap: 6px;
    }
}

/* An overdue row is painted in the danger surface, which is ALSO tone-warning's pill background — so
   an "Overdue" pill on an overdue row disappears into it and reads as loose red text beside its
   neighbours' pills. Lift it back onto the card's own surface. */
.record-run.is-overdue .record-run-status.tone-warning {
    background: var(--rec-surface);
}

.record-run-due {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 0.78rem;
    color: var(--rec-muted);
    white-space: nowrap;
}

.record-run-due.is-overdue {
    color: var(--rec-danger);
    font-weight: 600;
}

.record-run-due.is-due-soon {
    color: var(--rec-tone-active-fg);
    font-weight: 600;
}

.record-run-due-icon {
    font-size: 15px !important;
    width: 15px;
    height: 15px;
}

/* ── Won't Complete: a wrapper holds the run row + its optional inline reason editor. ──
   The wrapper is the list child, so the row and its editor divide from the NEXT run together
   rather than the editor reading as a row of its own. */
.record-run-item {
    display: flex;
    flex-direction: column;
}

/* The small top-right decline affordance. Muted by default so a worklist of runs
   isn't a wall of red; reddens on hover to signal the destructive intent. */
.record-run-decline-btn,
.record-run-decline-btn .mud-icon-root {
    color: var(--rec-faint) !important;
}
.record-run-decline-btn:hover,
.record-run-decline-btn:hover .mud-icon-root {
    color: var(--rec-danger) !important;
}

.record-run-decline-panel {
    /* Inset to the row's text column (16px padding past the 4px reserved edge), because the row
       itself no longer carries the padding a card used to give it. */
    margin: 0 16px 14px 20px;
    border: 1px solid var(--rec-danger-border);
    border-radius: 10px;
    background: var(--rec-danger-surface);
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.record-run-decline-title {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--rec-danger);
}

.record-run-decline-error {
    font-size: 0.8rem;
    color: var(--rec-danger);
}

.record-run-decline-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* ── Procedure picker (the catalogue screen + the wizard's step 1) ────────── */

/* One card of rows, per mockups/venuehq-shell procedures.html — the same shape the worklists take,
   because a list of procedures and a list of runs are read the same way. The list owns the border
   box; an entry owns only its content. Not NavRow: a procedure's description is user-authored prose
   that wraps to whatever length it is, where a NavRow's supporting line is a single truncating line. */
.record-pick-list {
    display: flex;
    flex-direction: column;
    margin-top: 12px;
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--rec-surface);
}

/* Behaviour groups in the catalogue picker (Procedures / Incidents, HQU-461): the group heading
   is InfoList's own (Boxed=false), so this only spaces one group's list off the previous group. */
.record-pick-group + .record-pick-group {
    margin-top: 20px;
}

.record-pick-entry {
    display: block;
    width: 100%;
    text-align: left;
    font: inherit;
    cursor: pointer;
    min-height: 68px;
    padding: 12px 16px;
    border: 0;
    background: var(--rec-surface);
}

.record-pick-entry + .record-pick-entry {
    border-top: 1px solid var(--rec-border-soft);
}

/* A catalogue entry with its favourite star beside it (HQU-839). The entry keeps its full tap
   target; the star is a tap-sized column on the trailing edge, divided off so it reads as its own
   control rather than as part of the entry. Amber when starred — the item screen's star colour. */
.record-pick-row {
    display: flex;
    align-items: stretch;
}

.record-pick-row + .record-pick-row {
    border-top: 1px solid var(--rec-border-soft);
}

.record-pick-row .record-pick-entry { flex: 1; min-width: 0; }

/* Build's folders in the picker (HQU-1058): the folder is a row with Build's folder glyph, and its
   entries sit indented beneath it so the top-level entries after it never read as inside it. */
.record-pick-folder + *,
* + .record-pick-folder,
.record-pick-folder-head + * {
    border-top: 1px solid var(--rec-border-soft);
}

.record-pick-folder-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    font-weight: 600;
    color: var(--rec-text);
    background: var(--rec-surface);
}

.record-pick-folder-head .record-pick-folder-icon { font-size: 20px; color: var(--rec-v-warning-fg); }

.record-pick-folder .record-pick-entry { padding-left: 46px; }

.record-pick-star {
    flex: none;
    width: calc(var(--rec-tap) + 10px);
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-left: 1px solid var(--rec-border-soft);
    background: var(--rec-surface);
    color: var(--rec-faint);
    cursor: pointer;
}

.record-pick-star:hover { background: var(--rec-row-hover); color: var(--rec-v-warning-fg); }

.record-pick-star.is-starred { color: var(--rec-v-warning-fg); }

.record-pick-entry:hover {
    background: var(--rec-row-hover);
}

.record-pick-entry.is-unavailable,
.record-pick-entry.is-unavailable:hover {
    cursor: not-allowed;
    background: var(--rec-sunken);
}

.record-pick-entry.is-unavailable .record-pick-name,
.record-pick-entry.is-unavailable .record-pick-description {
    color: var(--rec-muted);
}

.record-pick-availability {
    margin-top: 8px;
    font-size: 0.8rem;
    line-height: 1.4;
    font-weight: 600;
    color: var(--rec-body);
    overflow-wrap: anywhere;
}

.record-pick-name {
    font-weight: 600;
    color: var(--rec-text);
    line-height: 1.3;
}

.record-pick-description {
    margin-top: 6px;
    font-size: 0.85rem;
    line-height: 1.4;
    color: var(--rec-body);
    /* User-authored, unknown length: wrap and break so a long description can't overflow. */
    overflow-wrap: anywhere;
}

.record-pick-pager {
    display: flex;
    justify-content: center;
    margin-top: 16px;
}

/* ── Run form + item viewer: fields, sections, statements ─────────────────── */

.record-run-description {
    margin: 4px 0 12px;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--rec-body);
    overflow-wrap: anywhere; /* user-authored, unknown length */
}

/* How many steps this is, read BEFORE starting. It sets the expectation the focus screen's
   progress bar then keeps, which is the point of showing it here rather than only in there. */
.record-run-steps-note {
    margin: 10px 0 0;
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--rec-faint);
}

/* ── The run's opening screen: purpose and guardrails (read-only) ─────────── */

/* Goal / Applies to / Done when ride the standard read rows; the block only needs to sit
   clear of the card header the way the description above it does. */
.record-purpose {
    margin-top: 4px;
}

.record-purpose-block {
    margin-top: 18px;
}

/* One authored line per item. No bullets: these are sentences an operator wrote, not a
   checklist — nothing here is tickable, and it must not look like it is. */
.record-purpose-lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* HQU-526: the lines sit plainly on the group's white card now — no tinted pill, no accent
   edge. The card and its heading carry the block; the surface behind the lines is white to
   match the "Subjects" / "Description" cards on the same screen. */
.record-purpose-lines li {
    color: var(--rec-text);
    font-size: 0.92rem;
    line-height: 1.45;
    overflow-wrap: anywhere; /* user-authored, unknown length */
}

/* The run form's field list. The rows and the group are <InfoRow>/<InfoList> now (see the
   --row-* block at the foot of this sheet), so all that is left here is the offset from the
   block above it. */
.record-form-fields {
    margin-top: 16px;
}

/* The read viewer's value blocks — one per authored step (see RecordItemScreen). Each is an
   <InfoList> and carries its own heading and row separators; this only spaces them, the way the
   mockup's stacked <section>s do. */
.record-value-groups {
    display: grid;
    gap: 20px;
    margin-top: 16px;
}

/* An asset's folded fields (HQU-1114): the "Show all details" toggle and, open, the card it reveals. */
.record-details-more {
    display: grid;
    gap: 12px;
    margin-top: -8px;
}

/* Step instruction/description text under a field's label. */
.record-form-instr {
    font-size: 0.82rem;
    line-height: 1.4;
    color: var(--rec-muted);
    overflow-wrap: anywhere;
}

/* Statement: render-only audit text, no input. */
.record-form-statement {
    padding: 12px 14px;
    border-radius: 10px;
    background: var(--rec-sunken);
    border-left: 3px solid var(--rec-edge);
}

.record-form-statement-label {
    font-weight: 600;
    color: var(--rec-text);
    line-height: 1.35;
}

/* Disabled-with-note for deferred field types (FileUpload / RelatedEntity). */
.record-form-unsupported {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 12px;
    border-radius: 10px;
    background: var(--rec-sunken);
    color: var(--rec-faint);
    font-size: 0.85rem;
    font-style: italic;
}

.record-form-unsupported .mud-icon-root {
    font-size: 18px;
}

/* A file-upload field on the records form (HQU-1153): what is stored, what will upload, and the picker. */
.record-file-field {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
}

.record-file-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
    margin: 0;
    padding: 0;
    list-style: none;
}

.record-file-item {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    padding: 4px 10px;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    font-size: var(--text-sm, 14px);
    color: var(--rec-text);
}

.record-file-item .mud-icon-root { flex: none; font-size: 18px; color: var(--rec-muted); }
.record-file-item.is-pending { border-style: dashed; }
.record-file-item.is-replaced .record-file-name { color: var(--rec-faint); text-decoration: line-through; }

.record-file-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.record-file-note { flex: none; font-size: 0.8rem; color: var(--rec-muted); }

.record-file-remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--rec-muted);
    cursor: pointer;
}

.record-file-remove:hover { background: var(--rec-hover); color: var(--rec-text); }

.record-file-undo {
    flex: none;
    padding: 2px 8px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--rec-text);
    font: inherit;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}

.record-file-undo:hover { background: var(--rec-hover); }

.record-file-pick { position: relative; }
.record-file-pick:focus-within { box-shadow: var(--focus-ring, 0 0 0 2px var(--rec-accent)); }
.record-file-pick.is-busy { opacity: 0.6; cursor: default; }

.record-file-pick .record-file-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: inherit;
    font-size: 0;
}

/* YesNo radios sit in a row on a phone width. */
.record-form-yesno {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 4px;
}

/* ── "Unknown" wants a reason ─────────────────────────────────────────────────
   The box only exists while Unknown is chosen, so it is drawn as a well that hangs
   off that answer rather than as a field that appeared from nowhere: a tinted panel
   with an ink edge on the left, a real label above it, and a white input inside so
   the part you can type in still reads as the part you can type in.

   Quiet, not amber. Same reasoning as .rec-focus-required — "unknown" is a legitimate
   answer, not a mistake, and nothing has gone wrong on this screen yet. The only
   colour in here is the Required pill, and that leaves as soon as it is satisfied. */
.record-form-why {
    margin-top: 10px;
    padding: 12px 14px 14px;
    border: 1px solid var(--rec-border-soft);
    border-left: 3px solid var(--rec-edge);
    border-radius: 8px;
    background: var(--rec-raised);
    animation: record-why-in 140ms ease-out;
}

.record-form-why-label {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    font-size: 14px;
    font-weight: 600;
    color: var(--rec-body);
}

/* Rendered ONLY while the box is empty (see RecordRunScreen), so it is a live piece of
   state, not decoration: it disappearing is the acknowledgement that the rule is met. */
.record-form-why-req {
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--rec-tone-warning-bg);
    color: var(--rec-tone-warning-fg);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

/* The input is the lit surface inside the well — MudBlazor's outlined variant is
   transparent, which on a tinted panel reads as a disabled field. */
.record-form-why .mud-input.mud-input-outlined {
    border-radius: 6px;
    background: var(--rec-surface);
}

.record-form-why .mud-input-control {
    min-height: 0;
}

@keyframes record-why-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .record-form-why { animation: none; }
}

/* Location field (HQU-1474): the coordinates box, then its ways to set a pin, then the satellite picker
   when asked for. The actions wrap on a phone rather than squeezing. */
.record-geo-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
}

.record-geo-note {
    margin: 6px 2px 0;
    font-size: 14px;
}

.record-geo-note--warn {
    color: var(--rec-tone-warning-fg);
}

.record-geo-map {
    height: 320px;
    margin-top: 10px;
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    overflow: hidden;
}

/* DateTime field: the date and time pickers sit side by side, each taking half the row (HQU-257). */
.record-form-datetime-row {
    display: flex;
    gap: 8px;
}

.record-form-datetime-row > * {
    flex: 1 1 0;
    min-width: 0;
}

/* Asset autocomplete option: name over a muted module line. */
.record-asset-option {
    display: flex;
    flex-direction: column;
}

.record-asset-name {
    font-weight: 500;
    color: var(--rec-text);
}

.record-asset-module {
    font-size: 0.76rem;
    color: var(--rec-faint);
}

/* ── Single-item read-only viewer ─────────────────────────────────────────── */

/* The viewer's own meta row is gone — the identifier and the module moved into the page head's
   eyebrow (RecordScreenHead). The separator stays: the activity rows still use it. */
.record-item-sep { opacity: 0.5; }

/* ── The closed record's immutability tag (HQU-297) ───────────────────────────
   A BLOCK, not the small .record-status-tag capsule, and that is the point: it
   occupies the slot an edit control would have taken on an open record, so it has
   to be big enough to be what the eye lands on there. Nothing sits beside it —
   there is no disabled edit button to explain, which is the whole design.

   Lifecycle family, so it borrows the same tone-* palette .record-status-tag uses
   (--rec-tag-*), one axis, one vocabulary. Never blue: blue is screen mode. */
.record-lock {
    margin: 4px 0 14px;
    padding: 14px 16px;
    border-radius: 10px;
    border: 1px solid currentColor;
}

.record-lock-state {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.01em;
}

/* The dashed rule is load-bearing: it separates the state (what this record IS)
   from the attribution and the promise (why there is nothing to press). */
.record-lock-rule {
    height: 0;
    margin: 11px 0 9px;
    border-top: 1px dashed currentColor;
    opacity: 0.35;
}

.record-lock-line {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 0.85rem;
    line-height: 1.45;
    opacity: 0.92;
}

.record-lock.tone-neutral { background: var(--rec-tag-neutral-bg); color: var(--rec-tag-neutral-fg); }
.record-lock.tone-info    { background: var(--rec-tag-info-bg);    color: var(--rec-tag-info-fg); }
.record-lock.tone-warning { background: var(--rec-tag-warning-bg); color: var(--rec-tag-warning-fg); }
.record-lock.tone-success { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); }
.record-lock.tone-danger  { background: var(--rec-tag-danger-bg);  color: var(--rec-tag-danger-fg); }

/* ── The OPEN record's block (RecordInProgressPanel) ──────────────────────────
   The twin of .record-lock and deliberately built on it: same slot, same tone
   palette, same dashed rule between "what this record IS" and the detail under
   it. What differs is the only thing that should — a closed record has nothing
   to press, and an open one has the two things you can do about it.

   Side by side above ~560px, stacked below: on a phone the actions belong under
   the state they act on, and a 50/50 split there gives two buttons too narrow
   to carry their own labels.

   The row itself draws NOTHING — it is the mockup's .recordhead (mockups/venuehq-shell
   run-detail-view.html), a tinted tag beside a column of plain actions, not one tinted box around
   both. The tone belongs to the state, because it is what makes "In progress" read as a status;
   wrapping the buttons in it made the two exits look like part of the status rather than the
   answer to it. So the box lives on .record-open-state. */
.record-open {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    gap: 20px;
    margin: 4px 0 14px;
}

/* The tag: sized by its content, never stretched to half the row. */
.record-open-state {
    flex: 0 0 auto;
    min-width: 264px;
    padding: 14px 16px;
    border-radius: 10px;
    border: 1px solid currentColor;
}

@media (max-width: 559px) {
    .record-open { gap: 14px; }
    .record-open-state,
    .record-open-acts { flex-basis: 100%; min-width: 0; }
    .record-open-acts { max-width: none; }
}

.record-open-status {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.01em;
}

.record-open-rule {
    height: 0;
    margin: 11px 0 9px;
    border-top: 1px dashed currentColor;
    opacity: 0.35;
}

.record-open-line {
    font-size: 0.85rem;
    line-height: 1.45;
    opacity: 0.92;
}

/* The actions take the rest of the row, and stack full-width once it runs out. */
/* A stacked pair of calls-to-action, not a banner: bounded so the two exits read
   as buttons beside the state tag rather than sprawling the full content column.
   The flex-basis floors the width so they never crowd the tag; the max-width caps
   it so "Continue this Procedure" doesn't stretch to 1100px. */
.record-open-acts {
    flex: 1 1 360px;
    min-width: 260px;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    align-items: stretch;
}

/* The stacked pair fills the column so its height tracks the state tag beside it,
   rather than floating short at the top with the tag towering over two small
   buttons (HQU-497). The column is already as tall as the tag (align-items:stretch
   on .record-open); flex:1 splits that height between the two buttons. */
.record-open-acts .mud-button-root {
    flex: 1 1 0;
    min-height: 0;
}

/* Cancelling is a real action, not a mistake — so it is a legible outlined
   button rather than a hidden one. It reads as danger, and it is second. */
.record-open-cancel.mud-button-outlined {
    border-color: var(--rec-danger);
    color: var(--rec-danger);
}

/* Tone sits on the row so currentColor resolves inside the tag; only the TAG paints it. */
.record-open.tone-neutral { color: var(--rec-tag-neutral-fg); }
.record-open.tone-info    { color: var(--rec-tag-info-fg); }
.record-open.tone-warning { color: var(--rec-tag-warning-fg); }
.record-open.tone-success { color: var(--rec-tag-success-fg); }
.record-open.tone-danger  { color: var(--rec-tag-danger-fg); }

.record-open.tone-neutral .record-open-state { background: var(--rec-tag-neutral-bg); }
.record-open.tone-info    .record-open-state { background: var(--rec-tag-info-bg); }
.record-open.tone-warning .record-open-state { background: var(--rec-tag-warning-bg); }
.record-open.tone-success .record-open-state { background: var(--rec-tag-success-bg); }
.record-open.tone-danger  .record-open-state { background: var(--rec-tag-danger-bg); }


/* Read-only field value (the staff twin of the Web ReadOnlyValue) — the content of an <InfoRow>'s
   value slot. Size, weight and colour come from the ROW it sits in (--row-read-*): restating them
   here is what let this renderer drift away from the label it belongs to. Only what the row cannot
   know stays — the wrap and the line height. */
.record-rov-value {
    line-height: 1.4;
    overflow-wrap: anywhere;
}

.record-rov-value a { color: var(--rec-link); text-decoration: underline; overflow-wrap: anywhere; }

/* Nothing recorded. Matches <InfoRow>'s own em-dash, because it IS the same statement. */
.record-rov-empty {
    font-weight: 400;
    color: var(--row-empty-fg, var(--rec-faint));
}

/* The mockup's .field-note — the Yes/No comment under its answer. It sits inside the value slot,
   so it has to say its own weight back down: the value above it is the thing being scanned. */
.record-rov-note {
    margin-top: 3px;
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.4;
    color: var(--rec-faint);
    overflow-wrap: anywhere;
}

/* A link line under a value — a Location's "Open in Google Maps" (HQU-1474). */
.record-rov-link {
    display: inline-block;
    margin-top: 3px;
    font-size: 0.875rem;
    color: var(--rec-link);
    text-decoration: underline;
}

/* Hash-free tamper verdict banner. Tone classes carry the colour. */
.record-verdict {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 10px;
    border: 1px solid transparent;
    margin: 4px 0 14px;
}

/* The reassuring verdict rides at the FOOT of the item viewer, under the last panel — so it needs
   the gap above it that its top-slot twin gets below. */
.record-verdict-foot { margin-top: 18px; }
.record-verdict-foot .record-verdict { margin: 0; }

.record-verdict-text { display: flex; flex-direction: column; gap: 2px; }
.record-verdict-headline { font-weight: 600; line-height: 1.3; }
.record-verdict-sub { font-size: 0.85rem; line-height: 1.4; opacity: 0.9; }

.record-verdict.tone-success { background: var(--rec-v-success-bg); border-color: var(--rec-v-success-bd); color: var(--rec-v-success-fg); }
.record-verdict.tone-danger  { background: var(--rec-v-danger-bg);  border-color: var(--rec-v-danger-bd);  color: var(--rec-v-danger-fg); }
.record-verdict.tone-warning { background: var(--rec-v-warning-bg); border-color: var(--rec-v-warning-bd); color: var(--rec-v-warning-fg); }
.record-verdict.tone-neutral { background: var(--rec-v-neutral-bg); border-color: var(--rec-v-neutral-bd); color: var(--rec-v-neutral-fg); }

/* ── Panels: relations, activity, related assets, the wizard's tree ───────── */

.record-panel {
    margin-top: 18px;
    padding-top: 14px;
    border-top: 1px solid var(--rec-border-soft);
}

.record-panel-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-weight: 600;
    color: var(--rec-text);
    margin-bottom: 8px;
}

.record-panel-empty {
    font-size: 0.88rem;
    color: var(--rec-faint);
}

/* On paper the panel is a card of its own, because its rows are transparent: a relation row and an
   activity row draw nothing but their hover, and with the page card gone they would sit straight on
   the paper with nothing under them. The top rule above becomes the card's own edge — a rule AND a
   border is two lines saying one thing. Same shape the mockup's sections take
   (mockups/venuehq-shell run-detail-view.html: an <h2> over a .card). */
.record-page .record-panel {
    padding: 14px 16px 16px;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 10px;
}

/* ── Linked-item dropdown (RecordRelatedItemPicker) ────────────────────────────
   Its failure + truncation lines sit INSIDE a form field, so they stay small and
   inline — the full-height RecordAsyncView states belong to screens, not fields. */
.record-picker-error {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.88rem;
    color: var(--rec-v-danger-fg);
}

.record-picker-hint {
    margin-top: 4px;
    font-size: 0.78rem;
    color: var(--rec-faint);
}

/* Relation row — the navigate link is its own button; the tree's checkbox sits to its LEFT
   (the .record-rel-row flex leaves that slot) without disturbing the link. */
.record-rel-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.record-rel-open {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 6px;
    background: none;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    text-align: left;
    color: inherit;
    font: inherit;
    min-width: 0;
}

.record-rel-open:hover { background: var(--rec-row-hover); }

.record-rel-icon { font-size: 1.1rem; color: var(--rec-muted); flex: none; }

.record-rel-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--rec-text);
}

.record-rel-kind {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--rec-faint);
    flex: none;
}

.record-activity-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    margin-top: 6px;
    padding: 8px;
    background: none;
    border: 1px solid var(--rec-border-soft);
    border-radius: 8px;
    cursor: pointer;
    color: var(--rec-link);
    font: inherit;
}

.record-activity-more:hover { background: var(--rec-row-hover); }

/* Status dot — 8px round, tone-coloured (shared by the activity list). */
.record-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex: none;
    margin-top: 6px;
    background: var(--rec-dot-neutral);
}

.record-status-dot.tone-success { background: var(--rec-dot-success); }
.record-status-dot.tone-danger  { background: var(--rec-dot-danger); }
.record-status-dot.tone-warning { background: var(--rec-dot-warning); }
.record-status-dot.tone-info    { background: var(--rec-dot-info); }
.record-status-dot.tone-neutral { background: var(--rec-dot-neutral); }

/* ── Record Activity/comment feed (HQU-547) — the staff mirror of the console's FeedTimeline. The
   panel itself is the shared .record-panel card; these style the composer and the entry rows. ── */
.record-comment-box {
    display: flex;
    align-items: flex-end;
    gap: 8px;
    padding: 8px 10px;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    margin-bottom: 12px;
}

.record-comment-input {
    flex: 1;
    min-width: 0;
    border: none;
    background: none;
    resize: none;
    font: inherit;
    color: var(--rec-text);
    line-height: 1.45;
    max-height: 160px;
    outline: none;
}

.record-comment-input::placeholder { color: var(--rec-faint); }

/* The composer is a borderless textarea INSIDE .record-comment-box, so the visible box IS the
   container's border. The textarea already drops its own outline, but the portal's universal
   `*:focus-visible` (hque-overrides.css) still box-shadows the textarea itself on focus, drawing a
   SECOND, inset box within the container — the "double selected box" (HQU-574). Kill that inner
   ring and let the container carry the single focus affordance via :focus-within, the same way the
   authoring composer's own bordered textarea does. */
.record-comment-input:focus,
.record-comment-input:focus-visible {
    outline: none;
    box-shadow: none;
}

.record-comment-box:focus-within { border-color: var(--rec-accent); }

/* HQU-875: sized to sit with the ghost tools rather than dominate them — a 28px ink pill with a
   15px glyph once there is something to post; disabled it drops to a ghost icon (no grey slab). */
.record-comment-send {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin-left: 2px;
    padding: 0;
    border: none;
    border-radius: 7px;
    background: var(--rec-text);
    color: #fff;
    cursor: pointer;
}

.record-comment-send:disabled {
    background: transparent;
    color: var(--rec-faint);
    opacity: 0.55;
    cursor: default;
}

/* The composer's bottom-right tools (HQU-850): attach a file, add a photo, then send. */
.record-comment-tools {
    flex: none;
    display: flex;
    align-items: center;
    gap: 4px;
}

/* A label the size of the send button, ghost rather than ink — attaching is a side door, posting
   is the action. The real <input type=file> sits inside it, invisible but still focusable, so the
   ring shows on the label via :focus-within. */
.record-comment-tool {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    color: var(--rec-muted);
    cursor: pointer;
}

.record-comment-tool:hover { background: var(--rec-hover); color: var(--rec-text); }
.record-comment-tool:focus-within { box-shadow: var(--focus-ring, 0 0 0 2px var(--rec-accent)); }
.record-comment-tool.is-busy { opacity: 0.6; cursor: default; }

.record-comment-tool .record-comment-file {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: inherit;
    font-size: 0;
}

@media (pointer: coarse) {
    .record-comment-tool { width: 44px; height: 44px; }
    .record-comment-send { width: 40px; height: 40px; }
}

/* HQU-683: the keyboard-shortcut hint under the composer, so it's clear how a comment is posted. */
.record-comment-hint {
    margin-top: 4px;
    font-size: var(--text-xs, 12px);
    color: var(--rec-faint);
}

.record-comment-hint--error { color: var(--rec-v-warning-fg); }

/* ── Attachments in the Activity feed (HQU-850) ───────────────────────────────
   A tile under each "Attachment added" entry: the thumbnail (or a file icon), then the name and
   what it is. The whole tile is the button that opens the viewer. */
.record-attachment-tile {
    display: flex;
    align-items: center;
    /* Explicit: the UA centres a flex <button>'s contents, which floated the tile's thumbnail and
       name into the middle of it. */
    justify-content: flex-start;
    width: 100%;
    gap: 10px;
    max-width: 360px;
    margin-top: 6px;
    padding: 6px;
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    background: var(--rec-surface);
    color: var(--rec-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.record-attachment-tile:hover { background: var(--rec-hover); }
.record-attachment-tile:focus-visible { outline: none; box-shadow: var(--focus-ring, 0 0 0 2px var(--rec-accent)); }

.record-attachment-thumb,
.record-attachment-icon {
    flex: none;
    width: 64px;
    height: 64px;
    border-radius: 6px;
}

.record-attachment-thumb { object-fit: cover; display: block; background: var(--rec-hover); }

.record-attachment-icon {
    display: grid;
    place-items: center;
    background: var(--rec-hover);
    color: var(--rec-muted);
}

.record-attachment-caption { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.record-attachment-name {
    font-size: 14px;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.record-attachment-meta { font-size: 12px; color: var(--rec-faint); }

/* ── The attachment viewer ────────────────────────────────────────────────────
   The surface's modal shape (.record-guard), widened for a photo. The image fits inside the
   viewport on both axes, so a tall phone photo is never cut off or scrolled. */
.record-viewer:focus { outline: none; }

.record-guard-box.record-viewer-box {
    margin-top: 5vh;
    max-width: min(960px, calc(100vw - 32px));
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.record-viewer-head {
    display: flex;
    align-items: center;
    gap: 12px;
}

.record-viewer-name {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 700;
    color: var(--rec-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.record-viewer-close {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    color: var(--rec-muted);
    cursor: pointer;
}

.record-viewer-close:hover { background: var(--rec-hover); color: var(--rec-text); }

.record-viewer-body {
    display: grid;
    place-items: center;
    min-height: 200px;
    border-radius: 8px;
    background: var(--rec-hover);
}

.record-viewer-image {
    display: block;
    max-width: 100%;
    max-height: 70vh;
    object-fit: contain;
}

.record-viewer-file {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 32px;
    color: var(--rec-muted);
}

.record-viewer-note { margin: 0; padding: 32px; color: var(--rec-muted); }

.record-viewer-acts {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
}

.record-viewer-meta { margin-right: auto; font-size: 13px; color: var(--rec-faint); }

.record-comment-hint kbd {
    font-family: inherit;
    font-size: 0.9em;
    padding: 0 4px;
    border: 1px solid var(--rec-border, var(--border-default));
    border-radius: 3px;
    background: var(--rec-subtle, var(--canvas-subtle));
    color: var(--rec-ink, var(--fg-muted));
}

.record-activity-feed-list { display: flex; flex-direction: column; gap: 4px; }

.record-activity-feed-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 6px;
}

.record-activity-feed-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }

.record-activity-feed-line { display: flex; align-items: baseline; gap: 8px; min-width: 0; flex-wrap: wrap; }

.record-activity-feed-action { font-weight: 500; color: var(--rec-text); font-size: 0.9rem; }

.record-activity-feed-user { font-size: 0.8rem; color: var(--rec-muted); }

.record-activity-feed-comment {
    font-size: 0.9rem;
    color: var(--rec-body);
    line-height: 1.45;
    white-space: pre-wrap; /* keep the author's line breaks (HQU-954) */
    overflow-wrap: anywhere; /* user-authored, unknown length */
}

.record-activity-feed-time { font-size: 0.78rem; color: var(--rec-muted); }

/* ── QR scanner ───────────────────────────────────────────────────────────── */

.record-scan-viewport {
    position: relative;
    width: 100%;
    max-width: 420px;
    margin: 8px auto 0;
    aspect-ratio: 1 / 1;
    border-radius: 12px;
    overflow: hidden;
    background: #000;
}

.record-scan-viewport.is-hidden { display: none; }

.record-scan-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* A centred square reticle to aim the code into. Pointer-transparent overlay. */
.record-scan-reticle {
    position: absolute;
    inset: 18%;
    border: 3px solid rgba(255, 255, 255, 0.9);
    border-radius: 12px;
    box-shadow: 0 0 0 100vmax rgba(22, 33, 29, 0.28);
    pointer-events: none;
}

/* ── Focus mode: the record being filled in ───────────────────────────────────
   mockups/venuehq-shell/execute.html (.focus / .steps / .focus-*). The one state on
   this surface that is not a card on a page — it IS the page, and both hosts take
   their chrome away for it (RecordFocusState).

   Two fixed edges and a scrolling middle: the header says which record and how far
   through, the foot holds the only two moves, and the body is the single step. On a
   phone that means the primary action is always under the thumb no matter how long
   the step's instruction runs. */
.rec-focus {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    width: 100%;
    min-height: 100%;
    background: var(--rec-surface);
}

.rec-focus-top {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 24px;
    background: var(--rec-surface);
    border-bottom: 1px solid var(--rec-border);
}

/* The leave affordance. A <button> and not a link, because leaving has to pass through
   the screen's own handler for the unsaved-work guard to run. Reset hard: a UA button
   centres its text and brings its own font, neither of which belongs in a header row. */
.rec-focus-leave {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: 0 0 auto;
    min-height: var(--rec-tap);
    padding: 0 14px 0 10px;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    color: var(--rec-text);
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
}

.rec-focus-leave:hover {
    background: var(--rec-sunken);
}

.rec-focus-title {
    min-width: 0;
    font-family: var(--rec-font-display);
    font-weight: 600;
    font-size: 16px;
    color: var(--rec-text);
}

/* The record's name can be long and the subject line longer. One line, clipped —
   the header must not grow a second row and push the step off the fold. */
.rec-focus-title > span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* One line, always. A wrapped reassurance line pushes the step's heading below the fold on a
   phone, which trades the thing being read for a line about how it is saved. */
.rec-focus-title small {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--rec-font-body);
    font-weight: 400;
    font-size: 14px;
    color: var(--rec-faint);
}

.rec-focus-count {
    margin-left: auto;
    flex: 0 0 auto;
    font-size: 15px;
    font-weight: 600;
    color: var(--rec-body);
}

/* The progress bar. Ticks rather than a percentage: "step 5 of 9" is a promise about
   how much is left, and nine segments make that legible at a glance where a bar at 44%
   does not. Lifecycle colours, not the pen family — these report what the RECORD is. */
.rec-focus-steps {
    display: flex;
    gap: 4px;
    padding: 12px 24px 0;
}

.rec-focus-steps i {
    flex: 1 1 0;
    height: 6px;
    border-radius: 999px;
    background: var(--rec-sunken);
}

.rec-focus-steps i.is-done {
    background: var(--rec-dot-success);
}

.rec-focus-steps i.is-now {
    background: var(--rec-dot-warning);
}

/* A long one-screen form's answered bar (HQU-1444): one thin line, since there are no steps to tick. */
.rec-focus-answered {
    margin: 12px 24px 0;
    height: 6px;
    border-radius: 999px;
    background: var(--rec-sunken);
    overflow: hidden;
}

.rec-focus-answered i {
    display: block;
    height: 100%;
    background: var(--rec-dot-success);
    transition: width 0.2s ease;
}

/* 704px is the mockup's, and it is a reading measure rather than a layout: one step
   is one question, and a control stretched across a 1400px monitor reads as a form. */
.rec-focus-body {
    flex: 1 1 auto;
    width: 100%;
    max-width: 704px;
    padding: 26px 24px 34px;
}

.rec-focus-body h1 {
    margin: 0;
    font-family: var(--rec-font-display);
    font-size: 27px;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.012em;
    color: var(--rec-text);
}

.rec-focus-help {
    margin: 10px 0 0;
    font-size: 16px;
    color: var(--rec-body);
}

/* A step that captures nothing. Muted and italic so it reads as the screen telling you
   something rather than as a value someone recorded. */
.rec-focus-noinput {
    margin: 18px 0 0;
    font-size: 15px;
    font-style: italic;
    color: var(--rec-faint);
}

/* A Statement in the step body is an instruction card, not an input, so it renders bare — without
   the .rec-focus-input wrapper that carries the spacing below. Give it the same top gap so back-to-back
   instructions (and an instruction following a question) breathe instead of stacking flush (HQU-728). */
.rec-focus-body .record-form-statement {
    margin-top: 24px;
}

.rec-focus-input {
    margin-top: 24px;

    /* MudBlazor paints a ticked checkbox and a chosen radio in the theme primary, which on this host
       is the console's accent blue — the one colour the records palette does not use. Re-point the
       palette variable over this subtree so a value you record carries the same ink as the button
       that commits it. TOKENS ONLY: not one MudBlazor rule is restated here. */
    --mud-palette-primary: var(--rec-accent);
    --mud-palette-primary-rgb: 22, 33, 29;
}

.rec-focus-input > label {
    display: block;
    margin-bottom: 8px;
    font-size: 15px;
    color: var(--rec-body);
}

.rec-focus-req {
    margin-left: 3px;
    color: var(--rec-danger);
}

/* The authored instruction under a field's prompt. Quieter than the prompt and tighter to it than
   to the control, so it reads as part of the question. `anywhere` because these are routinely a
   pasted document URL, which would otherwise run off a phone screen. */
.rec-focus-fieldhelp {
    margin: -2px 0 8px;
    font-size: 14px;
    line-height: 1.45;
    color: var(--rec-muted);
    overflow-wrap: anywhere;
}

/* Stands in for the prompt on a step whose heading already asked the question. Quiet on purpose:
   it is a note about the field, not a warning — the loud version of this read as an error on a
   screen where nothing had gone wrong yet. */
.rec-focus-required {
    display: block;
    margin-bottom: 8px;
    font-size: 14px;
    color: var(--rec-faint);
}

.rec-focus-required::before {
    content: "*";
    margin-right: 4px;
    color: var(--rec-danger);
}

.rec-focus-error {
    margin-top: 6px;
    font-size: 13px;
    color: var(--rec-danger);
}

/* The controls sit at floor scale here, not at form scale: this is one question read at arm's
   length with gloves on, so the input is the biggest thing under the heading.

   The element selectors are load-bearing. MudBlazor styles its slot as `.mud-input > input`, which
   out-specifies a plain two-class rule — the first version of this block set 18px and the input
   stayed at 14, silently. Keep the tag on the slot selectors. */
.rec-focus-input .mud-input input.mud-input-slot,
.rec-focus-input .mud-input textarea.mud-input-slot,
.rec-focus-input .mud-input div.mud-input-slot {
    font-size: 18px;
    min-height: 44px;
}

.rec-focus-input .mud-input-control {
    min-height: 60px;
}

.rec-focus-input .mud-radio p.mud-typography,
.rec-focus-input .mud-checkbox p.mud-typography,
.rec-focus-input .mud-radio span.mud-typography,
.rec-focus-input .mud-checkbox span.mud-typography {
    font-size: 17px;
}

/* The mockup's .bigchoice. A yes/no is the commonest thing anyone records on a phone, and a 20px
   radio dot is not a target for someone in gloves — so each option becomes a full-height bordered
   box that splits the row. The radio itself stays: the semantics (and the keyboard) are the
   MudRadioGroup's, and only the size and the box are ours. */
/* MudRadioGroup renders THREE nested boxes before the options: the class we set lands on the outer
   .mud-input-control, then .mud-input-control-input-container, then .mud-radio-group — and only the
   innermost one is the row the radios sit in. Styling either wrapper laid out a single child and
   left the options at their natural width inside it (measured, not assumed). So the two wrappers
   only pass the width down, and the row rules go on .mud-radio-group. */
.rec-focus-input .record-form-yesno,
.rec-focus-input .record-form-yesno .mud-input-control-input-container,
.rec-focus-input .record-form-yesno .mud-radio-group {
    width: 100%;
}

.rec-focus-input .record-form-yesno .mud-radio-group {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 12px;
}

/* And each option brings its OWN .mud-input-control pair, so the flex item in that row is the
   wrapper, not the <label class="mud-radio"> the box is drawn on. Sizing the label alone left three
   content-width boxes in a 656px row; the label still takes flex:1 to fill the wrapper it sits in. */
.rec-focus-input .record-form-yesno .mud-radio-group > .mud-input-control {
    flex: 1 1 0;
    min-width: 0;
}

.rec-focus-input .record-form-yesno .mud-radio {
    flex: 1 1 0;
    min-width: 0;
    min-height: 62px;
    margin: 0;
    padding: 0 10px;
    justify-content: center;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
}

.rec-focus-input .record-form-yesno .mud-radio:hover {
    background: var(--rec-sunken);
}

/* The chosen one carries the ink edge, so which option is selected reads from across a deck rather
   than from a 10px dot. :has is the whole mechanism — MudBlazor puts no class on the outer label —
   and a browser without it simply keeps the plain boxes and the dot, which is the old behaviour. */
.rec-focus-input .record-form-yesno .mud-radio:has(input:checked) {
    border-color: var(--rec-accent);
    box-shadow: inset 0 0 0 1px var(--rec-accent);
    background: var(--rec-accent-soft);
}

/* The reason box is SUBORDINATE to the answer above it, so it does not take the 18px
   floor scale the primary controls get — 16px, still a comfortable phone target, and the
   difference is what says "this belongs to the Unknown you just pressed". The element
   selector and the .rec-focus-input prefix are both load-bearing: they have to out-specify
   the block above, which sets every input slot on this screen to 18px. */
.rec-focus-input .record-form-why .mud-input textarea.mud-input-slot {
    font-size: 16px;
    min-height: 0;
}

/* A lone checkbox gets the tap target too, without the split-the-row treatment: there is only one,
   so it sizes to its label rather than spanning the column. DESCENDANT, not child — MudCheckBox
   buries its <label class="mud-checkbox"> under the same .mud-input-control pair the radios use
   (see the note above), so a `>` here matches nothing at all. */
.rec-focus-input .mud-checkbox {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    min-height: 62px;
    margin: 0;
    padding: 0 16px 0 6px;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
}

.rec-focus-input .mud-checkbox:hover {
    background: var(--rec-sunken);
}

.rec-focus-input .mud-checkbox:has(input:checked) {
    border-color: var(--rec-accent);
    box-shadow: inset 0 0 0 1px var(--rec-accent);
    background: var(--rec-accent-soft);
}

.rec-focus-foot {
    position: sticky;
    bottom: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 24px;
    background: var(--rec-surface);
    border-top: 1px solid var(--rec-border);
}

/* Trailing, not leading: the actions cluster at the LEFT margin — under the column of
   questions they belong to — and this eats whatever is left over on the right. */
.rec-focus-spacer {
    flex: 1 1 auto;
}

.rec-focus-back {
    min-height: var(--rec-tap);
    padding: 0 18px;
    white-space: nowrap;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    color: var(--rec-text);
    font-family: inherit;
    font-size: 16px;
    font-weight: 600;
    cursor: pointer;
}

.rec-focus-back:hover {
    background: var(--rec-sunken);
}

/* The mockup's .btn-lg. The step's one forward move, so it is the largest target on the
   screen and it never shrinks to its label. */
.rec-focus-go.mud-button-root {
    min-height: 56px;
    min-width: 220px;
    padding: 0 26px;
    font-size: 17px;
    white-space: nowrap;
}

/* Save-and-stay. Sized to the primary rather than to Back, because the two of them are the
   pair an operator chooses between; Back is a different kind of thing. Quiet by weight —
   outlined against the primary's fill — so the row still has exactly one obvious move. */
.rec-focus-save.mud-button-root {
    min-height: 56px;
    min-width: 128px;
    padding: 0 22px;
    font-size: 17px;
    white-space: nowrap;
    border-color: var(--rec-border);
    color: var(--rec-text);
}

.rec-focus-save.mud-button-root:hover {
    background: var(--rec-sunken);
    border-color: var(--rec-border);
}

/* Phone: the foot leaves the flow and pins to the viewport, and the body buys back the
   room it now covers — otherwise the last control on a long step sits under the button
   that submits it. */
@media (max-width: 760px) {
    .rec-focus-top { padding: 10px 14px; }
    .rec-focus-title { font-size: 15px; }
    .rec-focus-leave span { display: none; } /* the arrow alone; the title needs the width */

    /* The reassurance line is desktop furniture. On a phone the header row has to hold the record's
       name AND the step count in 390px, and the guard dialog says the same thing at the moment it
       actually matters — when someone presses Leave with work outstanding. */
    .rec-focus-title small { display: none; }

    .rec-focus-steps { padding: 10px 14px 0; }
    .rec-focus-answered { margin: 10px 14px 0; }
    .rec-focus-body { padding: 20px 14px 180px; } /* clears the wrapped two-row foot */
    .rec-focus-body h1 { font-size: 23px; }

    /* Three options at 390px would be three unreadable slivers, so let them wrap onto a second row
       at full tap height. Two (a plain yes/no) still fit side by side, which is why this wraps
       rather than forcing a column. */
    .rec-focus-input .record-form-yesno .mud-radio-group { flex-wrap: wrap; }
    .rec-focus-input .record-form-yesno .mud-radio-group > .mud-input-control { flex: 1 1 140px; }

    .rec-focus-foot {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px));
    }

    /* Both feet on one row: nowrap and a tighter scale, rather than flex-growing the primary until
       its label breaks over two lines. flex 0 1 auto lets it shrink its padding, never its words. */
    .rec-focus-back { padding: 0 12px; font-size: 15px; }
    .rec-focus-save.mud-button-root,
    .rec-focus-go.mud-button-root { min-width: 0; flex: 0 1 auto; padding: 0 14px; font-size: 16px; min-height: 52px; }

    /* Three controls will not fit on one 390px row, and none of them can be dropped — this runs
       installed as a PWA, where there is no browser back to fall back on. So the foot wraps and
       Back takes a full-width row of its own UNDER the two save actions: still a full tap target,
       still reachable, just not competing with them for the row that matters. */
    .rec-focus-foot { flex-wrap: wrap; }
    .rec-focus-foot .rec-focus-back { order: 2; flex: 1 1 100%; }
    .rec-focus-foot .rec-focus-save.mud-button-root { min-width: 96px; }
}

/* ── Run wizard (HQU-919) ─────────────────────────────────────────────────────
   ONE 720px column for the wizard's top bar and every step, centred in the page. The steps are
   ordinary .record-page screens inside it, so their own --page-max clamp is lifted here. */
.record-wizard {
    width: 100%;
    max-width: 720px;
    margin-inline: auto;
}

.record-wizard .record-page { max-width: none; }

/* The top bar: ✕, "New record", the stepper. A rule under it rather than a bar of its own colour —
   it sits inside the surface's chrome, not in place of it. */
.record-wizard-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 14px;
    margin-bottom: 28px;
    border-bottom: 1px solid var(--rec-border);
}

.record-wizard-title {
    font-family: var(--rec-font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--rec-text);
}

.record-wizard-steps {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 0 auto;
    padding: 0;
    list-style: none;
}

.record-wizard-steps > li { display: flex; align-items: center; }

.record-wizard-sep {
    width: 24px;
    height: 1px;
    background: var(--rec-border);
}

.record-wizard-sep.is-done { background: var(--rec-text); }

.record-wizard-step {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    padding: 0 6px;
    border: 0;
    border-radius: 6px;
    background: none;
    font: inherit;
    font-size: 14px;
    color: var(--rec-muted);
}

.record-wizard-step.is-reachable { cursor: pointer; }
.record-wizard-step.is-reachable:hover { background: var(--rec-hover); }
.record-wizard-step.is-reachable:hover .record-wizard-step-label { text-decoration: underline; }

.record-wizard-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 1px solid var(--rec-border);
    border-radius: 50%;
    font-size: 12px;
    font-weight: 600;
    color: var(--rec-muted);
    flex: none;
}

.record-wizard-step-num .mud-icon-root { font-size: 15px; color: var(--rec-text); }

.record-wizard-step.is-done .record-wizard-step-num { background: var(--rec-sunken); border-color: var(--rec-sunken); }
.record-wizard-step.is-current { color: var(--rec-text); font-weight: 600; }
.record-wizard-step.is-current .record-wizard-step-num {
    background: var(--rec-accent);
    border-color: var(--rec-accent);
    color: var(--rec-surface);
}

/* The phone's "Step 2 of 3" and the bar under the top bar — hidden on a desk, where the stepper says it. */
.record-wizard-count {
    display: none;
    margin-left: auto;
    font-size: 13px;
    color: var(--rec-muted);
}

.record-wizard-progress { display: none; }

/* "Workspace · Playground · Change" / "Recording · Sample Procedure · Change" over a step's title. */
.record-wizard-context {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 6px;
    font-size: 14px;
    color: var(--rec-muted);
}

/* The record a follow-up follows up (HQU-939) — its label over the link card, above the step. */
.record-wizard-followup { padding-bottom: 0; }
.record-wizard-followup .rtl-file { margin-bottom: 4px; }

.record-wizard-context strong {
    min-width: 0;
    overflow-wrap: anywhere;
    font-weight: 600;
    color: var(--rec-text);
}

/* A button that reads as a link — "Change" steps back through wizard STATE, which has no URL. The
   padding widens the tap target without moving the word off the line it sits on. */
.record-link-btn {
    padding: 4px 6px;
    margin: -4px -6px;
    border: 0;
    border-radius: 4px;
    background: none;
    font: inherit;
    font-weight: 500;
    color: var(--rec-link);
    cursor: pointer;
}

.record-link-btn:hover { text-decoration: underline; }

/* Step 1's rich pick row: kind tile · name + one-line description · chevron. */
.record-pick-main {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.record-pick-entry--rich {
    display: flex;
    align-items: center;
    gap: 16px;
}

.record-pick-entry--rich .record-pick-main { flex: 1; }

.record-pick-entry--rich .record-pick-description {
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.record-pick-lead {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background: var(--rec-tag-info-bg);
    color: var(--rec-tag-info-fg);
    flex: none;
}

.record-pick-lead.is-incident { background: var(--rec-tag-warning-bg); color: var(--rec-tag-warning-fg); }
.record-pick-lead .mud-icon-root { font-size: 20px; }

.record-pick-chev { font-size: 20px; color: var(--rec-muted); flex: none; }

/* Step 2's one card: search on top, the asset rows under it. */
.record-asset-card {
    margin-top: 16px;
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    background: var(--rec-surface);
    overflow: hidden;
}

.record-asset-card-search {
    padding: 16px;
    border-bottom: 1px solid var(--rec-border-soft);
}

.record-asset-card-search .mud-input-control { margin: 0; }

.record-asset-card-note {
    margin: 0;
    padding: 12px 20px 16px;
    font-size: 13px;
    color: var(--rec-muted);
}

.record-tree-level { display: flex; flex-direction: column; }

/* One asset row. The row IS the checkbox's label; the expander sits outside it, trailing. Depth
   indents the row's content, not its background, so a selected child still tints edge to edge. */
.record-asset-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 16px 0 calc(20px + var(--tree-depth, 0) * 28px);
    border-bottom: 1px solid var(--rec-border-soft);
}

.record-asset-row.is-selected { background: var(--rec-tag-info-bg); }

.record-asset-row-main {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 56px;
    padding: 8px 0;
    cursor: pointer;
}

div.record-asset-row-main { cursor: default; }

.record-asset-check {
    width: 20px;
    height: 20px;
    margin: 0;
    flex: none;
    accent-color: var(--rec-tag-info-fg);
    cursor: pointer;
}

.record-asset-check-spacer { width: 20px; flex: none; }

.record-asset-row-text { display: flex; flex-direction: column; min-width: 0; }

.record-asset-row-name {
    font-size: 15px;
    font-weight: 600;
    color: var(--rec-text);
    overflow-wrap: anywhere;
}

.record-asset-row-sub { font-size: 13px; color: var(--rec-muted); }

/* The "N related" expander — a real button, ≥32px on a desk and a full tap target on a phone. */
.record-asset-expand {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-height: 32px;
    padding: 0 8px 0 10px;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    font: inherit;
    font-size: 13px;
    color: var(--rec-text);
    white-space: nowrap;
    cursor: pointer;
    flex: none;
}

.record-asset-expand:hover { background: var(--rec-hover); }
.record-asset-expand-icon { font-size: 18px; transition: transform 0.15s ease; }
.record-asset-expand.is-open .record-asset-expand-icon { transform: rotate(180deg); }

.record-tree-note {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px 10px calc(54px + var(--tree-depth, 0) * 28px);
    border-bottom: 1px solid var(--rec-border-soft);
    font-size: 0.85rem;
}

.record-tree-muted { color: var(--rec-faint); }

/* Step 2's foot: the running selection as chips, Skip, Continue. Pinned to the bottom of the view
   so the way on stays in reach under a long tree. */
.record-wizard-foot {
    position: sticky;
    bottom: 0;
    z-index: 2;
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
    padding: 12px 16px;
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    background: var(--rec-surface);
    box-shadow: 0 -4px 16px var(--rec-shadow);
}

.record-wizard-foot-selection {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.record-wizard-foot-count { font-size: 14px; color: var(--rec-muted); }

.record-asset-chip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    max-width: 100%;
    min-height: 32px;
    padding: 0 2px 0 12px;
    border-radius: 999px;
    background: var(--rec-tag-info-bg);
    color: var(--rec-tag-info-fg);
    font-size: 14px;
    font-weight: 500;
}

.record-asset-chip-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.record-asset-chip-remove.mud-icon-button {
    width: 28px;
    height: 28px;
    padding: 0;
    color: inherit;
}

.record-asset-chip-remove .mud-icon-root { font-size: 16px; }

.record-wizard-foot-actions { display: flex; align-items: center; gap: 8px; flex: none; }

.record-wizard-skip { border-color: transparent; background: none; }

.record-wizard-phone { display: none; }

/* A run/wizard step's primary action sits at the trailing edge — the auto-width .record-btn, not a
   full-bleed bar. A flex row rather than text-align so the button keeps its own width and the row
   owns the gap above. */
.record-actions-end {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
}

/* Step 3: "N steps, one at a time." on the left of Start record. */
.record-start-actions { align-items: center; }
.record-start-actions .record-run-steps-note { margin: 0 auto 0 0; }

/* Step 3's summary: ONE <dl> card — Recording, Venue, Assets — each with its Change on the right. */
.record-start-summary {
    margin: 16px 0 0;
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    background: var(--rec-surface);
    overflow: hidden;
}

.record-start-row {
    display: grid;
    grid-template-columns: 140px minmax(0, 1fr) auto;
    gap: 16px;
    align-items: start;
    padding: 16px 20px;
}

.record-start-row + .record-start-row { border-top: 1px solid var(--rec-border-soft); }

.record-start-row > dt { font-size: 14px; color: var(--rec-faint); padding-top: 1px; }

.record-start-row > dd {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
    font-size: 15px;
    color: var(--rec-text);
}

.record-start-name { font-weight: 600; }

.record-start-description { font-size: 14px; color: var(--rec-muted); overflow-wrap: anywhere; }

.record-start-assets { display: flex; flex-wrap: wrap; gap: 8px; }

/* The last look before the set is frozen, so the FULL name shows (HQU-1390): a tag that wraps, not a
   capsule — a 999px radius on a wrapped name drew an oval blob — and an unbroken ID breaks inside
   the card instead of running under its clip. */
.record-start-asset {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    max-width: 100%;
    min-height: 28px;
    padding: 4px 12px;
    border-radius: 8px;
    background: var(--rec-tag-info-bg);
    color: var(--rec-tag-info-fg);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

/* ── Phone: the staff PWA at 390px. The stepper becomes "Step N of 3" + a bar; step 2's rows and
   controls take full tap targets; the foot stacks a full-width Continue over a Skip link. */
@media (max-width: 600px) {
    .record-wizard-bar {
        gap: 8px;
        margin-bottom: 0;
        padding-bottom: 10px;
        border-bottom: 0;
    }

    .record-wizard-close.mud-icon-button { border-color: transparent; background: none; }
    .record-wizard-steps { display: none; }
    .record-wizard-count { display: inline; }

    .record-wizard-progress {
        display: block;
        height: 3px;
        margin-bottom: 20px;
        background: var(--rec-border-soft);
    }

    .record-wizard-progress > div { height: 100%; background: var(--rec-accent); }

    .record-asset-row { padding-left: calc(16px + var(--tree-depth, 0) * 20px); }
    .record-asset-row-main { min-height: 60px; }
    .record-asset-check { width: 22px; height: 22px; }
    .record-asset-row-name { font-size: 16px; }
    .record-asset-expand { min-height: 44px; min-width: 44px; justify-content: center; }
    .record-tree-note { padding-left: calc(52px + var(--tree-depth, 0) * 20px); }

    .record-wizard-foot {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
        padding: 12px;
    }

    .record-wizard-foot-count { display: none; }

    /* At most two rows of chips (HQU-1391). Unbounded, every pick grew the pinned tray until it
       covered the list it repeats and then the search box; the rest scroll inside it, and Continue
       already says how many are picked. */
    .record-wizard-foot-selection {
        max-height: 96px;
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    .record-asset-chip { min-height: 44px; padding-left: 14px; }
    .record-asset-chip-remove.mud-icon-button { width: 44px; height: 44px; }

    .record-wizard-foot-actions { flex-direction: column-reverse; align-items: stretch; gap: 4px; }
    .record-wizard-continue { min-height: 52px; }
    .record-wizard-desk { display: none; }
    .record-wizard-phone { display: inline; }

    .record-start-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; }
    .record-start-row > dt { grid-column: 1; }
    .record-start-row > dd { grid-column: 1; grid-row: 2; }
    .record-start-row > :last-child { grid-column: 2; grid-row: 1; }

    /* Step 3's Start (HQU-1445) pins and stretches exactly like step 2's Continue above, so every step of the
       wizard keeps its primary action in one place under the thumb. It was a small right-aligned button at
       the end of the page, below the fold with four related items. Tablet width up keeps the inline one. */
    .record-start-actions {
        position: sticky;
        bottom: 0;
        z-index: 2;
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        padding: 12px;
        border: 1px solid var(--rec-border);
        border-radius: 10px;
        background: var(--rec-surface);
        box-shadow: 0 -4px 16px var(--rec-shadow);
    }
    .record-start-actions .record-run-steps-note { margin: 0; text-align: center; }
    .record-start-actions .record-btn { width: 100%; min-height: 52px; }
}

#blazor-error-ui {
    background: #ffffe0;
    color: #000;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(22, 33, 29, 0.2);
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

/* ── Tablet (≥768px): the sign-in tile gets room to breathe. Phone stays kiosk-tight.
   Widens the tile moderately and gives the name-tile grid a third column (the screen that benefits
   most on a mounted tablet). .record-card is PWA-only now, so this no longer reaches the portal
   at all — the screens there are on paper and take their width from .record-page. */
@media (min-width: 768px) {
    .record-card {
        max-width: 560px;
        padding: 40px 36px;
    }
    .record-tile-grid {
        grid-template-columns: repeat(3, 1fr);
        gap: 14px;
    }
    .record-run,
    .record-pick-entry { padding: 16px 18px; }
}

/* ============================================================================
   NavRow — one navigation row, shared by BOTH surfaces (see NavRow.razor).

   Every colour here resolves through a --nr-* property declared below, and each of
   those defaults to the manager console's token with the records palette as the
   fallback: var(--console-token, var(--rec-token)). On the portal, hque-tokens.css
   has defined the console token, so the row reads as console chrome; in the PWA it
   is undefined and the staff value applies. Both themes come free, because BOTH
   palettes re-point their own properties in their own dark blocks.

   That is also the extension point: a surface wrapper re-points --nr-* over a
   subtree rather than restating any rule below.
   ============================================================================ */
:root {
    --nr-surface:      var(--canvas-default, var(--rec-surface));
    --nr-surface-hover: var(--canvas-subtle, var(--rec-row-hover));
    --nr-border:       var(--border-default, var(--rec-border));
    --nr-title:        var(--fg-default, var(--rec-text));
    --nr-support:      var(--fg-muted, var(--rec-muted));
    --nr-chevron:      var(--fg-subtle, var(--rec-faint));
    --nr-accent:       var(--accent-fg, var(--rec-accent));
    --nr-icon-bg:      var(--canvas-inset, var(--rec-sunken));
    --nr-radius:       var(--radius-md, 8px);
    --nr-focus:        var(--focus-ring, 0 0 0 3px rgba(37, 99, 235, 0.30));
    /* Thumb-sized. The settings data tables this replaces were ~34px rows. */
    --nr-min-height:   56px;

    /* Metrics, tokenised for the same reason the colours are: the records surface renders these rows
       at the shell mockup's scale (68px, 16px title) and the authoring surface at the console's, and
       a surface must be able to say so by re-pointing properties rather than restating rules. */
    --nr-pad-y:        10px;
    --nr-pad-x:        14px;
    --nr-gap:          12px;
    --nr-title-size:   14px;
    --nr-support-size: 12px;
    /* The line BETWEEN rows. Defaults to the card's own border; a surface can soften it so a run of
       rows reads as one card with divisions rather than a stack of boxes. */
    --nr-divider:      var(--nr-border);
}

/* The list container. Rows share one border box so a run of them reads as one list
   rather than a stack of cards. */
.navrow-list {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--nr-border);
    border-radius: var(--nr-radius);
    overflow: hidden;
    background: var(--nr-surface);
}
.navrow-list > .navrow + .navrow {
    border-top: 1px solid var(--nr-divider);
}

.navrow {
    display: flex;
    align-items: stretch;
    background: var(--nr-surface);
    min-height: var(--nr-min-height);
}
.navrow.is-inactive .navrow-title,
.navrow.is-inactive .navrow-support { opacity: 0.55; }

/* The navigating element itself — <a> or <button>, reset to look like neither. */
.navrow-go {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: var(--nr-gap);
    padding: var(--nr-pad-y) var(--nr-pad-x);
    background: none;
    border: 0;
    border-radius: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.12s ease;
}
/* The app's global a:hover underlines links. A row is a surface, not a phrase — underlining
   its title AND its supporting line on hover reads as two links, so the hover is the
   background plus the title colour, and nothing else. */
.navrow-go:hover { background: var(--nr-surface-hover); text-decoration: none; }
.navrow-go:focus-visible {
    outline: none;
    box-shadow: var(--nr-focus);
    /* Above the sibling row's border so the ring is never clipped by it. */
    position: relative;
    z-index: 1;
}
.navrow-go:hover .navrow-title { color: var(--nr-accent); }
/* A row that goes nowhere is not a control: no pointer, no hover, no chevron. */
.navrow-go--static { cursor: default; }
.navrow-go--static:hover { background: none; }
.navrow-go--static:hover .navrow-title { color: var(--nr-title); }

.navrow-lead { flex: 0 0 auto; display: flex; align-items: center; }
.navrow-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--nr-radius);
    background: var(--nr-icon-bg);
    color: var(--nr-support);
}

.navrow-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.navrow-title {
    font-size: var(--nr-title-size);
    font-weight: 600;
    color: var(--nr-title);
    transition: color 0.12s ease;
    /* One line. A wrapping title turns a scannable list into a paragraph. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.navrow-support {
    font-size: var(--nr-support-size);
    color: var(--nr-support);
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    min-width: 0;
}
.navrow-support-text {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    min-width: 0;
    overflow-wrap: anywhere;
}

.navrow-trail {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--nr-support-size);
    color: var(--nr-support);
}

.navrow-chev {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    color: var(--nr-chevron);
    transition: transform 0.15s ease;
}

/* Disclosure rows (<NavRow Expanded>) turn the same glyph a quarter turn rather than swapping
   in ExpandMore — one chevron, drawn one way, whether the row goes somewhere or opens
   something. */
.navrow-chev.is-open { transform: rotate(90deg); }

/* Per-row controls. Outside .navrow-go, so a tap here never navigates. */
.navrow-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 12px 0 0;
}

/* Phone: the supporting line and trailing meta compete for a width that isn't there.
   Keep the title and the chevron; let the rest stack. */
@media (max-width: 600px) {
    .navrow-go { padding: 10px 12px; gap: 10px; }
    .navrow-trail { display: none; }
}

/* …except on the RECORDS surface, where the trailing content is the record's lifecycle tag and
   dropping it takes the answer off a screen whose whole question is "what state is this in". The
   mockup's phone treatment instead (phone.css .row): two columns — everything about the row on the
   left, the forward chevron on the right — with the tag moving under the meta line rather than
   fighting the title for width.

   Structure is untouched: this is the same markup laid out differently, which is the one thing a
   surface is allowed to do to a shared primitive. */
@media (max-width: 600px) {
    .hq-surface--record .navrow-go {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "main chev"
            "trail chev";
        column-gap: 12px;
        row-gap: 0;
        align-items: center;
        min-height: 74px;
        padding: 13px 14px;
    }

    .hq-surface--record .navrow-main { grid-area: main; }

    /* A row WITH a leading icon needs a fourth area; without :has() the icon and the title would be
       placed in the same cell and overlap. Rows on this surface rarely carry one, so the two-column
       form above stays the default and this only pays where it applies. */
    .hq-surface--record .navrow-go:has(.navrow-lead) {
        grid-template-columns: auto minmax(0, 1fr) auto;
        grid-template-areas:
            "lead main chev"
            "lead trail chev";
    }

    .hq-surface--record .navrow-lead { grid-area: lead; }

    .hq-surface--record .navrow-trail {
        display: flex;
        grid-area: trail;
        justify-self: start;
        margin-top: 9px;
    }

    .hq-surface--record .navrow-chev { grid-area: chev; align-self: center; }
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   THE label-and-value row (<InfoRow>) and its group (<InfoList>).

   One row, one group, both surfaces, both modes. This block lives in records.css because that
   sheet is loaded by BOTH apps — the PWA's index.html and the portal's (line 20) — so the
   primitive is styled once for everything that renders it.

   Everything below resolves through the --row-* semantic properties declared here. A surface
   wrapper re-points those properties over its subtree and nothing else; it never changes what
   renders. Adding a colour literal to a rule below re-opens the drift this whole block exists
   to close, so don't.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* The defaults ARE the authoring (manager console) values, so a caller with NO surface wrapper
   — a pre-login page, a dialog outside a layout — renders exactly as it did before. The literal
   fallbacks are for the PWA, which has no --fg- or --canvas- tokens of its own; it is wrapped
   in a RecordSurface at its root, so they should never actually be reached.

   Do NOT write a token glob as `--fg-*` immediately before a slash: the `*` plus the `/` is a
   comment terminator, and the rest of this comment then parses as CSS. That is what happened
   here — the stray text became a selector, this whole :root block became its body, and every
   --row-* default silently vanished. Nothing errored; the surfaces and .hq-rows-card happened
   to re-declare most of them, so only an unwrapped row (no surface, no card) showed it, by
   losing --row-pad-x and dropping its padding entirely. */
:root {
    --row-label-fg: var(--fg-muted, #47574f);
    --row-label-size: var(--text-sm, 13px);
    --row-label-weight: 500;
    --row-label-spacing: 0;
    --row-value-fg: var(--fg-default, #16211d);
    --row-value-size: var(--text-md, 14px);
    --row-help-fg: var(--fg-muted, #47574f);
    --row-help-size: var(--text-2xs, 11px);
    --row-required-fg: var(--danger-fg, #a31212);
    --row-error-fg: var(--danger-fg, #a31212);
    --row-empty-fg: var(--fg-subtle, #627268);
    --row-line: var(--border-muted, #e4e9e5);
    --row-pad-y: 14px;
    --row-pad-x: 0px;
    --row-group-bg: var(--canvas-default, #fff);
    --row-group-line: var(--border-default, #d3dad5);
    --row-group-radius: var(--radius-lg, 10px);
    --row-group-fg: var(--fg-default, #16211d);
    --row-group-title-size: var(--text-md, 14px);
    /* A boxed group's header band (<InfoList> as a card). In the authoring console it is the
       SAME band as <PanelHeader> (.panel-header in components.css) — 53px, 13px/500 title, a
       muted 14px icon — so an Information card and a Labels card side by side on the record view
       have one header height and one title voice (HQU-914). The record surface restates its own. */
    --row-card-head-min-height: 53px;
    --row-card-head-pad: 0 16px;
    --row-card-title-size: var(--text-sm, 13px);
    --row-card-title-weight: 500;
    --row-card-icon-size: var(--text-md, 14px);
    --row-card-icon-fg: var(--fg-subtle, #627268);

    /* Read-mode deltas. Label and value are the SAME size here (15px, the mockup's .field);
       what separates them is weight and colour — the label recedes to --ink-3 at 400, the
       value carries 500 in full ink, because what is being scanned down a column of these is
       the values. An edit row borrows this SIZE (the two modes share a label column, so the
       label must not resize when you flip between them) but keeps --row-label-fg/-weight: it
       identifies a control you are about to use, not a value you are scanning. */
    --row-read-label-fg: var(--fg-subtle, #627268);
    --row-read-label-weight: 400;
    --row-read-label-size: var(--text-15, 15px);
    --row-read-value-size: var(--text-15, 15px);

    /* A read row is INLINE — label in the left column, value beside it — which is the
       mockup's .field. The two tracks are a 40/60 split (2fr:3fr of the row, once the gap
       is taken out) so a field value gets the wider share (HQU-511).
       --row-read-columns is the whole layout switch: set it to a single
       track and the row stacks again, which is what the phone surface and the narrow
       breakpoint below do. The value carries weight because it is what gets scanned down a
       column of these; the label is the thing you already know you are looking for. */
    --row-read-columns: minmax(0, 2fr) minmax(0, 3fr);
    --row-read-gap: 20px;
    --row-read-value-weight: 500;

    /* An edit row takes the SAME two tracks (the mockup's .field-edit) — label left, control
       right — so flipping a page between reading and editing does not re-flow the labels out
       from beside their values to above them. Which is also why the edit label now takes the
       read label's SIZE: it is the same furniture in the same column, and only the value slot
       changes. It keeps its own weight and colour, because it still identifies a control you
       are about to use rather than a value you are scanning.

       An edit row aligns to START, not baseline: a grid item's first baseline can come from a
       <textarea>, whose baseline is its BOTTOM edge, so a 5-line multiline field would drag
       its label to the foot of the row. --row-edit-label-offset is what buys back the optical
       alignment a baseline would have given — it is the distance from the top of a dense
       outlined control to its first line of text — and it goes to 0 wherever the row stacks. */
    --row-edit-columns: 40% minmax(0, 1fr);
    --row-edit-gap: 20px;
    --row-edit-label-offset: 8px;
}

/* display:contents — a surface must not add a box. It exists to scope custom properties over
   its subtree, and custom properties inherit straight through it, so the layout the wrapper
   sits in is untouched. */
.hq-surface {
    display: contents;
}

.hq-surface--record {
    /* NavRow at the shell mockup's scale (mockups/venuehq-shell app.css, .row): a 68px row, a 16px
       title, a 14px meta line. The authoring console keeps the smaller default — a records row is
       read at arm's length on site, a settings row at a desk. TOKENS ONLY: not one rule below is
       restated here, which is the guard rail that stopped the four label/value families drifting. */
    --nr-min-height: 68px;
    --nr-pad-y: 12px;
    /* A boxed group's header keeps the records look: the group title's size at 600, a padded band. */
    --row-card-head-min-height: 0;
    --row-card-head-pad: 12px 16px;
    --row-card-title-size: var(--row-group-title-size);
    --row-card-title-weight: 600;
    --row-card-icon-size: var(--row-group-title-size);
    --row-card-icon-fg: var(--row-label-fg);
    --nr-pad-x: 16px;
    --nr-gap: 16px;
    --nr-title-size: 16px;
    --nr-support-size: 14px;
    --nr-radius: 10px;
    --nr-surface: var(--rec-surface);
    --nr-surface-hover: var(--rec-row-hover);
    --nr-border: var(--rec-border);
    /* Softer between rows than around the card, so a run of rows reads as one card. */
    --nr-divider: var(--rec-border-soft);
    --nr-title: var(--rec-text);
    --nr-support: var(--rec-faint);
    --nr-chevron: var(--rec-faint);
    /* Hovering a row must not recolour its title toward the link blue — on this surface the title is
       the record's name, and the row is a surface rather than a phrase. */
    --nr-accent: var(--rec-text);
    --nr-icon-bg: var(--rec-sunken);

    /* No type overrides. A record's label-and-value rows render at the AUTHORING scale —
       same label column, same sizes, same weights — because they are the same rows: a manager
       reading a value on /records and reading it in the console must not see two typographies
       of the same fact. The surface's own scale lives in --nr-* above, where it belongs: a
       NavRow is a touch target read at arm's length, a field row is text.

       The --rec-* palette this surface would have pointed the colour tokens at is byte-identical
       to the authoring defaults anyway (#16211d / #47574f / #627268 / #d3dad5 / #e4e9e5 / #fff),
       so dropping them changed no colour. The PWA, which defines no --fg- or --canvas- tokens,
       lands on the literal fallbacks in the :root block above — the same values again. */

    /* The one exception, and it is layout rather than type: an EDIT row stays stacked here.
       Capture on this surface is focus mode — one step per screen, label over control, thumb-
       sized targets — so a 40% label column beside the input is the wrong shape for it. What
       a reader sees is identical to authoring; what a recorder touches is not. */
    --row-edit-columns: minmax(0, 1fr);
    --row-edit-gap: 0px;
    --row-edit-label-offset: 0px;
}

/* Restates the defaults so authoring content nested inside a record surface wins back. */
.hq-surface--authoring {
    --row-label-fg: var(--fg-muted);
    --row-label-size: var(--text-sm);
    --row-label-weight: 500;
    --row-label-spacing: 0;
    --row-value-fg: var(--fg-default);
    --row-value-size: var(--text-md);
    --row-help-fg: var(--fg-muted);
    --row-help-size: var(--text-2xs);
    --row-required-fg: var(--danger-fg);
    --row-error-fg: var(--danger-fg);
    --row-empty-fg: var(--fg-subtle);
    --row-line: var(--border-muted);
    --row-group-bg: var(--canvas-default);
    --row-group-line: var(--border-default);
    --row-group-radius: var(--radius-lg);
    --row-group-fg: var(--fg-default);
    --row-group-title-size: var(--text-md);
    --row-card-head-min-height: 53px;
    --row-card-head-pad: 0 16px;
    --row-card-title-size: var(--text-sm);
    --row-card-title-weight: 500;
    --row-card-icon-size: var(--text-md);
    --row-card-icon-fg: var(--fg-subtle);

    --row-read-label-fg: var(--fg-subtle);
    --row-read-label-weight: 400;
    --row-read-label-size: var(--text-15);
    --row-read-value-size: var(--text-15);
    --row-read-columns: minmax(0, 2fr) minmax(0, 3fr);
    --row-read-gap: 20px;
    --row-read-value-weight: 500;
    --row-edit-columns: 40% minmax(0, 1fr);
    --row-edit-gap: 20px;
    --row-edit-label-offset: 8px;
}

/* ── The group ─────────────────────────────────────────────────────────────────────────── */

/* A plain container. Rows carry their own separators, so the group draws none — which is also
   why it does not care whether every child is a row (a statement or a picker can sit between
   two of them). */
.hq-rows {
    display: grid;
    gap: 0;
}

.hq-rows-card {
    --row-pad-x: 16px;
    background: var(--row-group-bg);
    border: 1px solid var(--row-group-line);
    border-radius: var(--row-group-radius);
    overflow: hidden;
}

.hq-rows-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 0 6px;
    color: var(--row-group-fg);
}

.hq-rows-card > .hq-rows-header {
    box-sizing: border-box;
    min-height: var(--row-card-head-min-height);
    padding: var(--row-card-head-pad);
    border-bottom: 1px solid var(--row-line);
    --row-group-icon-size: var(--row-card-icon-size);
    --row-group-icon-fg: var(--row-card-icon-fg);
}
.hq-rows-card > .hq-rows-header .hq-rows-title {
    font-size: var(--row-card-title-size);
    font-weight: var(--row-card-title-weight);
}

/* A boxed group on the records surface holds things that are NOT rows — an asset picker, a row of
   chips, a BelongsTo tree, a Statement's own tinted block. A row pads itself with --row-pad-x; those
   do not, so inside a card they would sit flush against its edge. The group insets them instead of
   each caller remembering to.

   Scoped to this surface's screens (.record-page / .record-screen) on purpose: <InfoList> is shared
   with the authoring console, where boxed groups are hand-composed forms that already handle their
   own non-row children. */
.record-page .hq-rows-card > .hq-rows > :not(.hq-row),
.record-screen .hq-rows-card > .hq-rows > :not(.hq-row) {
    margin: 12px var(--row-pad-x);
}

.hq-rows-title {
    font-weight: 600;
    font-size: var(--row-group-title-size);
    line-height: 1.3;
}

.hq-rows-hint {
    font-weight: 400;
    font-size: var(--row-help-size);
    color: var(--row-help-fg);
}

/* A boxed group's title sits ABOVE its card as a quiet section label (HQU-1047) — the same voice
   as the Settings index's group labels (.settings-index-group-label in admin.css: 13px/600, muted),
   expressed in --row-* terms so a records surface re-points it like everything else here. */
.hq-rows-section {
    min-width: 0;
}
.hq-rows-heading {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 8px;
    font-size: var(--row-label-size);
    font-weight: 600;
    line-height: 1.3;
    color: var(--row-label-fg);
}

/* ── The row ───────────────────────────────────────────────────────────────────────────── */

.hq-row {
    margin: 0;
    padding: var(--row-pad-y) var(--row-pad-x);
    border-bottom: 1px solid var(--row-line);
}

.hq-row:last-child {
    border-bottom: 0;
}

/* Both modes are the same two-track row — label left, value right. They differ in breathing
   room and in what the value track holds: an edit row hosts a control, a read row hosts text.
   Same markup, same furniture, same columns; only the value slot changes. */
.hq-row--edit {
    --row-pad-y: 14px;
    display: grid;
    grid-template-columns: var(--row-edit-columns);
    column-gap: var(--row-edit-gap);
    row-gap: 4px;
    align-items: start;
}

.hq-row--read {
    --row-pad-y: 14px;
    display: grid;
    grid-template-columns: var(--row-read-columns);
    column-gap: var(--row-read-gap);
    row-gap: 4px;
    align-items: baseline;
}

/* The mockup's .field: label in the left track, value beside it, baselines aligned. The sizes,
   the colour, the weights and the track list all come from the surface (see --row-read-*), so
   the phone keeps its stacked rows without a second rule here. row-gap is what separates them
   when the track list collapses to one column — the label's own 4px margin would double it. */
.hq-row--read .hq-row-label {
    margin: 0;
    color: var(--row-read-label-fg);
    font-size: var(--row-read-label-size);
    font-weight: var(--row-read-label-weight);
}

.hq-row--read .hq-row-value {
    font-size: var(--row-read-value-size);
    font-weight: var(--row-read-value-weight);
}

/* The label sits in the left track, so its stacked bottom margin goes (row-gap covers the
   collapsed case) and the offset takes over: it drops the label to meet the first line of
   text inside the control beside it. Size comes from the READ token on purpose — see the
   --row-edit-* comment; weight and colour stay the edit label's own. */
.hq-row--edit .hq-row-label {
    margin: 0;
    padding-top: var(--row-edit-label-offset);
    font-size: var(--row-read-label-size);
}

/* A row with no label renders no <dt>, so the value would otherwise land in the LABEL track and
   be squeezed to it. Nothing but the value means nothing to align to — take both. */
.hq-row-value:only-child {
    grid-column: 1 / -1;
}

/* Not enough width for two tracks — the threshold tracks the label column, so it moved up with
   it. Flipping the ONE token is the whole change. */
@media (max-width: 860px) {
    .hq-row--read {
        --row-read-columns: minmax(0, 1fr);
        --row-read-gap: 0px;
    }

    .hq-row--edit {
        --row-edit-columns: minmax(0, 1fr);
        --row-edit-gap: 0px;
        --row-edit-label-offset: 0px;
    }
}

/* The breakpoint is on the VIEWPORT, so a row in a narrow BOX inside a wide window — a dialog,
   a drawer — has to say so itself: <InfoList Class="hq-rows--stacked">. */
.hq-rows--stacked {
    --row-read-columns: minmax(0, 1fr);
    --row-read-gap: 0px;
    --row-edit-columns: minmax(0, 1fr);
    --row-edit-gap: 0px;
    --row-edit-label-offset: 0px;
}

/* The opposite opt-out: a DESK form on the records surface — the record form, where somebody keeps a
   register up to date, and the new-request form — wants the authoring label column back, not focus
   mode's stacked capture rows (HQU-1074). Set on the group, so the 860px rule above, which sets the
   tokens on the row itself, still stacks it on a phone. */
.hq-rows--columns {
    --row-edit-columns: 40% minmax(0, 1fr);
    --row-edit-gap: 20px;
    --row-edit-label-offset: 8px;
}

.hq-row-label {
    display: block;
    margin: 0 0 4px;
    font-size: var(--row-label-size);
    font-weight: var(--row-label-weight);
    letter-spacing: var(--row-label-spacing);
    line-height: 1.3;
    color: var(--row-label-fg);
}

.hq-row-required {
    margin-left: 3px;
    color: var(--row-required-fg);
}

.hq-row-help {
    display: block;
    margin-top: 3px;
    font-size: var(--row-help-size);
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.45;
    color: var(--row-help-fg);
}

.hq-row-value {
    margin: 0;
    min-width: 0;
    font-size: var(--row-value-size);
    line-height: 1.45;
    color: var(--row-value-fg);
}

/* Read values are user-authored text of unknown length and shape. */
.hq-row--read .hq-row-value {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.hq-row-empty {
    color: var(--row-empty-fg);
    font-style: italic;
    font-weight: 400;
}

.hq-row-error {
    margin-top: 4px;
    font-size: var(--row-help-size);
    font-weight: 600;
    color: var(--row-error-fg);
}

/* ── Screen mode: the band, the save bar and the leave guard (HQU-296) ──────────
   Every colour below resolves through --rec-mode-*, which nothing else in this
   sheet may reference. That is what makes the mode readable at a glance: if it is
   ink blue you are doing something, and if it is not you are reading. */

/* width/align-self because the PWA shell is a CENTERED flex column: without them the band
   shrinks to its text and floats mid-screen instead of reading as a strip across the top. */
.record-mode-band {
    position: sticky;
    top: 0;
    z-index: 19;
    width: 100%;
    align-self: stretch;
    box-sizing: border-box;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 12px;
    padding: 12px 16px;
    color: var(--rec-mode-on);
    background: var(--rec-mode);
}

.record-mode-band strong {
    font-size: 0.98rem;
    font-weight: 700;
}

.record-mode-band span {
    font-size: 0.9rem;
    opacity: 0.92;
}

/* Saving steps one shade deeper rather than changing hue: the operator should read it
   as "the same thing, further along", not as a new state that needs interpreting. */
.record-mode-band--saving {
    background: var(--rec-mode-strong);
}

.record-mode-band--saved {
    background: var(--rec-mode-saved);
}

/* The edit bar brackets the screen with the band: rule at the top in the mode colour,
   so the two ends of a long form both report the mode without the middle needing to. */
.record-edit-bar {
    position: sticky;
    bottom: 0;
    z-index: 18;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    background: var(--rec-surface);
    border-top: 2px solid var(--rec-mode);
    box-shadow: 0 -6px 18px var(--rec-shadow);
}

/* MudBlazor's Color.Primary would paint the surface accent here. The save button has to
   carry the MODE colour instead — the button colour is one of the three things reporting
   the mode, and an accent-coloured one reports nothing. */
.record-edit-bar-save.mud-button-filled {
    background-color: var(--rec-mode);
    color: var(--rec-mode-on);
}

.record-edit-bar-save.mud-button-filled:hover:not(:disabled) {
    background-color: var(--rec-mode-strong);
}

.record-edit-bar-cancel {
    color: var(--rec-body);
}

.record-edit-bar-spacer {
    flex: 1 1 auto;
}

.record-edit-bar-hint {
    font-size: 0.85rem;
    color: var(--rec-muted);
}

/* On a phone the hint wraps to its own line under the buttons rather than squeezing them:
   the actions are what the thumb needs, the hint is what the eye needs. */
@media (max-width: 560px) {
    .record-edit-bar-spacer {
        display: none;
    }

    .record-edit-bar-hint {
        flex: 1 0 100%;
        order: 3;
    }
}

.record-guard {
    position: fixed;
    inset: 0;
    z-index: 100;
}

.record-guard-scrim {
    position: fixed;
    inset: 0;
    background: rgba(22, 33, 29, 0.45);
}

.record-guard-box {
    position: relative;
    z-index: 1;
    margin: 14vh auto 0;
    max-width: 440px;
    padding: 20px;
    border-radius: 14px;
    background: var(--rec-surface);
    box-shadow: 0 20px 50px var(--rec-shadow);
}

.record-guard-title {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--rec-text);
}

.record-guard-body {
    margin: 8px 0 18px;
    font-size: 0.92rem;
    line-height: 1.45;
    color: var(--rec-body);
}

.record-guard-acts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Keeping the work is the primary; discarding it is quiet and reads as danger. */
.record-guard-stay.mud-button-filled {
    background-color: var(--rec-mode);
    color: var(--rec-mode-on);
}

.record-guard-stay.mud-button-filled:hover:not(:disabled) {
    background-color: var(--rec-mode-strong);
}

.record-guard-leave {
    color: var(--rec-danger);
}

/* ============================================================================
   HQU-298 — Today, and the records list.

   The two screens people arrive on. Everything below serves one of three things:
   the lifecycle tag that says what a record IS, the sectioned Today layout, and
   the records list's filter chips.
   ============================================================================ */

/* ── The lifecycle tag (RecordStatusTag) ──────────────────────────────────────
   The FILLED earth-and-safety pill, on the StatusTone axis (BehaviourFlagDefinitions
   → StatusTone → tone-*). Distinct from .record-run-status above, which is the
   worklist card's pill on RecordRunPresentation's own five-tone vocabulary; both
   land on tone-* classes, and each scopes its own palette off the same suffix.

   Strictly the lifecycle family: never blue. Blue is the screen-MODE axis, and a
   glance at the colour has to say which of the two questions is being answered. */
:root {
    --rec-tag-neutral-bg: #e5eae7; --rec-tag-neutral-fg: #55665f;
    --rec-tag-info-bg:    #ddeef0; --rec-tag-info-fg:    #0e5a66;
    --rec-tag-warning-bg: #fce9dd; --rec-tag-warning-fg: #a93b08;
    --rec-tag-success-bg: #dcebe1; --rec-tag-success-fg: #12603b;
    --rec-tag-danger-bg:  #fbe4e2; --rec-tag-danger-fg:  #a31212;
}

.record-status-tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: var(--text-sm, 13px);
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

/* The dot carries the tone at small sizes, where the fill alone is too little colour
   to read at a glance down a long list. */
.record-status-tag::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}

.record-status-tag.tone-neutral { background: var(--rec-tag-neutral-bg); color: var(--rec-tag-neutral-fg); }
.record-status-tag.tone-info    { background: var(--rec-tag-info-bg);    color: var(--rec-tag-info-fg); }
.record-status-tag.tone-warning { background: var(--rec-tag-warning-bg); color: var(--rec-tag-warning-fg); }
.record-status-tag.tone-success { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); }
.record-status-tag.tone-danger  { background: var(--rec-tag-danger-bg);  color: var(--rec-tag-danger-fg); }

/* ── Rows (RecordRowList) ─────────────────────────────────────────────────────
   The rows themselves are NavRow and are styled above; only the overdue accent is
   new. It is a LEFT EDGE, not a recolour of the row or the tag: the tag says what
   the record is, and lateness is a separate fact that must not overwrite it. */
.record-row-list .navrow.is-overdue {
    box-shadow: inset 3px 0 0 0 var(--rec-tag-danger-fg);
}

.record-row-list .navrow.is-overdue .navrow-support {
    color: var(--rec-tag-danger-fg);
}

/* ── Assets map (HQU-1474) ─────────────────────────────────────────────
   The map takes the column; a selected pin's card sits beside it on a wide screen and under it on a phone. The
   type filter is a row of toggle chips — every type on by default, one tap hides it. */
.record-assetmap-filter {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 12px;
}

.record-assetmap-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 0 14px;
    border: 1px solid var(--rec-border);
    border-radius: 999px;
    background: var(--rec-surface);
    color: var(--rec-muted);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
}

.record-assetmap-chip:hover { background: var(--rec-hover); }

.record-assetmap-chip.is-on {
    border-color: var(--rec-accent);
    color: var(--rec-text);
    font-weight: 600;
}

.record-assetmap-chip-count { color: var(--rec-faint); font-weight: 400; }

.record-assetmap-body {
    display: flex;
    gap: 16px;
    align-items: flex-start;
}

.record-assetmap-map {
    flex: 1 1 auto;
    min-width: 0;
    height: min(70vh, 640px);
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    overflow: hidden;
}

.record-assetmap-list { flex: 1 1 auto; min-width: 0; }

.record-assetmap-card {
    flex: 0 0 280px;
    padding: 14px 16px;
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    background: var(--rec-surface);
}

.record-assetmap-card-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 8px;
}

.record-assetmap-card-title {
    font-weight: 600;
    color: var(--rec-text);
    overflow-wrap: anywhere;
}

.record-assetmap-card-status,
.record-assetmap-card-coords {
    margin-top: 8px;
    font-size: 14px;
    color: var(--rec-muted);
}

.record-assetmap-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}

.record-assetmap-modules {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-top: 12px;
}

@media (max-width: 760px) {
    .record-assetmap-body { flex-direction: column; align-items: stretch; }
    .record-assetmap-map { height: 60vh; }
    .record-assetmap-card { flex-basis: auto; }
}

/* ── The asset register (RecordAssetsScreen) ──────────────────────────────────
   Rows are NavRow in the shared .navrow-list card, so nothing here restyles them. The only
   addition is the truncation note under the card: it is a footnote about the LIST, not a row in
   it, so it sits outside the card and reads at the muted size. */
.record-asset-capped {
    margin: 10px 2px 0;
    font-size: 14px;
}

/* ── Button ─────────────────────────────────────────────────────────────
   The shell mockup's .btn / .btn-primary (app.css). A primary action here is INK, not the brand
   accent — the mockups have no accent at all, and on this surface colour is spent on what a record
   IS (the lifecycle family) and what you are DOING to it (the ink-blue mode family). A blue CTA
   would put a third colour family on a screen whose other two are load-bearing.

   Renders on an <a> as readily as a <button>, so a control that navigates can stay a real link.
   Note the explicit justify/align: a UA centres a flex <button>'s content for you and does NOT do
   the same for an <a>, so leaving it out gives two shapes for one class. */
.record-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: var(--rec-tap);
    padding: 0 18px;
    border: 1px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-surface);
    color: var(--rec-text);
    font-family: var(--rec-font-body);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

.record-btn:hover { background: var(--rec-hover); text-decoration: none; }

.record-btn--primary {
    background: var(--rec-accent);
    border-color: var(--rec-accent);
    color: var(--rec-surface);
}

.record-btn--primary:hover { background: var(--rec-accent-hover); }

.record-btn .record-btn-icon { font-size: 20px; color: inherit; }

/* Full-width variant, for the card screens (sign-in, enrolment, device management) where a
   control owns its own row and the card is only ~370px wide. The auto-width default is for a
   control sharing a row with others; on a phone card there is nothing to share with. */
.record-btn--block {
    display: flex;
    width: 100%;
}

/* A disabled control has to LOOK unavailable, or a staff member taps it repeatedly and
   concludes the app is broken. Declared for both marker shapes so it holds on the <button>
   and on anything that carries the class with aria-disabled. */
.record-btn:disabled,
.record-btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: default;
}

.record-btn:disabled:hover { background: var(--rec-surface); }
.record-btn--primary:disabled:hover { background: var(--rec-accent); }

/* ── Which organisation this is ────────────────────────────────────────────
   An eyebrow above the title on the ANONYMOUS card screens (HQU-746). The signed-in
   surface names the org in its top bar instead, so this only ever appears where there
   is no chrome to carry it. Muted and small: it is context, never the headline. */
.record-org-head {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-bottom: 4px;
    color: var(--rec-muted);
    font-size: 0.82rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.record-org-head .mud-icon-root { font-size: 16px; }

/* ── The screen on paper: head, sections, states ─────────────────────────
   mockups/venuehq-shell app.css (.page / .pagehead / .section). Every screen on this surface is an
   eyebrow / title / one-line-sub head, then sections, each section a card of rows — deliberately NOT
   RecordPageScaffold's centred header and NOT a .record-card, because these are screens being READ
   on paper rather than drill-ins being navigated.

   These classes belong to RecordScreenHead, not to any one screen: Today wore them first under
   .record-today-* names, and HQU-428 gave the same head to the four screens inside the shell.

   The screens render in two hosts: the portal's /records column, where the layout supplies the page
   padding and the width cap, and the PWA's centred .record-shell, where it does not. The cap below
   is what makes one screen behave in both. */
.record-screen {
    width: 100%;
    max-width: var(--page-max, 940px);
}

.record-head {
    display: flex;
    align-items: flex-start;
    gap: 20px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

/* Pulled up and out so the glyph sits on the title's line and on the column's left edge, rather
   than indenting the h1 everything below it is aligned to. */
.record-head-back {
    flex: 0 0 auto;
    margin: 10px 0 0 -8px;
}

/* A back arrow shown ONLY on a phone (HQU-902) — the record viewer's way back to Today, where the
   chrome's own way out is truncated or off screen. */
.record-head--phone-back .record-head-back { display: none; }
@media (max-width: 760px) {
    .record-head--phone-back .record-head-back { display: inline-flex; }
}

.record-headline {
    flex: 1 1 260px;
    min-width: 0;
}

.record-eyebrow {
    margin: 0 0 4px;
    font-size: 14px;
    color: var(--rec-faint);
    /* Reserve the line so the head doesn't jump when the date arrives with the data. */
    min-height: 1.2em;
}
/* The module name in a record's eyebrow opens that module's list (HQU-1451) — quiet until pointed at, as .rtl-ref. */
.record-eyebrow-link { color: inherit; text-decoration: none; }
.record-eyebrow-link:hover { color: var(--rec-text); text-decoration: underline; }

/* At most three lines (HQU-1396): a 255-character record name ran to 7 lines at desktop and 12 on a
   phone, pushing the actions and Details below the fold. The full name is in the h1's tooltip, and a
   record's Details (or its Name field on Edit) shows it again. */
/* The title and its small control (HQU-1452). The control's slot is one title line tall — the same
   font-size as the h1 at every tier — so the star centres on the FIRST line of a long, wrapped name. */
.record-head-titlerow { display: flex; align-items: flex-start; gap: 6px; }
.record-head-titlerow > .record-head-title { flex: 0 1 auto; min-width: 0; }
.record-head-title-action {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    height: 1.15em;
    font-size: 30px;
}

.record-head-title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
    margin: 0;
    font-family: var(--rec-font-display);
    font-size: 30px;
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.012em;
    color: var(--rec-text);
    overflow-wrap: anywhere;
}

/* A module description is free text, and one long unbroken run (a pasted URL, a code) must wrap
   inside the head rather than run off the card and get clipped at the window edge (HQU-1300). */
.record-head-sub {
    margin: 6px 0 0;
    font-size: 16px;
    color: var(--rec-muted);
    min-height: 1.4em;
    overflow-wrap: anywhere;
}

/* NOTHING in the headline is interactive, so nothing in it should ever wear a focus ring — and
   yet a pale blue rounded box turns up around the title now and then. Focus lands on the h1
   (a dialog closing and restoring focus onto a node that has since re-rendered is the usual
   way), and both hosts then draw it:

     · the portal, from hque-overrides.css's universal `*:focus-visible`, which rings ANY
       element focus reaches — box-shadow in the tenant accent at 30%, radius 6px, which is
       exactly the box;
     · the PWA, from the browser's own default `outline: auto`, since it loads no overrides.

   So both are killed here rather than in either host: this is the RCL's own head, it is the
   same defect on both surfaces, and a class selector out-specifies the universal rule wherever
   the two stylesheets happen to land in the cascade. Real controls in the head — the back
   button, the actions slot — are untouched and keep their rings. */
.record-eyebrow:focus,
.record-eyebrow:focus-visible,
.record-head-title:focus,
.record-head-title:focus-visible,
.record-head-sub:focus,
.record-head-sub:focus-visible {
    outline: none;
    box-shadow: none;
}

/* Aligned with the title rather than the eyebrow — the head's optical baseline is the h1. */
/* A flex row, not inline boxes: a MudIconButton and a .record-btn are both inline-flex, and left to
   sit on a text line they aligned by baseline, which dropped the icon-only star below the button
   beside it (HQU-846). Centred on one axis, they share one top and one bottom edge. */
.record-head-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 18px;
    /* Wrapped under the title, the controls keep to the trailing edge: the split control's menu opens
       right-anchored, and from the left edge it would run off a phone's screen (HQU-1419). */
    margin-left: auto;
}

.record-section {
    margin-top: 28px;
}

.record-section-head {
    margin: 0 0 10px;
    font-family: var(--rec-font-display);
    font-size: 15px;
    font-weight: 600;
    color: var(--rec-muted);
}

/* A second group heading in one list (the wizard's Recent / All workspaces, HQU-1443). */
.record-section-head--next { margin-top: 22px; }

.record-count {
    color: var(--rec-faint);
    font-weight: 500;
    margin-left: 4px;
}

/* On paper there is no card, so every NON-list outcome — loading, failure, empty, no-match — gets
   the box the rows' card would otherwise have provided. One rule rather than a wrapper per screen:
   RecordAsyncView owns two of these states, so a screen cannot box them all from the outside.
   Both paper columns take it: .record-screen (the converted screens) and .record-page (the
   scaffolded ones, which lost their page card with it). */
.record-screen .record-state,
.record-page .record-state {
    margin-top: 28px;
    padding: 22px 16px;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 10px;
}

@media (max-width: 600px) {
    .record-head { gap: 14px; }
    .record-head-title, .record-head-title-action { font-size: 25px; }
    /* Its own row under the title on a phone, the icon controls at its trailing edge (HQU-1419). */
    .record-head-actions { width: 100%; justify-content: flex-end; margin-top: 0; }
    .record-section { margin-top: 22px; }
}

/* ── The records list ─────────────────────────────────────────────────────────
   The whole filter block — chips plus the module selector — held apart from the list it filters.
   It sits ABOVE the async view rather than inside it, so a filter somebody just changed does not
   vanish while the re-fetch it triggered is in flight. */
.record-filter-bar {
    margin-bottom: 14px;
}

/* Search — a display-name filter above the chips (HQU-496), the records-surface twin of the
   management list's .til-search: same shape, painted in the paper palette instead of the admin
   tokens so it belongs on this surface. */
.record-search-wrap {
    position: relative;
    max-width: 360px;
    margin-bottom: 12px;
}

/* Positioning only — size and colour are set inline on the MudIcon so the icon-size utility
   class can't win a specificity fight over them (the management search does the same). */
.record-search-icon {
    position: absolute;
    left: 10px;
    top: 50%;
    transform: translateY(-50%);
    pointer-events: none;
}

/* 38px everywhere (HQU-1411), the .record-select filters' height — it is the one list search, <SearchBox>. */
.record-search {
    width: 100%;
    height: 38px;
    box-sizing: border-box;
    padding: 8px 12px 8px 36px;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    color: var(--rec-text);
    font-size: var(--text-sm, 14px);
    outline: none;
    transition: border-color 0.15s;
}

.record-search::placeholder {
    color: var(--rec-faint);
}

.record-search:focus {
    border-color: var(--rec-muted);
}

/* Filter chips. They scroll horizontally on a phone rather than wrapping to three
   rows and pushing the list itself below the fold. */
.record-filters {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 4px;
    -webkit-overflow-scrolling: touch;
}

.record-chip {
    flex: none;
    padding: 6px 14px;
    min-height: 34px;
    border: 1px solid var(--rec-border);
    border-radius: 999px;
    background: var(--rec-surface);
    color: var(--rec-muted);
    font-size: var(--text-sm, 13px);
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
}

.record-chip:hover {
    background: var(--rec-row-hover);
    color: var(--rec-text);
}

/* The selected chip is filled ink, not a tinted lifecycle colour: which filter is on
   is something YOU did, and the lifecycle family is reserved for what records are. */
.record-chip.is-on {
    background: var(--rec-text);
    border-color: var(--rec-text);
    color: var(--rec-surface);
    font-weight: 600;
}


/* One-row variant (HQU-803): a bar with a single chip sits it beside the search instead of on
   its own line underneath. The search gives up width first, so both stay on one row on a phone. */
.record-filter-bar.is-inline {
    display: flex;
    align-items: center;
    gap: 10px;
}

.record-filter-bar.is-inline .record-search-wrap {
    flex: 0 1 360px;
    min-width: 0;
    margin-bottom: 0;
}

.record-filter-bar.is-inline .record-filters {
    flex: none;
    padding-bottom: 0;
}

/* Fill variant (HQU-845), the records list: the search TAKES the row and the dropdowns sit at its
   end, GitHub's list-filter shape. Wraps rather than squeezing — on a phone the search keeps its own
   line and the dropdowns share the one under it. */
.record-filter-bar.is-fill { flex-wrap: wrap; }

.record-filter-bar.is-fill .record-search-wrap { flex: 1 1 240px; }
.record-filter-bar.is-fill .record-search { height: 38px; }

/* A compact dropdown, the search box's twin: same height, border, radius and type size, so the row
   reads as one strip of controls. appearance:none drops the UA's own arrow for the MudIcon beside
   it, which lines up with the search's glyph. */
.record-select-wrap {
    position: relative;
    flex: 0 1 auto;
    min-width: 0;
}

.record-select {
    appearance: none;
    -webkit-appearance: none;
    height: 38px;
    max-width: 240px;
    padding: 0 34px 0 12px;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    color: var(--rec-text);
    font-family: inherit;
    font-size: var(--text-sm, 14px);
    font-weight: 500;
    text-overflow: ellipsis;
    cursor: pointer;
    outline: none;
    transition: border-color 0.15s;
}

.record-select:hover { background: var(--rec-row-hover); }
.record-select:focus-visible { border-color: var(--rec-muted); }

/* A filter that is ON wears ink, the same "you did this" family as the selected chip. */
.record-select.is-on {
    border-color: var(--rec-text);
    font-weight: 600;
}

.record-select-wrap .record-select-icon {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 22px;
    color: var(--rec-muted);
    pointer-events: none;
}

/* ONE dropdown list on the records surface (HQU-1075). The native selects opened the OS list (square,
   system-blue highlight) while the MudBlazor pickers opened a rounded popover, so the same screen
   showed two dropdowns. Both open lists now wear one look: paper surface, the control's border and
   radius, the row-hover grey, and the selected row in the ink family the "is-on" filter uses.

   Native side: a customizable select (appearance: base-select) where the browser has it AND the
   pointer is fine. On a phone the OS picker stays — it is the best dropdown there is (HQU-845) — and
   a browser without base-select keeps its own list. The picker sits in the top layer, so the portal
   shell's overflow clip can't cut it off. Mud side: give the picker PopoverClass="record-popover". */
@media (pointer: fine) {
    @supports (appearance: base-select) {
        .record-select, .record-select::picker(select) {
            appearance: base-select;
        }

        /* A base-select lays its value out at the TOP of the box, so the fixed 38px .record-select read
           top-heavy beside every other control. Centre it. */
        .record-select { display: inline-flex; align-items: center; }

        /* The MudIcon beside each select is the arrow; the selected row's tint is the tick. */
        .record-select::picker-icon,
        .record-select option::checkmark {
            display: none;
        }

        .record-select::picker(select) {
            margin-block: 4px;
            padding: 4px 0;
            background: var(--rec-surface);
            border: 1px solid var(--rec-border);
            border-radius: 8px;
            box-shadow: 0 6px 18px var(--rec-shadow);
            color: var(--rec-text);
            font-weight: 400;
            max-height: 320px;
        }

        .record-select option {
            padding: 7px 12px;
            font-size: var(--text-sm, 14px);
            cursor: pointer;
        }

        .record-select option:hover, .record-select option:focus-visible {
            background: var(--rec-row-hover);
            outline: none;
        }

        .record-select option:checked {
            background: var(--rec-accent-soft);
            font-weight: 600;
        }
    }
}

.mud-popover.record-popover {
    margin-block: 4px;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    box-shadow: 0 6px 18px var(--rec-shadow) !important;
}

.record-popover .mud-list { padding: 4px 0; }

.record-popover .mud-list-item {
    color: var(--rec-text);
    font-size: var(--text-sm, 14px);
}

.record-popover .mud-list-item:hover { background: var(--rec-row-hover); }

.record-popover .mud-list-item.mud-selected-item {
    background: var(--rec-accent-soft);
    color: var(--rec-text);
    font-weight: 600;
}

/* On a phone the three controls STACK (HQU-901): sharing a row, the two dropdowns shrank to empty
   arrow boxes whose chosen value couldn't be read. Each takes the full width on its own line. */
@media (max-width: 600px) {
    .record-filter-bar.is-fill { flex-direction: column; align-items: stretch; gap: 8px; }
    .record-filter-bar.is-fill .record-search-wrap { flex: none; width: 100%; }
    .record-filter-bar.is-fill .record-select-wrap { flex: none; width: 100%; }
    .record-filter-bar.is-fill .record-select { width: 100%; max-width: none; }
}

.record-list-more {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    margin-top: 16px;
}

.record-list-count {
    font-size: var(--text-sm, 13px);
    color: var(--rec-faint);
}

/* ── The records list as a feed (RecordFeedTable, HQU-941) ───────────────────
   The management run feed's shape (TableRunFeed.razor.css) in this sheet's own palette: ONE frame,
   a light column header, day headings as rows inside it, and a shared column grid. On a phone the
   frame dissolves and each day's rows become a card under their heading. */
.rft {
    /* The rows switch to the card layout on the TABLE's width, not the viewport's (HQU-1389): the
       portal's sidebar changes the room, and at tablet width the fixed columns left Record ~70px. */
    container: rft / inline-size;
    display: flex;
    flex-direction: column;
    background: var(--rec-surface);
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    overflow: hidden;
}

.rft-head,
.rft-row {
    display: grid;
    /* Status is sized for the longest label a pill carries — "Awaiting inspection" (HQU-1134);
       132px only ever fitted the run statuses, so an asset's "Under maintenance" ran into Record. */
    grid-template-columns: 176px minmax(0, 1fr) minmax(0, 180px) 96px 72px 18px;
    column-gap: 16px;
    align-items: center;
    padding: 0 20px;
}

.rft-head {
    padding-top: 9px;
    padding-bottom: 9px;
    background: var(--rec-raised);
    border-bottom: 1px solid var(--rec-border-soft);
    font-size: 12px;
    font-weight: 600;
    color: var(--rec-faint);
    letter-spacing: 0.02em;
}

.rft-head-end { text-align: right; }

.rft-day {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
    padding: 14px 20px 8px;
}

.rft-group + .rft-group .rft-day { border-top: 1px solid var(--rec-border-soft); }

.rft-day-name {
    font-family: var(--rec-font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--rec-text);
}

.rft-day-detail {
    font-size: 13px;
    color: var(--rec-faint);
}

.rft-row {
    position: relative;
    min-height: 76px;
    padding-top: 10px;
    padding-bottom: 10px;
    border-top: 1px solid var(--rec-border-soft);
    transition: background-color 80ms ease;
}

.rft-row:hover { background: var(--rec-row-hover); }

/* Register mode (HQU-1152/1155): a flat table for anything but runs and incidents — no Duration, no date, no day headings,
   so the first row sits straight under the column header. */
.rft.is-register .rft-head,
.rft.is-register .rft-row { grid-template-columns: 176px minmax(0, 1fr) minmax(0, 180px) 18px; }
.rft.is-register .rft-rows .rft-row:first-child { border-top: none; }

/* A behaviour's modules table (HQU-1155, RecordModuleTable): Module · Record prefix · Records, flat. */
.rft.is-modules .rft-head,
.rft.is-modules .rft-row { grid-template-columns: minmax(0, 1fr) 140px 96px 18px; }
.rft.is-modules.no-count .rft-head,
.rft.is-modules.no-count .rft-row { grid-template-columns: minmax(0, 1fr) 140px 18px; }
.rft.is-modules .rft-row { min-height: 52px; }
.rft.is-modules .rft-rows .rft-row:first-child { border-top: none; }

.rmt-prefix {
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--rec-muted);
}

.rmt-count {
    text-align: right;
    font-size: 14px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--rec-text);
}

.rmt-prefix.is-none,
.rmt-count.is-none { color: var(--rec-faint); font-weight: 400; }

/* Status pill: icon + label. The icons differ in SHAPE, so status never rests on hue alone. */
.rft-status { min-width: 0; }

.rft-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 10px 0 8px;
    border-radius: 999px;
    /* The .record-status-tag size, so a status reads the same in the list as on Home (HQU-1417). */
    font-size: var(--text-sm, 13px);
    font-weight: 600;
    white-space: nowrap;
    max-width: 100%;
}

/* A label longer than the column still ends inside its pill, never over the next column. */
.rft-pill-text {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rft-pill-icon {
    width: 14px;
    height: 14px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 2.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.rft-pill--completed  { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); }
.rft-pill--inprogress { background: var(--rec-tag-warning-bg); color: var(--rec-tag-warning-fg); }
.rft-pill--notstarted { background: var(--rec-tag-neutral-bg); color: var(--rec-tag-neutral-fg); }
.rft-pill--failed     { background: var(--rec-tag-danger-bg);  color: var(--rec-tag-danger-fg); }
.rft-pill--stopped    { background: var(--rec-tag-neutral-bg); color: var(--rec-tag-neutral-fg); }
.rft-pill--active     { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); }

/* Record column: headline, then the record's TYPE (its module) and code, subjects, the shield. */
.rft-record {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 3px;
    min-width: 0;
}

.rft-name {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    max-width: 100%;
    min-width: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--rec-text);
    text-decoration: none;
}

.rft-name:hover { text-decoration: none; }

/* The link's hit area stretched over the whole row: a click anywhere opens the record. The ring is
   drawn on the row instead, so it is not clipped to the headline text. */
.rft-name::after {
    content: "";
    position: absolute;
    inset: 0;
}
.rft-name:focus-visible { outline: none; box-shadow: none; }
.rft-row:has(.rft-name:focus-visible) { box-shadow: inset 0 0 0 2px var(--rec-accent); }

.rft-name-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The asset glyph — the same Inventory2 box the Assets list, menu and feed draw (HQU-1441); it was a
   hand-drawn cube here. */
.rft-glyph.mud-icon-root {
    width: 15px;
    height: 15px;
    font-size: 15px;
    flex: none;
    color: var(--rec-faint);
}

/* One line: the module name is the only part that truncates, so a long name never pushes the code
   or the version pill out of the clipped box (HQU-1342). */
.rft-type {
    display: flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    min-width: 0;
    font-size: 13px;
    color: var(--rec-muted);
    white-space: nowrap;
}

.rft-type-module {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rft-type-code { flex: none; }

/* The version a run was recorded against (HQU-1342) — an OUTLINE, the portal's definition-axis
   shape (.vchip--sm), so it reads as "which design" and never as a status capsule. Neutral, not
   the live colour: an older version is not a warning, just a different form. */
.rft-version {
    display: inline-flex;
    flex: none;
    align-items: center;
    height: 18px;
    padding: 0 6px;
    border: 1px solid var(--rec-border);
    border-radius: var(--radius-sm, 4px);
    font-size: 11px;
    font-weight: 600;
    color: var(--rec-muted);
}

.rft-subjects {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 12px;
    min-width: 0;
}

/* Above the row's stretched link, so a subject opens the asset rather than the record. */
.rft-subject {
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    max-width: 100%;
    font-size: 12px;
    font-weight: 500;
    color: var(--rec-muted);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.rft-subject .rft-glyph.mud-icon-root { width: 13px; height: 13px; font-size: 13px; }
.rft-subject:hover { color: var(--rec-text); text-decoration: underline; text-underline-offset: 2px; }

.rft-verified {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    color: var(--rec-muted);
}

.rft-verified svg {
    width: 13px;
    height: 13px;
    flex: none;
    fill: none;
    stroke: var(--rec-tag-success-fg);
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* Recorded by / Duration / Started */
.rft-by {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    font-size: 14px;
    color: var(--rec-muted);
}

.rft-av {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--rec-accent);
    color: var(--rec-surface);
    font-size: 10px;
    font-weight: 600;
}

.rft-by-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rft-by-name.is-none { color: var(--rec-faint); }

.rft-duration,
.rft-when {
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.rft-duration { color: var(--rec-text); }
/* An open record shows how long it has BEEN open, in the attention tone, so a stale one stands out. */
.rft-duration.is-open { color: var(--rec-tag-warning-fg); font-weight: 600; }
.rft-duration.is-none { color: var(--rec-faint); }

.rft-when {
    text-align: right;
    color: var(--rec-muted);
}

/* The chevron is an affordance, not information — faint until the row is under the cursor. */
.rft .rft-chev {
    font-size: 20px;
    color: var(--rec-border);
    transition: color 80ms ease, transform 80ms ease;
}
.rft-row:hover .rft-chev {
    color: var(--rec-muted);
    transform: translateX(2px);
}

/* Phone: the frame dissolves; each day is a heading over a card of its own. The rows themselves
   follow the container rule below. */
@media (max-width: 720px) {
    .rft {
        gap: 16px;
        background: transparent;
        border: none;
        border-radius: 0;
        overflow: visible;
    }

    .rft-group {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }

    .rft-day,
    .rft-group + .rft-group .rft-day {
        padding: 0 4px;
        border-top: none;
    }

    .rft-rows {
        background: var(--rec-surface);
        border: 1px solid var(--rec-border);
        border-radius: 10px;
        overflow: hidden;
    }
}

/* A table too narrow for its columns (a phone, a tablet, the portal beside its sidebar) reads each
   row as a card: pill + time / name / type / person · duration · shield. The fixed tracks need
   ~660px, so below ~900px Record would be squeezed to a few letters (HQU-1389). No column header —
   no columns. */
@container rft (max-width: 900px) {
    .rft-head { display: none; }

    /* The time shares the status row's area, right-aligned, rather than owning a column: a column
       of its own also reserved its width on the byline, truncating the person's name (HQU-1342). */
    .rft-row {
        grid-template-columns: auto auto auto minmax(0, 1fr);
        grid-template-areas:
            "status status status status"
            "name   name   name   name"
            "type   type   type   type"
            "subj   subj   subj   subj"
            "by     dur    ver    .";
        row-gap: 0;
        column-gap: 8px;
        min-height: 0;
        padding: 14px 16px;
    }

    .rft-rows .rft-row:first-child { border-top: none; }

    /* The record column's parts join the card's grid directly so the shield sits on the byline. */
    .rft-record   { display: contents; }
    .rft-status   { grid-area: status; }
    .rft-when     { grid-area: status; justify-self: end; align-self: center; }
    .rft-name     { grid-area: name; margin-top: 6px; font-size: 17px; }
    .rft-type     { grid-area: type; margin-top: 3px; }
    .rft-subjects { grid-area: subj; margin-top: 3px; }
    .rft-by       { grid-area: by; gap: 8px; margin-top: 6px; }
    .rft-duration { grid-area: dur; margin-top: 6px; }
    .rft-verified { grid-area: ver; margin-top: 6px; }

    .rft-duration::before {
        content: "·";
        margin-right: 8px;
        color: var(--rec-faint);
        font-weight: 400;
    }

    .rft-verified-text {
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .rft .rft-chev { display: none; }

    /* The modules table stays one line per module on a phone: name, prefix, count. */
    .rft.is-modules .rft-row {
        grid-template-columns: minmax(0, 1fr) auto auto;
        grid-template-areas: none;
        column-gap: 12px;
    }

    .rft.is-modules.no-count .rft-row { grid-template-columns: minmax(0, 1fr) auto; }

    .rft.is-modules .rft-name { grid-area: auto; margin-top: 0; font-size: 15px; }
}

/* The PWA landing's secondary links, below Today. */
.record-home-links {
    margin-top: 16px;
}

/* ── Signature prompt (HQU-757) ───────────────────────────────────────────────
   The PIN pad raised OVER work in progress, when something that records needs a person and
   there is not one. It is a sheet rather than a dialog because the content is the full tile +
   PIN screen, which on a phone is already the size of a page; boxing it in a dialog would give
   it two sets of chrome and a scrollbar of its own. The working tree stays mounted underneath,
   untouched, so declining returns to exactly what was on screen. */
.record-signature-overlay {
    align-items: flex-start;
    justify-content: center;
}

.record-signature-sheet {
    overflow-y: auto;
    width: 100%;
    max-width: 520px;
    max-height: 100dvh;
    padding: 12px;
}

/* ── Record timeline (HQU-925) ──────────────────────────────────────────────
   ONE chronological story of a record, in the GitHub PR conversation shape: a
   spine of 32px icon dots, one-line events for things that HAPPENED and cards
   for things that were SAID (a step's answer, a comment, a file). Rendered by
   RecordTimeline on both surfaces; .rtl--compact is the management density.
   Every colour is a palette token; tabular numerals for every time. */
.rtl { display: flex; flex-direction: column; gap: 16px; font-family: var(--rec-font-body); color: var(--rec-text); }
.rtl > .record-section-head { margin: 0; } /* the column's gap spaces it, as on the activity feed */
/* A headed timeline is a section of the record page, so it stands off the panel above it as the asset
   page's feed does (.rec-feed, HQU-1447) — without it "Activity" sat flush under the Assets card. */
.rtl--headed { margin-top: 28px; }
/* .rtl-composer too: CommentComposer's label must stay hidden outside a timeline/feed, e.g. in Que (HQU-1121). */
.rtl .visually-hidden, .rtl-composer .visually-hidden {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.rtl-filter {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    border-top: 1px solid var(--rec-border-soft); padding-top: 16px;
}
.rtl-spacer { flex: 1; }
/* The order toggle and "Jump to latest" (HQU-1076): quiet text buttons, the size the static label was. */
.rtl-order {
    display: inline-flex; align-items: center; gap: 4px;
    min-height: 32px; padding: 0 8px; border: 0; border-radius: 6px; background: transparent;
    font: 500 13px var(--rec-font-body); color: var(--rec-faint); cursor: pointer;
}
.rtl-order:hover { color: var(--rec-text); background: var(--rec-row-hover); }
.rtl-order-icon { font-size: 18px !important; }
.rtl-end { list-style: none; height: 0; margin: -14px 0 0; padding: 0; } /* cancels the list gap */
.rtl-seg { display: inline-flex; flex-wrap: wrap; background: var(--rec-sunken); border-radius: 8px; padding: 3px; gap: 2px; }
.rtl-seg-btn {
    min-height: 32px; padding: 0 12px; border: 0; border-radius: 6px; background: transparent;
    font: 500 13px var(--rec-font-body); color: var(--rec-muted); cursor: pointer;
}
.rtl-seg-btn:hover { color: var(--rec-text); }
.rtl-seg-btn.is-on { background: var(--rec-surface); color: var(--rec-text); box-shadow: 0 1px 2px var(--rec-shadow); }
.rtl-seg-btn:focus-visible { outline: none; } /* no selected ring (HQU-934) */
.rtl-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--rec-muted); cursor: pointer; }

.rtl-list { position: relative; list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.rtl-list::before {
    content: ""; position: absolute; left: 15px; top: 8px; bottom: 8px; width: 2px;
    background: var(--rec-border-soft);
}
.rtl-day { position: relative; font-size: 13px; font-weight: 600; color: var(--rec-faint); padding: 6px 0 0 46px; }
.rtl-none { padding-left: 46px; font-size: 14px; color: var(--rec-faint); }

.rtl-ev { position: relative; display: flex; gap: 14px; align-items: flex-start; scroll-margin-top: 80px; }
.rtl-ev :target, .rtl-ev:target .rtl-card { box-shadow: 0 0 0 2px var(--rec-accent); border-radius: 10px; scroll-margin-top: 80px; }

.rtl-dot {
    flex: 0 0 32px; height: 32px; border-radius: 50%; z-index: 1;
    display: flex; align-items: center; justify-content: center;
    background: var(--rec-surface); border: 1px solid var(--rec-border); color: var(--rec-muted);
}
.rtl-dot .mud-icon-root { font-size: 16px; width: 16px; height: 16px; }
.rtl-dot--muted { color: var(--rec-faint); }
.rtl-dot--ok { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); border-color: var(--rec-tag-success-bg); }
.rtl-dot--ink { background: var(--rec-accent); border-color: var(--rec-accent); color: var(--rec-surface); }
.rtl-dot--tone.tone-neutral { background: var(--rec-tag-neutral-bg); color: var(--rec-tag-neutral-fg); border-color: var(--rec-tag-neutral-bg); }
.rtl-dot--tone.tone-info    { background: var(--rec-tag-info-bg);    color: var(--rec-tag-info-fg);    border-color: var(--rec-tag-info-bg); }
.rtl-dot--tone.tone-warning { background: var(--rec-tag-warning-bg); color: var(--rec-tag-warning-fg); border-color: var(--rec-tag-warning-bg); }
.rtl-dot--tone.tone-success { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); border-color: var(--rec-tag-success-bg); }
.rtl-dot--tone.tone-danger  { background: var(--rec-tag-danger-bg);  color: var(--rec-tag-danger-fg);  border-color: var(--rec-tag-danger-bg); }

.rtl-line { padding-top: 6px; font-size: 14px; line-height: 20px; color: var(--rec-muted); min-width: 0; overflow-wrap: anywhere; }
.rtl-line--grow { flex: 1; }
.rtl-line b, .rtl-card-h b { color: var(--rec-text); font-weight: 600; }
/* Names are user-typed and can be right-to-left (Arabic, Hebrew). Isolated, each reads in its own direction
   without dragging the " · 12:01 pm" after it into the middle of the name (HQU-1312). */
.rtl-line b, .rtl-card-h b, .rtl-ref, .rtl-when, .rtl-file-name,
.rec-feed-post-line b, .rec-feed-post-meta time { unicode-bidi: isolate; }
.rtl-line .record-status-tag { padding: 1px 8px; font-size: 12px; vertical-align: 1px; }
.rtl-when { color: var(--rec-faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rtl-line a, .rtl-card a:not(.rtl-file) { color: var(--rec-link); }

.rtl-pill {
    display: inline-flex; align-items: center; gap: 6px; margin-top: 6px;
    padding: 3px 10px; border-radius: 999px; font-size: 13px; font-weight: 600; line-height: 18px;
}
.rtl-pill.tone-success { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); }
.rtl-pill.tone-danger  { background: var(--rec-tag-danger-bg);  color: var(--rec-tag-danger-fg); }
.rtl-pill .rtl-pill-icon { font-size: 15px; width: 15px; height: 15px; }

.rtl-card {
    flex: 1; min-width: 0; background: var(--rec-surface);
    border: 1px solid var(--rec-border); border-radius: 10px; overflow: hidden;
}
.rtl-card-h {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 10px 16px; background: var(--rec-raised); border-bottom: 1px solid var(--rec-border-soft);
    font-size: 14px; color: var(--rec-muted);
}
.rtl-card-b { padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; }
.rtl-stepn { font-size: 12px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--rec-faint); }
.rtl-answer { display: flex; flex-direction: column; gap: 6px; }
.rtl-answer + .rtl-answer { border-top: 1px solid var(--rec-border-soft); padding-top: 10px; }
.rtl-answer-label { font-size: 13px; font-weight: 600; color: var(--rec-muted); }
.rtl-prompt { margin: 0; font-size: 14px; line-height: 21px; color: var(--rec-faint); white-space: pre-line; }
.rtl-value { margin: 0; font-size: 17px; font-weight: 500; color: var(--rec-text); overflow-wrap: anywhere; white-space: pre-line; }
.rtl-value.is-empty { color: var(--rec-faint); font-weight: 400; font-size: 15px; }
.rtl-note { margin: 0; font-size: 14px; color: var(--rec-muted); white-space: pre-line; }
.rtl-comment { margin: 0; font-size: 15px; line-height: 23px; white-space: pre-wrap; overflow-wrap: anywhere; }

.rtl-av {
    width: 22px; height: 22px; border-radius: 50%; flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--rec-accent); color: var(--rec-surface); font-size: 10px; font-weight: 600;
}

/* A linked record named in a timeline line (HQU-940): reads as the bold name, underlines on hover. */
.rtl-ref { color: inherit; text-decoration: none; }
.rtl-ref:hover { text-decoration: underline; }

.rtl-links { display: flex; flex-direction: column; gap: 8px; }
/* Wraps (HQU-1393): on a phone a status pill or Open button beside a long name left the name ~85px
   and 20 lines tall. The text keeps at least 160px; past that the trailing control drops to its own
   line, still at the trailing edge. */
.rtl-file {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 10px 12px;
    border: 1px solid var(--rec-border-soft); border-radius: 8px; background: var(--rec-raised);
    color: var(--rec-text); text-decoration: none;
}
.rtl-file > .record-status-tag,
.rtl-file > .rtl-file-open { margin-left: auto; }
a.rtl-file:hover { background: var(--rec-row-hover); text-decoration: none; }
.rtl-file-badge {
    flex: none; width: 34px; height: 40px; border-radius: 4px; box-sizing: border-box;
    display: flex; align-items: flex-end; justify-content: center; padding-bottom: 5px;
    background: var(--rec-danger-surface); color: var(--rec-danger); font-size: 10px; font-weight: 700;
}
.rtl-file-badge--link { height: 34px; align-items: center; padding: 0; border-radius: 6px; background: var(--rec-tag-info-bg); color: var(--rec-tag-info-fg); }
.rtl-file-badge--link .mud-icon-root { font-size: 18px; }
.rtl-file-text { display: flex; flex-direction: column; flex: 1 1 160px; min-width: 0; }
/* At most three lines; the post links to the record, which carries the full name. */
.rtl-file-name {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
    font-weight: 600; font-size: 15px; overflow-wrap: anywhere;
}
.rtl-file-meta { font-size: 13px; color: var(--rec-faint); }
.rtl-file-open { min-height: 36px; padding: 0 14px; font-size: 14px; }

.rtl-photo { display: flex; flex-direction: column; gap: 6px; }
.rtl-photo-btn {
    display: block; padding: 0; border: 1px solid var(--rec-border-soft); border-radius: 8px;
    background: var(--rec-sunken); overflow: hidden; cursor: zoom-in; max-width: 100%; width: fit-content;
}
.rtl-photo-btn img { display: block; max-width: 100%; max-height: 320px; object-fit: contain; }
.rtl-photo-btn:focus-visible { outline: none; } /* no selected ring (HQU-934) */
.rtl-photo-ph { display: flex; align-items: center; justify-content: center; width: 220px; height: 140px; color: var(--rec-faint); }

.rtl-diff { margin-top: 6px; font-size: 13px; border: 1px solid var(--rec-border-soft); border-radius: 6px; overflow: hidden; }
.rtl-diff > div { padding: 4px 10px; overflow-wrap: anywhere; }
.rtl-diff-old { background: var(--rec-tag-danger-bg); color: var(--rec-tag-danger-fg); }
.rtl-diff-new { background: var(--rec-tag-success-bg); color: var(--rec-tag-success-fg); }

.rtl-composer-label { display: block; font-weight: 600; color: var(--rec-text); }
.rtl-composer-input {
    width: 100%; box-sizing: border-box; padding: 10px 12px; resize: vertical;
    border: 1px solid var(--rec-edge); border-radius: 6px; background: var(--rec-surface);
    font: 15px var(--rec-font-body); color: var(--rec-text);
}
.rtl-composer-input:focus { outline: none; border-color: var(--rec-accent); } /* border only, no ring (HQU-934) */
.rtl-composer-acts { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rtl-composer-key { font-size: 12px; color: var(--rec-faint); }
/* No hardware keyboard on a touch device: the Comment button is the way to post (HQU-955). */
@media (hover: none) { .rtl-composer-key { display: none; } }
/* Photos held in a CommentComposer draft, above the text box until they are sent. */
.rtl-composer-photos { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.rtl-composer-photo {
    position: relative; width: 72px; height: 72px; border-radius: 6px; overflow: hidden;
    border: 1px solid var(--rec-border-soft); background: var(--rec-sunken);
}
.rtl-composer-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rtl-composer-photo-x {
    position: absolute; top: 3px; right: 3px; display: flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%;
    background: var(--rec-text); color: var(--rec-surface); cursor: pointer;
}
.rtl-composer-photo-x .mud-icon-root { font-size: 14px; }
/* The "+" attach menu (HQU-1121). It opens UPWARD: the composer sits at the foot of a pane that clips
   overflow, so a list dropping down would be cut off. Each item is a <label> with its file input laid
   invisibly over it, so a tap opens the picker. */
.rtl-attach-wrap { position: relative; }
.rtl-attach { position: relative; min-width: var(--rec-tap); padding: 0; }
.rtl-attach:focus-visible { box-shadow: none; } /* no selected ring (HQU-934) */
.rtl-attach.is-busy { opacity: .6; }
/* With AttachText: a paperclip and its label ("Add photo or doc") instead of the bare "+" (HQU-1234). */
.rtl-attach--labelled { display: inline-flex; align-items: center; gap: .35rem; padding: 0 .7rem; }
.rtl-attach-wrap > .record-comment-file { display: none; } /* the paste target; never seen */
/* The timeline's own Attach is a <label> around the real input (RecordTimeline): the input fills the label,
   invisibly, so it keeps focus and the tap while the browser's "Choose files" control never shows (HQU-1332). */
.rtl-attach > .record-comment-file {
    position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: 0;
}
.rtl-attach-scrim { position: fixed; inset: 0; z-index: 20; }
.rtl-attach-menu {
    position: absolute; left: 0; bottom: calc(100% + 6px); z-index: 21; min-width: 160px;
    list-style: none; margin: 0; padding: 4px 0;
    background: var(--rec-surface); border: 1px solid var(--rec-border); border-radius: 8px;
    box-shadow: 0 6px 18px var(--rec-shadow);
}
.rtl-attach-menu[hidden], .rtl-attach-scrim[hidden] { display: none; }
.rtl-attach-item {
    position: relative; display: flex; align-items: center; gap: 10px; padding: 7px 12px;
    font-size: var(--text-sm, 14px); color: var(--rec-text); cursor: pointer;
}
.rtl-attach-item:hover, .rtl-attach-item:focus-within { background: var(--rec-row-hover); }
.rtl-attach-item .mud-icon-root { font-size: 18px; color: var(--rec-muted); }
.rtl-attach-item .record-comment-file {
    position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: 0;
}
/* A document in the draft: its icon and name in the photo tile's place. */
.rtl-composer-photo.rtl-composer-doc {
    width: auto; max-width: 220px; height: 44px; padding: 0 34px 0 10px;
    display: flex; align-items: center; gap: 8px; background: var(--rec-surface);
}
.rtl-composer-doc .mud-icon-root { flex: 0 0 auto; font-size: 22px; color: var(--rec-muted); }
.rtl-composer-doc-name { font-size: 13px; color: var(--rec-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Management density — the same story, tighter. */
.rtl--compact .rtl-list { gap: 12px; }
.rtl--compact .rtl-card-h { padding: 9px 14px; }
.rtl--compact .rtl-card-b { padding: 12px 14px; gap: 6px; }
.rtl--compact .rtl-prompt { font-size: 13px; line-height: 20px; }
.rtl--compact .rtl-value { font-size: 16px; }
.rtl--compact .rtl-file-name { font-size: 14px; }
.rtl--compact .rtl-file-meta { font-size: 12px; }
.rtl--compact .record-btn { min-height: 36px; font-size: 14px; padding: 0 14px; }

/* A finger needs a 44px target, whatever the density. */
@media (pointer: coarse) {
    .rtl-seg-btn { min-height: 44px; }
    .rtl--compact .record-btn, .rtl-file-open { min-height: 44px; }
    .rtl-toggle { min-height: 44px; }
}

/* Phone: full-width cards, a narrower spine, nothing that scrolls sideways. */
@media (max-width: 760px) {
    .rtl-ev { gap: 10px; }
    .rtl-card-h, .rtl-card-b { padding-left: 12px; padding-right: 12px; }
    .rtl-day, .rtl-none { padding-left: 42px; }
    .rtl-photo-btn img { max-height: 240px; }
}

/* The status line under a run's title (HQU-925) — ONE lifecycle pill and the sentence that
   explains it ("Reopened today 8:56 am by … · first completed 29 Sept"), with the run's lesser
   exit, Cancel, at its end. Replaces the lock tag and the in-progress panel on a run. */
.record-status-line {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: 0 0 18px;
    font-size: 14px;
    color: var(--rec-muted);
}

.record-status-line-act {
    margin-left: auto;
    min-height: 32px;
    padding: 0 8px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    font: 500 14px var(--rec-font-body);
    color: var(--rec-danger);
    cursor: pointer;
}

.record-status-line-act:hover { text-decoration: underline; }
.record-status-line-act:focus-visible { outline: 2px solid var(--rec-accent); outline-offset: 1px; }

@media (pointer: coarse) {
    .record-status-line-act { min-height: 44px; }
}

/* Cancel lives on the status line from tablet width up, and at the page foot on a phone (HQU-1431),
   where the wrapped status line put it opposite "Set a follow-up day". */
.record-cancel-foot { display: none; }

/* The Scan screen's way out when a code won't scan (HQU-1442). */
.record-scan-fallback {
    margin: 14px 0 0;
    text-align: center;
    font-size: 14px;
    color: var(--rec-muted);
}

.record-scan-fallback a {
    color: var(--rec-text);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}
@media (max-width: 600px) {
    .record-cancel--wide { display: none; }
    .record-cancel-foot { display: flex; justify-content: center; margin-top: 24px; }
    .record-cancel-foot .record-status-line-act { margin-left: 0; }
}

/* ── Follow-up day (HQU-540) ───────────────────────────────────────────────────
   Two homes: the Leave dialog of a draft run (.record-followup — a checkbox and,
   once ticked, a date) and the viewer's status line (RecordFollowUpControl — the
   day as a tag plus one quiet link, or an inline date editor). Native date input
   on purpose: the phone's own picker, and a plain yyyy-MM-dd value with no zone. */
.record-followup {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: -6px 0 18px;
    font-size: 0.92rem;
    color: var(--rec-body);
}

.record-followup-check {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    cursor: pointer;
}

.record-followup-check input {
    width: 18px;
    height: 18px;
    accent-color: var(--rec-mode);
}

.record-followup-date {
    min-height: 34px;
    padding: 4px 8px;
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    background: var(--rec-surface);
    font: 500 14px var(--rec-font-body);
    color: var(--rec-text);
}

.record-followup-date:focus-visible { outline: 2px solid var(--rec-accent); outline-offset: 1px; }

.record-followup-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--rec-text);
}

.record-followup-tag.is-due { font-weight: 600; }

.record-followup-icon.mud-icon-root { font-size: 18px; color: var(--rec-muted); }

.record-followup-edit {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

.record-followup-btn { min-height: 34px; }

.record-followup-link {
    min-height: 32px;
    padding: 0 6px;
    border: 0;
    border-radius: 6px;
    background: transparent;
    font: 500 14px var(--rec-font-body);
    color: var(--rec-link);
    cursor: pointer;
}

.record-followup-link:hover:not(:disabled) { text-decoration: underline; }
.record-followup-link:focus-visible { outline: 2px solid var(--rec-accent); outline-offset: 1px; }

.record-followup-error { flex-basis: 100%; color: var(--rec-danger); }

@media (pointer: coarse) {
    .record-followup-link,
    .record-followup-check,
    .record-followup-date,
    .record-followup-btn { min-height: 44px; }
}

/* ── The activity feed (FeedTimeline + FeedPost, HQU-957/966) ─────────────────────────────
   ONE feed for both hosts: the Records Home stream, a record's own activity, and a caller's entries.
   Its cards, comments, files and photos are the record timeline's rtl-* rules above; its tabs are
   rtl-seg, its toggle rtl-toggle, its composer rtl-composer-*. This adds only what a feed has and a
   record's story does not: who + where on each post, the scope bar, replies, "new updates". Every
   colour is a --rec-* token, so the PWA (which loads only this sheet) and the portal match. */

.rec-feed { display: flex; flex-direction: column; gap: 14px; margin-top: 28px; font-family: var(--rec-font-body); color: var(--rec-text); }
.rec-feed .record-section-head { margin: 0; }
.rec-feed .visually-hidden {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.rec-feed-top { scroll-margin-top: 16px; }
.rec-feed-bar { display: flex; align-items: center; gap: 8px; }

/* The heading row, and beside it the scope in one quiet line (HQU-1425) — it only says what the breadcrumb
   set, so it is the faintest thing on the row. Under the heading on a phone. */
.rec-feed-top { display: flex; align-items: baseline; gap: 4px 16px; flex-wrap: wrap; }
.rec-feed-top .record-section-head { flex: 1 1 auto; }
.rec-feed-scope {
    margin: 0; display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%;
    font-size: 12.5px; color: var(--rec-faint);
}
.rec-feed-scope-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-feed-scope .rec-feed-chip-icon.mud-icon-root { font-size: 14px; width: 14px; height: 14px; }
.rec-feed-chip-icon.mud-icon-root { font-size: 16px; width: 16px; height: 16px; }


.rec-feed-composer .rtl-card-b { padding: 12px 14px; }
/* Compact until focused (HQU-1425): one line, the actions row hidden — hidden, not removed, so its file
   inputs stay wired. */
.rtl-composer.is-compact .rtl-card-b { padding: 8px 10px; }
.rtl-composer.is-compact .rtl-composer-input { resize: none; padding: 8px 12px; }
.rtl-composer.is-compact .rtl-composer-acts { display: none; }
.rec-feed-filter { display: flex; align-items: center; gap: 4px 8px; flex-wrap: wrap; }
.rec-feed-filter .record-count { margin-left: 2px; }

/* "N new updates" — sticky so it is there wherever the reader has scrolled to. */
.rec-feed-fresh { display: flex; justify-content: center; position: sticky; top: 8px; z-index: 2; }
.rec-feed-fresh-pill {
    display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 16px;
    border: 0; border-radius: 999px; background: var(--rec-link); color: var(--rec-surface);
    font: 600 14px var(--rec-font-body); cursor: pointer; box-shadow: 0 4px 12px var(--rec-shadow);
}

.rec-feed-day { display: flex; flex-direction: column; gap: 10px; }
.rec-feed-day-label { margin: 6px 0 0; font: 600 14px var(--rec-font-body); color: var(--rec-muted); }
.rec-feed-posts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }

/* One post: avatar + who did what, where; the body under the sentence; the actions row. */
.rec-feed-post { display: flex; flex-direction: column; }
.rec-feed-post-h { display: flex; gap: 12px; padding: 14px 16px 0; }
.rec-feed-av {
    flex: none; width: 40px; height: 40px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--rec-accent); color: var(--rec-surface); font-size: 14px; font-weight: 700;
}
.rec-feed-av--sm { width: 28px; height: 28px; font-size: 12px; }
.rec-feed-post-who { flex: 1; min-width: 0; }
.rec-feed-post-line { font-size: 15px; line-height: 21px; color: var(--rec-muted); overflow-wrap: anywhere; }
.rec-feed-post-line b { color: var(--rec-text); font-weight: 600; }
.rec-feed-post-line a { color: inherit; }
.rec-feed-post-meta {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 2px;
    font-size: 13px; color: var(--rec-faint); font-variant-numeric: tabular-nums;
}
.rec-feed-kind { display: inline-flex; align-items: center; gap: 4px; font-weight: 600; color: var(--rec-muted); }
.rec-feed-kind-icon.mud-icon-root { font-size: 15px; width: 15px; height: 15px; }
.rec-feed-chip {
    display: inline-flex; align-items: center; gap: 4px; padding: 0 8px; border-radius: 999px;
    border: 1px solid var(--rec-border); color: var(--rec-muted); font-weight: 600; line-height: 20px;
    min-width: 0; max-width: min(100%, 180px); /* one line, cut short — the title holds the full name (HQU-1428) */
}
.rec-feed-chip-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-feed-chip .rec-feed-chip-icon.mud-icon-root { font-size: 13px; width: 13px; height: 13px; }

.rec-feed-post-b { padding: 12px 16px 0 68px; display: flex; flex-direction: column; gap: 8px; }
.rec-feed-status-change { margin: 0; display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--rec-muted); }
.rec-feed-status-word { font-weight: 600; color: var(--rec-text); }

.rec-feed-post-acts {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
    margin-top: 10px; padding: 2px 12px 2px 60px; border-top: 1px solid var(--rec-border-soft);
}
.rec-feed-post-end { height: 14px; }

/* Reply, in the meta line (HQU-1426): always there on touch and once a post has replies; for a mouse, on
   hover or when focus is inside the post — still in the tab order, so a keyboard reaches it. */
.rec-feed-reply-act {
    display: inline-flex; align-items: center; gap: 4px; min-height: 28px; padding: 0 8px; margin-left: 2px;
    border: 0; border-radius: 6px; background: transparent; cursor: pointer;
    font: 600 13px var(--rec-font-body); color: var(--rec-muted);
}
.rec-feed-reply-act:hover { background: var(--rec-hover); color: var(--rec-text); }
.rec-feed-reply-act .rec-feed-act-icon.mud-icon-root { font-size: 14px; width: 14px; height: 14px; }
@media (pointer: fine) {
    .rec-feed-post:not(.has-replies) .rec-feed-reply-act,
    .rec-feed-event:not(.has-replies) .rec-feed-reply-act { opacity: 0; }
    .rec-feed-post:hover .rec-feed-reply-act, .rec-feed-post:focus-within .rec-feed-reply-act,
    .rec-feed-event:hover .rec-feed-reply-act, .rec-feed-event:focus-within .rec-feed-reply-act { opacity: 1; }
}
@media (pointer: coarse) { .rec-feed-reply-act { min-height: 40px; } }

/* Event rows (HQU-1423): a routine one-fact event is ONE row, and a run of them is one bordered list rather
   than a card each — kind icon, the sentence, then status, where and when. Their meta sits on the right on a
   wide screen and wraps to its own line on a phone. */
.rec-feed-events {
    list-style: none; margin: 0; padding: 0;
    background: var(--rec-surface); border: 1px solid var(--rec-border); border-radius: 10px; overflow: hidden;
}
.rec-feed-events > li + li { border-top: 1px solid var(--rec-border-soft); }
.rec-feed-event {
    display: flex; align-items: center; gap: 4px 12px; flex-wrap: wrap; min-height: 48px;
    padding: 8px 14px; box-sizing: border-box;
}
.rec-feed-event-icon {
    flex: none; width: 30px; height: 30px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--rec-raised); border: 1px solid var(--rec-border-soft); color: var(--rec-muted);
}
.rec-feed-event-icon .mud-icon-root { font-size: 16px; width: 16px; height: 16px; }
.rec-feed-event-line {
    flex: 1 1 280px; min-width: 0; font-size: 14.5px; line-height: 20px; color: var(--rec-muted); overflow-wrap: anywhere;
}
.rec-feed-event-line b { color: var(--rec-text); font-weight: 600; unicode-bidi: isolate; }
.rec-feed-event-line a { color: inherit; }
.rec-feed-event-meta {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end;
    margin-left: auto; min-width: 0; max-width: 100%;
    font-size: 13px; color: var(--rec-faint); font-variant-numeric: tabular-nums;
}
.rec-feed-event-meta time { white-space: nowrap; unicode-bidi: isolate; }
.rec-feed-event-meta .record-status-tag { padding: 1px 8px; font-size: 12px; }

/* One person's batch as one row (HQU-1424), opening to the event rows underneath. */
.rec-feed-group-toggle {
    display: inline-flex; align-items: center; gap: 2px; min-height: 28px; padding: 0 8px;
    border: 1px solid var(--rec-border); border-radius: 999px; background: var(--rec-surface); cursor: pointer;
    font: 600 13px var(--rec-font-body); color: var(--rec-text);
}
.rec-feed-group-toggle:hover { background: var(--rec-hover); }
.rec-feed-group-toggle .rec-feed-act-icon.mud-icon-root { font-size: 16px; width: 16px; height: 16px; }
@media (pointer: coarse) { .rec-feed-group-toggle { min-height: 40px; } }
.rec-feed-group-items {
    list-style: none; margin: 0; padding: 0 0 0 28px;
    background: var(--rec-raised); border-top: 1px solid var(--rec-border-soft);
}
.rec-feed-group-items > li + li { border-top: 1px solid var(--rec-border-soft); }
.rec-feed-act {
    display: inline-flex; align-items: center; gap: 6px; min-height: 40px; padding: 0 10px;
    border: 0; border-radius: 8px; background: transparent; cursor: pointer;
    font: 600 14px var(--rec-font-body); color: var(--rec-muted); text-decoration: none;
}
.rec-feed-act:hover { background: var(--rec-hover); color: var(--rec-text); text-decoration: none; }
.rec-feed-act-icon.mud-icon-root { font-size: 16px; width: 16px; height: 16px; }

/* Replies, inside the post's card. */
.rec-feed-thread {
    display: flex; flex-direction: column; gap: 12px; padding: 12px 16px 12px 68px;
    background: var(--rec-raised); border-top: 1px solid var(--rec-border-soft);
}
.rec-feed-reply { display: flex; gap: 10px; align-items: flex-start; }
.rec-feed-reply--compose { align-items: center; }
.rec-feed-reply-bubble {
    min-width: 0; padding: 8px 12px; font-size: 14px;
    background: var(--rec-surface); border: 1px solid var(--rec-border-soft); border-radius: 10px;
}
.rec-feed-reply-h { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }
.rec-feed-reply-h time { font-size: 13px; color: var(--rec-faint); }
.rec-feed-reply-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.rec-feed-reply-field { flex: 1; min-width: 0; }
.rec-feed-reply-input {
    width: 100%; box-sizing: border-box; min-height: 40px; padding: 0 14px;
    border: 1px solid var(--rec-edge); border-radius: 999px;
    font: 14px var(--rec-font-body); background: var(--rec-surface); color: var(--rec-text);
}
.rec-feed-reply-input:focus { outline: none; border-color: var(--rec-accent); }

/* System housekeeping: one quiet line, no card. */
.rec-feed-sys { display: flex; align-items: center; gap: 10px; padding: 2px 16px; font-size: 14px; color: var(--rec-muted); }
.rec-feed-sys-dot {
    flex: none; width: 28px; height: 28px; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--rec-border); background: var(--rec-surface); color: var(--rec-faint);
}
.rec-feed-sys-dot .mud-icon-root { font-size: 14px; width: 14px; height: 14px; }
.rec-feed-sys-text { min-width: 0; overflow-wrap: anywhere; }
.rec-feed-sys-text b { color: var(--rec-text); font-weight: 600; }
.rec-feed-sys-text .rec-feed-chip { margin-left: 4px; }

.rec-feed-more { display: flex; justify-content: center; padding: 8px 0 24px; }
.rec-feed-end { font-size: 13px; color: var(--rec-faint); }

@media (max-width: 600px) {
    .rec-feed-post-b, .rec-feed-thread { padding-left: 16px; }
    .rec-feed-post-acts { padding-left: 8px; }
    /* The event's meta on its own line, under the sentence and lined up with it. */
    .rec-feed-event-meta { flex-basis: 100%; justify-content: flex-start; margin-left: 42px; max-width: calc(100% - 42px); }
    .rec-feed-group-items { padding-left: 0; }
}

/* ══ Records nav (HQU-965) ═══════════════════════════════════════════════════
   RecordNavList — Home · the workspace's modules grouped by behaviour · Scan a code — rendered by
   BOTH hosts: the portal's rail (.rec-nav, a bottom bar on a phone) and the Staff PWA's menu drawer.
   Global, not scoped: Records.UI components carry no scoped CSS, and the portal rail's scoped sheet
   cannot reach markup a Records.UI component renders. Each token falls back to the --rec-* palette,
   because the PWA loads only this sheet; in the portal the hque tokens win, so the rail still lines
   up row for row with Build's (HQU-926). */
.rec-navlist {
    padding: 4px 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.rec-navlink {
    display: flex;
    align-items: center;
    /* Explicit: a UA centres a flex button's content and not a link's, and the portal's More
       button sits in this list beside the links. */
    justify-content: flex-start;
    gap: 11px;
    min-height: var(--tap-min, var(--rec-tap));
    padding: 0 12px;
    border: 0;
    border-radius: var(--radius-sm, 8px);
    background: none;
    font-family: inherit;
    font-size: var(--text-lg, 1rem);
    font-weight: 500;
    color: var(--fg-muted, var(--rec-muted));
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}

.rec-navlink:hover {
    background: var(--hover-bg, var(--rec-hover));
    color: var(--fg-default, var(--rec-text));
    text-decoration: none;
}

/* Filled ink — the "you are here" family, not the brand accent. */
.rec-navlink[aria-current="page"] {
    background: var(--emphasis-bg, var(--rec-accent));
    color: var(--emphasis-fg, var(--rec-surface));
    font-weight: 600;
}

.rec-navlink .rec-navlink-icon {
    font-size: var(--text-2xl, 1.4rem);
    flex: none;
    color: inherit;
}

.rec-navlink-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The behaviours, between Home and Scan a code. */
.rec-navgroups {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* The Scan entry after the behaviours gets a little air, so it reads as its own destination. */
.rec-navgroups + .rec-navlink { margin-top: 10px; }

/* Phone-only destination (the portal's More button). */
.rec-nav-more { display: none; }

/* Desk rows at the management rail's density (HQU-926). */
@media (min-width: 761px) {
    .rec-nav .rec-navlink {
        gap: 10px;
        min-height: 40px;
        padding: 8px 11px;
        font-size: var(--text-15, 0.94rem);
    }
}

/* Phone: the portal rail becomes a bottom bar of Home · Scan a code · More. The behaviours do
   not fit a bar, so it is hidden here and rides in the More sheet. */
@media (max-width: 760px) {
    .rec-nav .rec-navlist {
        flex: 1 1 auto;
        flex-direction: row;
        gap: 0;
        padding: 0;
    }

    .rec-nav .rec-navgroups { display: none; }
    .rec-nav .rec-navgroups + .rec-navlink { margin-top: 0; }

    .rec-nav .rec-navlink {
        flex: 1 1 0;
        min-width: 0;
        flex-direction: column;
        gap: 3px;
        align-items: center;
        justify-content: center;
        min-height: 66px;
        padding: 8px 2px 10px;
        border-radius: 0;
        font-size: var(--text-xs, 0.72rem);
        text-align: center;
    }

    .rec-nav .rec-navlink .rec-navlink-icon { font-size: var(--text-3xl, 1.75rem); }

    .rec-nav .rec-navlink:hover { background: transparent; }

    /* A filled tile is too much colour across a bottom bar; the marker becomes a top edge. */
    .rec-nav .rec-navlink[aria-current="page"] {
        background: transparent;
        color: var(--fg-default, var(--rec-text));
        font-weight: 600;
        box-shadow: inset 0 3px 0 var(--emphasis-bg, var(--rec-accent));
    }

    .rec-nav .rec-nav-more { display: flex; }
}

/* The stacked list in a sheet or drawer (the portal's phone More sheet, the PWA's menu). */
.rec-navlist--sheet { padding: 0; }

/* ── Workspace selector (HQU-965) — Records' topbar filter, a chip that opens a MudMenu (HQU-1454) ── */
.rec-ws-picker-menu, .rec-ws-picker-menu .mud-menu-activator { min-width: 0; max-width: 100%; }
.rec-ws-picker {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    max-width: 260px;
    padding: 0 8px;
    border: 1px solid var(--border-default, var(--rec-border));
    border-radius: var(--radius-sm, 8px);
    background: var(--canvas-default, var(--rec-surface));
    color: var(--fg-default, var(--rec-text));
    font: 500 var(--text-sm, 0.85rem) var(--rec-font-body);
}

button.rec-ws-picker { cursor: pointer; text-align: left; }
button.rec-ws-picker:hover { background: var(--rec-row-hover); }
button.rec-ws-picker:focus-visible { outline: 2px solid var(--rec-accent); outline-offset: 1px; }

.rec-ws-picker .rec-ws-picker-icon,
.rec-ws-picker .rec-ws-picker-caret {
    flex: none;
    font-size: 1.1rem;
    color: var(--fg-muted, var(--rec-muted));
    pointer-events: none;
}

.rec-ws-picker--single { border-color: transparent; background: transparent; }
.rec-ws-picker-name { flex: 1 1 auto; min-width: 0; padding: 0 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Staff PWA menu (HQU-965) — the topbar's Menu button opens the Records nav in a drawer ── */
.record-topbar-menu { color: var(--rec-muted); }
.record-topbar-menu:hover { color: var(--rec-accent); }

/* A finger needs a 44px target (HQU-1374). These small icon buttons measured 26–28px on a phone: Menu and Home on
   every screen, Home's day and month arrows, Manage device's Remove tile and a file field's ×. The icon stays its
   size; the button grows. Sized, not stretched with a pseudo-element: Menu and Home sit side by side, and two
   overlapping hit areas would send a tap to whichever is later in the DOM. */
@media (pointer: coarse) {
    .record-topbar-menu.mud-icon-button,
    .record-topbar-home.mud-icon-button,
    .record-topbar-signout-icon.mud-icon-button,
    .record-daybar .mud-icon-button,
    .record-month-bar .mud-icon-button,
    .record-manage-remove.mud-icon-button,
    .record-file-remove { width: 44px; height: 44px; }
}

/* The right group stays whole (HQU-1384): the left cluster is the one that gives way, so Sign out
   never wraps onto two lines or slides past the edge. */
.record-topbar-right {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    min-width: 0;
}

.record-topbar-signout { white-space: nowrap; }

/* The icon-only Sign out, shown only at tablet width — see the media queries below. */
.record-topbar-signout-icon { display: none; }

.record-navscrim {
    position: fixed;
    inset: 0;
    z-index: 1200;
    background: rgba(22, 33, 29, 0.32);
}

.record-navdrawer {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 1201;
    width: min(320px, 86vw);
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 12px calc(14px + env(safe-area-inset-bottom, 0px));
    background: var(--rec-surface);
    border-right: 1px solid var(--rec-border);
    box-shadow: 4px 0 24px var(--rec-shadow);
    overflow-y: auto;
}

.record-navdrawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 0 4px;
    font: 600 1rem var(--rec-font-display);
    color: var(--rec-text);
}

.record-navdrawer .rec-ws-picker { max-width: none; width: 100%; }
/* MudMenu wraps the chip in its own two boxes; in the drawer both stretch with it. */
.record-navdrawer .rec-ws-picker-menu, .record-navdrawer .rec-ws-picker-menu .mud-menu-activator { display: flex; width: 100%; }

/* At tablet width Sign out collapses to its icon (HQU-1384) — it is also in the Menu drawer — and
   the workspace selector narrows, so a long name and the venue still fit beside them. */
@media (max-width: 900px) {
    .record-topbar-signout { display: none; }
    .record-topbar-signout-icon { display: inline-flex; }
    .record-topbar-ws .rec-ws-picker { max-width: clamp(120px, 22vw, 260px); }
}

/* On a phone the bar already carries Menu, Home, the person and Sign out; the selector moves to the
   head of the drawer rather than squeezing everything else. */
@media (max-width: 600px) {
    .record-topbar-ws { display: none; }
    /* …and Sign out moves into the drawer too (HQU-1128), so the bar stays one row on a phone. */
    .record-topbar-signout,
    .record-topbar-signout-icon { display: none; }
    .record-topbar { padding-left: 8px; padding-right: 8px; }
}

/* Sign out at the foot of the drawer — present at every width, the only one on a phone. */
.record-navdrawer-signout { align-self: flex-start; margin-top: auto; }

/* ── Records Home (HQU-966): Needs doing · Pinned · the feed ─────────────────────────────────── */

/* The section head with its one way out ("All records") at the far end. */
.record-section-bar {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}
.record-section-bar .record-section-head { margin-bottom: 10px; }

.record-link {
    color: var(--rec-link);
    font-size: var(--text-sm, 13px);
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}
.record-link:hover { text-decoration: underline; }

/* The day's needs-doing list, capped so a long day scrolls inside itself rather than pushing
   Coming up, the pins and the feed off the page. */
.record-needs-scroll {
    max-height: 420px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* A group inside a section — "Coming up" under the day's list. */
.record-subhead {
    margin: 20px 0 10px;
    font-family: var(--rec-font-display);
    font-size: 13px;
    font-weight: 600;
    color: var(--rec-faint);
}

/* WHY a row is listed, beside its status: quiet text, never a second coloured tag. */
.record-why {
    margin-right: 8px;
    color: var(--rec-faint);
    font-size: 12px;
    white-space: nowrap;
}

/* Pinned — favourites as one wrapping row of chips. */
.record-pinned-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.record-pin {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 280px;
    min-height: 34px;
    padding: 6px 12px;
    border: 1px solid var(--rec-border);
    border-radius: 999px;
    background: var(--rec-surface);
    color: var(--rec-text);
    font-size: var(--text-sm, 13px);
    text-decoration: none;
}
.record-pin:hover { background: var(--rec-row-hover); }

.record-pin-icon { font-size: 16px !important; color: var(--rec-v-warning-fg); }
.record-pin-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── The Records form (HQU-973/967) ── */
.record-form .record-actions-end { gap: 8px; }

@media (max-width: 599.98px) {
    .record-why { display: none; }
    .record-pin { max-width: 100%; }
}

/* ── The record's manage column (HQU-967): status, people, links, tags, history — portal only ── */
.record-item-grid.has-aside {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 28px;
    align-items: start;
}
.record-item-main { min-width: 0; }
/* A grey rule between the record and its manage column (HQU-1448). The aside STRETCHES to the row so the
   rule runs the whole way down beside the content, not just as far as the manage blocks reach; the column
   is 20px wider to keep the blocks at their 280px. */
.record-item-grid.has-aside > .record-item-aside {
    align-self: stretch;
    border-left: 1px solid var(--rec-border);
    padding-left: 19px;
}

@media (max-width: 1023.98px) {
    .record-item-grid.has-aside { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .record-item-grid.has-aside > .record-item-aside { margin-top: 28px; border-left: 0; padding-left: 0; }
}

.record-manage { display: flex; flex-direction: column; }

.record-manage-block {
    padding: 12px 0;
    border-bottom: 1px solid var(--rec-border-soft);
    font-size: var(--text-sm, 13px);
    color: var(--rec-body);
}
.record-manage-block:first-child { padding-top: 0; }
.record-manage-block:last-child { border-bottom: 0; }

.record-manage-label {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
    color: var(--rec-faint);
    font-size: 12px;
    font-weight: 600;
}

/* A block whose label folds it (Tag codes, HQU-1460) — the label itself is the button, the caret at its end. */
.record-manage-toggle {
    width: 100%;
    align-items: center;
    padding: 0;
    border: 0;
    background: none;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}
.record-manage-toggle:hover { color: var(--rec-text); }
.record-manage-toggle:focus-visible { outline: 2px solid var(--rec-accent); outline-offset: 2px; }
.record-manage-toggle[aria-expanded="false"] { margin-bottom: 0; }
.record-manage-toggle .record-manage-toggle-icon.mud-icon-root { font-size: 18px; width: 18px; height: 18px; }

/* The tag-code panel's "Assign a code" is a heading of this column, so it wears the column's label
   rather than the panel's own darker title (HQU-1460). Three classes to outrank the panel's scoped rule. */
.record-manage-block .tcp-assign .tcp-assign-title {
    color: var(--rec-faint);
    font-size: 12px;
    font-weight: 600;
}

.record-manage-link {
    border: 0;
    padding: 0;
    background: none;
    color: var(--rec-link);
    font: inherit;
    font-weight: 500;
    cursor: pointer;
}
.record-manage-link:hover { text-decoration: underline; }
.record-manage-link:disabled { color: var(--rec-faint); cursor: default; text-decoration: none; }

.record-manage-muted { color: var(--rec-faint); }
.record-manage-error { margin-top: 6px; color: var(--rec-danger); }

.record-manage-menu {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 6px 0;
    padding: 4px;
    border: 1px solid var(--rec-border);
    border-radius: 8px;
    background: var(--rec-surface);
}

.record-manage-opt,
.record-manage-row {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 32px;
    padding: 4px 6px;
    border: 0;
    border-radius: 6px;
    background: none;
    color: var(--rec-text);
    font: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    /* Explicit: the "Show QR code" row is a <button>, and a button does not lay out like an <a>. */
    justify-content: flex-start;
}
.record-manage-opt:hover,
.record-manage-row:hover { background: var(--rec-row-hover); }
.record-manage-row { flex-wrap: wrap; column-gap: 8px; row-gap: 0; padding-left: 0; }

.record-manage-person {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
}

.record-manage-name { min-width: 0; flex: 1; overflow-wrap: anywhere; }
/* A linked record: the name keeps the width it needs and the code · module line wraps beneath it when
   the panel is narrow. With the name's flex-basis at 0 the line beside it never wrapped, and the name
   was squashed to one word per line instead (HQU-1331). */
.record-manage-row--link > .record-manage-name { flex: 1 1 auto; }
.record-manage-row--link > .record-manage-muted { min-width: 0; overflow-wrap: anywhere; }
/* "1 failed" on a linked check that found a fault (HQU-1336) — the records list's Failed tone. */
.record-manage-failed {
    padding: 0 7px;
    border-radius: 999px;
    background: var(--rec-tag-danger-bg);
    color: var(--rec-tag-danger-fg);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
}
.record-manage-icon { font-size: 18px !important; color: var(--rec-faint); }
.record-manage-input { margin-top: 6px; }

/* On a phone the panel stacks under the feed and is used by touch (HQU-1398): Change / Create /
   Assign to me were 18px tall, the remove ✕ 24px and the rows 32px. Each becomes a 44px target; the
   text stays its size. */
@media (max-width: 720px) {
    .record-manage-label { align-items: center; }

    .record-manage-link {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
        padding: 0 8px;
        margin-right: -8px;          /* the hit area grows, the label keeps its trailing edge */
    }

    .record-manage-opt,
    .record-manage-row,
    .record-manage-person { min-height: 44px; }

    .record-manage-person .mud-icon-button { width: 44px; height: 44px; }
}

.record-manage-tags { display: flex; flex-wrap: wrap; gap: 6px; }

.record-tag-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--rec-accent-soft);
    color: var(--rec-text);
    font-size: 12px;
}
.record-tag-x {
    border: 0;
    padding: 0 2px;
    background: none;
    color: var(--rec-faint);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
}
.record-tag-x:hover { color: var(--rec-danger); }

/* ── A run's execution detail on an agent vertical (HQU-967) ── */
.record-exec .record-verdict { margin-bottom: 12px; }
.record-exec-steps { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.record-exec-step {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    font-size: var(--text-sm, 13px);
}
.record-exec-step-label { flex: 1; min-width: 0; color: var(--rec-text); }
.record-exec-step-status,
.record-exec-step-meta { color: var(--rec-faint); }
.record-exec-step-note { flex-basis: 100%; padding-left: 16px; color: var(--rec-muted); }

/* ── A record's version history (HQU-967) ── */
.record-hist { display: flex; flex-direction: column; gap: 6px; margin-top: 20px; }
.record-hist-day {
    margin: 14px 0 4px;
    color: var(--rec-faint);
    font-size: 12px;
    font-weight: 600;
}
.record-hist-entry {
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    background: var(--rec-surface);
}
.record-hist-row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    background: none;
    color: var(--rec-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.record-hist-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.record-hist-dot.tone-success { background: var(--rec-dot-success); }
.record-hist-dot.tone-danger  { background: var(--rec-dot-danger); }
.record-hist-dot.tone-info    { background: var(--rec-dot-info); }
.record-hist-summary { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.record-hist-type { font-weight: 600; }
.record-hist-meta { color: var(--rec-faint); font-size: 12px; }
.record-hist-version {
    padding: 1px 8px;
    border-radius: 999px;
    background: var(--rec-accent-soft);
    color: var(--rec-muted);
    font-size: 12px;
}
.record-hist-detail { padding: 0 12px 12px 30px; }
.record-hist-diff {
    display: grid;
    grid-template-columns: minmax(40%, max-content) 1fr;
    gap: 4px 14px;
    margin: 0;
    font-size: var(--text-sm, 13px);
}
.record-hist-diff dt { color: var(--rec-faint); }
.record-hist-diff dd { margin: 0; overflow-wrap: anywhere; }
.record-hist-del { background: var(--rec-danger-surface); text-decoration: line-through; }
.record-hist-add { background: var(--rec-v-success-bg); }
.record-hist-arrow { margin: 0 6px; color: var(--rec-faint); }

/* A file field's change as the files themselves (HQU-1153): removed struck in red, added in green. */
.record-hist-files { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.record-hist-files-arrow { color: var(--rec-faint); font-size: 18px; }
.record-hist-file { display: flex; flex-direction: column; gap: 4px; width: 112px; margin: 0; }
.record-hist-file-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 112px;
    height: 84px;
    padding: 0;
    overflow: hidden;
    border: 2px solid var(--rec-border);
    border-radius: 6px;
    background: var(--rec-sunken);
    color: var(--rec-muted);
    cursor: pointer;
}
.record-hist-file-btn img { width: 100%; height: 100%; object-fit: cover; }
.record-hist-file-btn .mud-icon-root { font-size: 28px; }
.record-hist-file-btn.is-gone { cursor: default; }
.record-hist-file.is-del .record-hist-file-btn { border-color: var(--rec-v-danger-bd); }
.record-hist-file.is-del .record-hist-file-btn img { opacity: .55; filter: grayscale(.6); }
.record-hist-file.is-add .record-hist-file-btn { border-color: var(--rec-v-success-bd); }
.record-hist-file figcaption { display: flex; flex-direction: column; min-width: 0; font-size: 12px; line-height: 1.3; }
.record-hist-file-state { font-weight: 600; }
.record-hist-file.is-del .record-hist-file-state { color: var(--rec-v-danger-fg); }
.record-hist-file.is-add .record-hist-file-state { color: var(--rec-v-success-fg); }
.record-hist-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--rec-muted); }
.record-hist-file.is-del .record-hist-file-name { text-decoration: line-through; }
.record-hist-tech { display: flex; gap: 8px; margin-top: 10px; color: var(--rec-faint); font-size: 12px; }
.record-hist-tech code { color: var(--rec-muted); }
.record-hist-foot { margin-top: 8px; }
.record-hist-checks { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.record-hist-check { display: flex; align-items: center; gap: 6px; font-size: var(--text-sm, 13px); }
.record-hist-check.tone-success .mud-icon-root { color: var(--rec-dot-success); }
.record-hist-check.tone-danger .mud-icon-root  { color: var(--rec-dot-danger); }
.record-hist-check.tone-warning .mud-icon-root { color: var(--rec-dot-warning); }
.record-hist-check.tone-neutral .mud-icon-root { color: var(--rec-faint); }

/* ── Records Home's day switcher and month view (HQU-968) ── */
.record-daybar,
.record-month-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0 0 12px;
}
.record-daybar-label {
    min-width: 96px;
    text-align: center;
    font-family: var(--rec-font-display);
    font-weight: 600;
    color: var(--rec-text);
}
.record-daybar .record-chip { display: inline-flex; align-items: center; gap: 4px; min-height: 30px; padding: 4px 12px; }
.record-day-empty { padding: 16px 0; }

.record-month {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 4px;
    margin-bottom: 16px;
}
.record-month-dow {
    padding: 4px;
    color: var(--rec-faint);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
}
.record-month-cell {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 76px;
    padding: 6px;
    border: 1px solid var(--rec-border-soft);
    border-radius: 8px;
    background: var(--rec-surface);
    color: var(--rec-text);
    font: inherit;
    text-align: left;
    cursor: pointer;
    overflow: hidden;
}
.record-month-cell:hover { background: var(--rec-row-hover); }
.record-month-cell.is-muted { opacity: 0.55; }
.record-month-cell.is-today .record-month-date { color: var(--rec-surface); background: var(--rec-text); }
.record-month-cell.is-selected { border-color: var(--rec-text); }
.record-month-date {
    align-self: flex-start;
    min-width: 22px;
    padding: 0 6px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 600;
}
.record-month-event,
.record-month-more {
    overflow: hidden;
    color: var(--rec-muted);
    font-size: 11px;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.record-month-more { color: var(--rec-faint); }

@media (max-width: 599.98px) {
    .record-month-cell { min-height: 44px; padding: 4px; }
    .record-month-event { display: none; }
    .record-month-cell.has-items::after {
        content: "";
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: var(--rec-text);
    }
}

/* ── Records Home, managers only: records by status (HQU-969, was Build's Recent) ── */
/* Too narrow for every column, it scrolls sideways — and says so: a shade on the right edge while
   there is more to the right (the surface-coloured cover scrolls with the content and hides the
   shade at the end). HQU-1420. */
.record-throughput-scroll {
    overflow-x: auto;
    border: 1px solid var(--rec-border);
    border-radius: 10px;
    background:
        linear-gradient(to left, var(--rec-surface) 40%, transparent) right / 32px 100% no-repeat local,
        linear-gradient(to left, color-mix(in srgb, var(--rec-text) 14%, transparent), transparent) right / 12px 100% no-repeat scroll,
        var(--rec-surface);
}
.record-throughput-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm, 13px);
}
.record-throughput-table th,
.record-throughput-table td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--rec-border-soft);
    text-align: left;
    white-space: nowrap;
}
.record-throughput-table tbody tr:last-child th,
.record-throughput-table tbody tr:last-child td { border-bottom: 0; }
.record-throughput-table thead th { color: var(--rec-faint); font-size: 12px; font-weight: 600; }
/* Two-word headings ("Not started", "In progress") may break, so the counts need less width. */
.record-throughput-table thead th.is-num { white-space: normal; }
.record-throughput-table tbody th { font-weight: 500; }
/* The Module column: a long name wraps (up to two lines, then "…") instead of setting the table's
   width, and stays put while the counts scroll under it (HQU-1420). */
.record-throughput-table tr > :first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    min-width: 140px;
    background: var(--rec-surface);
}
.record-throughput-table tbody th { white-space: normal; }
.record-throughput-table tbody th a {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    max-width: 260px;
    overflow: hidden;
    overflow-wrap: anywhere;
}
.record-throughput-table a { color: var(--rec-text); text-decoration: none; }
.record-throughput-table a:hover { text-decoration: underline; }
.record-throughput-table .is-num { text-align: right; font-variant-numeric: tabular-nums; }
.record-throughput-table .is-zero { color: var(--rec-faint); }
.record-agent-activity { margin-top: 0; }

/* ── Parts panel (HQU-1353) — "Part of" + "Parts" on an asset, with the manager's Move / Remove / Add part.
   The labels and small text actions reuse the Manage column's (.record-manage-label / -link / -muted / -error). */
.record-parts-section + .record-parts-section {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--rec-border-soft);
}

.record-parts-row {
    display: flex;
    align-items: center;
    gap: 8px;
}
.record-parts-row > .record-rel-row { flex: 1; min-width: 0; }

.record-parts-acts {
    display: flex;
    flex: none;
    align-items: center;
    gap: 12px;
    font-size: 13px;
}

.record-parts-group {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin: 8px 0 2px;
    padding: 0 6px;
    color: var(--rec-muted);
    font-size: 12px;
    font-weight: 600;
}
.record-parts-count { color: var(--rec-faint); font-variant-numeric: tabular-nums; }

.record-parts-pick,
.record-parts-confirm {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 6px 0 10px;
    padding: 10px;
    border: 1px solid var(--rec-border-soft);
    border-radius: 8px;
    font-size: 13px;
    color: var(--rec-body);
}
.record-parts-pick > .record-manage-link { align-self: flex-end; }

/* Phone: the actions drop under the row rather than squeezing the label to nothing. */
@media (max-width: 480px) {
    .record-parts-row { flex-wrap: wrap; }
    .record-parts-acts { width: 100%; justify-content: flex-end; padding: 0 6px 6px; }
}

/* Run wizard: unticking a parent offers to untick its parts too (HQU-1354). */
.record-asset-offer {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 14px;
    margin: 0 20px 4px;
    padding: 10px 12px;
    border: 1px solid var(--rec-border-soft);
    border-radius: 8px;
    font-size: 13px;
    color: var(--rec-body);
}
