/* ============================================================================
   COUNTRYSIDE CANNABIS CO. — Expense Application
   Layer 2 of 3 · components.css

   The product component library. Every screen built after this one imports
   tokens.css + components.css and composes these classes. Nothing in this
   file contains a raw colour, font, radius or spacing value — semantic
   tokens only. If a screen needs something that isn't here, add it here.

   Contents
     1. Reset + base
     2. Type utilities
     3. Layout
     4. App chrome (header, logo, theme toggle)
     5. Button
     6. Field · Input · Select · DatePicker · CurrencyInput · Textarea
     7. FileDropzone · ReceiptThumbnail
     8. DataTable (stacks to cards < 768px)
     9. Badge / Chip
    10. ValidationBanner
    11. Toast
    12. Modal
    13. EmptyState
    14. Skeleton
   ========================================================================= */

/* --- 1. RESET + BASE ---------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scrollbar-color: var(--fg-muted) var(--surface-sunk);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: var(--weight-regular);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
p { text-wrap: pretty; }
h1, h2, h3, h4 { text-wrap: balance; }
[hidden] { display: none !important; }

/* One focus treatment for the entire application. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-input);
}

::selection { background: var(--accent); color: var(--accent-fg); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- 2. TYPE UTILITIES -------------------------------------------------- */
.h1, .h2, .h3, .h4,
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-regular);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  margin: 0;
}
.h1, h1 { font-size: var(--fs-h1); }
.h2, h2 { font-size: var(--fs-h2); }
.h3, h3 { font-size: var(--fs-h3); }
.h4, h4 { font-size: var(--fs-h4); }

@media (max-width: 640px) {
  .h1, h1 { font-size: var(--fs-h2); }
  .h2, h2 { font-size: var(--fs-h3); }
}

.lead      { font-size: var(--fs-lg); color: var(--fg-secondary); max-width: 62ch; margin: 0; }
.body-sm   { font-size: var(--fs-sm); }
.caption   { font-size: var(--fs-caption); color: var(--fg-muted); }
.text-secondary { color: var(--fg-secondary); }
.text-muted     { color: var(--fg-muted); }

/* Eyebrow. In DARK theme the accent (Light Gold on Eerie Black, 10.91:1)
   carries the text. In LIGHT theme Golden Tobacco as text is 1.64:1 and
   forbidden by accessibility rule 1 — the accent appears as a fill mark
   instead and the words are set in Gun Powder (9.23:1). */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--fs-eyebrow);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin: 0;
}
.eyebrow::before {
  content: '';
  inline-size: var(--space-4);
  block-size: 2px;
  background: var(--accent);
  flex: none;
}
[data-theme='dark'] .eyebrow { color: var(--accent); }
[data-theme='dark'] .eyebrow::before { background: currentColor; }

/* Monetary + km figures. Tabular so every column aligns on the decimal.
   Always --fg: 15.05:1 light / 14.10:1 dark — these are compliance controls. */
.money,
.numeric {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  text-align: right;
  color: var(--fg);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}
.money--lg { font-size: var(--fs-h4); }
.money--neg { color: var(--status-block-ink); }

/* --- 3. LAYOUT --------------------------------------------------------- */
.container {
  max-inline-size: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-6);
}
@media (max-width: 640px) { .container { padding-inline: var(--space-4); } }

.stack   { display: flex; flex-direction: column; gap: var(--space-4); }
.stack-2 { display: flex; flex-direction: column; gap: var(--space-2); }
.stack-6 { display: flex; flex-direction: column; gap: var(--space-6); }
.stack-8 { display: flex; flex-direction: column; gap: var(--space-8); }
.row     { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.grid-2  { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); }
.grid-3  { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-6); }
.grid-4  { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); }
@media (max-width: 900px) { .grid-3, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); } }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-6);
  box-shadow: var(--shadow-card);
}
.card--sunk { background: var(--surface-sunk); box-shadow: none; }
.card--flush { padding: 0; overflow: hidden; }
.rule { border: 0; border-block-start: 1px solid var(--border); margin: 0; }

/* --- 4. APP CHROME ----------------------------------------------------- */
.app-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(14px);
  border-block-end: 1px solid var(--border);
}
.app-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
}

/* Logo lockup. Clear zone = height of the icon glyph, applied as padding.
   The full-colour / inverse pair swaps on the theme attribute in CSS so the
   correct lockup is painted on the first frame with no JS involvement. */
.logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  text-decoration: none;
  flex: none;
}
.logo__lockup { block-size: 34px; inline-size: auto; }
.logo__icon   { block-size: 30px; inline-size: auto; }
[data-theme='light'] .logo__lockup--inverse { display: none; }
[data-theme='dark']  .logo__lockup--full    { display: none; }
/* The product name is set in type only where the lockup is too small to carry
   it — i.e. the phone header, which shows the icon. It is never absent. */
.logo__name {
  display: none;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  letter-spacing: var(--tracking-display);
  line-height: 1.15;
  color: var(--fg);
}
.logo__context {
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary);
  border-inline-start: 1px solid var(--border);
  padding-inline-start: var(--space-3);
  margin-inline-start: var(--space-1);
}
@media (max-width: 640px) {
  .logo__lockup { display: none; }
  .logo__context { display: none; }
  /* Icon + wordmark in type. Wraps to two lines inside 11ch so it fits a
     375px header beside the theme toggle without truncating the name. */
  .logo__name { display: block; font-size: var(--fs-sm); max-inline-size: 11ch; }
}
@media (min-width: 641px) { .logo__icon { display: none; } }

