/* ChefOS shared design layer. Loaded by _Layout after site.css, so nothing here needs !important to win.
   Contents: tokens -> utilities -> typography -> forms/focus -> cards -> chips -> segmented choice -> action bar -> disclosure ->
   empty state / filter bar -> page header -> deviation prompt -> confirm dialog -> pagination.
   Rules: every colour pair used for text here is >= 4.5:1 (ratios in the task-1 report); button variants are defined in site.css.
   New form UI must use these classes rather than a page-local <style> copy. */

:root {
    /* Spacing scale (4/8/12/16/24/32 px) */
    --sp-1: 0.25rem;
    --sp-2: 0.5rem;
    --sp-3: 0.75rem;
    --sp-4: 1rem;
    --sp-6: 1.5rem;
    --sp-8: 2rem;

    /* Type scale */
    --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --fs-h1: 1.75rem;
    --fs-h2: 1.25rem;
    --fs-card-title: 1.05rem;
    --fs-body: 1rem;
    --fs-muted: 0.875rem;
    --fs-group: 0.8rem;

    /* Colour */
    --brand: #37BBA1;           /* DailyChef logo colour (sidebar). White on it fails AA, so text on it is --brand-ink. */
    --brand-ink: #0B2E27;       /* 6.12:1 on --brand, 14.6:1 on white */
    --brand-hover: #5FCFB9;     /* sidebar hover; ink on it 7.75:1 */
    --blue: #0052cc;
    --blue-dark: #003d99;
    --focus: #1565c0;           /* 5.75:1 on white */
    --text: #1f2937;
    --text-muted: #5b6573;      /* 5.9:1 on white, 5.5:1 on the page grey */
    --text-group: #475569;
    --border: #cbd5e1;
    --border-strong: #94a3b8;
    --surface: #ffffff;
    --page: #f5f6fa;
    --ok: #166534;     --ok-bg: #dcfce7;
    --bad: #991b1b;    --bad-bg: #fee2e2;
    --warn: #92400e;   --warn-bg: #fef3c7;
    --info: #075985;   --info-bg: #e0f2fe;
    --neutral: #334155; --neutral-bg: #e2e8f0;
    --radius: 8px;
    --shadow: 0 1px 3px rgba(0,0,0,0.1);
}

/* hidden always wins, even over a component's own display (a flex row, a grid). */
[hidden] { display: none !important; }
.invisible { visibility: hidden; }

/* ── Typography: one font, one scale ── */
h1 { font-size: var(--fs-h1); line-height: 1.2; }
h2 { font-size: var(--fs-h2); line-height: 1.25; }
.card-title { font-size: var(--fs-card-title); font-weight: 600; margin: 0; }
.group-label { font-size: var(--fs-group); font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-group); }
.text-muted { color: var(--text-muted); font-size: var(--fs-muted); }
.small { font-size: var(--fs-muted); }
.fw-semibold { font-weight: 600; }
.font-monospace { font-family: ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace; }
.nowrap { white-space: nowrap; }
.ac-dt { white-space: nowrap; }  /* date / time cells stay on one line ("14 Oct 20:31") */

/* Margin utilities on the spacing scale */
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-3 { margin-bottom: var(--sp-4); }
.mb-4 { margin-bottom: var(--sp-6); }
.mt-2 { margin-top: var(--sp-2); }
.mt-4 { margin-top: var(--sp-6); }

/* ── Forms ── */
.form-label { display: block; font-size: 0.85rem; font-weight: 600; color: #333; margin-bottom: var(--sp-1); }
.form-select { width: 100%; padding: 0.4rem 0.6rem; border: 1px solid #ccc; border-radius: 4px; font-size: 0.9rem; min-height: 44px; background: #fff; }
.form-select:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 2px rgba(0,82,204,0.2); }
.form-check-input { width: 24px; height: 24px; flex: 0 0 auto; }
/* Keyboard focus: a solid 3px ring on everything interactive (the old 2px / 20% box-shadow is kept as the mouse-focus hint). */
a:focus-visible, button:focus-visible, summary:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible,
.btn:focus-visible, .form-control:focus-visible, .form-control[readonly]:focus-visible, .form-select:focus-visible {
    outline: 3px solid var(--focus);
    outline-offset: 2px;
}

/* ── Cards ── */
.card { padding: var(--sp-4); border-radius: var(--radius); }
.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }
.card-head, .card-header { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); }
.card-header { font-weight: 600; }
.card-body { margin-bottom: var(--sp-3); }
.card-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); }
/* Status shows as a left border + a chip. */
.card[data-status="ok"] { border-left: 5px solid #15803d; }
.card[data-status="bad"] { border-left: 5px solid #b91c1c; }
.card[data-status="warn"] { border-left: 5px solid #b45309; }

/* Equal-height grid: every card stretches, and its actions stick to the bottom so buttons line up across a row. */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--sp-4); align-items: stretch; margin: var(--sp-4) 0; }
.card-grid > .card { display: flex; flex-direction: column; margin: 0; }
.card-grid > .card .card-actions { margin-top: auto; padding-top: var(--sp-3); }
.card-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 0 0 var(--sp-4); }
@media (max-width: 900px) { .card-grid--2 { grid-template-columns: minmax(0, 1fr); } }

