/* base.css — reset, design tokens, typography, and the page shell.
   Mobile-first. No inline styles (the CSP forbids them); it all lives here. */

:root {
  /* Palette — warm "paper & petrol" vintage car-show theme */
  --paper:       #fffbe9;
  --paper-2:     #fffefb;
  --ink:         #000000;
  --ink-soft:    #66645d;
  --line:        #ecd9a0;
  --petrol:      #855400;
  --petrol-dark: #6e4400;
  --amber:       #ff9f1c;
  --amber-soft:  #ffcd28;
  --good:        #2f6b46;
  --good-bg:     #e7f0e6;
  --bad:         #9d2f2a;
  --bad-bg:      #f6e4e1;

  /* A4 (WCAG 2.2 AA). --amber is 2.97:1 on paper — fine as a decorative accent
     (header rule, handles, fills) but failing for text/links. --amber-text is the
     AA-contrast link/text amber (5.04:1 on paper, 5.79:1 on #fff). --line at
     1.32:1 is fine for decorative dividers but fails SC 1.4.11 (3:1) as the
     boundary of an interactive control; --line-strong (3.57:1 on paper, 4.10:1 on
     #fff) is the border for inputs and bordered controls only. */
  --amber-text:  #9a5b00;
  --line-strong: #b48722;

  /* A2 (admin theme). The header band is a dedicated surface family so an
     admin "banner colour" recolours the band only — never --petrol, which is
     also the app-wide accent text (dashboard figures, headings, links). The
     defaults reproduce the stock band exactly (--banner = old --petrol-dark,
     --banner-fg = old --paper-2, --banner-fg-soft = old --amber-soft). The
     served /theme.css overrides these (and --paper/--paper-2) when an admin
     customises, and carries the fixed dark palette under prefers-color-scheme. */
  --banner:        #fff3cf;
  --banner-fg:     #10201d;
  --banner-fg-soft:#10201d;

  /* Type scale */
  --font-body: "Sora", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, sans-serif;
  --font-display: "Space Grotesk", "Sora", ui-sans-serif, system-ui, sans-serif;
  --fs-100: 0.82rem;
  --fs-200: 0.95rem;
  --fs-300: 1.05rem;
  --fs-400: 1.35rem;
  --fs-600: 2rem;

  /* Spacing */
  --sp-1: 0.35rem;
  --sp-2: 0.70rem;
  --sp-3: 1.10rem;
  --sp-4: 1.60rem;
  --sp-5: 2.40rem;

  /* Layout */
  --measure: 40rem;   /* readable body + header content column */
  --shell:   64rem;   /* full-bleed bar inner cap (header + nav) */
  --tap:     44px;    /* minimum touch-target size (real devices) */

  --radius: 12px;
  --shadow: 0 18px 50px rgba(220,160,40,.16);
  --focus: #cf8117;
  --glow: 0 14px 30px rgba(255,159,28,.35);
  --grad-bright: linear-gradient(135deg, #ffcd28, #ff9f1c, #dcf06b);
  --grad-text-ramp: linear-gradient(120deg, #986300, #9b6116, #7d6e00);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-300);
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
/* Yellow rebrand: stationary gradient field (no animation) + faint dot grid.
   Pseudo-elements paint above the body background, below all content.

   ⛔ IT IS A TINT OVER --paper, NOT A REPLACEMENT FOR IT. The first version
   painted three gradients at .45-.55 alpha over a 28px blur, which drowned the
   body colour: a tenant could set a custom background in admin settings, see
   "A custom theme is set" with their hex values, watch /theme.css serve
   `--paper: #ebedfe` correctly -- and still get the stock orange-and-green
   field on every page. Custom branding is a Tier C inclusion and a +$50 add-on,
   so the colour half of it was sold and not delivered.

   mix-blend-mode is what makes it a tint: `multiply` in light mode darkens the
   chosen colour through the gradient's shape instead of covering it, so a pale
   lilac stays lilac and a cream stays cream. Dark mode uses `screen` for the
   same reason inverted -- multiply against a near-black --paper would crush the
   field to invisible.

   NO GATE IN THIS REPO CAN SEE A REGRESSION HERE. `go build` and `go vet` never
   read CSS and the template-render gate asserts on markup, so this must be
   checked by rendering a page with a custom theme set and reading the computed
   background. */
body::before {
  content: ""; position: fixed; inset: -60px; z-index: -2; pointer-events: none;
  mix-blend-mode: multiply;
  background:
    linear-gradient(115deg, transparent 0%, rgba(255,205,40,.21) 22%, transparent 42%),
    linear-gradient(160deg, transparent 30%, rgba(255,159,28,.17) 55%, transparent 75%),
    linear-gradient(70deg,  transparent 40%, rgba(214,243,107,.20) 62%, transparent 84%);
  filter: blur(28px);
}
@media (prefers-color-scheme: dark) {
  body::before { mix-blend-mode: screen; }
}
body::after {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image: radial-gradient(rgba(150,120,30,.06) 1px, transparent 1px);
  background-size: 24px 24px;
}

/* A4 (WCAG 2.2 AA): skip link — SC 2.4.1 Bypass Blocks. Off-screen until it
   takes keyboard focus, then pinned at the top over the header. */
.skip-link {
  position: absolute;
  left: var(--sp-2);
  top: -3.5rem;
  z-index: 100;
  padding: var(--sp-1) var(--sp-3);
  background: var(--banner);
  color: var(--banner-fg);
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 8px 8px;
  transition: top .15s ease;
}
.skip-link:focus { top: 0; }

/* Screen-reader-only text utility. */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap;
}

.site-header { background: transparent; color: var(--banner-fg); padding: var(--sp-3) var(--sp-3) 0; }
.site-header__inner {
  max-width: var(--shell); margin: 0 auto;
  display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center;
  padding: var(--sp-3) var(--sp-4);
  border: 2px solid transparent; border-radius: 24px;
  background-image: linear-gradient(var(--banner), var(--banner)), var(--grad-bright);
  background-origin: border-box; background-clip: padding-box, border-box;
  box-shadow: 0 18px 50px rgba(220,160,40,.18);
}
.site-header__mark { font-weight: 800; letter-spacing: .28em; font-size: var(--fs-400); }
/* Free-placement header band (D-027). The 1000px reference canvas is positioned
   and scaled by brand_render.js; it starts hidden so there is no flash before
   the layout is applied. */
.brandbar {
  position: relative; max-width: var(--shell); margin: 0 auto;
  overflow: hidden; visibility: hidden;
  border: 2px solid transparent; border-radius: 24px;
  background-image: linear-gradient(var(--banner), var(--banner)), var(--grad-bright);
  background-origin: border-box; background-clip: padding-box, border-box;
  box-shadow: 0 18px 50px rgba(220,160,40,.18);
}
.brandbar__canvas { position: relative; }
.brandbar__logo { position: absolute; z-index: 1; }
.brandbar__logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Text wordmark fallback, hidden until brand_render.js reveals it on image-load
   failure (D-067). display:none keeps it out of the a11y tree until active, so
   screen readers hear exactly one brand element. Fills the logo box the image
   would occupy, so a swap never reflows the band. */
.brandbar__wordmark { display: none; width: 100%; height: 100%; align-items: center; justify-content: center; font-weight: 800; letter-spacing: .28em; font-size: var(--fs-400); color: var(--banner-fg); white-space: nowrap; overflow: hidden; }
.brandbar__logo--fallback img { display: none; }
.brandbar__logo--fallback .brandbar__wordmark { display: flex; }
.brandbar__powered { position: absolute; z-index: 2; color: var(--banner-fg-soft); font-weight: 600; white-space: nowrap; line-height: 1; }
/* Admin header-layout editor. The stage is the same 1000px reference space,
   scaled to fit the settings column by branding_editor.js. */
.be-intro { margin-top: var(--sp-4); } /* header-layout heading — was an inline style blocked by style-src 'self' */
.be-wrap { position: relative; width: 100%; overflow: hidden; border-radius: 6px 6px 0 0; margin-top: var(--sp-2); }
.be-stage {
  position: relative; width: 1000px; height: 150px; user-select: none;
  border: 2px solid transparent; border-radius: 24px;
  background-image: linear-gradient(var(--banner), var(--banner)), var(--grad-bright);
  background-origin: border-box; background-clip: padding-box, border-box;
}
.be-el { position: absolute; cursor: grab; }
.be-el.be-el--active { cursor: grabbing; }
.be-el--logo { z-index: 1; outline: 1px dashed var(--amber-soft); outline-offset: 2px; }
.be-el--logo img { width: 100%; height: 100%; object-fit: contain; display: block; pointer-events: none; }
.be-el--powered { z-index: 2; color: var(--banner-fg-soft); font-weight: 600; white-space: nowrap; line-height: 1; outline: 1px dashed var(--amber-soft); outline-offset: 2px; }
.be-handle { position: absolute; background: var(--amber); border: 2px solid #fff; z-index: 5; }
.be-handle--c { right: -7px; bottom: -7px; width: 14px; height: 14px; border-radius: 50%; cursor: nwse-resize; }
.be-handle--r { right: -7px; top: 50%; margin-top: -8px; width: 12px; height: 16px; border-radius: 3px; cursor: ew-resize; }
.be-handle--b { bottom: -7px; left: 50%; margin-left: -8px; width: 16px; height: 12px; border-radius: 3px; cursor: ns-resize; }
.be-toolbar { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; margin: var(--sp-2) 0; font-size: var(--fs-100); }
.be-toolbar label { display: flex; gap: 6px; align-items: center; }
.settings-logo-preview { display: block; max-height: 72px; max-width: 100%; width: auto; object-fit: contain; margin-top: var(--sp-2); }
.site-header__tag { font-size: var(--fs-100); letter-spacing: .08em; text-transform: uppercase; color: var(--banner-fg-soft); }

/* Role-aware navigation bar — full-bleed bar, centered wrapping inner.
   The bar background/border span the viewport (matching .site-header); the
   inner row is capped at --shell, centered, and wraps so it can never
   overflow at any role or width. */
.site-nav {
  background: var(--paper-2);
  border-bottom: 1px solid var(--line);
}
.site-nav__inner {
  max-width: var(--shell);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-1) var(--sp-3);
  padding: var(--sp-1) var(--sp-3);
}
.site-nav__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-3);
}
.site-nav__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-1);
  color: var(--petrol);
  font-weight: 600;
  font-size: var(--fs-200);
  text-decoration: none;
}
.site-nav__link:hover { text-decoration: underline; }
.site-nav__session { display: flex; align-items: center; gap: var(--sp-2); }
.site-nav__role {
  font-size: var(--fs-100);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-soft);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .15rem .6rem;
}
.site-nav__logout { margin: 0; }
.site-nav__button {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  font: inherit;
  font-size: var(--fs-100);
  font-weight: 700;
  color: var(--paper-2);
  background: var(--petrol);
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}
.site-nav__button:hover { background: var(--petrol-dark); }