/* Theme toggle — Light / Dark / System, always reachable in the header. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  flex: none;
}
.theme-toggle__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 34px;
  padding-inline: var(--space-3);
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: var(--fg-secondary);
  font-size: var(--fs-sm);
  font-weight: var(--weight-medium);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.theme-toggle__btn svg { inline-size: 16px; block-size: 16px; flex: none; }
.theme-toggle__btn:hover { color: var(--fg); }
.theme-toggle__btn[aria-checked='true'] {
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow-card);
}
.theme-toggle__label { display: inline; }
@media (max-width: 900px) {
  .theme-toggle__label { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); }
  .theme-toggle__btn { min-inline-size: var(--hit-min); justify-content: center; padding-inline: var(--space-2); }
}

/* --- 5. BUTTON --------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-block-size: var(--hit-min);
  padding: var(--space-3) var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  background: transparent;
  font-size: var(--fs-sm);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  text-decoration: none;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.btn svg { inline-size: 16px; block-size: 16px; flex: none; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn--block { inline-size: 100%; }
.btn--sm { min-block-size: 36px; padding: var(--space-2) var(--space-3); }

/* Primary — Golden Tobacco fill, Eerie Black text. Never white text. */
.btn--primary { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
.btn--primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn--secondary { color: var(--fg); border-color: var(--border-control); }
.btn--secondary:hover:not(:disabled) { border-color: var(--border-strong); background: var(--surface-sunk); }

.btn--ghost { color: var(--fg-secondary); }
.btn--ghost:hover:not(:disabled) { color: var(--fg); background: var(--surface-sunk); }

.btn--danger { background: var(--status-block-mark); color: var(--status-block-on); border-color: var(--status-block-mark); }
.btn--danger:hover:not(:disabled) { background: var(--status-block-ink); border-color: var(--status-block-ink); }

/* --- 6. FIELDS --------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: var(--space-2); }
.field__label {
  font-size: var(--fs-sm);
  font-weight: var(--weight-medium);
  color: var(--fg);
}
.field__label .req { color: var(--status-block-ink); margin-inline-start: 2px; }
.field__hint { font-size: var(--fs-sm); color: var(--fg-secondary); margin: 0; }
.field__foot { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }

/* Inline validation. Icon + word + colour — never colour alone. 7:1 ink. */
.field__msg {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  font-weight: var(--weight-medium);
  margin: 0;
}
.field__msg svg { inline-size: 16px; block-size: 16px; flex: none; margin-block-start: 3px; }
.field__msg--block   { color: var(--status-block-ink); }
.field__msg--flag    { color: var(--fg); }
.field__msg--success { color: var(--status-success-ink); }

.field__counter { font-size: var(--fs-caption); color: var(--fg-secondary); font-variant-numeric: tabular-nums; }
.field__counter.is-over { color: var(--status-block-ink); font-weight: var(--weight-semibold); }
/* Below the required minimum is an error, not a hint. */
.field__counter.is-under { color: var(--status-block-ink); font-weight: var(--weight-semibold); }

.input, .select, .textarea {
  inline-size: 100%;
  min-block-size: var(--hit-min);
  padding: var(--space-3);
  background: var(--surface);
  color: var(--fg);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-input);
  font-size: var(--fs-base);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-muted); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--border-strong); }
.input:disabled, .select:disabled, .textarea:disabled {
  background: var(--surface-sunk); color: var(--fg-muted); cursor: not-allowed;
}
.input[aria-invalid='true'], .textarea[aria-invalid='true'], .select[aria-invalid='true'] {
  border-color: var(--status-block-mark);
  border-inline-start-width: 3px;
}
.textarea { min-block-size: 104px; resize: vertical; line-height: var(--lh-body); }

/* Select — caret drawn from the token set, no OS chrome. */
.select {
  appearance: none;
  padding-inline-end: var(--space-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 19px) calc(50% + 1px), calc(100% - 13px) calc(50% + 1px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

/* DatePicker — native control, brand-aligned indicator. */
.input--date { font-variant-numeric: tabular-nums; }
.input--date::-webkit-calendar-picker-indicator { opacity: 0.55; cursor: pointer; }
.input--date:hover::-webkit-calendar-picker-indicator { opacity: 1; }
[data-theme='dark'] .input--date::-webkit-calendar-picker-indicator { filter: invert(1); }

/* CurrencyInput — right-aligned, tabular, two decimals enforced on blur. */
.currency { position: relative; display: flex; align-items: center; }
.currency__symbol {
  position: absolute;
  inset-inline-start: var(--space-3);
  font-size: var(--fs-base);
  color: var(--fg-secondary);
  pointer-events: none;
}
.currency__input {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  font-weight: var(--weight-medium);
  padding-inline: var(--space-8) var(--space-3);
}
.currency__suffix {
  position: absolute;
  inset-inline-end: var(--space-3);
  font-size: var(--fs-caption);
  letter-spacing: 0.04em;
  color: var(--fg-muted);
  pointer-events: none;
}
.currency:has(.currency__suffix) .currency__input { padding-inline-end: var(--space-12); }

/* --- 7. FILE DROPZONE + RECEIPT THUMBNAIL ------------------------------ */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
  background: var(--surface-sunk);
  border: 1px dashed var(--border-control);
  border-radius: var(--radius-card);
  text-align: center;
  color: var(--fg-secondary);
  transition: border-color var(--dur-base) var(--ease), background var(--dur-base) var(--ease);
}
.dropzone__mark {
  display: grid;
  place-items: center;
  inline-size: 48px;
  block-size: 48px;
  border-radius: var(--radius-card);
  background: var(--accent-wash);
  color: var(--fg);
}
.dropzone__mark svg { inline-size: 22px; block-size: 22px; }
.dropzone__title { font-size: var(--fs-base); font-weight: var(--weight-semibold); color: var(--fg); }
.dropzone.is-dragover { border-color: var(--accent); background: var(--accent-wash); }
.dropzone input[type='file'] { position: absolute; inline-size: 1px; block-size: 1px; opacity: 0; }

.receipt {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  align-items: center;
}
.receipt__thumb {
  position: relative;
  flex: none;
  inline-size: 52px;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-input);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  overflow: hidden;
  color: var(--fg-muted);
}
.receipt__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.receipt__thumb svg { inline-size: 18px; block-size: 18px; }
.receipt__body { min-inline-size: 0; flex: 1; }
.receipt__name {
  font-size: var(--fs-sm);
  font-weight: var(--weight-medium);
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.receipt__meta { font-size: var(--fs-caption); color: var(--fg-secondary); font-variant-numeric: tabular-nums; }
.receipt__remove {
  flex: none;
  inline-size: var(--hit-min);
  block-size: var(--hit-min);
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  background: transparent;
  color: var(--fg-secondary);
}
.receipt__remove:hover { color: var(--status-block-ink); border-color: var(--border); }
.receipt__remove svg { inline-size: 16px; block-size: 16px; }

/* --- 8. DATA TABLE ----------------------------------------------------- */
.table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  overflow: auto;
  max-block-size: 460px;
}
.table { inline-size: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table caption {
  caption-side: top;
  text-align: start;
  padding: var(--space-4) var(--space-4) 0;
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
}
.table thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  background: var(--surface);
  border-block-end: 1px solid var(--border-strong);
  padding: var(--space-3) var(--space-4);
  text-align: start;
  font-size: var(--fs-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-secondary);
  white-space: nowrap;
}
.table td {
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border);
  vertical-align: middle;
}
.table tbody tr:nth-child(even) td { background: var(--surface-sunk); }
.table tbody tr:hover td { background: var(--accent-wash); }
.table tbody tr:last-child td { border-block-end: 0; }
.table th.is-numeric, .table td.is-numeric {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  color: var(--fg);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}
.table tfoot td {
  position: sticky;
  inset-block-end: 0;
  background: var(--surface);
  border-block-start: 1px solid var(--border-strong);
  font-weight: var(--weight-semibold);
}
.table__entity { color: var(--fg-secondary); font-size: var(--fs-caption); }

