/* =====================================================================
   Ideals Precision Series Rewards — the whole design system.

   Extracted from the approved clickable prototype (docs/prototype-reference.html)
   and extended with the chrome a real site needs: brand lockup, skip link,
   pagination, filter bars, admin navigation, empty states, focus rings.

   Rules this file lives by:
     - Mobile first. Attendees arrive by scanning a QR code at the venue, so
       the phone is the primary surface. Everything works at 360px, nothing
       scrolls sideways, and the tab bar is reachable with one thumb.
     - Tap targets are at least 44px on touch pointers.
     - Form controls are 16px so iOS does not zoom the viewport on focus.
     - Dark only, deliberately. The prototype is dark and that was signed off.
       There is no light palette and no prefers-color-scheme branch: <body>
       paints its own background and colour so nothing bleeds through.
     - The palette is fixed and approved. Depth comes from borders, shadow and
       gradient — never from inventing a new hue.
     - No inline styles anywhere in the app (the CSP forbids them), so every
       one-off spacing the prototype expressed with style="" has a class here.
     - Every interactive element states all of its moods: hover, active,
       focus-visible, disabled and busy. The focus ring is never removed.
   ===================================================================== */

/* ------------------------------------------------------------ tokens */

:root {
  /* ---- approved palette. Do not add hues; derive from these. */
  --bg: #191E24;
  --surface: #23292F;
  --surface-2: #2A3138;
  --surface-3: #313941;
  --hero-a: #14342C;
  --hero-b: #1F4A3C;
  --accent: #5FBF8D;
  --accent-d: #3E9E72;
  --ink: #FFFFFF;
  --muted: #A3ADB3;
  --faint: #79848B;
  --line: #333B42;
  --line-2: #3E474F;          /* the brighter border a raised surface takes */
  --danger: #E0785F;
  --warn: #DCA84E;

  --font: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
  --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* ---- type scale. One ratio, used everywhere, so nothing is "roughly" a size. */
  --fs-2xs: .6875rem;   /* 11 — eyebrows, table headers, tags */
  --fs-xs: .75rem;      /* 12 — hints, footer, meta */
  --fs-sm: .8125rem;    /* 13 — dense UI, secondary copy */
  --fs-md: .875rem;     /* 14 — body copy in prose */
  --fs-base: .9375rem;  /* 15 — default */
  --fs-lg: 1.0625rem;   /* 17 — card and panel titles */
  --fs-xl: 1.375rem;    /* 22 — page titles */
  --fs-2xl: 1.75rem;    /* 28 — hero numbers, auth headings */
  --fs-3xl: 2.125rem;   /* 34 — the one big number on the error page */

  --lh-tight: 1.2;
  --lh-heading: 1.28;
  --lh-body: 1.6;
  --track-caps: .1em;   /* letter-spacing for uppercase micro type */
  --track-tight: -.011em;

  /* ---- spacing rhythm. Everything vertical is a step on this scale. */
  --sp-1: .25rem;
  --sp-2: .5rem;
  --sp-3: .75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 2.75rem;

  /* ---- form */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 14px;
  --r-pill: 999px;
  --tap: 44px;

  /* ---- depth. Two shadows only: resting, and lifted. */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .34);
  --shadow-2: 0 1px 2px rgba(0, 0, 0, .38), 0 10px 26px -14px rgba(0, 0, 0, .85);
  --shadow-3: 0 18px 48px -20px rgba(0, 0, 0, .92);
  --ring: 0 0 0 4px rgba(95, 191, 141, .22);
  --ring-danger: 0 0 0 4px rgba(224, 120, 95, .22);
  --hairline: inset 0 1px 0 rgba(255, 255, 255, .04);

  --ease: cubic-bezier(.2, .7, .3, 1);
  --dur: .16s;

  /* derived, used by tags, flashes and callouts */
  --info-bg: #1f3a4d;
  --info-ink: #7FC4E8;
  --warn-bg: #3d3520;
  --ok-bg: #24402f;
  --bad-bg: #3d2723;
  --bad-line: #5a3a34;
}

/* Montserrat's lowercase runs slightly wide at small sizes; when we know it is
   really loaded (layout.js stamps data-fonts) we can tighten headings a touch.
   With the system stack the tracking stays at 0, which is what those faces want. */
html[data-fonts="hosted"] h1,
html[data-fonts="hosted"] h2,
html[data-fonts="hosted"] .brand-word,
html[data-fonts="hosted"] .hcard-points,
html[data-fonts="hosted"] .stat .v { letter-spacing: var(--track-tight); }

/* ------------------------------------------------------------ reset */

* { box-sizing: border-box; }

html {
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  background: var(--bg);
}

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  min-height: 100vh;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 700;
  line-height: var(--lh-heading);
  letter-spacing: var(--track-tight);
  color: var(--ink);
}
h3, h4 { font-weight: 600; letter-spacing: 0; }
p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; height: auto; }
svg { display: block; }
hr { border: 0; border-top: 1px solid var(--line); margin: var(--sp-5) 0; }
b, strong { font-weight: 700; }
small { font-size: var(--fs-xs); }