/* Staff-entry banner — makes the assisted-entry page unmistakable */
.staff-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
  background: var(--amber-soft);
  border: 1px solid var(--amber);
  border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-4);
  font-size: var(--fs-200);
  color: var(--ink);
}
.staff-banner__label {
  font-size: var(--fs-100);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--ink);
  background: var(--amber);
  border-radius: 999px;
  padding: .15rem .65rem;
  white-space: nowrap;
}

.page { flex: 1; width: 100%; max-width: var(--measure); margin: 0 auto; padding: var(--sp-4) var(--sp-3) var(--sp-5); }

.site-footer { border-top: 1px solid var(--line); color: var(--ink-soft); font-size: var(--fs-100); text-align: center; padding: var(--sp-3); }

.reg__title { font-size: var(--fs-600); line-height: 1.1; margin: 0 0 var(--sp-2); letter-spacing: -.01em; }
.reg__lede { margin: 0 0 var(--sp-4); color: var(--ink-soft); }
/* D-100: the standing closed-registration page's secondary links block. */
.reg__closed-actions { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-4); color: var(--ink-soft); }

/* Admin dashboard — stat grid, manage tiles, recent-entries table */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}
.dash-stat {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.dash-stat__num { font-size: var(--fs-600); font-weight: 800; line-height: 1.1; color: var(--petrol); }
.dash-stat__label { font-size: var(--fs-100); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
/* Stranded-payment monitor liveness, rendered under the Pending card tile.
   --warn must stay visually distinct from the normal note: the whole point is
   that "not reporting" cannot be mistaken for "nothing wrong". */
.dash-stat__note { display: block; margin-top: .35rem; font-size: var(--fs-100); color: var(--ink-soft); }
.dash-stat__note--warn { color: var(--danger, #b3261e); font-weight: 600; }

.dash-section__title { font-size: var(--fs-400); margin: var(--sp-4) 0 var(--sp-2); }

.dash-table { width: 100%; border-collapse: collapse; font-size: var(--fs-200); background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.dash-table th, .dash-table td { text-align: left; padding: var(--sp-1) var(--sp-2); border-bottom: 1px solid var(--line); }
.dash-table th { font-size: var(--fs-100); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); background: var(--paper); }
.dash-table tr:last-child td { border-bottom: 0; }
.dash-status { font-size: var(--fs-100); background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: .1rem .55rem; white-space: nowrap; }

.dash-empty { color: var(--ink-soft); background: var(--paper-2); border: 1px dashed var(--line); border-radius: var(--radius); padding: var(--sp-3); text-align: center; }
.dash-updated { font-size: var(--fs-100); color: var(--ink-soft); margin: var(--sp-2) 0 0; }

/* D-084: resume-payment desk block on an unpaid card record's detail panel. */
.resume-pay-desk { background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--sp-3); margin: var(--sp-3) 0; text-align: center; }
.resume-pay-desk__hint { color: var(--ink-soft); font-size: var(--fs-200); margin: 0 0 var(--sp-3); }
.resume-pay-desk__qr { display: block; margin: 0 auto var(--sp-2); width: 220px; height: 220px; max-width: 100%; background: #fff; border-radius: var(--radius); }
.resume-pay-desk__link { font-size: var(--fs-100); word-break: break-all; margin: 0; }

.dash-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--sp-2);
}
.dash-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-3);
  text-decoration: none;
  color: var(--ink);
  box-shadow: var(--shadow);
}
a.dash-tile:hover { border-color: var(--petrol); }
.dash-tile strong { color: var(--petrol); }
.dash-tile span { font-size: var(--fs-100); color: var(--ink-soft); }
.dash-tile__icon { width: 26px; height: 26px; color: var(--petrol); margin-bottom: var(--sp-1); flex-shrink: 0; }
.svg-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.dash-tile--soon { opacity: .55; box-shadow: none; }
.dash-tile--soon strong { color: var(--ink-soft); }
.dash-tile--soon .dash-tile__badge {
  align-self: flex-start;
  margin-top: var(--sp-1);
  font-size: var(--fs-100);
  text-transform: uppercase;
  letter-spacing: .08em;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: .05rem .5rem;
}