/* Below 768px a monetary table becomes stacked cards. It never scrolls
   horizontally — a partly-visible currency column is a compliance risk. */
@media (max-width: 767px) {
  .table-wrap { border: 0; background: transparent; overflow: visible; max-block-size: none; }
  .table, .table tbody, .table tr, .table td { display: block; inline-size: 100%; }
  .table thead, .table tfoot { display: none; }
  .table caption { padding-inline: 0; }
  .table tr {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    padding: var(--space-2) var(--space-4);
    margin-block-end: var(--space-3);
    box-shadow: var(--shadow-card);
  }
  .table tbody tr:nth-child(even) td,
  .table tbody tr:hover td { background: transparent; }
  .table td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding-inline: 0;
    padding-block: var(--space-2);
    border-block-end: 1px solid var(--border);
  }
  .table td:last-child { border-block-end: 0; }
  .table td::before {
    content: attr(data-label);
    flex: none;
    font-size: var(--fs-caption);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--fg-secondary);
  }
  .table td.is-numeric { justify-content: space-between; }
  .table-total {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) var(--space-4);
    background: var(--surface-sunk);
    border: 1px solid var(--border);
    border-radius: var(--radius-card);
    font-weight: var(--weight-semibold);
  }
}
@media (min-width: 768px) { .table-total { display: none; } }

/* --- 9. BADGE / CHIP --------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  font-size: var(--fs-caption);
  font-weight: var(--weight-semibold);
  line-height: 1.4;
  white-space: nowrap;
}
.chip svg { inline-size: 13px; block-size: 13px; flex: none; }

/* Status chips: wash fill + 7:1 ink + a glyph. Colour is never the only cue. */
.chip--block   { background: var(--status-block-wash);   color: var(--status-block-ink);   border-color: var(--status-block-mark); }
.chip--flag    { background: var(--status-flag-mark);    color: var(--status-flag-ink);    border-color: var(--status-flag-mark); }
.chip--info    { background: var(--status-info-wash);    color: var(--status-info-ink);    border-color: var(--status-info-mark); }
.chip--success { background: var(--status-success-wash); color: var(--status-success-ink); border-color: var(--status-success-mark); }
.chip--neutral { background: var(--status-neutral-wash); color: var(--status-neutral-ink); border-color: var(--status-neutral-mark); }

/* Entity chip — carries a legal entity name exactly as Finance's books
   record it. Deliberately quiet: it is a reference, not a status. */
.chip--entity {
  background: var(--surface-sunk);
  color: var(--fg-secondary);
  border-color: var(--border);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
}
.chip--entity::before {
  content: '';
  inline-size: 3px;
  block-size: 12px;
  background: var(--accent);
  border-radius: 1px;
  flex: none;
}

/* --- 10. VALIDATION BANNER --------------------------------------------- */
.banner {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid;
  border-inline-start-width: 3px;
  border-radius: var(--radius-card);
}
.banner__mark { flex: none; margin-block-start: 2px; }
.banner__mark svg { inline-size: 18px; block-size: 18px; }
.banner__body { min-inline-size: 0; flex: 1; }
.banner__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--fs-sm);
  font-weight: var(--weight-semibold);
  margin: 0;
}
.banner__count { font-variant-numeric: tabular-nums; opacity: 0.75; }
.banner__list { margin: var(--space-2) 0 0; padding-inline-start: var(--space-4); font-size: var(--fs-sm); }
.banner__list li { margin-block-start: var(--space-1); }
.banner__list a { text-decoration: underline; text-underline-offset: 2px; }
.banner--block   { background: var(--status-block-wash);   border-color: var(--status-block-mark);   color: var(--status-block-ink); }
.banner--flag    { background: var(--status-flag-wash);    border-color: var(--status-flag-mark);    color: var(--fg); }
.banner--info    { background: var(--status-info-wash);    border-color: var(--status-info-mark);    color: var(--status-info-ink); }
.banner--success { background: var(--status-success-wash); border-color: var(--status-success-mark); color: var(--status-success-ink); }

/* --- 11. TOAST --------------------------------------------------------- */
.toast-stack {
  position: fixed;
  inset-block-end: var(--space-6);
  inset-inline-end: var(--space-6);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  inline-size: min(380px, calc(100vw - var(--space-8)));
  pointer-events: none;
}
@media (max-width: 640px) {
  .toast-stack { inset-inline: var(--space-4); inset-block-end: var(--space-4); inline-size: auto; }
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--status-info-mark);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lift);
  pointer-events: auto;
  animation: toast-in var(--dur-base) var(--ease);
}
.toast--success { border-inline-start-color: var(--status-success-mark); }
.toast--block   { border-inline-start-color: var(--status-block-mark); }
.toast--flag    { border-inline-start-color: var(--status-flag-mark); }
.toast__mark { flex: none; margin-block-start: 2px; color: var(--fg-secondary); }
.toast--success .toast__mark { color: var(--status-success-ink); }
.toast--block   .toast__mark { color: var(--status-block-ink); }
.toast__mark svg { inline-size: 17px; block-size: 17px; }
.toast__body { flex: 1; min-inline-size: 0; }
.toast__title { font-size: var(--fs-sm); font-weight: var(--weight-semibold); }
.toast__text  { font-size: var(--fs-sm); color: var(--fg-secondary); margin: 0; }
.toast__close {
  flex: none;
  inline-size: 28px; block-size: 28px;
  display: grid; place-items: center;
  border: 0; background: transparent; color: var(--fg-secondary);
  border-radius: var(--radius-input);
}
.toast__close:hover { color: var(--fg); background: var(--surface-sunk); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* --- 12. MODAL --------------------------------------------------------- */
.modal {
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-modal);
  background: var(--surface);
  color: var(--fg);
  box-shadow: var(--shadow-modal);
  inline-size: min(520px, calc(100vw - var(--space-8)));
  max-block-size: min(86vh, 720px);
  overflow: hidden;
}
.modal::backdrop { background: var(--scrim); backdrop-filter: blur(2px); }
.modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-6) var(--space-6) var(--space-4);
  border-block-end: 1px solid var(--border);
}
.modal__title { font-family: var(--font-display); font-size: var(--fs-h4); margin: 0; }
.modal__body { padding: var(--space-6); overflow: auto; }
.modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6) var(--space-6);
  border-block-start: 1px solid var(--border);
  background: var(--surface);
}
@media (max-width: 640px) {
  .modal { inline-size: 100%; max-inline-size: none; margin: 0 auto auto; border-radius: var(--radius-modal); }
  .modal__foot { flex-direction: column-reverse; }
  .modal__foot .btn { inline-size: 100%; }
}

