/* Reset plus the primitives every page uses: button, field, card, table, badge. */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    min-height: 100vh;
    display: flex;              /* sticky footer without a fixed height anywhere */
    flex-direction: column;
    font-family: var(--font-sans);
    font-size: var(--fs-300);
    line-height: 1.5;
    color: var(--color-text);
    background: var(--color-bg);
}

h1, h2, h3, h4 { margin: 0 0 var(--sp-3); line-height: 1.25; color: var(--c-navy); }
h1 { font-size: var(--fs-600); }
h2 { font-size: var(--fs-500); }
h3 { font-size: var(--fs-400); }
p { margin: 0 0 var(--sp-3); }
a { color: var(--c-blue-dark); }
img { max-width: 100%; height: auto; }

.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--sp-4); }
.muted { color: var(--color-text-muted); font-size: var(--fs-200); }
/* A paragraph that IS the body of a card or a banner: the card already supplies the padding, and
   the browser's default margin pushes the text off-centre inside it. Was an inline margin:0. */
.flush { margin: 0; }
.section-title { margin-bottom: var(--sp-5); }

.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Button ------------------------------------------------------------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-5);
    border: 1px solid transparent; border-radius: 999px;
    font: inherit; font-weight: 600; text-decoration: none; cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
/* Filled buttons carry NAVY text on the brand green: white text on #AFCA0B is 1.8:1
 * and fails WCAG AA. This is the one place the palette forces the choice. */