/* Cash handling (Payment P2) — awaiting-cash queue, confirm lines, receipts */
.cash-queue { display: flex; flex-direction: column; gap: var(--sp-3); margin-bottom: var(--sp-4); }

.cash-group { display: flex; flex-direction: column; gap: var(--sp-2); }
.cash-group__header {
  margin: 0;
  font-size: var(--fs-200);
  font-weight: 800;
  color: var(--petrol);
  text-transform: none;
  border-bottom: 2px solid var(--line);
  padding-bottom: var(--sp-1);
}

.cash-line {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-2) var(--sp-3);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-1) var(--sp-3);
  align-items: center;
}
.cash-line__info { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cash-line__name { color: var(--ink); }
.cash-line__vehicle { font-size: var(--fs-200); color: var(--ink-soft); }
.cash-line__meta { font-size: var(--fs-100); color: var(--ink-soft); }

.cash-line__due { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.cash-line__due-label { font-size: var(--fs-100); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
.cash-line__due-amount { font-size: var(--fs-400); font-weight: 800; color: var(--petrol); }

.cash-line__form {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-2);
  border-top: 1px dashed var(--line);
  padding-top: var(--sp-2);
}
.cash-line__received { display: flex; flex-direction: column; gap: 2px; }
.cash-line__received > span { font-size: var(--fs-100); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
.cash-line__received .field__input { max-width: 9rem; }

.cash-line__change { font-size: var(--fs-200); font-weight: 700; color: var(--petrol); min-height: 1.2em; flex: 1; }
.cash-line__change--short { color: var(--amber-text); }

.cash-line__confirm {
  background: var(--petrol);
  color: var(--paper-2);
  border: 0;
  border-radius: var(--radius);
  font-weight: 800;
  padding: var(--sp-1) var(--sp-3);
  cursor: pointer;
}
.cash-line__confirm:hover { filter: brightness(1.1); }
.cash-line__confirm:disabled { opacity: .6; cursor: wait; }

.cash-result { grid-column: 1 / -1; }
.cash-result:empty { display: none; }
.cash-error {
  margin: 0;
  font-size: var(--fs-200);
  color: var(--ink);
  background: var(--amber-soft);
  border: 1px solid var(--amber);
  border-radius: var(--radius);
  padding: var(--sp-1) var(--sp-2);
}

.cash-confirmed { display: flex; flex-direction: column; gap: 2px; }
.cash-confirmed__change { margin: 0; font-size: var(--fs-400); color: var(--petrol); }
.cash-confirmed__change strong { font-weight: 800; }
.cash-confirmed__line { margin: 0; font-size: var(--fs-200); color: var(--ink); }
.cash-confirmed__meta { margin: 0; font-size: var(--fs-100); color: var(--ink-soft); }

/* --- Track D: public content pages + the admin content-block editor --------
   No inline styles (CSP style-src 'self'); everything lives here. */

/* Public content page (/about, /schedule). Readable column inherited from
   .page; blocks stack with comfortable spacing. */
.content-page { }
.content-page__title { font-size: var(--fs-600); line-height: 1.1; margin: 0 0 var(--sp-4); letter-spacing: -.01em; }
.content-page__empty { color: var(--ink-soft); }
.content-block { margin: 0 0 var(--sp-4); }
.content-block__header { font-size: var(--fs-400); color: var(--petrol); margin: 0 0 var(--sp-2); }
.content-block__body { color: var(--ink); }
.content-block__body p { margin: 0 0 var(--sp-2); }
.content-block__body ul { margin: 0 0 var(--sp-2); padding-left: var(--sp-4); }
.content-block__body li { margin: 0 0 var(--sp-1); }
.content-block__body a { color: var(--amber-text); text-decoration: underline; }

/* --- Public "How to vote" page (/how-to-vote) ------------------------------
   The QR destination printed on show signage. It reuses .content-page /
   .content-block for the column and section rhythm; these rules only add the
   numbered-step list, the ballot callouts, and the texting panel. Colours come
   from the existing tokens (--ink, --ink-soft, --amber-text, --petrol) so the
   page follows the admin theme and keeps the A4 contrast floors — no new
   palette, and never bare --amber for text. */
.htv-lede { font-size: var(--fs-400); line-height: 1.4; margin: 0 0 var(--sp-4); }
.htv-note {
  margin: 0 0 var(--sp-4);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--line-strong);
  background: var(--paper-2);
  border-radius: 0 var(--radius) var(--radius) 0;
}
/* Numbered steps. The order is meaningful, so it stays an <ol> and assistive
   tech announces the count; the marker is the ordinal itself. */
.htv-steps { margin: 0 0 var(--sp-3); padding-left: var(--sp-4); }
.htv-step { margin: 0 0 var(--sp-2); line-height: 1.5; }
.htv-step__title { display: block; font-weight: 700; }
.htv-rule {
  margin: 0;
  padding: var(--sp-3);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.htv-ballot { margin: 0 0 var(--sp-3); line-height: 1.5; }
.htv-ballot__who { display: block; font-weight: 700; color: var(--petrol); }
.htv-aside { margin: 0; color: var(--ink-soft); font-size: var(--fs-200); line-height: 1.5; }
.htv-sms { margin: 0 0 var(--sp-2); line-height: 1.5; }
.htv-sms__number { font-weight: 700; color: var(--amber-text); text-decoration: underline; white-space: nowrap; }
.htv-sms__example {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: .05em;
  padding: 0 var(--sp-1);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 6px;
}

/* Admin content-block editor. .ce-block is one stacked, draggable-by-buttons
   block; the bar carries move/delete controls. */
.ce__head { margin-bottom: var(--sp-3); }
.ce__view { color: var(--petrol); font-weight: 600; white-space: nowrap; }
.ce-form { display: flex; flex-direction: column; gap: var(--sp-3); }
.ce-status { margin: 0; padding: var(--sp-2) var(--sp-3); border-radius: var(--radius); font-weight: 600; }
.ce-status--ok { background: var(--good-bg); color: var(--good); }
.ce-status--err { background: var(--bad-bg); color: var(--bad); }
.ce-blocks { display: flex; flex-direction: column; gap: var(--sp-3); }
.ce-block { border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper-2); padding: var(--sp-3); margin: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.ce-block__bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); flex-wrap: wrap; }
.ce-block__tag { font-weight: 700; letter-spacing: .12em; text-transform: uppercase; font-size: var(--fs-100); color: var(--ink-soft); }
.ce-block__moves { display: flex; align-items: center; gap: var(--sp-1); }
.ce-move { font: inherit; min-width: var(--tap); min-height: var(--tap); border: 1px solid var(--line-strong); border-radius: 8px; background: var(--paper); color: var(--petrol); cursor: pointer; }
.ce-move:hover { border-color: var(--petrol); }
.ce-del { min-height: var(--tap); cursor: pointer; }
.ce-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.ce-meta { margin: 0; font-size: var(--fs-100); color: var(--ink-soft); }

/* Track D content editor — body formatting toolbar (B / I / • List). */
.ce-toolbar { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-bottom: var(--sp-1); }
.ce-fmt { font: inherit; font-weight: 700; min-width: var(--tap); min-height: 2.1rem; padding: 0 .65rem; border: 1px solid var(--line-strong); border-radius: 6px; background: var(--paper); color: var(--petrol); cursor: pointer; line-height: 1; }
.ce-fmt:hover { border-color: var(--petrol); }
.ce-fmt:active { transform: translateY(1px); }
.ce-fmt--i { font-style: italic; }
.ce-hint-bullet { white-space: nowrap; }

/* Track D content editor — WYSIWYG body box (contenteditable). Looks like the
   text inputs; shows real bold/italic/lists while editing. */
.ce-rte { min-height: 5rem; padding: .6rem .75rem; border: 1px solid var(--line-strong); border-radius: 8px; background: #fff; color: var(--ink); line-height: 1.5; }
.ce-rte:focus { outline: none; border-color: var(--focus); box-shadow: 0 0 0 4px rgba(255,205,40,.3); }
.ce-rte:empty::before { content: attr(data-placeholder); color: var(--ink-soft); }
.ce-rte p { margin: 0 0 var(--sp-2); }
.ce-rte ul { margin: 0 0 var(--sp-2); padding-left: var(--sp-4); }
.ce-rte li { margin: 0 0 var(--sp-1); }
.ce-rte a { color: var(--amber-text); text-decoration: underline; }

/* --- Track D-D3: card directories (Vendors) ------------------------------- */
/* Admin editor. Groups nest cards; cards reuse the .ce-* toolbar / WYSIWYG box
   styles from the content editor. */
.cd-form { display: flex; flex-direction: column; gap: var(--sp-4); }
.cd-groups { display: flex; flex-direction: column; gap: var(--sp-4); }
.cd-group { border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper-2); padding: var(--sp-3); margin: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
.cd-cards { display: flex; flex-direction: column; gap: var(--sp-3); padding-left: var(--sp-2); border-left: 3px solid var(--line); }
.cd-card { border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); padding: var(--sp-3); margin: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.cd-addr { border: 1px dashed var(--line); border-radius: var(--radius); padding: var(--sp-2) var(--sp-3); margin: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.cd-addr legend { padding: 0 var(--sp-1); }
.cd-logo-preview-wrap { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.cd-logo-preview { max-width: 160px; max-height: 90px; object-fit: contain; border: 1px solid var(--line); border-radius: 8px; background: #fff; padding: var(--sp-1); }
.cd-logo-remove { min-height: var(--tap); cursor: pointer; }

/* Public directory page. Groups stack; cards sit in a responsive grid. */
.cd-public-group { margin: 0 0 var(--sp-5); }
.cd-public-group__title { font-size: var(--fs-400); color: var(--petrol); margin: 0 0 var(--sp-3); padding-bottom: var(--sp-1); border-bottom: 1px solid var(--line); }
.cd-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--sp-3); }
.cd-public-card { border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); padding: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); }
.cd-public-card__logo { display: flex; align-items: center; justify-content: center; min-height: 80px; }
.cd-public-card__logo img { max-width: 100%; max-height: 110px; object-fit: contain; }
.cd-public-card__name { font-size: var(--fs-300); margin: 0; color: var(--ink); }
.cd-public-card__desc { color: var(--ink); }
.cd-public-card__desc p { margin: 0 0 var(--sp-2); }
.cd-public-card__desc ul { margin: 0 0 var(--sp-2); padding-left: var(--sp-4); }
.cd-public-card__desc a { color: var(--amber-text); text-decoration: underline; }
.cd-public-card__meta { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--fs-100); color: var(--ink-soft); }
.cd-public-card__meta a { color: var(--petrol); text-decoration: none; font-weight: 600; }
.cd-public-card__meta a:hover { text-decoration: underline; }
.cd-public-card__addr { display: flex; flex-direction: column; }