/* [hidden] must win over any display rule below it — the modal roots and the
   client-side error hints rely on it. */
[hidden] { display: none !important; }

/* One ring, everywhere, and it survives on every background: a solid accent
   outline plus a soft halo so it reads over the hero as well as over a table
   row. Never trade this for a "cleaner" look. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
  box-shadow: var(--ring);
}

/* ------------------------------------------------------------ accessibility */

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

.skip-link {
  position: absolute;
  left: var(--sp-2);
  top: -4rem;
  z-index: 100;
  background: var(--accent-d);
  color: #fff;
  padding: var(--sp-3) var(--sp-4);
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  box-shadow: var(--shadow-2);
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: 0; }

/* The main region gets tabindex="-1" so the skip link can move focus to it. */
[tabindex="-1"]:focus { outline: none; box-shadow: none; }

/* ------------------------------------------------------------ app shell */

.phone {
  background: var(--bg);
  max-width: 60rem;
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

@supports (min-height: 100dvh) {
  .phone { min-height: 100dvh; }
}

@media (min-width: 48rem) {
  .phone {
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    overflow: hidden;
    min-height: 0;
    margin: var(--sp-5) auto var(--sp-7);
    box-shadow: var(--shadow-3);
  }
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .035), rgba(255, 255, 255, 0)),
    var(--bg);
  position: relative;
}

/* ---- brand lockup: mark, wordmark, programme eyebrow */

.brand {
  display: inline-flex;
  align-items: center;
  gap: .625rem;
  min-width: 0;
  text-decoration: none;
  color: inherit;
  border-radius: var(--r-sm);
  padding: 2px;
  margin: -2px;
  transition: opacity var(--dur) var(--ease);
}
a.brand:hover { opacity: .82; }
a.brand:active { opacity: .7; }

.brand-mark {
  flex: 0 0 auto;
  border-radius: 9px;
  box-shadow: 0 2px 8px -2px rgba(0, 0, 0, .7), inset 0 0 0 1px rgba(255, 255, 255, .07);
}

.brand-lines {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.1;
}
.brand-word {
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.brand-eyebrow {
  font-size: .625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .13em;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

/* The lockup already names the programme, so the breadcrumb is desktop-only —
   on a 360px screen those pixels belong to the content. */
.crumbs {
  display: none;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  min-width: 0;
  padding-left: var(--sp-3);
  margin-left: var(--sp-1);
  border-left: 1px solid var(--line);
}
.crumbs a { text-decoration: none; }
.crumb-root { color: var(--faint); }
.crumb-sep { color: var(--faint); }
.crumb-leaf {
  font-weight: 600;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tb-act {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-shrink: 0;
  margin-left: auto;
}
.tb-act form { margin: 0; display: inline-flex; }

.icon-btn,
.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: var(--fs-xs);
  text-decoration: none;
  flex-shrink: 0;
}

.icon-btn {
  color: var(--muted);
  border: 1px solid var(--line);
  background: var(--surface);
  font-family: inherit;
  font-weight: 600;
  cursor: pointer;
  position: relative;
  padding: 0;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    background-color var(--dur) var(--ease);
}
.icon-btn:hover { color: var(--ink); border-color: var(--accent); background: var(--surface-2); }
.icon-btn:active { background: var(--surface-3); }

/* Keeps the 34px look but gives the control a 44px hit area on touch. */
.icon-btn::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
}

.avatar {
  background: linear-gradient(150deg, var(--hero-b), var(--surface-3));
  border: 1px solid var(--line-2);
  font-size: var(--fs-2xs);
  font-weight: 700;
  color: var(--ink);
  letter-spacing: .02em;
}

.wrap {
  padding: var(--sp-4) var(--sp-4) var(--sp-6);
  flex: 1 1 auto;
  min-width: 0;
}

/* ------------------------------------------------------------ hero */

.hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-md);
  padding: var(--sp-5) var(--sp-4) var(--sp-5);
  background:
    radial-gradient(120% 140% at 100% 0%, rgba(95, 191, 141, .30), transparent 58%),
    linear-gradient(152deg, var(--hero-a) 0%, #1A4034 46%, var(--hero-b) 100%);
  border: 1px solid rgba(95, 191, 141, .16);
  box-shadow: var(--shadow-2), var(--hairline);
  margin-bottom: var(--sp-3);
}
.hero-deco {
  position: absolute;
  right: -70px;
  top: -40px;
  width: 260px;
  height: 260px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #63C598, #3E9E72 45%, transparent 70%);
  opacity: .30;
  pointer-events: none;
}
.hero-hi {
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: var(--lh-heading);
  margin-bottom: var(--sp-4);
  position: relative;
  overflow-wrap: anywhere;
}
.hero-cards {
  display: grid;
  gap: var(--sp-3);
  position: relative;
}
.hcard {
  background: rgba(9, 20, 16, .34);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--r-sm);
  padding: var(--sp-4);
  min-width: 0;
  box-shadow: var(--hairline);
  backdrop-filter: blur(2px);
}
.hcard-t {
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: #A9CFBC;
  margin-bottom: var(--sp-2);
}
.hcard-points {
  display: flex;
  align-items: center;
  gap: .4rem;
  font-size: var(--fs-2xl);
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--sp-2);
}
.hcard-sub { font-size: var(--fs-sm); color: #C8D4CE; line-height: 1.45; }
.hcard-note { font-size: var(--fs-xs); color: var(--warn); margin-top: var(--sp-2); }

/* ------------------------------------------------------------ guide strip */

.guide {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-bottom: var(--sp-5);
  text-decoration: none;
  min-height: var(--tap);
  box-shadow: var(--shadow-1);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}
.guide > * { min-width: 0; }
.guide strong { color: var(--ink); }
.guide span:last-child { color: var(--accent); font-weight: 600; }
.guide:hover { border-color: var(--accent); background: var(--surface-2); }
.guide:active { transform: translateY(1px); }

/* ------------------------------------------------------------ tabs */

.tabs {
  display: flex;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-5);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--muted);
  white-space: nowrap;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: none;
  border-top: 0;
  border-left: 0;
  border-right: 0;
  font-family: inherit;
  cursor: pointer;
  text-decoration: none;
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* three tabs, one thumb: they share the width on a phone rather than
     huddling in the left corner. */
  flex: 1 1 auto;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.tab:hover { color: var(--ink); }