/* --- 13. EMPTY STATE --------------------------------------------------- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-12) var(--space-6);
  text-align: center;
  border: 1px dashed var(--border-control);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.empty__mark {
  display: grid; place-items: center;
  inline-size: 44px; block-size: 44px;
  border-radius: var(--radius-card);
  background: var(--surface-sunk);
  color: var(--fg-secondary);
}
.empty__mark svg { inline-size: 20px; block-size: 20px; }
.empty__title { font-family: var(--font-display); font-size: var(--fs-h4); margin: 0; }
.empty__text { font-size: var(--fs-sm); color: var(--fg-secondary); max-inline-size: 42ch; margin: 0; }

/* --- 14. SKELETON ------------------------------------------------------ */
.skeleton {
  background: linear-gradient(90deg, var(--skeleton-base) 25%, var(--skeleton-sheen) 37%, var(--skeleton-base) 63%);
  background-size: 400% 100%;
  border-radius: var(--radius-input);
  animation: skeleton-sweep 1.4s var(--ease) infinite;
}
.skeleton--text  { block-size: 12px; }
.skeleton--line  { block-size: 14px; }
.skeleton--title { block-size: 22px; border-radius: var(--radius-input); }
.skeleton--thumb { inline-size: 52px; aspect-ratio: 3 / 4; border-radius: var(--radius-input); flex: none; }
.skeleton--block { block-size: 96px; border-radius: var(--radius-card); }
@keyframes skeleton-sweep { from { background-position: 100% 0; } to { background-position: 0 0; } }

/* --- 15. CAPTURE SURFACES --------------------------------------------------
   Intake channels, OCR field review, the arithmetic blocks and the annotation
   review panel. All four are compliance-facing: the arithmetic and the
   annotation panel carry --fg on --surface / --surface-sunk, which measures
   15.05:1 light and 14.10:1 dark — comfortably past the 7:1 floor.
   ------------------------------------------------------------------------- */

/* Intake channel picker — camera, upload, email forward, drag-and-drop. */
.channels { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); }
@media (max-width: 900px) { .channels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .channels { grid-template-columns: minmax(0, 1fr); } }

.channel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  min-block-size: var(--hit-min);
  padding: var(--space-4);
  text-align: start;
  background: var(--surface);
  border: 1px dashed var(--border-control);
  border-radius: var(--radius-card);
  color: var(--fg);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.channel:hover:not(:disabled) { border-color: var(--border-strong); background: var(--surface-sunk); }
.channel[aria-pressed='true'] { border-style: solid; border-color: var(--accent); background: var(--accent-wash); }
.channel:disabled { opacity: 0.5; cursor: not-allowed; }
.channel__mark { color: var(--fg-secondary); }
.channel__mark svg { inline-size: 22px; block-size: 22px; }
.channel__title { font-weight: var(--weight-semibold); font-size: var(--fs-sm); }
.channel__note { font-size: var(--fs-caption); color: var(--fg-secondary); }
.channel__order {
  font-size: var(--fs-caption);
  font-variant-numeric: tabular-nums;
  color: var(--fg-muted);
}

/* Receipt viewer. A scan never sits directly on --bg — it always has a
   --surface card behind it so it stays legible in both themes. */
.viewer {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-3);
  display: grid;
  gap: var(--space-2);
}
.viewer__stage {
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  display: grid;
  place-items: center;
  min-block-size: 180px;
  overflow: hidden;
}
.viewer__stage img, .viewer__stage canvas, .viewer__stage video {
  max-inline-size: 100%;
  max-block-size: 320px;
  display: block;
}
.viewer__caption { font-size: var(--fs-caption); color: var(--fg-secondary); }

/* OCR field review. Confidence is never carried by colour alone: the chip has
   an icon and the word Verify beside it. */
.review-grid { display: grid; gap: var(--space-3); }
.review-row {
  display: grid;
  grid-template-columns: 1fr minmax(140px, 200px) auto;
  align-items: center;
  gap: var(--space-3);
}
@media (max-width: 640px) {
  .review-row { grid-template-columns: 1fr auto; }
  .review-row .review-row__control { grid-column: 1 / -1; }
}
.review-row__label { font-size: var(--fs-sm); font-weight: var(--weight-medium); }
.review-row__hint { font-size: var(--fs-caption); color: var(--fg-secondary); }
.review-row.is-verify .review-row__control .input { border-color: var(--status-flag-mark); border-inline-start-width: 3px; }
.review-row.is-missing .review-row__control .input { border-color: var(--status-block-mark); border-inline-start-width: 3px; }

/* Arithmetic block — a compliance control. Tabular, high contrast, and the
   accent appears only as the rule down its edge. */
.arith {
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius-input);
  padding: var(--space-3) var(--space-4);
  color: var(--fg);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  line-height: 1.5;
}
.arith + .arith { margin-block-start: var(--space-2); }
.arith__label {
  display: block;
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin-block-end: var(--space-1);
}
.arith strong { font-weight: var(--weight-semibold); }
.arith--override { border-inline-start-color: var(--status-flag-mark); }
.arith--zero { border-inline-start-color: var(--status-info-mark); }

/* The annotation review panel. A first-class surface, never a toast: the crop,
   the transcription in quotes, the receipt total, the proposal, the arithmetic
   and three explicit actions. */
.annotation {
  background: var(--surface);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--status-flag-mark);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  display: grid;
  gap: var(--space-4);
}
.annotation__head { display: flex; align-items: flex-start; gap: var(--space-3); }
.annotation__title {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  color: var(--fg);
  margin: 0;
}
.annotation__body { display: grid; grid-template-columns: 200px 1fr; gap: var(--space-4); }
@media (max-width: 640px) { .annotation__body { grid-template-columns: minmax(0, 1fr); } }
.annotation__crop {
  background: var(--surface-sunk);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-input);
  padding: var(--space-2);
  display: grid;
  gap: var(--space-2);
  place-content: start center;
}
.annotation__crop img, .annotation__crop canvas {
  max-inline-size: 100%;
  border-radius: 2px;
  display: block;
}
.annotation__crop figcaption {
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
  text-align: center;
}
/* The transcription, shown as quoted text so it reads as "what we think it
   says" rather than as a value. */
.annotation__quote {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--fg);
  margin: 0;
}
.annotation__quote::before { content: '\201C'; }
.annotation__quote::after { content: '\201D'; }
.annotation__meta { font-size: var(--fs-caption); color: var(--fg-secondary); }
.annotation__question {
  font-size: var(--fs-base);
  font-weight: var(--weight-medium);
  color: var(--fg);
  margin: 0;
}
.annotation__actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
@media (max-width: 480px) {
  .annotation__actions { flex-direction: column; }
  .annotation__actions .btn { inline-size: 100%; }
}