/* ── Chips: every status is one of these ── */
.chip { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.15rem 0.6rem; border-radius: 999px; font-size: 0.85rem; font-weight: 600; line-height: 1.3; white-space: nowrap; background: var(--neutral-bg); color: var(--neutral); }
/* ── Plain list: a numbered row list, label left, chip right, rows >= 48 px (Packing pre-start section A) ── */
.plain-list { list-style: none; margin: 0; padding: 0; counter-reset: plain-row; }
.plain-list > li { counter-increment: plain-row; display: flex; align-items: center; gap: var(--sp-3); min-height: 48px; padding: var(--sp-2) 0; border-bottom: 1px solid var(--border); }
.plain-list > li:last-child { border-bottom: 0; }
.plain-list > li::before { content: counter(plain-row); flex: 0 0 1.75rem; text-align: right; color: var(--text-muted); font-size: var(--fs-muted); font-variant-numeric: tabular-nums; }
.plain-list > li > a { flex: 1 1 auto; min-width: 0; align-self: stretch; display: flex; align-items: center; overflow-wrap: anywhere; color: var(--text); text-decoration: none; }
.plain-list > li > a:hover { text-decoration: underline; }
.plain-list > li > .chip { flex: 0 0 auto; margin-left: auto; }
.chip--ok { background: var(--ok-bg); color: var(--ok); }
.chip--bad { background: var(--bad-bg); color: var(--bad); }
.chip--warn { background: var(--warn-bg); color: var(--warn); }
.chip--info { background: var(--info-bg); color: var(--info); }
.chip--neutral { background: var(--neutral-bg); color: var(--neutral); }

/* ── Segmented choice ──
   <div class="seg" role="radiogroup"><label class="seg__opt seg__opt--ok"><input type="radio" ...><span>Pass</span></label> ... </div>
   Selected colour by meaning: --ok / --bad / --warn (damaged) / --na; an option with no modifier selects in blue. */