.tab:active { color: var(--accent); }
.tab.on,
.tab[aria-current="page"] {
  color: var(--ink);
  font-weight: 700;
  border-bottom-color: var(--accent);
}

/* ------------------------------------------------------------ admin nav */

.adminnav {
  display: flex;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-5);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.adminnav::-webkit-scrollbar { display: none; }

.adminnav a {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: var(--sp-3) var(--sp-3);
  min-height: 46px;
  font-size: var(--fs-sm);
  color: var(--muted);
  white-space: nowrap;
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.adminnav a:hover { color: var(--ink); }
.adminnav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 700;
  border-bottom-color: var(--accent);
}

.badge {
  display: inline-block;
  min-width: 1.35rem;
  padding: .05rem .35rem;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  color: var(--ink);
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-align: center;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
}
.badge-warn { background: var(--warn-bg); color: var(--warn); }
.badge-info { background: var(--info-bg); color: var(--info-ink); }

/* ------------------------------------------------------------ cards */

.grid { display: grid; gap: var(--sp-4); }

.card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 0;
}
.card-art {
  position: relative;
  background:
    radial-gradient(120% 120% at 50% 0%, rgba(95, 191, 141, .10), transparent 60%),
    var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  min-height: 148px;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  overflow: hidden;
  box-shadow: var(--shadow-1), var(--hairline);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.card:hover .card-art { border-color: var(--line-2); }
.card-art .pill { position: absolute; top: var(--sp-2); right: var(--sp-2); }
.card-label {
  position: absolute;
  top: var(--sp-2);
  left: var(--sp-3);
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--faint);
}
.card-name {
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1.35;
  overflow-wrap: anywhere;
}
.card-desc { font-size: var(--fs-sm); color: var(--muted); line-height: 1.5; }

.pill {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: rgba(0, 0, 0, .62);
  border: 1px solid rgba(255, 255, 255, .13);
  border-radius: var(--r-pill);
  padding: .22rem .6rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  backdrop-filter: blur(3px);
}
.dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  box-shadow: 0 0 0 3px rgba(95, 191, 141, .16);
}
.dot-warn { background: var(--warn); box-shadow: 0 0 0 3px rgba(220, 168, 78, .16); }
.dot-danger { background: var(--danger); box-shadow: 0 0 0 3px rgba(224, 120, 95, .16); }
.dot-faint { background: var(--faint); box-shadow: none; }

/* ------------------------------------------------------------ buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  padding: var(--sp-3) var(--sp-5);
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--surface-2);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  min-height: var(--tap);
  text-decoration: none;
  text-align: center;
  box-shadow: var(--shadow-1);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.btn:hover { border-color: var(--accent); background: var(--surface-3); }
.btn:active { transform: translateY(1px); box-shadow: none; }
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
.btn:disabled:hover,
.btn[aria-disabled="true"]:hover { border-color: var(--line-2); background: var(--surface-2); }

.btn-primary {
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-d) 100%);
  border-color: var(--accent-d);
  color: #08201A;
  font-weight: 700;
  box-shadow: var(--shadow-2), inset 0 1px 0 rgba(255, 255, 255, .22);
}
.btn-primary:hover {
  background: linear-gradient(180deg, #6FCB9A 0%, #46A97B 100%);
  border-color: var(--accent);
}
.btn-primary:active { box-shadow: inset 0 1px 3px rgba(0, 0, 0, .3); }
.btn-primary:disabled,
.btn-primary[aria-disabled="true"] { box-shadow: none; }
.btn-primary:disabled:hover,
.btn-primary[aria-disabled="true"]:hover {
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-d) 100%);
  border-color: var(--accent-d);
}

.btn-sm { padding: .4rem var(--sp-3); min-height: var(--tap); font-size: var(--fs-xs); }
.btn-pill { border-radius: var(--r-pill); }
.btn-danger {
  border-color: var(--bad-line);
  color: var(--danger);
  background: var(--bad-bg);
}
.btn-danger:hover { border-color: var(--danger); background: #472B26; }
.btn-danger:focus-visible { outline-color: var(--danger); box-shadow: var(--ring-danger); }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }

/* Busy: portal.js / admin.js set disabled + aria-busy on submit, and swap in
   data-loading-text. This is the visible half of that contract — a spinner in
   front of the label so the control obviously did something. */