/* Unmatched tray card. */
.tray { display: grid; gap: var(--space-3); }
.tray-card {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
@media (max-width: 560px) {
  .tray-card { grid-template-columns: 56px 1fr; }
  .tray-card__actions { grid-column: 1 / -1; }
  .tray-card__actions .btn { inline-size: 100%; }
}
.tray-card__thumb {
  inline-size: 56px;
  aspect-ratio: 3 / 4;
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  display: grid;
  place-items: center;
  color: var(--fg-muted);
  overflow: hidden;
}
.tray-card__thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.tray-card__title { font-size: var(--fs-sm); font-weight: var(--weight-medium); }
.tray-card__meta { font-size: var(--fs-caption); color: var(--fg-secondary); }

/* Product navigation for the capture flow — real app nav, not view controls. */
.tabs {
  display: flex;
  gap: var(--space-1);
  overflow-x: auto;
  border-block-end: 1px solid var(--border);
}
.tab {
  min-block-size: var(--hit-min);
  padding: var(--space-3) var(--space-4);
  border: 0;
  border-block-end: 2px solid transparent;
  background: transparent;
  color: var(--fg-secondary);
  font-size: var(--fs-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}
.tab:hover { color: var(--fg); }
.tab[aria-selected='true'] { color: var(--fg); border-block-end-color: var(--accent); }
.panel[hidden] { display: none; }

/* --- 16. CODING SURFACES ---------------------------------------------------
   The entity field, the live per-entity totals, the split remainder and the
   entity × category cross-tab. The remainder and the cross-tab figures are
   compliance controls: --fg on --surface / --surface-sunk measures 15.05:1
   light and 14.10:1 dark, well past the 7:1 floor.
   ------------------------------------------------------------------------- */

/* Entity is the most consequential field on the line — mis-allocation books
   expense to the wrong company's ledger — so it is given its own panel rather
   than sitting in the grid with everything else. */
.entity-field {
  background: var(--surface);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--accent);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  display: grid;
  gap: var(--space-3);
}
.entity-field__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.entity-field__label {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  color: var(--fg);
}
.entity-field__note { font-size: var(--fs-caption); color: var(--fg-secondary); max-inline-size: 52ch; }
.entity-field .select { font-size: var(--fs-lg); min-block-size: 52px; }
/* The chosen entity's prefix stays visible the whole time the line is open. */
.entity-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--accent);
  color: var(--accent-fg);
  border-radius: var(--radius-input);
  font-weight: var(--weight-semibold);
  font-size: var(--fs-sm);
}
.entity-badge__prefix {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  padding-inline-start: var(--space-2);
  border-inline-start: 1px solid color-mix(in srgb, var(--accent-fg) 30%, transparent);
}

/* Live per-entity running totals — visible at all times while coding. */
.running {
  position: sticky;
  inset-block-start: 74px;
  z-index: 30;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(12px);
  border-block-end: 1px solid var(--border);
  padding-block: var(--space-3);
}
@media (max-width: 640px) { .running { inset-block-start: 60px; } }
.running__inner { display: flex; gap: var(--space-4); overflow-x: auto; align-items: stretch; }
.running__cell {
  flex: none;
  min-inline-size: 132px;
  padding-inline-end: var(--space-4);
  border-inline-end: 1px solid var(--border);
}
.running__cell:last-child { border-inline-end: 0; }
.running__prefix {
  font-size: var(--fs-caption);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  color: var(--fg-secondary);
}
.running__amount {
  display: block;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  font-weight: var(--weight-semibold);
  color: var(--fg);
  font-size: var(--fs-lg);
}
.running__count { font-size: var(--fs-caption); color: var(--fg-secondary); }
.running__cell--grand .running__amount { font-family: var(--font-display); font-size: var(--fs-h4); }

/* The split remainder. Error-coloured while non-zero, and never small. */
.remainder {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding: var(--space-4);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--status-success-mark);
  border-radius: var(--radius-card);
  color: var(--fg);
}
.remainder.is-open { border-inline-start-color: var(--status-block-mark); }
.remainder__label {
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary);
}
.remainder__value {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}
.remainder.is-open .remainder__value { color: var(--status-block-ink); }
.remainder__note { font-size: var(--fs-sm); color: var(--fg-secondary); max-inline-size: 46ch; }
.remainder.is-open .remainder__note { color: var(--status-block-ink); }

.leg {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 90px 110px 40px;
  gap: var(--space-2);
  align-items: end;
  padding-block: var(--space-2);
}
@media (max-width: 900px) { .leg { grid-template-columns: 1fr 1fr; } }
.leg__computed {
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
  font-variant-numeric: tabular-nums;
  grid-column: 1 / -1;
}

/* Attendees — structured rows, not free text. */
.attendee { display: grid; grid-template-columns: 1fr 1fr auto 40px; gap: var(--space-2); align-items: center; }
@media (max-width: 640px) { .attendee { grid-template-columns: 1fr 1fr; } }
.attendee__external { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-caption); color: var(--fg-secondary); white-space: nowrap; }

/* The entity × category cross-tab. Per-entity subtotal rows are emphasised
   with a top rule and a Display-font label. */
.xtab-table th.is-numeric, .xtab-table td.is-numeric { min-inline-size: 92px; }
.xtab-table tr.is-subtotal td {
  border-block-start: 1px solid var(--border-strong);
  background: var(--surface) !important;
  font-weight: var(--weight-semibold);
}
.xtab-table tr.is-subtotal td:first-child {
  font-family: var(--font-display);
  font-size: var(--fs-base);
  font-weight: var(--weight-regular);
}
.xtab-table tr.is-grand td {
  border-block-start: 2px solid var(--border-strong);
  background: var(--surface-sunk) !important;
  font-weight: var(--weight-semibold);
}
.xtab-table tr.is-grand td:first-child {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--weight-regular);
}
.xtab-cards { display: none; }
/* A monetary table never scrolls sideways: below 768px it becomes cards. */
@media (max-width: 767px) {
  .xtab-wrap { display: none; }
  .xtab-cards { display: grid; gap: var(--space-3); }
}
.xtab-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-4);
}
.xtab-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--border);
}
.xtab-card__name { font-family: var(--font-display); font-size: var(--fs-h4); }
.xtab-card__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: var(--space-2);
  border-block-end: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.xtab-card__row:last-of-type { border-block-end: 0; }
.xtab-card__total {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-start: var(--space-2);
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--border-strong);
  font-weight: var(--weight-semibold);
}

/* --- 17. THE VALIDATION CHECKLIST -----------------------------------------
   The highest-stakes screen in the application. Severity is carried by a chip
   (icon + word + colour) and a left border — never by the message text, which
   stays at --fg on --surface so every finding reads at 15.05:1 light and
   14.10:1 dark, well past the 7:1 floor a compliance control needs.
   ------------------------------------------------------------------------- */