/* Card-directory per-tier style (D-029) — Sponsors. The editor control row plus
   the bounded public size scale. An unstyled group (the Vendor directory) emits
   no class and keeps the default sizing defined above; md in every scale equals
   that default, so a Sponsors tier left at md looks identical to a Vendor card. */
.cd-tier-style { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); padding: var(--sp-2) var(--sp-3); border: 1px dashed var(--line); border-radius: var(--radius); }
.cd-tier-style__field { flex: 1 1 8rem; min-width: 8rem; }

/* Per-card logo image size within a tier (6-step scale; md = default). */
.cd-public-group.cd-logo--xxl .cd-public-card__logo { min-height: 150px; }
.cd-public-group.cd-logo--xxl .cd-public-card__logo img { max-height: 200px; }
.cd-public-group.cd-logo--xl  .cd-public-card__logo { min-height: 120px; }
.cd-public-group.cd-logo--xl  .cd-public-card__logo img { max-height: 160px; }
.cd-public-group.cd-logo--lg  .cd-public-card__logo { min-height: 100px; }
.cd-public-group.cd-logo--lg  .cd-public-card__logo img { max-height: 130px; }
.cd-public-group.cd-logo--md  .cd-public-card__logo { min-height: 80px; }
.cd-public-group.cd-logo--md  .cd-public-card__logo img { max-height: 110px; }
.cd-public-group.cd-logo--sm  .cd-public-card__logo { min-height: 64px; }
.cd-public-group.cd-logo--sm  .cd-public-card__logo img { max-height: 84px; }
.cd-public-group.cd-logo--xs  .cd-public-card__logo { min-height: 48px; }
.cd-public-group.cd-logo--xs  .cd-public-card__logo img { max-height: 60px; }