.btn[aria-busy="true"] {
  opacity: 1;
  cursor: progress;
  color: transparent;
  position: relative;
  pointer-events: none;
}
.btn[aria-busy="true"]::before {
  content: '';
  position: absolute;
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-right-color: transparent;
  color: var(--ink);
  opacity: .95;
  animation: spin .62s linear infinite;
}
.btn-primary[aria-busy="true"]::before { color: #08201A; }
.btn-danger[aria-busy="true"]::before { color: var(--danger); }

@keyframes spin { to { transform: rotate(360deg); } }

.linkbtn {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
  border-radius: var(--r-sm);
}
.linkbtn[aria-busy="true"] { opacity: .6; cursor: progress; }

.hint { font-size: var(--fs-xs); color: var(--faint); margin-top: var(--sp-1); line-height: 1.5; }
.hint-error { color: var(--danger); }

/* ------------------------------------------------------------ tables */

.tablewrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow-1);
}

table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
th {
  text-align: left;
  padding: var(--sp-3);
  background: var(--surface-2);
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--faint);
  font-weight: 700;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
td {
  padding: var(--sp-3);
  border-top: 1px solid var(--line);
  vertical-align: top;
  line-height: 1.5;
}
tbody tr:first-child td { border-top: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.nowrap, th.nowrap { white-space: nowrap; }
tbody tr { transition: background-color var(--dur) var(--ease); }
tbody tr:hover td { background: rgba(255, 255, 255, .028); }
caption {
  caption-side: top;
  text-align: left;
  padding: var(--sp-3);
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--faint);
  font-weight: 700;
  border-bottom: 1px solid var(--line);
}

/* ------------------------------------------------------------ empty states */

.empty {
  color: var(--faint);
  text-align: center;
  padding: var(--sp-6) var(--sp-4);
  font-size: var(--fs-sm);
}
td.empty { border-top: 1px solid var(--line); }

.empty-state {
  position: relative;
  border: 1px dashed var(--line-2);
  border-radius: var(--r-md);
  padding: var(--sp-6) var(--sp-5);
  text-align: center;
  color: var(--faint);
  font-size: var(--fs-sm);
  line-height: 1.55;
  background:
    radial-gradient(90% 120% at 50% 0%, rgba(95, 191, 141, .05), transparent 62%),
    var(--surface);
}
/* A quiet mark rather than an illustration: it says "nothing here yet" without
   pretending to be a picture. */
.empty-state::before {
  content: '';
  display: block;
  width: 34px;
  height: 34px;
  margin: 0 auto var(--sp-3);
  border-radius: 50%;
  border: 2px dashed var(--line-2);
  opacity: .9;
}
.empty-state strong {
  display: block;
  color: var(--muted);
  font-size: var(--fs-lg);
  font-weight: 600;
  margin-bottom: var(--sp-1);
  letter-spacing: 0;
}
/* A call to action inside an empty state gets its own line — inline-flex would
   leave it stranded mid-sentence. */
.empty-state .btn {
  display: flex;
  width: fit-content;
  margin: var(--sp-4) auto 0;
}

/* ------------------------------------------------------------ tags */

.tag {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .2rem .5rem .2rem .45rem;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  white-space: nowrap;
  line-height: 1.5;
  background: var(--surface-3);
  color: var(--muted);
  vertical-align: middle;
}
/* The status dot carries the meaning at a glance in a dense queue; the word
   carries it for anyone who cannot see colour. */
.tag::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
  opacity: .95;
}

.tag-new,
.tag-pending,
.tag-queued,
.tag-signup {
  background: var(--info-bg);
  color: var(--info-ink);
  border-color: rgba(127, 196, 232, .22);
}

.tag-contacted,
.tag-invited,
.tag-pending_approval,
.tag-pending-approval,
.tag-awaiting {
  background: var(--warn-bg);
  color: var(--warn);
  border-color: rgba(220, 168, 78, .24);
}