.check-group { margin-block-end: var(--space-8); }
.check-group__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding-block-end: var(--space-3);
  margin-block-end: var(--space-3);
  border-block-end: 1px solid var(--border-strong);
}
.check-group__title {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  color: var(--fg);
}
.check-group__count {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  color: var(--fg-secondary);
}

.check-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--border);
  border-radius: var(--radius-card);
  margin-block-end: var(--space-2);
  color: var(--fg);
}
@media (max-width: 700px) {
  .check-item { grid-template-columns: 1fr; }
  .check-item__actions { justify-self: stretch; }
  .check-item__actions .btn { inline-size: 100%; }
}
.check-item--block { border-inline-start-color: var(--status-block-mark); }
.check-item--flag  { border-inline-start-color: var(--status-flag-mark); }
.check-item--info  { border-inline-start-color: var(--status-info-mark); }
.check-item:target,
.check-item.is-highlighted { outline: 2px solid var(--focus-ring); outline-offset: 2px; }

.check-item__message {
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
  color: var(--fg);
  margin: 0;
}
.check-item__meta {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-block-start: var(--space-2);
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
}
.check-item__code {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  font-weight: var(--weight-semibold);
}
.check-item__actions { display: flex; gap: var(--space-2); align-items: center; }

/* The submit bar. Never a silently dead button: the reason sits beside it. */
.submit-bar {
  position: sticky;
  inset-block-end: 0;
  z-index: 25;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--surface) 94%, transparent);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lift);
}
.submit-bar__reason {
  font-size: var(--fs-sm);
  color: var(--fg);
  max-inline-size: 64ch;
  margin: 0;
}
.submit-bar.is-blocked .submit-bar__reason { color: var(--status-block-ink); font-weight: var(--weight-medium); }
.submit-bar__counts { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* The rule catalogue — rules as data, expressions on show. */
.rule-row {
  display: grid;
  grid-template-columns: 92px 1fr;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  border-block-end: 1px solid var(--border);
  align-items: start;
}
@media (max-width: 640px) { .rule-row { grid-template-columns: 1fr; } }
.rule-row__code {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
  font-size: var(--fs-sm);
  color: var(--fg);
}
.rule-row__name { font-size: var(--fs-sm); font-weight: var(--weight-medium); }
.rule-row__meta { font-size: var(--fs-caption); color: var(--fg-secondary); margin-block-start: 2px; }
.rule-row__expr {
  display: block;
  margin-block-start: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  font-size: var(--fs-caption);
  color: var(--fg);
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

/* --- 18. THE APPROVER'S REVIEW ---------------------------------------------
   Everything the approver needs without opening anything, plus a receipt viewer
   that reads the stored bytes in place. Partial-claim figures render as a
   three-value block at --fg on --surface-sunk (15.05:1 light, 16.98:1 dark) so
   the disclosure is never a colour-only signal.
   ------------------------------------------------------------------------- */

/* Report status, consistent everywhere: icon + text + colour. */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-input);
  font-size: var(--fs-sm);
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}
.status-badge svg { inline-size: 15px; block-size: 15px; flex: none; }
.status-badge--draft     { background: var(--status-neutral-wash); color: var(--status-neutral-ink); border-color: var(--status-neutral-mark); }
.status-badge--validating{ background: var(--status-info-wash);    color: var(--status-info-ink);    border-color: var(--status-info-mark); }
.status-badge--submitted { background: var(--status-info-wash);    color: var(--status-info-ink);    border-color: var(--status-info-mark); }
.status-badge--review    { background: var(--status-flag-mark);    color: var(--status-flag-ink);    border-color: var(--status-flag-mark); }
.status-badge--info      { background: var(--status-flag-wash);    color: var(--fg);                 border-color: var(--status-flag-mark); }
.status-badge--approved  { background: var(--status-success-wash); color: var(--status-success-ink); border-color: var(--status-success-mark); }
.status-badge--rejected  { background: var(--status-block-wash);   color: var(--status-block-ink);   border-color: var(--status-block-mark); }
.status-badge--paid      { background: var(--status-success-mark); color: var(--accent-fg);          border-color: var(--status-success-mark); }

/* Per-entity totals: Display-font names, the prefix as a Badge. */
.entity-totals { display: grid; gap: var(--space-2); }
.entity-total {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
@media (max-width: 560px) { .entity-total { grid-template-columns: 1fr auto; } }
.entity-total__name {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--fg);
}
.entity-total__count { font-size: var(--fs-caption); color: var(--fg-secondary); }
.entity-total--grand {
  background: var(--surface-sunk);
  border-color: var(--border-strong);
}
.entity-total--grand .entity-total__name { font-size: var(--fs-h4); }

/* A line as the approver sees it. */
.review-line {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: var(--space-4);
  margin-block-end: var(--space-3);
}
.review-line.is-held { border-inline-start: 3px solid var(--status-block-mark); }
.review-line__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.review-line__body { display: grid; grid-template-columns: 1fr 200px; gap: var(--space-4); margin-block-start: var(--space-3); }
@media (max-width: 760px) { .review-line__body { grid-template-columns: minmax(0, 1fr); } }

/* The three-value partial-claim block. Never in a drawer, never colour-only:
   the difference carries the FLAG treatment plus an icon and the word. */
.disclosure {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  overflow: hidden;
  margin-block-start: var(--space-3);
}
@media (max-width: 480px) { .disclosure { grid-template-columns: minmax(0, 1fr); } }
.disclosure__cell {
  background: var(--surface-sunk);
  padding: var(--space-3);
  color: var(--fg);
}
.disclosure__label {
  display: block;
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin-block-end: var(--space-1);
}
.disclosure__value {
  display: block;
  font-size: var(--fs-h4);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  color: var(--fg);
}
.disclosure__cell--difference { background: var(--status-flag-wash); }
.disclosure__cell--difference .disclosure__value { font-weight: var(--weight-semibold); }
.disclosure__reason {
  grid-column: 1 / -1;
  background: var(--surface);
  padding: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--fg);
}