/* Tier heading size + weight (md = default; bold = the default heading weight). */
.cd-public-group.cd-title--lg .cd-public-group__title { font-size: 1.7rem; }
.cd-public-group.cd-title--md .cd-public-group__title { font-size: var(--fs-400); }
.cd-public-group.cd-title--sm .cd-public-group__title { font-size: 1.1rem; }
.cd-public-group.cd-weight--bold   .cd-public-group__title { font-weight: 700; }
.cd-public-group.cd-weight--normal .cd-public-group__title { font-weight: 400; }

/* Per-card name size within a tier (md = default). */
.cd-public-group.cd-name--lg .cd-public-card__name { font-size: 1.3rem; }
.cd-public-group.cd-name--md .cd-public-card__name { font-size: var(--fs-300); }
.cd-public-group.cd-name--sm .cd-public-card__name { font-size: 0.92rem; }

/* ---------------------------------------------------------------------------
   Voting-context cross-links (Track D, D-D5)
   The "back to voting" banner (top of a public page reached from a car's voting
   page) and the "explore the show" row (bottom of the voting page and of those
   public pages). Both are token-gated in the templates, so these styles apply
   only when the affordance is actually rendered.
   --------------------------------------------------------------------------- */
.back-to-voting {
  max-width: var(--measure);
  margin: 0 auto var(--sp-2);
}
.back-to-voting__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-2);
  color: var(--petrol);
  font-weight: 600;
  font-size: var(--fs-200);
  text-decoration: none;
}
.back-to-voting__link:hover { text-decoration: underline; }

.explore-row {
  max-width: var(--measure);
  margin: var(--sp-4) auto 0;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
}
.explore-row__label {
  display: block;
  margin-bottom: var(--sp-1);
  font-size: var(--fs-100);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-soft);
}
.explore-row__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
}
.explore-row__item { margin: 0; }
.explore-row__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-1);
  color: var(--petrol);
  font-weight: 600;
  font-size: var(--fs-200);
  text-decoration: none;
}
.explore-row__link:hover { text-decoration: underline; }

/* ---------------------------------------------------------------------------
   A4 — WCAG 2.2 AA: visible focus + device-preference auto-activation
   --------------------------------------------------------------------------- */

/* Visible keyboard focus for every interactive element (SC 2.4.7 Focus Visible,
   SC 2.4.13 Focus Appearance). :focus-visible so a mouse click doesn't ring the
   control. The D-D5 cross-links and the nav links inherit this via the element
   selectors; no per-component rule needed. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[contenteditable="true"]:focus-visible {
  outline: 2px solid var(--petrol);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Controls on the dark petrol fill need a light ring to keep ≥3:1 against it. */
.site-nav__button:focus-visible,
.btn--primary:focus-visible,
.cash-line__confirm:focus-visible {
  outline-color: var(--amber-soft);
}

/* Reduced motion (SC 2.3.3): honor the OS/browser preference by neutralizing
   transitions and animations. Inert when no preference is expressed. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Higher contrast (prefers-contrast: more): promote soft text to full ink and
   strengthen every divider/control border + the focus ring. The default already
   meets AA; this is the device-preference uplift, inert when no preference. */
@media (prefers-contrast: more) {
  :root {
    --ink-soft:    #2a2620;
    --line:        #8a6a20;
    --line-strong: #7a5a10;
    --amber-text:  #6e4200;
  }
  a:focus-visible,
  button:focus-visible,
  input:focus-visible,
  select:focus-visible,
  textarea:focus-visible,
  summary:focus-visible,
  [tabindex]:focus-visible,
  [contenteditable="true"]:focus-visible {
    outline-width: 3px;
  }
}

/* Charity Recipient page (D-041). Public profile header (logo + contact),
   the up-to-two header images, and the editor's image rows. Mirrors the
   content-page and card-directory tokens; no new colours. */
.charity-head { margin: 0 0 var(--sp-4); }
.charity-head__logo { display: flex; align-items: center; min-height: 80px; margin: 0 0 var(--sp-2); }
.charity-head__logo img { max-width: 100%; max-height: 130px; object-fit: contain; }
.charity-head__contact { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-3); color: var(--ink); }
.charity-head__contact a { color: var(--amber-text); text-decoration: underline; }
.charity-head__addr { display: flex; flex-direction: column; color: var(--ink-soft); }
.charity-images { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--sp-3); margin: 0 0 var(--sp-4); }
.charity-images__item img { width: 100%; height: auto; border-radius: var(--radius); border: 1px solid var(--line); display: block; }
/* editor layout (reuses .field, .ce-*, .cd-logo-preview, .cd-logo-preview-wrap) */
.charity-logo, .charity-imgs, .charity-contact, .charity-blocks { margin: 0 0 var(--sp-4); }
.charity-img { display: flex; flex-direction: column; gap: var(--sp-1); padding: var(--sp-2) 0; border-bottom: 1px solid var(--line); }
.charity-addr { margin: var(--sp-2) 0 0; padding: var(--sp-2) 0 0; border-top: 1px solid var(--line); }


/* ============================================================================
   Yellow rebrand — slice 1 component layer (appended; later source wins).
   Self-hosted @font-face (CSP style-src 'self'); until the woff2 files are
   dropped in /static/fonts the families fall back to the system stack. The
   gradient/colour identity below is active immediately, font-independent.
   ============================================================================ */
@font-face { font-family:"Sora"; font-style:normal; font-weight:300 700; font-display:swap; src:url("/static/fonts/sora-variable.woff2") format("woff2"); }
@font-face { font-family:"Space Grotesk"; font-style:normal; font-weight:400 700; font-display:swap; src:url("/static/fonts/space-grotesk-variable.woff2") format("woff2"); }

.reg__title, .content-page__title {
  font-family: var(--font-display); letter-spacing: -.02em;
  background: var(--grad-text-ramp);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--petrol);
}
.dash-section__title, .reg-form__legend, .content-block__header,
.cd-public-group__title, .dash-stat__num { font-family: var(--font-display); }
@media (forced-colors: active) {
  .reg__title, .content-page__title {
    -webkit-text-fill-color: currentColor !important; background: none !important; color: CanvasText !important;
  }
}