.tag-processing,
.tag-fulfilled,
.tag-approved,
.tag-joined,
.tag-active,
.tag-sent,
.tag-allowlist {
  background: var(--ok-bg);
  color: var(--accent);
  border-color: rgba(95, 191, 141, .24);
}

.tag-rejected,
.tag-cancelled,
.tag-failed,
.tag-disabled {
  background: var(--bad-bg);
  color: var(--danger);
  border-color: var(--bad-line);
}

/* ------------------------------------------------------------ sections & panels */

.section-h {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: var(--track-caps);
  color: var(--faint);
  font-weight: 700;
  margin: var(--sp-6) 0 var(--sp-3);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
/* A hairline that runs out from the label to the edge — cheap, and it makes a
   long admin page read as sections rather than one column of stuff. */
.section-h::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg, var(--line), transparent);
}

.page-title {
  font-size: var(--fs-xl);
  margin-bottom: var(--sp-4);
  line-height: var(--lh-tight);
}
.panel-title { font-size: var(--fs-lg); font-weight: 600; margin-bottom: var(--sp-2); }

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-4);
  box-shadow: var(--shadow-1), var(--hairline);
}
.panel + .panel { margin-top: var(--sp-4); }

.stat-row { display: flex; flex-wrap: wrap; gap: var(--sp-5); }
.stat { min-width: 5.5rem; }
.stat .v {
  font-size: var(--fs-2xl);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.stat .v.warn { color: var(--warn); }
.stat .v.accent { color: var(--accent); }
.stat .k {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--faint);
  font-weight: 700;
  margin-top: var(--sp-2);
}
.stat a { text-decoration: none; }
.stat a:hover .v { color: var(--accent); }

.mono { font-family: var(--mono); font-size: var(--fs-xs); overflow-wrap: anywhere; }