.seg { display: inline-flex; border: 2px solid var(--border-strong); border-radius: var(--radius); overflow: hidden; background: #fff; flex: 0 0 auto; }
.seg__opt { position: relative; display: block; margin: 0; padding: 0; cursor: pointer; border-right: 2px solid var(--border-strong); font-weight: 600; }
.seg__opt:last-child { border-right: 0; }
.seg__opt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.seg__opt span { display: flex; align-items: center; justify-content: center; min-width: 4.5rem; min-height: 44px; padding: 0 1rem; }
.seg__opt:hover input:not(:checked) + span { background: #f1f3f5; }
.seg__opt input:checked + span { background: var(--blue); color: #fff; }
.seg__opt--ok input:checked + span { background: #15803d; color: #fff; }
.seg__opt--bad input:checked + span { background: #b91c1c; color: #fff; }
.seg__opt--warn input:checked + span { background: #b45309; color: #fff; }
.seg__opt--na input:checked + span { background: #334155; color: #fff; }
.seg__opt input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: -3px; }
.seg--lg .seg__opt span { min-height: 48px; }
.seg--block { display: flex; width: 100%; }
/* Button flavour: a result button that posts (Pass / Fail / N/A). aria-pressed marks the chosen one; a read-only run keeps it coloured with a tick. */
.seg > button.seg__opt { border: 0; border-right: 2px solid var(--border-strong); border-radius: 0; background: #fff; color: var(--neutral); font: inherit; font-weight: 600; min-width: 5.5rem; min-height: 44px; padding: 0 1rem; cursor: pointer; }
.seg--lg > button.seg__opt { min-height: 48px; }
.seg > button.seg__opt:last-child { border-right: 0; }
.seg > button.seg__opt:hover:not(:disabled):not([aria-pressed="true"]) { background: #f1f3f5; }
.seg > button.seg__opt[aria-pressed="true"] { background: var(--blue); color: #fff; }
.seg > button.seg__opt--ok[aria-pressed="true"] { background: #15803d; }
.seg > button.seg__opt--bad[aria-pressed="true"] { background: #b91c1c; }
.seg > button.seg__opt--warn[aria-pressed="true"] { background: #b45309; }
.seg > button.seg__opt--na[aria-pressed="true"] { background: #334155; }
.seg > button.seg__opt:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.seg > button.seg__opt:disabled { cursor: default; color: #64748b; -webkit-text-fill-color: #64748b; background: #f8fafc; }
.seg > button.seg__opt[aria-pressed="true"]:disabled { color: #fff; -webkit-text-fill-color: #fff; }
/* Compact button group (Forms on/off: three states in a narrow stacked cell): the buttons shrink and wrap their text instead of overflowing. */
.seg--compact { max-width: 100%; }
.seg > button.seg__opt--compact, .seg--compact > button.seg__opt { min-width: 0; padding: 0 0.6rem; flex: 1 1 auto; line-height: 1.15; overflow-wrap: normal; word-break: normal; }
.forms-layout-select { min-width: 9rem; max-width: 100%; }
.seg > button.preop-result-chosen::before { content: "\2713\00a0"; font-weight: 700; }
.seg__opt input:disabled { cursor: default; }
.seg--block .seg__opt { flex: 1 1 0; }
.seg > a.seg__opt { display: flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 1.25rem; color: var(--neutral); text-decoration: none; }
.seg--lg > a.seg__opt { min-height: 48px; }
.seg > a.seg__opt:hover { background: #f1f3f5; }
.seg > a.seg__opt[aria-current="page"] { background: var(--blue); color: #fff; }
.seg > a.seg__opt:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
fieldset:disabled .seg { opacity: 0.6; }

/* site.css gives .content overflow-y:auto, which makes it the scrollport of every position:sticky child - and since it never scrolls itself, the
   sticky action bars (and the impersonation banner) never stuck to the window. clip keeps the sideways containment without becoming a scroll container. */
.content { overflow-x: clip; overflow-y: visible; }

/* ── Sticky action bar: Save, then secondary actions, then Submit on the right (margin-left:auto on the last primary). ── */
.action-bar { position: sticky; bottom: 0; z-index: 5; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-4);
    padding: var(--sp-3) 0 calc(var(--sp-3) + env(safe-area-inset-bottom, 0px)); background: #fff; border-top: 1px solid var(--border); }
.action-bar .action-bar__end, .action-bar > .btn-success:last-child { margin-left: auto; }

/* ── Disclosure: summary with a chevron, 44px, keeps list-item so the browser still treats it as a disclosure widget. ── */
.disclosure { margin: var(--sp-1) 0; }
.disclosure > summary { display: list-item; list-style: none; cursor: pointer; min-height: 44px; padding: 0.7rem 0.25rem; font-weight: 600; color: var(--blue); }
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::before { content: "\25B8"; display: inline-block; width: 1.1em; transition: transform 0.15s; }
.disclosure[open] > summary::before { transform: rotate(90deg); }

/* ── Add-reveal: an add form collapsed behind a button. A <details> so it works with JS off; the summary is a 48px button, the form opens beneath it. Rendered open when the add was refused, a prompt is pending, or it is a re-check prefill. ── */
.add-reveal > summary { list-style: none; display: inline-flex; align-items: center; min-height: 48px; cursor: pointer; }
.add-reveal > summary::-webkit-details-marker { display: none; }
.add-reveal[open] > summary { margin-bottom: var(--sp-2); }

/* ── Empty state and filter bar ── */
.empty-state { margin: var(--sp-4) 0; padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--text-muted); background: #fff; border: 1px dashed var(--border-strong); border-radius: var(--radius); }
.empty-state > :last-child { margin-bottom: 0; }
.filter-bar { background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); padding: var(--sp-3) var(--sp-4); margin: 0 0 var(--sp-4); flex-wrap: wrap; align-items: flex-end; gap: var(--sp-3); }
.filter-bar label { display: block; font-size: 0.85rem; font-weight: 600; color: #333; margin-bottom: var(--sp-1); }
.filter-bar .btn { align-self: flex-end; }
.filter-bar label.inline-check { display: inline-flex; margin-bottom: 0; font-size: var(--fs-body); }

/* ── Page header (Pages/Shared/_PageHeader.cshtml) ──
   row 1 back link / breadcrumb, row 2 h1 + inline status chip with the actions on the right, row 3 meta line.
   Also what the existing <div class="page-header"> on the API-keys pages needs: a row of title + button. */
.page-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2) var(--sp-4); margin-bottom: var(--sp-4); }
.page-header__back { flex: 0 0 100%; margin: 0; font-size: var(--fs-muted); }
.page-header__title { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); flex: 1 1 auto; min-width: 0; }
.page-header__title h1 { margin: 0; }
.page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-left: auto; }
.page-header__meta { flex: 0 0 100%; margin: 0; color: var(--text-muted); font-size: var(--fs-muted); }
.page-header > h1 { margin: 0; }

/* ── QA record cards: one card per row of a form (a scale, a swab point, a knife, a changeover, a pre-op check) ──
   <section class="card" data-status="ok|bad|warn"> <div class="card-head"><span class="kicker">Location</span><h3 class="card-title">Code</h3><span class="chip">...</span></div> ... </section>
   A live chip (atp-swab.js / scale-calibration.js) carries data-verdict; the server renders the same attribute, so the palette is one set of rules. */
.chip[data-verdict="Pass"], .chip[data-state="Pass"] { background: var(--ok-bg); color: var(--ok); }
.chip[data-verdict="Fail"], .chip[data-state="Deviation"], .chip[data-state="Fail"] { background: var(--bad-bg); color: var(--bad); }
.chip[data-verdict="Resolved"] { background: var(--warn-bg); color: var(--warn); }
.card[data-voided] { background: #f8fafc; opacity: 0.85; }
.card[data-voided] .card-title { text-decoration: line-through; }
.card-head .card-title { font-weight: 700; }
.kicker { font-size: var(--fs-group); font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text-group); background: #f1f5f9; border-radius: 4px; padding: 0.1rem 0.5rem; }
.group-heading { margin: var(--sp-6) 0 var(--sp-2); }
.card-stack > .card { margin: 0 0 var(--sp-3); }
.sub-block { margin: var(--sp-2) 0; padding: var(--sp-1) 0; }
.sub-block[data-active="false"] { color: var(--text-group); }
.sub-block > .group-label { margin-bottom: var(--sp-1); }
.fieldset-box { border: 1px solid var(--border); border-radius: 6px; padding: var(--sp-2) var(--sp-3); margin: var(--sp-2) 0; }
.fieldset-box legend { font-size: 0.9rem; width: auto; padding: 0 var(--sp-1); }
.card--narrow { max-width: 720px; }
.card--signoff { max-width: 640px; }
.card--signoff textarea { width: 100%; }

/* A row of fields inside a card: wraps, never stretches, fields top-aligned so a wrapped "Now" button cannot push a neighbour down (S3). */
.field-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: flex-start; margin-bottom: var(--sp-3); }
.field-row > .form-group, .field-row > div { margin: 0; }
.field-row--end { align-items: flex-end; }
.field-row--center { align-items: center; }
.field-row--divider { border-top: 1px dashed var(--border); padding-top: var(--sp-2); }
.field-row[hidden] { display: none; }
.field-row .grow { flex: 1 1 14rem; min-width: 0; }
.input-num { width: 9rem; font-size: 1.1rem; }
.reading-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-2); margin-bottom: var(--sp-3); }
.reading-grid > .form-group { margin: 0; }
.reading-grid input[type=number] { width: 100%; font-size: 1.1rem; }
@media (max-width: 900px) { .reading-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.inline-check { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: 44px; margin: 0; font-weight: 400; font-size: var(--fs-body); }
.inline-check input { width: 24px; height: 24px; flex: 0 0 auto; }
.readout { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); margin: var(--sp-1) 0; }
.readout > span { white-space: nowrap; }
.readout .is-bad, .is-bad { color: var(--bad); font-weight: 700; }
.is-ok { color: var(--ok); font-weight: 700; }
.stacked-field { display: block; margin: var(--sp-3) 0; }
.max-640 { max-width: 640px; }
.max-720 { max-width: 720px; }
.max-480 { max-width: 480px; }
.full-width { width: 100%; }
.flex-between { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--sp-2); }
.mt-3 { margin-top: var(--sp-4); }
.mb-1 { margin-bottom: var(--sp-1); }
.mt-0 { margin-top: 0; }
.ms-auto { margin-left: auto; }
.display-inline { display: inline; }
.d-flex-wrap { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }

/* Two-column form grid inside a card (collapses to one column below 900 px); .span-full takes the whole row, a nested .form-grid does too. */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-3); }
.form-grid > .form-group { margin: 0; }
.form-grid > .span-full, .form-grid > .form-grid { grid-column: 1 / -1; }
.form-grid > .form-grid { margin-bottom: 0; }
@media (max-width: 899px) { .form-grid { grid-template-columns: minmax(0, 1fr); } }
.note-box { background: #f1f5f9; border-radius: 6px; padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3); }
.card-section { border-top: 1px dashed var(--border-strong); margin-top: var(--sp-4); padding-top: var(--sp-3); }
.card .card { box-shadow: none; border: 1px solid var(--border); }
.card > .card-title { margin-bottom: var(--sp-3); }
.max-820 { max-width: 820px; }
.field-row > .form-group:has(.date-entry) { flex: 1 1 16rem; max-width: 22rem; }

/* Read-only label / value list (a submitted report). */
.detail-list { display: grid; grid-template-columns: minmax(9rem, 14rem) minmax(0, 1fr); gap: var(--sp-1) var(--sp-4); margin: 0; }
.detail-list dt { font-weight: 600; color: var(--text-group); }
.detail-list dd { margin: 0; }
.pre-wrap { white-space: pre-wrap; }
@media (max-width: 599px) { .detail-list { grid-template-columns: minmax(0, 1fr); } .detail-list dd { margin-bottom: var(--sp-2); } }
.photo-grid { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.photo-grid__item { width: 140px; }
.photo-grid img { width: 140px; height: 140px; object-fit: cover; border: 1px solid var(--border); border-radius: 4px; display: block; }
.is-voided { opacity: 0.85; }
.is-voided h1 { text-decoration: line-through; }
.table-sm { font-size: var(--fs-muted); }
.form-grid > fieldset, fieldset.plain { border: 0; padding: 0; margin: 0; min-width: 0; }
legend.form-label { padding: 0; float: none; width: auto; }
textarea.form-control { min-height: 5rem; }

/* A box of readings inside a card (the pre-op temperature block). */
.reading-box { border: 1px solid var(--border); border-radius: 6px; padding: var(--sp-3); margin-bottom: var(--sp-3); background: #f8fafc; }
.chip[data-verdict="InRange"] { background: var(--ok-bg); color: var(--ok); }
.chip[data-verdict="OutOfRange"] { background: var(--bad-bg); color: var(--bad); }
.chip[data-verdict="NotJudged"] { display: none; }
.progress { display: block; width: 100%; height: 10px; border: 0; border-radius: 4px; background: #e5e7eb; accent-color: #15803d; }
.progress::-webkit-progress-bar { background: #e5e7eb; border-radius: 4px; }
.progress::-webkit-progress-value { background: #15803d; border-radius: 4px; }
.progress::-moz-progress-bar { background: #15803d; border-radius: 4px; }
.col-show-narrow { display: none; font-size: var(--fs-muted); color: var(--text-group); white-space: pre-wrap; }
@media (max-width: 900px) { .col-hide-narrow { display: none; } .col-show-narrow { display: block; } }
.table-sm th, .table-sm td { padding: var(--sp-2) var(--sp-3); vertical-align: top; }

/* The live Pass / Below-limit chip next to a temperature input (ccp-live-limit.js) is a chip like every other. */
.ccp-live-chip { margin-top: var(--sp-1); }
.chip[data-state="pass"] { background: var(--ok-bg); color: var(--ok); }
.chip[data-state="below"], .chip[data-state="fail"] { background: var(--bad-bg); color: var(--bad); }

/* Utilities used by the QA record pages in place of inline styles. */
.mt-1 { margin-top: var(--sp-1); }
.mt-3 { margin-top: var(--sp-4); }
.my-2 { margin-top: var(--sp-2); margin-bottom: var(--sp-2); }
.m-0 { margin: 0; }
.ms-2 { margin-left: var(--sp-2); }
.ms-4 { margin-left: var(--sp-6); }
.d-block { display: block; }
.text-center { text-align: center; }
.is-retired { opacity: 0.6; }
.is-dimmed { opacity: 0.55; }
.card--error { background: #fff3f3; }
.mw-5 { max-width: 5rem; } .mw-7 { max-width: 7rem; } .mw-8 { max-width: 8rem; } .mw-9 { max-width: 9rem; } .mw-10 { max-width: 10rem; }
.max-500 { max-width: 500px; } .max-760 { max-width: 760px; }
.card--done { border-left: 4px solid #15803d; }
.note-rail { border-left: 4px solid #607d8b; padding-left: var(--sp-3); }
.key-box { background: #f8f9fa; padding: var(--sp-4); border-radius: 4px; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: 1.1rem; word-break: break-all; margin-bottom: var(--sp-4); }
.otp-input { font-size: 1.5rem; text-align: center; letter-spacing: 0.5rem; }
.text-bad { color: var(--bad); }
.text-warn { color: var(--warn); }
.is-warn { color: var(--warn); font-weight: 700; }
.is-struck { text-decoration: line-through; color: #64748b; }
.basis-full { flex-basis: 100%; }
.max-560 { max-width: 560px; }
.plain { border: 0; padding: 0; margin: 0; min-width: 0; }
.list-indent { margin: 0 0 0 var(--sp-6); padding: 0; }
.list-plain { list-style: none; padding: 0; margin: 0; }
.section-heading { margin: var(--sp-6) 0 var(--sp-2); }
.section-heading--sub { font-size: var(--fs-card-title); margin-top: var(--sp-4); }
/* Follow-on rows of a record table (notes, deviation banners, voided lines). */
.row-muted > td, td.row-muted { background: #fafafa; }
.row-bad > td, td.row-bad { background: #fff4f4; }
.row-warn > td, td.row-warn { background: #fff8e1; }
.row-voided > td, td.row-voided { background: #f2f2f2; }
tr.is-struck td { text-decoration: line-through; color: #64748b; }

/* Large (48 px) data-entry controls on the long forms. */
.action-bar .btn, .card-actions .btn { min-height: 48px; }
.action-bar__end { margin-left: auto; }
.action-bar > .btn-primary:last-child { margin-left: auto; }

/* Page-level note under a header: "Showing: Awaiting sign-off", status lines, "read-only" notes. */
.status-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-3); color: var(--text-muted); font-size: var(--fs-muted); }

/* ── Filter bar (Pages/Shared/_FilterBar.cshtml): fields, then Apply (explicit, never on change) and Clear ── */
.filter-bar { display: flex; }
.filter-bar__field { min-width: 0; }
.filter-bar__field .form-control, .filter-bar__field .form-select { min-width: 10rem; }
.filter-bar__field input[type="date"] { min-width: 11rem; }
.filter-bar__actions { display: flex; align-items: center; gap: var(--sp-3); }
.filter-showing { margin: 0 0 var(--sp-3); }

/* ── Deviation-confirm prompt (Pages/Shared/_DeviationConfirm.cshtml) ──
   One copy for every form (QMR 022, Scale calibration, Knives, ATP swabs, Batch cleaning). The save button is danger (filled), Edit is secondary. */
.ccp-confirm { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); margin: var(--sp-2) 0; padding: 0.6rem var(--sp-3);
    background: #fff4f4; border: 1px solid #f5c2c7; border-left: 4px solid #b00020; border-radius: 4px; color: #7a0016; font-weight: 600; grid-column: 1 / -1; }
.ccp-confirm .field-error-icon { flex: 0 0 18px; display: inline-block; }
.ccp-confirm-text { flex: 1 1 14rem; }
.ccp-confirm-actions { display: inline-flex; flex-wrap: wrap; gap: var(--sp-2); }
.ccp-confirm-actions .btn { min-height: 48px; display: inline-flex; align-items: center; }

/* ── Confirm dialog (confirm-dialog.js): neutral header, Cancel (secondary) on the left, Confirm (primary, or danger) on the right ── */
.confirm-dialog .validation-dialog-header { background: #eef2f7; border-bottom: 1px solid var(--border); color: #1e293b; }
.confirm-dialog .validation-dialog-footer { justify-content: space-between; gap: var(--sp-2); }
.confirm-dialog .validation-dialog-footer .btn { min-width: 8rem; }

/* ── Pagination (Admin/PageUsage) ── */
.pagination { display: flex; flex-wrap: wrap; gap: var(--sp-1); list-style: none; margin: var(--sp-4) 0; padding: 0; }
.page-item { display: block; }
.page-link { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; padding: 0 var(--sp-3); border: 1px solid var(--border); border-radius: 6px; background: #fff; color: var(--blue); text-decoration: none; }
.page-link:hover { background: #e8f0fe; text-decoration: none; }
.page-item.active .page-link { background: var(--blue); border-color: var(--blue); color: #fff; }
.page-item.disabled .page-link { color: #4b5563; background: #e5e7eb; pointer-events: none; }

/* ── Pre-op run wizard: a wider card, and a sticky bar of Back / progress / Next ── */
.card--wizard { max-width: 880px; }
.preop-nav { max-width: 880px; }
.preop-nav__progress { flex: 1 1 10rem; min-width: 8rem; }
.preop-nav__progress .progress { margin-top: var(--sp-1); }
.preop-layout-switch { margin-top: var(--sp-2); }

/* A prompt that is a statement plus a question puts the question on its own line (ChefOS.Web.Pages.Shared.DeviationConfirmModel.Split). */
.ccp-confirm-question { display: block; margin-top: var(--sp-1); }

/* ── Work-instruction text (QMR 022 guidance): lighter than the data it sits beside - a quiet rule and small muted type, not a filled alert ── */
.guidance-box { border-left: 3px solid var(--border-strong); padding: var(--sp-1) var(--sp-3); color: var(--text-muted); font-size: var(--fs-muted); background: transparent; }
.guidance-box ul { margin: var(--sp-1) 0 var(--sp-1) var(--sp-6); padding: 0; }

/* QA summary links are inline text in a list, not 44 px touch rows (site.css forces that for table links); the row gets the spacing instead. */
[data-qa-summary] a, .ac-summary a { display: inline; min-height: 0; }
[data-qa-summary] li { padding: var(--sp-1) 0; }

/* A save that lands on a row / card (#cal-row-7 ...) must not leave it flush against the top edge. */
[id], .preop-check, [data-deviation-confirm] { scroll-margin-top: calc(var(--sticky-top-h, 0px) + var(--sp-6)); }
/* What sticks to the top (B3 / T13): the impersonation banner (--banner-h = its measured 64 px: the 44 px stop button + 2 x 0.5rem padding + line box) and, on a QMR 022 / Packing Edit page, the section tabs
   (--tabs-h, a fixed height). Landing targets and scrollIntoView (which honours scroll-margin) clear their sum. The floor drawer's fixed menu button adds its own allowance in site.css. */
html { --banner-h: 0px; --tabs-h: 0px; --sticky-top-h: calc(var(--banner-h, 0px) + var(--tabs-h, 0px)); }
html:has(.impersonation-banner) { --banner-h: 4rem; }
html:has(.section-tabs) { --tabs-h: 3rem; }
.impersonation-banner { box-sizing: border-box; min-height: var(--banner-h, 0px); }
/* A target must also clear the sticky action bar at the bottom (focus / scrollIntoView / a tab jump near the end of the page). */
html:has(.action-bar) { --action-bar-h: 5.5rem; }
[id] { scroll-margin-bottom: var(--action-bar-h, 0px); }

/* ── Section tabs (_SectionTabs, QMR 022 + Packing pre-start): sticky under the banner, one fixed-height line, sideways scroll when narrow. Plain anchors. ── */
.section-tabs { position: sticky; top: var(--banner-h, 0px); z-index: 20; box-sizing: border-box; height: var(--tabs-h); display: flex; align-items: stretch; gap: var(--sp-1);
    margin: 0 0 var(--sp-3); overflow-x: auto; overflow-y: hidden; white-space: nowrap; background: #fff; border-bottom: 1px solid var(--border); scrollbar-width: thin; }
.section-tabs a { flex: 0 0 auto; display: inline-flex; align-items: center; gap: var(--sp-1); padding: 0 var(--sp-3); border-bottom: 3px solid transparent; font-weight: 600; text-decoration: none; color: var(--blue); }
.section-tabs a[aria-current="true"] { border-bottom-color: var(--brand, #37BBA1); color: var(--text); }
.section-tabs a:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.section-tabs__count { display: inline-block; min-width: 1.5em; padding: 0 0.4em; border-radius: 999px; background: var(--red, #b91c1c); color: #fff; font-size: var(--fs-muted); line-height: 1.5; text-align: center; }
@media (max-height: 600px) {
    /* landscape tablet with the keyboard open: the tabs would eat a third of what is left, so they scroll away with the page */
    html:has(.section-tabs) { --tabs-h: 0px; }
    .section-tabs { position: static; height: 3rem; }
}

/* Work-instruction boxes (T13, decision 3): a <details> collapsed by default; the bold limit line stays in the summary beside the label. */
details.guidance-box > summary { display: list-item; list-style: none; cursor: pointer; min-height: 44px; padding: 0.4rem 0.25rem; font-weight: 600; color: var(--text); }
details.guidance-box > summary::-webkit-details-marker { display: none; }
details.guidance-box > summary::before { content: "\25B8"; display: inline-block; width: 1.1em; transition: transform 0.15s; }
details.guidance-box[open] > summary::before { transform: rotate(90deg); }
/* the banner is exactly --banner-h tall: a long name is cut with an ellipsis, never wrapped (it would grow and cover the sticky tabs) */
.impersonation-banner > span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.impersonation-banner { max-height: var(--banner-h, none); }
details.guidance-box > summary .guidance-limit { font-weight: 400; color: var(--text); }
details.guidance-box[open] > summary { margin-bottom: var(--sp-1); }

/* Job picker (In-between cleaning Previous / Next product): a collapsed choose button / chosen job, or an open search + list of >= 48 px tappable rows. */
.job-picker { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
.job-picker--open { align-items: stretch; }
.form-group:has(> .job-picker--open) { grid-column: 1 / -1; }
.job-picker__chosen { font-weight: 600; overflow-wrap: anywhere; }
.job-picker__panel { border: 1px solid var(--border-strong); border-radius: 8px; padding: var(--sp-3); background: #f8fafc; }
.job-picker__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); max-height: 24rem; overflow-y: auto; }
.job-picker__row { width: 100%; min-height: 48px; display: grid; grid-template-columns: 7rem 8rem minmax(0, 1fr) auto; gap: var(--sp-2) var(--sp-3); align-items: center; text-align: left; padding: var(--sp-2) var(--sp-3); border: 1px solid var(--border-strong); border-radius: 6px; background: #fff; color: inherit; font: inherit; cursor: pointer; }
.job-picker__row:hover, .job-picker__row:focus-visible { border-color: var(--ok); background: #f0fdf4; }
.job-picker__row .chip { justify-self: start; }
.job-picker__job { font-weight: 700; }
a.job-picker__row { text-decoration: none; }
.job-picker__desc { overflow-wrap: anywhere; }
@media (max-width: 899px) { .job-picker__row { grid-template-columns: minmax(0, 1fr) auto; } .job-picker__desc { grid-column: 1 / -1; } }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
/* A9: skip link (first focusable element, visible only on focus) and a 44 px tap target for the link-styled "Clear filters". */
.skip-link { position: absolute; left: var(--sp-2, 0.5rem); top: -4rem; z-index: 1100; padding: var(--sp-3, 0.75rem) var(--sp-4, 1rem); background: #fff; color: var(--brand-ink, #0B2E27); border: 2px solid var(--brand-ink, #0B2E27); border-radius: var(--radius, 6px); font-weight: 700; }
.skip-link:focus { top: var(--sp-2, 0.5rem); }
.filter-clear { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--sp-2, 0.5rem); }
#main:focus { outline: none; }

/* ── Index start cards (one per area, today's state) ── */
.start-card__summary { margin: var(--sp-2) 0 0; font-weight: 600; }
.start-card .card-actions .btn, .start-card .card-actions form { max-width: 100%; }
.start-card .card-actions .btn { min-height: 44px; }

/* -- Dashboard (/): the reviewer lists, then one Today row per form with its areas as pills -- */
.dash-form { margin: var(--sp-4) 0 0; font-size: var(--fs-card-title); }
.dash-list { list-style: none; margin: var(--sp-2) 0; padding: 0; }
.dash-list > li { border-bottom: 1px solid var(--border); }
.dash-list > li:last-child { border-bottom: 0; }
.dash-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: 48px; padding: var(--sp-2) 0; color: var(--text); text-decoration: none; }
.dash-row:hover > span:first-child { text-decoration: underline; }
.dash-row > span:first-child { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.dash-row > .chip { flex: 0 0 auto; white-space: normal; text-align: right; }
@media (max-width: 600px) { .dash-row { flex-wrap: wrap; } .dash-row > .chip { text-align: left; } }
.dash-today { list-style: none; margin: var(--sp-2) 0; padding: 0; }
.dash-today > li { padding: var(--sp-3) 0; border-bottom: 1px solid var(--border); }
.dash-today > li:last-child { border-bottom: 0; }
.dash-today__name { font-weight: 600; margin-bottom: var(--sp-2); }
.dash-pills { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.dash-pill { min-height: 36px; white-space: normal; text-decoration: none; max-width: 100%; overflow-wrap: anywhere; }
.dash-pill:hover { text-decoration: underline; }
.dash-pill--muted { background: transparent; border: 1px dashed var(--border); color: var(--text-muted); font-weight: 500; }
/* unsaved-add.js: the JS-only "Clear" on an add / answer container (rendered hidden, shown while the add holds typed values). */
.save-add-clear { display: inline-flex; align-items: center; min-height: 44px; margin-top: var(--sp-3); }

/* ── Status strip (QMR 022 _StatusStrip.cshtml, T11): a standing status under the banners, In progress only, not sticky. Links are neutral; chips carry the tone. ── */
.status-strip { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--sp-2) var(--sp-6); padding: var(--sp-3); max-width: 100%; overflow-wrap: anywhere; }
.status-strip__part { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); min-width: 0; }
.status-strip__part > strong { flex: 0 0 auto; }
.status-strip__list { display: flex; flex-direction: column; gap: var(--sp-1); flex-basis: 100%; margin: 0; padding: 0; }
.status-strip__list a { color: var(--text); text-decoration: underline; }
.status-strip a.chip { text-decoration: none; }
.status-strip__ready { flex-basis: 100%; }