.site-nav__button { background: var(--grad-bright); color: #000; }
.site-nav__button:hover { background: var(--grad-bright); filter: brightness(1.04); }
.cash-line__confirm { background: var(--grad-bright); color: #000; box-shadow: var(--glow); }
.cash-line__confirm:hover { filter: brightness(1.04); }
.site-nav__button:focus-visible, .btn--primary:focus-visible, .cash-line__confirm:focus-visible { outline-color: #6e4400; }

/* ============================================================================
   Public directory tiles + detail overlay, and Charity profile polish (D-056;
   appended, later source wins). Uniform clickable tiles for Vendors & Sponsors
   share the existing .cd-grid; a tile is a fragment link that opens a pure-CSS
   :target dialog (no JS, CSP-clean). The older .cd-public-card* / .cd-logo--* /
   .cd-name--* rules above are now unused by the public pages but left in place.
   ============================================================================ */

/* Uniform tile (collapsed). Every tile is the same size regardless of content. */
.cd-tile {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--sp-2); min-height: 190px; padding: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper);
  color: var(--ink); text-decoration: none;
  transition: border-color .12s ease, transform .12s ease, box-shadow .12s ease;
}
.cd-tile:hover, .cd-tile:focus-visible { border-color: var(--petrol); transform: translateY(-2px); box-shadow: var(--glow); }
.cd-tile__logo { display: flex; align-items: center; justify-content: center; width: 100%; height: 96px; }
.cd-tile__logo img { max-width: 100%; max-height: 96px; object-fit: contain; }
.cd-tile__mark {
  display: flex; align-items: center; justify-content: center;
  width: 72px; height: 72px; border-radius: 50%;
  background: var(--line); color: var(--petrol);
  font-family: var(--font-display); font-weight: 700; font-size: 1.6rem; letter-spacing: .02em;
}
.cd-tile__name {
  font-family: var(--font-display); font-size: var(--fs-300); line-height: 1.2; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.cd-tile__cue { margin-top: auto; font-size: var(--fs-100); font-weight: 600; color: var(--petrol); }

/* Detail overlay: hidden until its id is the URL fragment (tile click). */
.cd-modal { display: none; }
.cd-modal:target {
  display: flex; position: fixed; inset: 0; z-index: 100;
  align-items: flex-start; justify-content: center;
  padding: var(--sp-4) var(--sp-3); overflow-y: auto; background: rgba(17,16,14,.55);
}
.cd-modal__scrim { position: fixed; inset: 0; display: block; }
.cd-modal__panel {
  position: relative; z-index: 1; width: 100%; max-width: 32rem; margin: auto;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--sp-4); box-shadow: 0 12px 40px rgba(0,0,0,.28);
}
.cd-modal__close {
  position: absolute; top: var(--sp-2); right: var(--sp-2);
  width: var(--tap); height: var(--tap); display: flex; align-items: center; justify-content: center;
  font-size: 1.7rem; line-height: 1; color: var(--ink-soft); text-decoration: none; border-radius: 8px;
}
.cd-modal__close:hover, .cd-modal__close:focus-visible { color: var(--ink); background: var(--paper-2); }
.cd-modal__logo { display: flex; align-items: center; justify-content: center; min-height: 80px; margin: 0 0 var(--sp-2); }
.cd-modal__logo img { max-width: 100%; max-height: 130px; object-fit: contain; }
.cd-modal__name { font-family: var(--font-display); font-size: var(--fs-400); color: var(--ink); margin: 0 0 var(--sp-3); padding-right: var(--tap); }
.cd-modal__desc { color: var(--ink); margin: 0 0 var(--sp-3); }
.cd-modal__desc p { margin: 0 0 var(--sp-2); }
.cd-modal__desc ul { margin: 0 0 var(--sp-2); padding-left: var(--sp-4); }
.cd-modal__desc a { color: var(--amber-text); text-decoration: underline; }
.cd-modal__meta { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--fs-200); color: var(--ink-soft); }
.cd-modal__meta a { color: var(--petrol); text-decoration: none; font-weight: 600; }
.cd-modal__meta a:hover { text-decoration: underline; }
.cd-modal__addr { display: flex; flex-direction: column; }
@media (prefers-reduced-motion: reduce) {
  .cd-tile { transition: none; }
  .cd-tile:hover, .cd-tile:focus-visible { transform: none; }
}

/* Charity profile: present the header (logo + name + contact) as one centered
   panel so a sparse profile reads as a deliberate unit rather than loose text,
   and give the body blocks comfortable line length + rhythm. */
.charity-head {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--sp-2); margin: 0 0 var(--sp-5); padding: var(--sp-4) var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper);
}
.charity-head__logo { justify-content: center; min-height: 0; margin: 0; }
.charity-head__contact { justify-content: center; margin: 0; }
.charity-head__addr { align-items: center; }
.content-block__body { line-height: 1.6; }
.content-block + .content-block { margin-top: var(--sp-5); }

/* --- Merch POS admin (D-061 slice 2) ------------------------------------- */
.merch-enable {
  margin: var(--sp-3) 0; padding: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper-2);
}
.merch-enable__state {
  display: flex; align-items: center; gap: var(--sp-2); margin: 0; font-size: var(--fs-300);
}
.merch-badge {
  display: inline-block; padding: 0.1em 0.6em; border-radius: 999px;
  background: var(--line); color: var(--ink-soft);
  font-size: var(--fs-200); font-weight: var(--bold); letter-spacing: 0.02em;
}
.merch-badge--on { background: var(--good-bg); color: var(--good); }
.merch-table-wrap { overflow-x: auto; }
.merch-table { width: 100%; border-collapse: collapse; margin-top: var(--sp-3); font-size: var(--fs-300); }
.merch-table th, .merch-table td {
  padding: var(--sp-2); text-align: left; border-bottom: 1px solid var(--line); vertical-align: middle;
}
.merch-table th { color: var(--ink-soft); font-weight: var(--bold); }
.merch-table__name { display: flex; align-items: center; gap: var(--sp-2); }
.merch-thumb { width: 40px; height: 40px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--line); }
.merch-table__act form { margin: 0; }
.merch-photo { margin-bottom: var(--sp-2); padding-bottom: var(--sp-2); border-bottom: 1px dashed var(--line); }
.merch-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--sp-2); margin-top: var(--sp-2);
}
.merch-grid__cell { display: flex; flex-direction: column; gap: 0.25em; }
.merch-grid__k { font-size: var(--fs-200); color: var(--ink-soft); }
.merch-custom { display: flex; gap: var(--sp-2); align-items: center; margin-bottom: var(--sp-2); flex-wrap: wrap; }
.field--check { display: flex; flex-direction: row; align-items: center; gap: var(--sp-2); }
.btn--sm { padding: 0.3em 0.7em; font-size: var(--fs-200); }
.ce-empty { color: var(--ink-soft); margin-top: var(--sp-3); }

/* --- Merch POS console (D-061 slice 3) + public storefront (slice 5) ----- */
/* Secondary .btn buttons on merch surfaces read as real buttons (plain .btn
   carries no fill in forms.css). --ghost is an outline action (Void). The public
   storefront (.shop) reuses the whole .pos-* card/cart vocabulary, so it shares
   this rule too. */
.pos .btn:not(.btn--primary):not(.btn--ghost),
.shop .btn:not(.btn--primary):not(.btn--ghost),
.merch-table .btn:not(.btn--primary):not(.btn--ghost) {
  background: var(--paper-2); border: 1px solid var(--line); color: var(--ink);
}
.btn--ghost { background: transparent; border: 1px solid var(--line); color: var(--ink); }
.btn--ghost:hover { background: var(--bad-bg); }