.rowuser { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.rowuser .avatar { width: 28px; height: 28px; font-size: .625rem; }

.kv { display: grid; grid-template-columns: 1fr; gap: 0 var(--sp-3); font-size: var(--fs-sm); margin: 0; }
.kv dt {
  color: var(--faint);
  text-transform: uppercase;
  font-size: var(--fs-2xs);
  letter-spacing: .06em;
  font-weight: 700;
}
.kv dd { margin: 0 0 var(--sp-3); overflow-wrap: anywhere; }

.thumbs { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.thumbs a {
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
  line-height: 0;
  transition: border-color var(--dur) var(--ease);
}
.thumbs a:hover { border-color: var(--accent); }
.thumbs img { display: block; width: 72px; height: 72px; object-fit: cover; }

/* ------------------------------------------------------------ flash */

.flash {
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  line-height: 1.5;
  border: 1px solid var(--line);
  border-left-width: 3px;
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  background: var(--surface);
  color: var(--muted);
  box-shadow: var(--shadow-1);
}
.flash p { min-width: 0; overflow-wrap: anywhere; }
.flash-success { background: #1b2f24; border-color: #2f5a41; border-left-color: var(--accent); color: #9FE0BC; }
.flash-error { background: var(--bad-bg); border-color: var(--bad-line); border-left-color: var(--danger); color: #F0A08C; }
.flash-warn { background: var(--warn-bg); border-color: #4A3D1F; border-left-color: var(--warn); color: #E3C877; }
.flash-info { background: #1c2a33; border-color: #2c4353; border-left-color: var(--info-ink); color: #9FC8E0; }

.flash-dismiss {
  margin-left: auto;
  flex-shrink: 0;
  background: none;
  border: 0;
  color: inherit;
  opacity: .65;
  font-size: 1.125rem;
  line-height: 1;
  cursor: pointer;
  padding: var(--sp-1) .35rem;
  min-width: 34px;
  min-height: 34px;
  border-radius: var(--r-sm);
  font-family: inherit;
  transition: opacity var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.flash-dismiss:hover { opacity: 1; background: rgba(255, 255, 255, .06); }

/* ------------------------------------------------------------ auth screens */

.authwrap { max-width: 24rem; margin: 0 auto; padding: var(--sp-6) var(--sp-5) var(--sp-7); width: 100%; }

/* layout.js already puts the auth screens inside .authwrap. If a view wraps its
   own content in it as well, the inner one must not double the padding. */
.authwrap .authwrap { max-width: none; margin: 0; padding: 0; }

/* The lockup layout.js renders above the sign-in card: mark over wordmark,
   centred, so the first thing a phone camera lands on is the brand. */
.authmark { display: flex; justify-content: center; margin-bottom: var(--sp-4); }
.authmark .brand { flex-direction: column; gap: var(--sp-3); text-align: center; }
.authmark .brand-lines { align-items: center; }
.authmark .brand-word { font-size: 1.25rem; }
.authmark .brand-eyebrow { font-size: var(--fs-2xs); letter-spacing: .16em; }
.authmark .brand-mark { border-radius: 13px; box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .9), inset 0 0 0 1px rgba(255, 255, 255, .08); }

/* layout.js renders the lockup above every auth screen, and the views under it
   open with their own "Ideals · Precision Series" eyebrow. Two of them stacked
   on one card reads as a mistake, so the lockup wins and the echo is
   suppressed — no information is lost, those words are still the first thing on
   the page, one line higher and set properly. */
.authmark ~ .authbrand .eyebrow { display: none; }
.authmark ~ .authbrand h1 { margin-top: 0; font-size: var(--fs-2xl); }

.authbrand { text-align: center; margin-bottom: var(--sp-5); }
.eyebrow {
  font-size: var(--fs-2xs);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}
.authbrand h1 { font-size: var(--fs-xl); margin-top: var(--sp-2); }
.authbrand p { color: var(--muted); font-size: var(--fs-md); margin-top: var(--sp-2); line-height: 1.5; }
.authcard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-5) var(--sp-4);
  box-shadow: var(--shadow-2), var(--hairline);
}

/* ------------------------------------------------------------ forms */

label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  margin-bottom: var(--sp-1);
  color: var(--ink);
}

input[type=text],
input[type=email],
input[type=password],
input[type=number],
input[type=search],
input[type=date],
select,
textarea {
  width: 100%;
  padding: var(--sp-3);
  font-family: var(--font);
  font-size: 16px;               /* 16px stops iOS zooming the viewport on focus */
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--ink);
  min-height: var(--tap);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .28);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
textarea { line-height: 1.5; resize: vertical; }

input::placeholder, textarea::placeholder { color: var(--faint); }
input:hover, select:hover, textarea:hover { border-color: #4A545D; }
input:focus, select:focus, textarea:focus { background: var(--surface-3); }
input:disabled, select:disabled, textarea:disabled {
  opacity: .55;
  cursor: not-allowed;
  background: var(--surface);
}

input[type=file] {
  width: 100%;
  font-family: var(--font);
  font-size: var(--fs-sm);
  color: var(--muted);
  padding: var(--sp-2);
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  min-height: var(--tap);
}
input[type=file]::file-selector-button {
  font-family: var(--font);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--ink);
  background: var(--surface-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  padding: var(--sp-2) var(--sp-3);
  margin-right: var(--sp-3);
  min-height: 36px;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
input[type=file]::file-selector-button:hover { border-color: var(--accent); }

input[type=checkbox], input[type=radio] {
  width: 20px;
  height: 20px;
  accent-color: var(--accent-d);
  vertical-align: middle;
}

[aria-invalid="true"] { border-color: var(--danger) !important; }
[aria-invalid="true"]:focus-visible { outline-color: var(--danger); box-shadow: var(--ring-danger); }

.field { margin-bottom: var(--sp-4); }
.field:last-child { margin-bottom: 0; }
.field-err { font-size: var(--fs-xs); color: var(--danger); margin-top: var(--sp-1); font-weight: 600; }

.checkline { display: flex; align-items: flex-start; gap: var(--sp-2); min-height: var(--tap); }
.checkline label { margin: 0; font-weight: 400; font-size: var(--fs-sm); color: var(--muted); line-height: 1.45; }

.dropzone {
  border: 1px dashed var(--line-2);
  border-radius: var(--r-sm);
  padding: var(--sp-5);
  text-align: center;
  color: var(--faint);
  font-size: var(--fs-sm);
  background: rgba(255, 255, 255, .015);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.dropzone:hover { border-color: var(--accent); background: rgba(95, 191, 141, .04); }
.dropzone:focus-within { border-color: var(--accent); }
.dropzone input[type=file] { margin-top: var(--sp-3); text-align: left; }

fieldset { border: 0; padding: 0; margin: 0 0 var(--sp-4); }
legend { padding: 0; font-size: var(--fs-sm); font-weight: 600; margin-bottom: var(--sp-1); }

/* ------------------------------------------------------------ filter bar */

.filterbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: flex-end;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-5);
  box-shadow: var(--shadow-1);
}
.filterbar .field { margin-bottom: 0; flex: 1 1 9rem; min-width: 0; }
.filterbar label {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--faint);
  font-weight: 700;
}
.filterbar .btn { flex: 0 0 auto; }

/* ------------------------------------------------------------ pagination */

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
}
.pagination .page-of {
  font-size: var(--fs-xs);
  color: var(--faint);
  margin-right: auto;
  font-variant-numeric: tabular-nums;
}
.pagination a,
.pagination .current,
.pagination .disabled {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0 var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  color: var(--ink);
  background: var(--surface-2);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.pagination a:hover { border-color: var(--accent); background: var(--surface-3); }
.pagination a:active { transform: translateY(1px); }
.pagination .current {
  background: var(--accent-d);
  border-color: var(--accent-d);
  color: #08201A;
  font-weight: 700;
}
.pagination .disabled { opacity: .35; color: var(--faint); background: transparent; }

/* ------------------------------------------------------------ modal */

.modal-root {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: grid;
  place-items: center;
  background: rgba(6, 9, 11, .74);
  padding: var(--sp-5);
  overflow-y: auto;
  backdrop-filter: blur(3px);
}
.modal-root[hidden] { display: none; }

.modal {
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  width: 100%;
  max-width: 29rem;
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: var(--shadow-3), var(--hairline);
}
.modal h2 { font-size: var(--fs-lg); margin-bottom: var(--sp-1); padding-right: 2.5rem; }
.modal-help { font-size: var(--fs-sm); color: var(--muted); margin-bottom: var(--sp-4); line-height: 1.5; }
.modal-close {
  float: right;
  background: none;
  border: none;
  color: var(--faint);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
  min-width: var(--tap);
  min-height: var(--tap);
  border-radius: var(--r-sm);
  margin: -.5rem -.5rem 0 0;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.modal-close:hover { color: var(--ink); background: rgba(255, 255, 255, .06); }

/* Set on <body> while a modal is open — no inline styles, the CSP forbids them. */
body.modal-open { overflow: hidden; }

/* ------------------------------------------------------------ callout */

.callout {
  background: #12241f;
  border: 1px solid #2a4a3c;
  border-left: 3px solid var(--accent);
  border-radius: var(--r-sm);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: #B8D6C7;
  margin-bottom: var(--sp-5);
}
.callout strong { color: var(--accent); }
.callout p + p { margin-top: var(--sp-2); }

.callout-warn {
  background: #2C2415;
  border-color: #4A3D1F;
  border-left-color: var(--warn);
  color: #E3C877;
}
.callout-warn strong { color: #F5DC96; }

.callout-danger {
  background: var(--bad-bg);
  border-color: var(--bad-line);
  border-left-color: var(--danger);
  color: #F0A08C;
}
.callout-danger strong { color: var(--danger); }

/* ------------------------------------------------------------ footer */

.foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  justify-content: center;
  align-items: center;
  padding: var(--sp-4) var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line);
  font-size: var(--fs-xs);
  background: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, .18));
}
.foot form { margin: 0; display: inline-flex; }
.foot a,
.foot .linkbtn {
  color: var(--faint);
  text-decoration: none;
  font-size: var(--fs-xs);
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--sp-1);
  transition: color var(--dur) var(--ease);
}
.foot a:hover,
.foot .linkbtn:hover { color: var(--ink); }
.foot a[aria-current="page"] { color: var(--muted); font-weight: 600; }