/* Receipt strip: thumbnail + a persistent viewed check. */
.receipt-strip { display: grid; gap: var(--space-2); }
.receipt-chip {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  gap: var(--space-2);
  align-items: center;
  padding: var(--space-2);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  text-align: start;
  color: var(--fg);
  inline-size: 100%;
  min-block-size: var(--hit-min);
}
.receipt-chip:hover { border-color: var(--border-strong); }
.receipt-chip.is-viewed { border-inline-start: 3px solid var(--status-success-mark); }
.receipt-chip__thumb {
  inline-size: 44px;
  aspect-ratio: 3 / 4;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 2px;
  display: grid;
  place-items: center;
  color: var(--fg-muted);
  overflow: hidden;
}
.receipt-chip__name {
  font-size: var(--fs-caption);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Handwriting, shown beside the crop. The outline is drawn over a DISPLAY COPY;
   the stored original is never annotated. */
.handwriting {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--space-3);
  margin-block-start: var(--space-3);
  padding: var(--space-3);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--status-flag-mark);
  border-radius: var(--radius-input);
}
@media (max-width: 560px) { .handwriting { grid-template-columns: minmax(0, 1fr); } }
.handwriting__crop {
  background: var(--surface);
  border: 1px solid var(--border-control);
  border-radius: 2px;
  min-block-size: 54px;
  display: grid;
  place-items: center;
  color: var(--fg-muted);
  font-size: var(--fs-caption);
  padding: var(--space-2);
  text-align: center;
}
.handwriting__quote {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--fg);
  margin: 0;
}
.handwriting__quote::before { content: '\201C'; }
.handwriting__quote::after { content: '\201D'; }
.handwriting__meta { font-size: var(--fs-caption); color: var(--fg-secondary); margin-block-start: var(--space-1); }

/* Comments, threaded on the line. */
.thread { display: grid; gap: var(--space-2); margin-block-start: var(--space-3); }
.thread__item {
  padding: var(--space-3);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-input);
  font-size: var(--fs-sm);
  color: var(--fg);
}
.thread__item--reply { margin-inline-start: var(--space-6); }
.thread__author { font-weight: var(--weight-semibold); font-size: var(--fs-caption); }
.thread__when { font-size: var(--fs-caption); color: var(--fg-secondary); }

/* Decision bar. Approve and Reject are never adjacent without a separator. */
.decisions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
.decisions__sep {
  inline-size: 1px;
  align-self: stretch;
  min-block-size: 32px;
  background: var(--border-strong);
}
@media (max-width: 640px) {
  .decisions { flex-direction: column; align-items: stretch; }
  .decisions .btn { inline-size: 100%; }
  .decisions__sep { inline-size: auto; block-size: 1px; min-block-size: 0; }
}
.btn--destructive-outline {
  background: transparent;
  color: var(--status-block-ink);
  border-color: var(--status-block-mark);
}
.btn--destructive-outline:hover:not(:disabled) {
  background: var(--status-block-wash);
  border-color: var(--status-block-ink);
}

/* ── the receipt viewer ─────────────────────────────────────────────────────
   Full-screen overlay on --surface. The scan sits on a neutral card with a
   deliberate border — in dark theme a white receipt against a dark surface
   would otherwise glare and bleed at the edges. Zoom and rotate are transforms
   on the display element only; the stored original is never rewritten.        */
.viewer-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: var(--surface);
}
.viewer-overlay[hidden] { display: none; }
.viewer-overlay__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  border-block-end: 1px solid var(--border);
  background: var(--surface);
}
.viewer-overlay__title { font-size: var(--fs-sm); font-weight: var(--weight-semibold); color: var(--fg); }
.viewer-overlay__meta { font-size: var(--fs-caption); color: var(--fg-secondary); }
.viewer-overlay__stage {
  overflow: auto;
  padding: var(--space-6);
  display: grid;
  place-items: center;
  background: var(--surface-sunk);
}
/* the neutral card the scan sits on — never directly on --bg */
.viewer-card {
  background: #FFFFFF;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-input);
  box-shadow: var(--shadow-lift);
  padding: var(--space-2);
  transition: transform var(--dur-base) var(--ease);
  transform-origin: center center;
}
.viewer-card img, .viewer-card canvas { display: block; max-inline-size: 100%; }
.viewer-overlay__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  border-block-start: 1px solid var(--border);
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
}
.viewer-controls { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* Screen-reader-only utility. */
.sr-only {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* --- 19. STORAGE SURFACES --------------------------------------------------
   Where the data actually is, stated in the chrome rather than buried in a
   settings page. Three rules govern everything here:

     · The "stored in this browser" notice is PERMANENT and never colour-only —
       icon plus words, set in --fg on --surface-sunk, which measures 15.06:1
       light and 17.27:1 dark. It is the one claim a user must never be wrong
       about, so it does not rely on a hue they may not perceive.
     · The usage indicator reads --fg-secondary normally, takes the FLAG
       treatment at 80% and the error treatment at 95%. The percentage is always
       printed beside the meter, so the bar is decoration and the number is the
       signal.
     · Export is a primary action with a determinate progress state. Zipping a
       month of photos is not instant, and an indeterminate spinner on a
       long-running write reads as a hang.
   ------------------------------------------------------------------------- */

/* ── the shell indicator ─────────────────────────────────────────────────── */

.storage-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 6px var(--space-3);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-input);
  background: var(--surface);
  color: var(--fg-secondary);
  font-size: var(--fs-caption);
  line-height: 1.2;
  text-decoration: none;
  min-block-size: 32px;
  flex: none;
}
.storage-status:hover { color: var(--fg); border-color: var(--border-strong); }
.storage-status svg { inline-size: 15px; block-size: 15px; flex: none; }
.storage-status__figure {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
  color: var(--fg);
}
.storage-status__of { color: var(--fg-muted); }

/* 80% — FLAG. Golden Tobacco fill with Eerie Black text: 9.65:1 light,
   10.91:1 dark, and the only permitted text-on-gold pairing. */
.storage-status--warn {
  background: var(--status-flag-mark);
  border-color: var(--status-flag-mark);
  color: var(--status-flag-ink);
}
.storage-status--warn .storage-status__figure,
.storage-status--warn .storage-status__of { color: var(--status-flag-ink); }

/* 95% — error. Wash fill with the 7:1 ink tier, never the mark colour as text. */
.storage-status--block {
  background: var(--status-block-wash);
  border-color: var(--status-block-mark);
  color: var(--status-block-ink);
}
.storage-status--block .storage-status__figure,
.storage-status--block .storage-status__of { color: var(--status-block-ink); }

.storage-meter {
  inline-size: 54px;
  block-size: 6px;
  border-radius: 3px;
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  overflow: hidden;
  flex: none;
}
.storage-meter__fill {
  display: block;
  block-size: 100%;
  background: var(--fg-secondary);
  transition: inline-size var(--dur-base) var(--ease);
}
.storage-status--warn  .storage-meter { background: var(--surface); border-color: var(--status-flag-ink); }
.storage-status--warn  .storage-meter__fill  { background: var(--status-flag-ink); }
.storage-status--block .storage-meter__fill  { background: var(--status-block-mark); }

/* 375px: the header already gives the logo an 11ch budget, so the indicator
   drops to the glyph and the percentage. It never disappears. */