.pos__grid {
  display: grid; grid-template-columns: 2fr 1fr; gap: var(--sp-4);
  margin-top: var(--sp-3); align-items: start;
}
.pos__h { font-size: var(--fs-300); margin: 0 0 var(--sp-2); }
.pos__products {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sp-3);
}
.pos-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper-2); padding: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2);
}
.pos-card--out { opacity: 0.6; }
.pos-card__head { display: flex; align-items: center; gap: var(--sp-2); }
.pos-card__thumb { width: 44px; height: 44px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--line); }
.pos-card__id { display: flex; flex-direction: column; }
.pos-card__name { font-weight: var(--bold); }
.pos-card__meta { font-size: var(--fs-200); color: var(--ink-soft); }
.pos-card__controls { display: flex; flex-direction: column; gap: var(--sp-2); }
.pos-card__soldout { margin: 0; font-size: var(--fs-200); color: var(--ink-soft); }
/* D-091 manual (open) line card. Set apart from the product cards above it with a
   dashed edge so a staffer scanning the column never taps it by mistake for a real
   product, and so it reads as "the escape hatch" rather than "another item". */
.pos-card--manual { border-style: dashed; }
/* The validation message is the ONLY feedback a staffer gets for a bad typed price
   or quantity, so it must read as an error, not as body text. Mirrors .ce-status--err
   colours; role="alert" on the element carries it to a screen reader. */
.pos-card__err {
  margin: 0; padding: var(--sp-1) var(--sp-2); border-radius: 6px;
  font-size: var(--fs-200); font-weight: 600;
  background: var(--bad-bg); color: var(--bad);
}
.pos-field { display: flex; flex-direction: column; gap: 0.2em; font-size: var(--fs-200); }
.pos-field > span { color: var(--ink-soft); }
.pos-field select, .pos-field input { width: 100%; }
.pos-field--qty { max-width: 6rem; }

.pos__cart {
  position: sticky; top: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper-2); padding: var(--sp-3);
}
.pos-cart__lines { display: flex; flex-direction: column; gap: var(--sp-1); margin-bottom: var(--sp-2); }
.pos-cart__empty { margin: 0; color: var(--ink-soft); font-size: var(--fs-200); }
.pos-cart__line { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-200); }
.pos-cart__desc { flex: 1; }
.pos-cart__amt { font-variant-numeric: tabular-nums; }
.pos-cart__rm {
  border: 0; background: transparent; color: var(--bad); cursor: pointer;
  font-size: var(--fs-300); line-height: 1; padding: 0 0.3em;
}
.pos-cart__total { margin: var(--sp-2) 0; font-size: var(--fs-300); }
.pos__cart .btn--primary { width: 100%; }
/* Slice 4: cash + card actions stack full-width; the card hint explains the flow. */
.pos-cart__actions { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-2); }
.pos-cart__hint { margin: var(--sp-2) 0 0; font-size: var(--fs-100); color: var(--ink-soft); }
/* Console payment-method selector (D-061): only Card reveals the surcharge note. */
.pos-cart__pay { border: 0; margin: var(--sp-2) 0 0; padding: 0; }
.pos-cart__pay-legend { padding: 0; margin-bottom: var(--sp-1); font-size: var(--fs-100); font-weight: var(--bold); }
.pos-cart__pay-opt { display: inline-flex; align-items: center; gap: 0.35em; margin-right: var(--sp-3); font-size: var(--fs-200); cursor: pointer; }
/* Card surcharge lines (D-061 slice 9). */
.pos-cart__surcharge { margin: var(--sp-1) 0; font-size: var(--fs-200); color: var(--ink-soft); }
.pos-cart__subtotal { margin: var(--sp-1) 0; font-size: var(--fs-200); display: flex; justify-content: space-between; }
.pos-cart__surcharge[data-pos-card-note] { display: block; }
.shop .pos-cart__surcharge { display: flex; justify-content: space-between; }

.pos__queue { margin-top: var(--sp-4); }
.pos-receipt {
  margin: var(--sp-3) 0; padding: var(--sp-3);
  border: 2px dashed var(--line); border-radius: var(--radius); background: var(--paper);
}
.pos-receipt__h { margin: 0 0 var(--sp-1); font-size: var(--fs-300); }
.pos-receipt__nums { margin: 0 0 var(--sp-2); font-weight: var(--bold); }
.pos-receipt__lines { list-style: none; margin: 0 0 var(--sp-2); padding: 0; display: flex; flex-direction: column; gap: 0.2em; }
.pos-receipt__lines li { display: flex; align-items: baseline; gap: var(--sp-2); font-size: var(--fs-200); }
.pos-receipt__qty { color: var(--ink-soft); }
.pos-receipt__amt { margin-left: auto; font-variant-numeric: tabular-nums; }
.pos-receipt__total { margin: 0 0 var(--sp-2); font-size: var(--fs-300); }
/* Receipt pickup QR (D-061 slice 6) — printed on the cash receipt so a walk-up
   buyer's printout is scannable at hand-over. */
.pos-receipt__qr { display: flex; flex-direction: column; align-items: flex-start; gap: 0.2em; margin: var(--sp-2) 0; }
.pos-receipt__qr img { width: 160px; height: 160px; image-rendering: pixelated; }
.pos-receipt__qrcap { font-size: var(--fs-100); color: var(--ink-soft); }

/* Scan-to-fulfil (D-061 slice 6) — the merch console camera scanner. */
.pos__scan { margin-top: var(--sp-4); }
.pos-scan__stage { display: flex; flex-direction: column; gap: var(--sp-2); max-width: 24rem; }
.pos-scan__video {
  width: 100%; aspect-ratio: 4 / 3; background: #000; border-radius: var(--radius);
  border: 1px solid var(--line); object-fit: cover;
}
.pos-scan__status { margin: 0; font-size: var(--fs-200); color: var(--ink-soft); }
.pos-scan__controls { display: flex; gap: var(--sp-2); }
.pos-scan__hint { margin: 0; font-size: var(--fs-100); color: var(--ink-soft); }