/* ------------------------------------------------------------ long-form copy */

.prose { max-width: 42rem; }
.prose h2 { font-size: var(--fs-lg); margin: var(--sp-6) 0 var(--sp-2); }
.prose h3 { font-size: var(--fs-base); margin: var(--sp-5) 0 var(--sp-1); }
.prose p { color: var(--muted); font-size: var(--fs-md); margin: var(--sp-2) 0; line-height: 1.65; }
.prose ul, .prose ol { color: var(--muted); font-size: var(--fs-md); padding-left: 1.15rem; margin: var(--sp-2) 0; line-height: 1.65; }
.prose li { margin: var(--sp-1) 0; }
.prose li::marker { color: var(--faint); }
.prose strong { color: var(--ink); }
.prose a { color: var(--accent); text-underline-offset: 2px; }
.prose a:hover { color: #7FD3AA; }
.prose code { font-family: var(--mono); font-size: var(--fs-sm); color: var(--accent); }

.list { color: var(--muted); font-size: var(--fs-md); padding-left: 1.1rem; margin: var(--sp-2) 0; line-height: 1.6; }
.list li { margin: var(--sp-1) 0; }
.list li::marker { color: var(--faint); }

/* ------------------------------------------------------------ error page

   Served by http/respond.js with no layout and no client script, so everything
   it needs is here: the mark is drawn as a background image rather than markup.
   Same geometry as views/icons.js brandMark(); if that changes, change this.   */

.page-error {
  display: grid;
  place-items: center;
  min-height: 100vh;
  background:
    radial-gradient(70% 60% at 50% 0%, rgba(31, 74, 60, .55), transparent 70%),
    var(--bg);
}
@supports (min-height: 100dvh) {
  .page-error { min-height: 100dvh; }
}
.page-error .wrap {
  max-width: 32rem;
  margin: 0 auto;
  padding: var(--sp-7) var(--sp-5);
  text-align: center;
  flex: 0 1 auto;
}
.page-error .wrap::before {
  content: '';
  display: block;
  width: 52px;
  height: 52px;
  margin: 0 auto var(--sp-5);
  border-radius: 15px;
  box-shadow: 0 12px 32px -14px rgba(0, 0, 0, .9), inset 0 0 0 1px rgba(255, 255, 255, .08);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='9' fill='%2314342C'/%3E%3Cpath d='M16 3.4 28.6 16 16 28.6 3.4 16Z' fill='%231F4A3C'/%3E%3Cpath d='M16 7.6 24.4 16 16 24.4 7.6 16Z' fill='%233E9E72'/%3E%3Ccircle cx='16' cy='16' r='4.3' fill='%235FBF8D'/%3E%3Ccircle cx='16' cy='16' r='1.65' fill='%230E2620'/%3E%3C/svg%3E");
  background-size: cover;
}
.page-error h1 { font-size: var(--fs-2xl); margin: var(--sp-2) 0 var(--sp-3); }
.page-error .muted { font-size: var(--fs-md); line-height: 1.6; }
.page-error .btn { margin-top: var(--sp-5); }

/* ------------------------------------------------------------ utilities

   The CSP forbids style attributes, so the handful of one-off adjustments the
   prototype expressed inline live here instead. Keep this list short.        */

.muted { color: var(--muted); }
.faint { color: var(--faint); }
.accent { color: var(--accent); }
.warn { color: var(--warn); }
.danger { color: var(--danger); }
.strong { font-weight: 700; }
.small { font-size: var(--fs-sm); }

.u-full { width: 100%; }
.u-center { text-align: center; }
.u-right { text-align: right; }
.u-grow { flex: 1 1 auto; }
.u-nowrap { white-space: nowrap; }
.u-break { overflow-wrap: anywhere; }

.u-mt-0 { margin-top: 0; }
.u-mt-sm { margin-top: var(--sp-2); }
.u-mt { margin-top: var(--sp-4); }
.u-mt-lg { margin-top: var(--sp-6); }
.u-mb-0 { margin-bottom: 0; }
.u-mb-sm { margin-bottom: var(--sp-2); }
.u-mb { margin-bottom: var(--sp-4); }
.u-mb-lg { margin-bottom: var(--sp-6); }

.stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.stack-sm { display: flex; flex-direction: column; gap: var(--sp-2); }
.row { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center; }
.row-between { display: flex; flex-wrap: wrap; gap: var(--sp-4); align-items: center; justify-content: space-between; }

/* ------------------------------------------------------------ breakpoints */

/* A concierge queue crushed into 360px turns an attendee's name into one
   letter per line. Give the admin tables a floor and let .tablewrap scroll —
   that is what it is for. The attendee tables are three short columns and read
   perfectly at 360, so they are left alone. */
@media (max-width: 40rem) {
  .page-admin .tablewrap table { min-width: 30rem; }

  /* The attendee's own submissions table used to be three short words per row
     and fitted 360 comfortably. It now carries a second line under the activity
     name — the post link, or "1 photo uploaded", or who was invited — and auto
     layout answers that by widening the first column until Points is pushed off
     the right-hand edge. .tablewrap scrolls, so nothing is lost, but a points
     column you have to swipe sideways to see is the wrong column to hide on the
     one screen that is entirely about points.

     Fixed layout with declared proportions makes the three columns share the
     width they actually have. Everything wraps rather than truncating, because
     the long values here — a URL, a colleague's address — are exactly the ones
     that must break anywhere. */
  .page-portal .tablewrap table { table-layout: fixed; width: 100%; }
  .page-portal .tablewrap th,
  .page-portal .tablewrap td {
    padding: var(--sp-3) var(--sp-2);
    overflow-wrap: anywhere;
  }
  .page-portal .tablewrap th:first-child,
  .page-portal .tablewrap td:first-child { width: 50%; }
  .page-portal .tablewrap th:last-child,
  .page-portal .tablewrap td:last-child { width: 22%; }
  .page-portal .tablewrap th { white-space: normal; }
}

/* Small phones: 360px is the design floor. Nothing may overflow it. */
@media (max-width: 22.5rem) {
  .brand-word { font-size: 1rem; }
  .wrap { padding: var(--sp-3) var(--sp-3) var(--sp-6); }
  .hero { padding: var(--sp-4) var(--sp-3); }
  .tab { padding: var(--sp-3) var(--sp-2); font-size: var(--fs-sm); }
  .stat-row { gap: var(--sp-4); }
}

@media (min-width: 40rem) {
  .crumbs { display: flex; }
  .hero-cards { grid-template-columns: 1fr 1fr; }
  .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .wrap { padding: var(--sp-5) var(--sp-5) var(--sp-6); }
  .kv { grid-template-columns: 12rem 1fr; }
  .kv dd { margin-bottom: var(--sp-1); }
  .cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-4); }
  .hero { padding: var(--sp-6) var(--sp-5); }
  .hero-hi { font-size: var(--fs-xl); }
  .panel { padding: var(--sp-5); }
  .authcard { padding: var(--sp-5); }
  .tab { flex: 0 0 auto; }
}

/* Compact buttons are only shrunk where a mouse is driving them. */
@media (min-width: 40rem) and (pointer: fine) {
  .btn-sm { min-height: 32px; }
  .icon-btn::after { inset: 0; }
}

/* ------------------------------------------------------------ motion */

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
  /* The spinner cannot spin, so the busy button says so with a solid ring
     instead of vanishing into nothing. */
  .btn[aria-busy="true"] { color: inherit; opacity: .6; }
  .btn[aria-busy="true"]::before { display: none; }
}