@media (max-width: 900px) {
  .storage-status__label, .storage-status__of { display: none; }
  .storage-status .storage-meter { inline-size: 34px; }
}
@media (max-width: 480px) {
  .storage-status { padding: 6px var(--space-2); }
  .storage-status .storage-meter { display: none; }
}

/* ── the permanent notice ────────────────────────────────────────────────── */

.storage-notice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-sunk);
  border-block-end: 1px solid var(--border);
  color: var(--fg);
  font-size: var(--fs-sm);
  line-height: var(--lh-tight);
}
.storage-notice__mark { flex: none; margin-block-start: 1px; }
.storage-notice__mark svg { inline-size: 18px; block-size: 18px; }
.storage-notice__body { min-inline-size: 0; flex: 1; }
.storage-notice__body b { font-weight: var(--weight-semibold); }
.storage-notice__body p { margin: 0; }
.storage-notice__detail {
  margin-block-start: var(--space-1);
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
}
.storage-notice__actions { display: flex; gap: var(--space-2); flex: none; flex-wrap: wrap; }
@media (max-width: 700px) {
  .storage-notice { flex-wrap: wrap; }
  .storage-notice__actions { inline-size: 100%; }
}

/* Durability, spelled out. A user who believes their data is safe when the
   browser may evict it is worse off than one who knows to export. */
.storage-notice--evictable { background: var(--status-flag-wash); }

/* ── determinate progress ────────────────────────────────────────────────── */

.progress {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
}
.progress__track {
  flex: 1;
  block-size: 8px;
  min-inline-size: 120px;
  border-radius: 4px;
  background: var(--surface-sunk);
  border: 1px solid var(--border-control);
  overflow: hidden;
}
.progress__bar {
  display: block;
  block-size: 100%;
  inline-size: 0;
  background: var(--accent);
  transition: inline-size 90ms linear;
}
.progress__figure {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
  color: var(--fg);
  min-inline-size: 4ch;
  text-align: right;
}
.progress__label {
  color: var(--fg-secondary);
  max-inline-size: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── the storage screen ──────────────────────────────────────────────────── */

.usage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--space-4);
}
.usage-cell {
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
}
.usage-cell__label {
  display: block;
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-secondary);
  margin-block-end: var(--space-2);
}
.usage-cell__value {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  line-height: 1.1;
}
.usage-cell__note {
  display: block;
  margin-block-start: var(--space-2);
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
}
.usage-cell--warn  { border-color: var(--status-flag-mark);  background: var(--status-flag-wash); }
.usage-cell--block { border-color: var(--status-block-mark); background: var(--status-block-wash); }
.usage-cell--block .usage-cell__value { color: var(--status-block-ink); }

.usage-bar {
  block-size: 12px;
  border-radius: 6px;
  background: var(--surface-sunk);
  border: 1px solid var(--border-control);
  overflow: hidden;
  margin-block: var(--space-3);
}
.usage-bar__fill { display: block; block-size: 100%; background: var(--fg-secondary); }
.usage-bar__fill--warn  { background: var(--status-flag-mark); }
.usage-bar__fill--block { background: var(--status-block-mark); }
.usage-bar__marks {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-caption);
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* The adapter in force, and the one that is not. A stub that looks live is
   worse than one that says it is a stub. */
.adapter-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-3);
  align-items: start;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.adapter-row + .adapter-row { margin-block-start: var(--space-2); }
.adapter-row--active { border-inline-start: 3px solid var(--status-success-mark); }
.adapter-row--stub   { border-inline-start: 3px solid var(--status-neutral-mark); opacity: 0.92; }
/* At 375px the three columns cannot coexist — measured overflowing its box by
   77px before this rule existed. The chips move above and below the text. */
@media (max-width: 700px) {
  .adapter-row { grid-template-columns: 1fr; }
  .adapter-row .chip { justify-self: start; }
}
/* Long identifiers in a reference table must wrap. A stacked card at 375px has
   no horizontal scroll by design — "a partly-visible currency column is a
   compliance risk" — so a 30-character store name has to break instead. */
.table td code { overflow-wrap: anywhere; }
@media (max-width: 767px) {
  .table td { flex-wrap: wrap; }
  .table td > * { min-inline-size: 0; }
}

/* A long database name or note must wrap rather than widen the row. */
.adapter-row > div { min-inline-size: 0; }
.adapter-row__name { display: block; overflow-wrap: anywhere; }
.adapter-row__detail { overflow-wrap: anywhere; }
.adapter-row__name {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--fg);
}
.adapter-row__detail {
  margin: var(--space-1) 0 0;
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
  line-height: var(--lh-body);
}

/* Integrity result rows. State is a chip plus a word, and every row names its
   invoice_ref, because that is the identifier a person can act on. */
.integrity-row {
  display: grid;
  grid-template-columns: 8ch 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--surface);
  font-size: var(--fs-sm);
}
.integrity-row + .integrity-row { margin-block-start: var(--space-1); }
.integrity-row__ref {
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  color: var(--fg);
}
.integrity-row__detail { color: var(--fg-secondary); font-size: var(--fs-caption); }
.integrity-row--ok       { border-inline-start: 3px solid var(--status-success-mark); }
.integrity-row--missing  { border-inline-start: 3px solid var(--status-block-mark); }
.integrity-row--mismatch { border-inline-start: 3px solid var(--status-block-mark); }
@media (max-width: 700px) {
  .integrity-row { grid-template-columns: 1fr; }
}

/* Receipt thumbnails in a list. Generated at intake at 400px so this row never
   decodes a 4 MB photo. */
.thumb-strip { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.thumb {
  inline-size: 56px;
  block-size: 56px;
  border-radius: var(--radius-input);
  border: 1px solid var(--border-control);
  background: var(--surface-sunk);
  object-fit: cover;
  display: block;
}
.thumb--absent {
  display: grid;
  place-items: center;
  font-size: var(--fs-caption);
  color: var(--fg-secondary);
  text-align: center;
  line-height: 1.15;
}

/* The restore outcome reuses .check-group / .check-item verbatim so it reads as
   the same control as the validation checklist. This is the one variant that
   list did not need. */
.check-item--success { border-inline-start-color: var(--status-success-mark); }

/* The export layout, shown as the tree it actually produces. Monospace is not
   in the type scale as a family, so this borrows the tabular figure treatment
   and a system mono stack — the same exception the money utility documents. */
.file-tree {
  margin: 0;
  padding: var(--space-4);
  background: var(--surface-sunk);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-caption);
  line-height: 1.7;
  color: var(--fg);
  overflow-x: auto;
  white-space: pre;
  max-inline-size: 100%;
}
.file-tree b { font-weight: var(--weight-semibold); }
.file-tree i { font-style: normal; color: var(--fg-secondary); }