/* Public order pickup page (D-061 slice 6). */
.pickup { max-width: 26rem; }
.pickup__status { font-weight: var(--bold); font-size: var(--fs-400); margin: var(--sp-1) 0 var(--sp-3); }
.pickup__status--ready { color: #2f6b2f; }
.pickup__status--done { color: var(--ink-soft); }
.pickup__status--wait { color: #8a5a00; }
.pickup__qr { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); margin: var(--sp-3) 0; }
.pickup__qr img { width: 256px; height: 256px; max-width: 100%; image-rendering: pixelated; }
.pickup__hint { margin: 0; text-align: center; font-size: var(--fs-200); color: var(--ink-soft); }
.pickup__summary { margin-top: var(--sp-3); padding-top: var(--sp-2); border-top: 1px solid var(--line); }
.pickup__items { margin: 0 0 var(--sp-1); }
.pickup__total { margin: 0; font-size: var(--fs-300); }
.pickup__fallback { margin-top: var(--sp-2); } /* D-082: brightness + order-number fallback */

/* Merch make board (D-082): reconciliation tiles, glanceable to-make rows, detail card. */
.make-recon { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: var(--sp-2); margin: var(--sp-2) 0 var(--sp-3); }
.make-recon__tile { border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper-2); padding: var(--sp-2) var(--sp-3); display: flex; flex-direction: column; }
.make-recon__n { font-size: var(--fs-400); font-weight: var(--bold); font-variant-numeric: tabular-nums; }
.make-recon__l { font-size: var(--fs-100); color: var(--ink-soft); }
.make-section--muted { color: var(--ink-soft); }
.make-row--muted { opacity: 0.72; }
.make-row--claimed { border-left: 3px solid var(--good, #2f6b2f); }
.make-row__open-form { margin: 0; width: 100%; }
.make-row__open { display: flex; flex-direction: column; gap: 0.15em; width: 100%; text-align: left; background: none; border: 0; padding: var(--sp-2) 0; cursor: pointer; color: inherit; font: inherit; }
.make-row__open:hover { background: var(--paper-2); }
.make-completed { opacity: 0.72; }
.make-detail__banner { font-weight: var(--bold); margin: 0 0 var(--sp-2); }
.make-detail__items { margin: var(--sp-2) 0; padding-left: 1.1rem; }
.make-detail__items li { margin: 0.2em 0; }
.make-detail__gather { font-weight: var(--bold); }
.make-detail__wait { color: #8a5a00; font-weight: var(--bold); }
.make-detail__done { color: var(--ink-soft); }
.make-detail__actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-2); }
.make-detail__actions form { margin: 0; }
.merch-make-lookup { margin-top: var(--sp-3); }

/* Merch sales report (D-061 slice 7). */
.report-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--sp-3); margin: var(--sp-3) 0; }
.report-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper-2); padding: var(--sp-3); margin-bottom: var(--sp-3);
}
.report-card__h { margin: 0 0 var(--sp-2); font-size: var(--fs-200); text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-soft); }
.report-figure { margin: 0; font-size: var(--fs-500); font-weight: var(--bold); font-variant-numeric: tabular-nums; }
.report-sub { margin: var(--sp-1) 0 0; color: var(--ink-soft); font-size: var(--fs-200); }
.report-list { list-style: none; margin: var(--sp-2) 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.2em; }
.report-list li { display: flex; justify-content: space-between; gap: var(--sp-2); font-size: var(--fs-200); }
.report-list li span { font-variant-numeric: tabular-nums; font-weight: var(--bold); }
.report-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); }

@media (max-width: 720px) {
  .pos__grid { grid-template-columns: 1fr; }
  .pos__cart { position: static; }
}

/* The second `.sr-only {` here was a duplicated line, and it never closed, so
   the file carried 432 `{` against 431 `}`. A browser applied CSS Nesting
   recovery: the 34 rules below were reparented to `.sr-only <selector>` and the
   block closed implicitly at EOF. Measured in a browser, not reasoned about.

   THIS REPO NEVER AUTHORED THE DEFECT -- it arrived on 2026-08-10 with a421768,
   which copied Samkoma's theme across wholesale. No template here uses .sr-only
   or .station__*, so there was no symptom; the damage was that every rule
   appended below line 1036 would have been born dead. That is the argument for
   a structural gate over a visual one: this copy had zero visible evidence. */
.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;
}

/* D-092 unified gate station. The design claim is "one obvious next action",
   which is a VISUAL claim - unstyled, the load-bearing state and error text
   renders as ordinary body copy at a sunny outdoor table. Sizing is deliberately
   generous: this is operated one-handed, standing, on a phone. */
.station { max-width: 44rem; }
.station__find { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: flex-end; margin-bottom: var(--sp-3); }
.station__find .field { flex: 1 1 16rem; }

.station__results { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.station__result-btn {
  width: 100%; text-align: left; display: grid; gap: 2px; cursor: pointer;
  padding: var(--sp-2); border: 1px solid var(--line); border-radius: 8px;
  background: var(--paper-2); font: inherit; min-height: 3rem;
}
.station__result-veh, .station__result-status { font-size: 0.9rem; opacity: 0.8; }
.station__empty { opacity: 0.75; }

.station__focus { border: 1px solid var(--line); border-radius: 10px; padding: var(--sp-3); }
.station__who h2 { margin: 0; }
.station__count { margin: 0 0 var(--sp-2); font-size: 0.9rem; opacity: 0.75; }

.station__progress { list-style: none; margin: 0 0 var(--sp-3); padding: 0; display: grid; gap: 4px; }
.station__veh { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: space-between; font-size: 0.95rem; }
.station__veh-state { opacity: 0.85; }
.station__veh--void { opacity: 0.6; text-decoration: line-through; }
.station__veh--void .station__veh-state { text-decoration: none; }

/* The current step is the one thing that must be unmissable. */
.station__step { border-top: 2px solid var(--line); padding-top: var(--sp-3); }
.station__step-title { margin: 0 0 var(--sp-2); font-size: 1.15rem; }
.station__step .btn,
.station__msg--warn .btn { min-height: 3rem; font-size: 1.05rem; }
.station__step form { margin-bottom: var(--sp-2); }
.station__due { font-size: 1.1rem; margin: 0 0 var(--sp-2); }
.station__hint { font-size: 0.9rem; opacity: 0.8; }
.station__denied, .station__complete { font-size: 1.05rem; }

/* Status messages carry money and check-in outcomes - they must not read as
   body text. Colour is never the ONLY signal: each is prefixed in the markup
   and role=alert/status carries it to a screen reader. */
.station__msg { padding: var(--sp-2); border-radius: 8px; border-left: 5px solid; margin: 0 0 var(--sp-3); font-size: 1.05rem; }
.station__msg--success { border-color: var(--good); background: var(--good-bg); }
.station__msg--error { border-color: var(--bad); background: var(--bad-bg); }
.station__msg--warn { border-color: var(--amber-text); background: var(--paper-2); }

/* D-092 slice 4 - inline walk-up registration. It sits BELOW the card in a
   collapsed <details> so the focused registrant stays the top of the screen:
   the common case at a gate is advancing someone who is already registered.
   The form's own fields reuse .reg-form / .field / .charge-box from forms.css,
   so only the disclosure and its result region need styling here. */
.station__register { margin-top: var(--sp-4); border: 1px solid var(--line); border-radius: 10px; padding: var(--sp-2) var(--sp-3); }
.station__register-toggle { cursor: pointer; font-size: 1.05rem; font-weight: 600; padding: var(--sp-2) 0; }
.station__register-form { margin-top: var(--sp-3); }
.station__register-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.station__register-actions .btn { min-height: 3rem; }
.station__register-result:empty { display: none; }
.station__register-result { margin-top: var(--sp-3); }