.btn--primary { background: var(--c-green); color: var(--c-navy); }
.btn--primary:hover { background: var(--c-green-hover); }
.btn--secondary { background: var(--c-navy); color: var(--c-white); }
.btn--secondary:hover { background: #123a58; }
.btn--outline { background: transparent; border-color: var(--color-border); color: var(--c-navy); }
.btn--outline:hover { border-color: var(--c-navy); }
.btn--ghost { background: transparent; color: var(--c-blue-dark); }
.btn--danger { background: transparent; border-color: var(--color-danger); color: var(--color-danger); }
.btn--sm { padding: var(--sp-2) var(--sp-4); font-size: var(--fs-200); }
.btn:focus-visible { outline: 3px solid var(--c-blue); outline-offset: 2px; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
/* Companion guard: the base rule is display:flex, so [hidden] alone would not hide it. */
.btn[hidden] { display: none; }

/* --- Form field --------------------------------------------------------- */
.field { display: block; margin-bottom: var(--sp-4); }
.field[hidden] { display: none; }
.field__label { display: block; margin-bottom: var(--sp-2); font-weight: 600; font-size: var(--fs-200); }
.input, .select, .textarea {
    width: 100%; padding: var(--sp-3);
    border: 1px solid var(--color-border); border-radius: var(--radius-sm);
    font: inherit; background: var(--color-surface); color: var(--color-text);
}
.input:focus, .select:focus, .textarea:focus {
    outline: 2px solid var(--c-blue); outline-offset: 1px; border-color: var(--c-blue);
}
.input.is-invalid, .select.is-invalid {
    border-color: var(--color-danger); box-shadow: 0 0 0 2px rgba(179, 38, 30, .15);
}
.field-note { margin-top: var(--sp-2); }

.form__error, .form__success {
    padding: var(--sp-3); border-radius: var(--radius-sm); font-size: var(--fs-200);
}
.form__error { background: var(--color-danger-bg); color: var(--color-danger); }
.form__error[hidden], .form__success[hidden] { display: none; }
.form__success { background: #eaf6ee; color: var(--c-green-dark); }

/* --- Card --------------------------------------------------------------- */
.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    padding: var(--sp-5);
}

/* --- Badge -------------------------------------------------------------- */
.badge {
    display: inline-block; padding: var(--sp-1) var(--sp-3);
    border-radius: 999px; font-size: var(--fs-100); font-weight: 600;
    background: var(--color-border); color: var(--c-navy);
}
.badge--collection { background: var(--phase-collection); color: var(--c-navy); }
.badge--sorting { background: var(--phase-sorting); color: var(--c-navy); }
.badge--destination { background: var(--phase-destination); color: var(--c-navy); }
.badge--danger { background: var(--color-danger-bg); color: var(--color-danger); }
/* Review states, keyed by the status the row carries rather than by a map in a script - a map
   would be a second list of statuses, and a fourth one would arrive in the database and get a grey
   badge with nobody able to say why. Which colour a state wears is a display rule, so CSS answers
   it. APPROVED deliberately keeps the neutral badge: green on every accepted row shouts louder
   than the two states that actually want somebody to do something. */
.badge--status-rejected { background: var(--color-danger-bg); color: var(--color-danger); }
.badge--status-blocked { background: var(--color-danger-bg); color: var(--color-danger); }
.badge--status-pending { background: var(--color-warning-bg); color: var(--color-warning); }
/* The rest of "not approved yet" (Corrections 141). Orange is for a state somebody is still waiting
   on; red stays for a decision that was actually taken against the operator, because collapsing
   rejected into the waiting colour throws away the one distinction an admin queue is read for.
   APPROVED and AUDITED are absent on purpose and keep the neutral badge. */
.badge--status-draft { background: var(--color-warning-bg); color: var(--color-warning); }
.badge--status-not_audited { background: var(--color-warning-bg); color: var(--color-warning); }
.badge--status-in_progress { background: var(--color-warning-bg); color: var(--color-warning); }
.badge--status-overdue { background: var(--color-warning-bg); color: var(--color-warning); }

/* --- Data table ---------------------------------------------------------
 * A grid rather than a <table>: the ledger views need a column to line up across
 * rows that are themselves grids, which display:contents gives for free. */
.data-table { display: grid; gap: 1px; background: var(--color-border);
    border: 1px solid var(--color-border); border-radius: var(--radius);
    /* No overflow:hidden here. A grid table wider than its container was clipping itself, so its
       border box still measured the container width and .table-scroll was never given anything to
       scroll - the last columns of the proofs table, including the document link, were rendered
       and physically unreachable. The rounding moves to .table-scroll instead. */
    min-width: max-content; }

/* A table whose columns are short enough to fit should FIT, not scroll.
   min-width:max-content above is there for the genuinely wide tables (the proof list, the config
   editors) where scrolling is the honest answer. On a five-column table it measured 1328px inside
   a 1088px container and pushed the row's own action button off the right edge - the primary thing
   you do with that row, hidden behind a scrollbar on a 1400px screen. */
.data-table--fit { min-width: 0; }
/* Companion guard: .data-table is display:grid, which beats the user agent's [hidden] rule.
   Without this, hiding an empty table does nothing and its column header stands over the
   empty state - which reads as data that failed to load. */
.data-table[hidden] { display: none; }
.data-table__row { display: grid; gap: 1px; background: var(--color-border); }
/* Companion guard, for the same reason as .data-table[hidden] above: the row is display:grid, and
   an author display rule beats the user agent's [hidden]. Without this row.hidden does nothing. */
.data-table__row[hidden] { display: none; }
.data-table__cell { background: var(--color-surface); padding: var(--sp-3); }
.data-table__head .data-table__cell { font-weight: 600; font-size: var(--fs-200); background: #eef2f4; }
.data-table__num { text-align: right; font-variant-numeric: tabular-nums; }
/* Wide content scrolls inside its own box; the page body never scrolls sideways. */
.table-scroll { overflow-x: auto; border-radius: var(--radius); }

@media print {
    *, *::before, *::after { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
    body { background: #fff; }
    .page-header, .no-print { display: none !important; }
    .card { break-inside: avoid; }
}

/* The site header is sticky, so an in-page jump (#unbacked, #reservations, #reconciliation) would
   land the target underneath it. Reserving the header's height means the heading you asked for is
   the heading you see. */
:target,
h1[id], h2[id], h3[id],
[data-role^="panel-"] { scroll-margin-top: 5rem; }
