/* ═══════════════════════════════════════════════════════════
   SPOTTAP — the club check-in app
   Floodlit Signage on Night Black: house blue on cold blue-black,
   Archivo for display, JetBrains Mono for anything tabular.
   Same tokens the owner panel wears — see docs/BRAND.md.
   ═══════════════════════════════════════════════════════════ */

/* ── Self-hosted fonts (no third-party requests). Two faces, both
   variable: Archivo carries weight and width, JetBrains Mono the
   figures and the tracked kickers. ── */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url('/fonts/archivo.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('/fonts/jetbrains-mono.woff2') format('woff2');
}

:root {
  /* Night Black. Cold on purpose: #0A0C11 is a blue-black, and the
     warm black this replaced was chosen when the accent was orange.
     A warm ground under a cool accent is what makes a palette look
     accidental. */
  --bg:      #0A0C11;
  --bg-2:    #111520;
  --surface: #111520;
  --raised:  #1D2433;
  --line:    rgba(222, 231, 247, 0.13);
  /* --house is SpotTap's own and never moves. --volt is the working
     accent: identical by default, replaced by a Pro club's colour. */
  --house:   #3D74FF;
  --volt:    #3D74FF;
  --volt-2:  #2457EA;
  --on-volt: #FFFFFF;
  --cobalt:  #5B8CFF;
  /* A runner who ran but could not verify, asking a captain to confirm them.
     Louder than pending because someone is waiting on an answer. */
  --amber:   #F2E85C;
  --red:     #E23B5A;
  --green:   #16A06B;
  --text:    #DEE7F7;
  --muted:   rgba(222, 231, 247, 0.58);
  --faint:   rgba(224, 232, 245, 0.40);
  --mono-xs: 0.6875rem;
  --font-display: 'Archivo', 'Arial Black', sans-serif;
  --font-body: 'Archivo', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, monospace;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ── The two light grounds ──────────────────────────────────────────────────
   A Pro club may put its members on Morning or Afternoon instead. The owner
   picks one for the whole club in the panel, so this is server-rendered onto
   the body — there is nothing for a member to choose and no script involved.

   Night is :root above, and stays the no-attribute default: a Standard club,
   or a Pro club that never chose, renders exactly as before.

   Only the ground and its neutrals move. --volt is the club's own colour and
   is written inline on the body, so it survives the switch untouched; what
   changes is --volt-ink, the readable-as-text version, computed per ground
   in html.js. Values are Morning Grey and Afternoon Cream from the brand
   book — the same the panel wears. */
body[data-ground="morning"] {
  --bg:      #EEF0F4;
  --bg-2:    #FAFBFD;
  --surface: #FAFBFD;
  --raised:  #FFFFFF;
  --line:    #D9DEE6;
  --text:    #0F1318;
  --muted:   #4F5866;
  --faint:   #626C7A;
  --on-volt: #FFFFFF;
  --volt-ink: #1B4DE4;
  --cobalt:  #2F55C4;
  --amber:   #8A6318;
  --red:     #B0322A;
  --green:   #23744F;
}
body[data-ground="afternoon"] {
  --bg:      #F7F4ED;
  --bg-2:    #FFFFFF;
  --surface: #FFFFFF;
  --raised:  #FFFFFF;
  --line:    #E8E2D6;
  --text:    #17140F;
  --muted:   #575144;
  --faint:   #6E6757;
  --on-volt: #FFFFFF;
  --volt-ink: #1B4DE4;
  --cobalt:  #2F55C4;
  --amber:   #6B4C0C;
  --red:     #8A2A1C;
  --green:   #2C6B45;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  line-height: 1.6;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
::selection { background: var(--volt); color: var(--on-volt); }
:focus-visible { outline: 2px solid var(--volt); outline-offset: 3px; }

/* Film grain over everything */
.grain {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 90;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── Chrome ── */
.topbar {
  display: flex; justify-content: center;
  padding: 1.2rem 1.25rem 0;
  position: relative;
}
/* Sign in / profile button: right edge on wide screens, tucked under the
   brand on phones where the big wordmark needs the full width. */
.auth-btn {
  position: absolute;
  right: 1.25rem; top: 50%;
  transform: translateY(-50%);
}
.brand-short { display: none; }
@media (max-width: 640px) {
  .topbar { justify-content: space-between; align-items: center; gap: 0.6rem; }
  .brand { font-size: 1.8rem; white-space: nowrap; }
  .brand-full { display: none; }
  .brand-short { display: inline; }
  .auth-btn { position: static; transform: none; white-space: nowrap; flex: none; }
}
/* Volt while its panel is open; muted pill when closed. Touch screens keep
   hover styles stuck after a tap, so neutralise that for the closed state. */
.auth-btn.is-open { border-color: var(--volt); color: var(--volt); }
@media (hover: none) {
  .auth-btn:not(.is-open):hover { border-color: rgba(255, 255, 255, 0.32); color: var(--muted); transform: none; }
}
.auth-panel { margin-bottom: 1.4rem; }
/* PIN inputs get an eye inside the box to show/hide what's typed. */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right: 2.6rem; }
.pw-eye {
  position: absolute;
  right: 0.3rem; top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  color: var(--muted);
  padding: 0.45rem;
  cursor: pointer;
  display: flex; align-items: center;
}
.pw-eye:hover { color: var(--volt); }
.pw-eye:focus-visible { color: var(--volt); outline: 2px solid var(--volt); outline-offset: 2px; border-radius: 6px; }
.brand {
  font-family: var(--font-display);
  font-size: clamp(2rem, 8vw, 2.6rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
/* Was a rotated script face — a handwriting accent in a software system reads
   as craft-fair. It keeps its job — the word in a heading that carries the
   colour — in the display face instead:
   no rotation, no second family, just the accent doing the emphasis. */
.script-accent {
  font-family: inherit;
  color: var(--volt);
  text-transform: inherit;
  letter-spacing: inherit;
  font-size: inherit;
  line-height: inherit;
}

/* The old display face had one weight, so every slot inherited 400 and looked right.
   Archivo is variable: it has to be told to be heavy, once, here — rather than
   chasing the fifteen selectors that ask for --font-display. */
h1, h2, h3, .tile b, .kicker {
  font-weight: 800;
  font-stretch: 108%;
  letter-spacing: -0.02em;
}
/* Numbers are the product. Tabular everywhere they sit in a column or tick up. */
.tile b, .num, table td, table th {
  font-variant-numeric: tabular-nums;
}
.foot-site a { color: var(--cobalt); text-decoration: none; }
.foot-site a:hover { text-decoration: underline; text-underline-offset: 4px; }
.foot {
  text-align: center;
  font-size: var(--mono-xs);
  letter-spacing: 0.28em;
  color: rgba(222, 231, 247, 0.45);
  padding: 2.5rem 1rem 2rem;
}
.foot-credit { margin-top: 0.5rem; letter-spacing: 0.18em; color: var(--volt); text-transform: uppercase; }
.foot-credit a { color: var(--volt); text-underline-offset: 3px; }
.foot-credit a:hover { text-decoration-thickness: 2px; }

.wrap { max-width: 460px; margin: 0 auto; padding: 0 1.25rem 2rem; }
.wrap.wide { max-width: 1080px; }

/* ── Admin dashboard ── */
.admin-head {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 1rem; flex-wrap: wrap;
  padding: 1.6rem 0 1.3rem;
}
.admin-head .kicker { margin-bottom: 0.35rem; }
.admin-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.8rem;
  margin-bottom: 1rem;
}
.tile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 1rem 1.2rem;
}
.tile b {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 2.1rem;
  line-height: 1;
  margin-bottom: 0.35rem;
  font-variant-numeric: tabular-nums;
}
.tile span { font-size: var(--mono-xs); letter-spacing: 0.18em; color: var(--muted); }
.tile-volt b { color: var(--volt); text-shadow: 0 0 30px color-mix(in srgb, var(--volt) 30%, transparent); }
.tile-cobalt b { color: var(--cobalt); }
.tile-amber b { color: var(--amber); text-shadow: 0 0 30px color-mix(in srgb, var(--amber) 25%, transparent); }
/* A tile acting as a filter says so while it is on. */
.tile-btn.is-on { border-color: var(--volt); box-shadow: 0 0 0 2px color-mix(in srgb, var(--volt) 25%, transparent); }
.tile-amber.is-on { border-color: var(--amber); box-shadow: 0 0 0 2px color-mix(in srgb, var(--amber) 30%, transparent); }
.tabs-row {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 1rem; flex-wrap: wrap;
  margin-top: 1.4rem; margin-bottom: 1.2rem;
}
.tabs-row .reg-tabs { margin-bottom: 0; flex: 1 1 auto; }
.tabs-actions { display: flex; gap: 0.5rem; padding-bottom: 0.5rem; }

.tile-btn { cursor: pointer; text-align: left; text-decoration: none; display: block; transition: border-color 0.18s, transform 0.18s var(--ease-out); }
.tile-btn:hover { border-color: color-mix(in srgb, var(--volt) 50%, transparent); transform: translateY(-2px); }
button.tile-btn:hover { border-color: var(--cobalt); }

/* ── Data table (members) ── */

/* The row number counts what is on screen, so it follows the search, the
   page and the sort rather than pretending to be an id. */
.table th.rank, .table td.rank { width: 2.5rem; color: var(--muted); font-family: var(--font-mono); font-size: 0.8125rem; }
.table th.sort { cursor: pointer; user-select: none; white-space: nowrap; }
.table th.sort:hover { color: var(--text); }
.table th.sort.is-on { color: var(--volt); }
.table th.sort.is-on::after { content: " \25BC"; font-size: 0.7rem; }
.table th.sort.is-on.is-up::after { content: " \25B2"; }
.table-tools {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap;
  margin-bottom: 0.9rem;
}
.pager { display: flex; align-items: center; gap: 0.5rem; }
.list-pager { justify-content: flex-end; margin: 0 0 0.7rem; }
.pager-label { font-size: var(--mono-xs); letter-spacing: 0.12em; color: var(--muted); font-variant-numeric: tabular-nums; }
.pager-size {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
}
.pager .btn:disabled { opacity: 0.35; cursor: default; transform: none; }
.search {
  width: min(340px, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  padding: 0.55rem 1.1rem;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.search::placeholder { color: rgba(222, 231, 247, 0.48); }
.search:focus {
  outline: none;
  border-color: var(--volt);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--volt) 18%, transparent);
}
/* .card.table-wrap beats .card's own padding regardless of rule order. */
.card.table-wrap { overflow: auto; max-height: 62vh; padding: 0; }
.card.scroll-card { overflow: auto; max-height: 55vh; }
/* Slim themed scrollbar everywhere something scrolls: the page itself, cards,
   modals and the notify runner picker. None shown when content fits. */
html, .table-wrap, .scroll-card, .modal-card, .pick-list { scrollbar-width: thin; scrollbar-color: rgba(222, 231, 247, 0.25) transparent; }
html::-webkit-scrollbar, .table-wrap::-webkit-scrollbar, .scroll-card::-webkit-scrollbar, .modal-card::-webkit-scrollbar, .pick-list::-webkit-scrollbar { width: 8px; height: 8px; }
html::-webkit-scrollbar-track, .table-wrap::-webkit-scrollbar-track, .scroll-card::-webkit-scrollbar-track, .modal-card::-webkit-scrollbar-track, .pick-list::-webkit-scrollbar-track { background: transparent; }
html::-webkit-scrollbar-thumb, .table-wrap::-webkit-scrollbar-thumb, .scroll-card::-webkit-scrollbar-thumb, .modal-card::-webkit-scrollbar-thumb, .pick-list::-webkit-scrollbar-thumb {
  background: rgba(222, 231, 247, 0.18);
  border-radius: 999px;
}
html::-webkit-scrollbar-thumb:hover, .table-wrap::-webkit-scrollbar-thumb:hover, .scroll-card::-webkit-scrollbar-thumb:hover, .modal-card::-webkit-scrollbar-thumb:hover, .pick-list::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--volt) 45%, transparent); }
/* border-collapse:separate keeps the sticky header solid — collapsed borders
   scroll with the rows and let content peek through the header line. */
.card.table-wrap { position: relative; isolation: isolate; }
.table { width: 100%; border-collapse: separate; border-spacing: 0; }
.table thead { position: sticky; top: 0; z-index: 5; background: var(--surface); }
.table th {
  font-size: var(--mono-xs);
  font-weight: 500;
  letter-spacing: 0.2em;
  color: var(--muted);
  text-align: left;
  padding: 0.9rem 1.2rem 0.7rem;
  border-bottom: 0;
  box-shadow: 0 1px 0 var(--line);
  white-space: nowrap;
  position: sticky;
  top: 0;
  background: var(--surface);
  z-index: 2;
}
.table .badge { margin-left: 0.55rem; vertical-align: middle; }
/* Regulars: the name itself goes volt — no pill. */
.table .is-regular { color: var(--volt); text-shadow: 0 0 18px color-mix(in srgb, var(--volt) 25%, transparent); }
.table .action .btn { padding: 0.3rem 0.85rem; font-size: 0.75rem; }
/* Long names/emails crop with an ellipsis; clicking the row expands them. */
.table .crop {
  display: inline-block;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}
.table tbody tr { cursor: pointer; }
.member-name {
  font-family: var(--font-display);
  font-size: 1.5rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.1;
  overflow-wrap: anywhere;
}
.member-name.is-regular { color: var(--volt); text-shadow: 0 0 24px color-mix(in srgb, var(--volt) 30%, transparent); }
.modal .run-meta em { overflow-wrap: anywhere; text-align: right; }
.table td {
  padding: 0.75rem 1.2rem;
  border-bottom: 1px dashed var(--line);
  font-size: 0.9rem;
  vertical-align: middle;
}
.table td.num, .table td.action { white-space: nowrap; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: rgba(255, 255, 255, 0.03); }
.table td b { font-weight: 600; }
.table .muted { color: var(--muted); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table .action { text-align: right; }

/* ── Pending review modal ── */
.modal {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(6, 5, 4, 0.8);
  display: flex; align-items: center; justify-content: center;
  padding: 1.5rem;
}
.modal[hidden] { display: none; }
.modal-card {
  background: var(--surface);
  border: 1px solid rgba(125, 136, 255, 0.45);
  border-radius: 18px;
  width: min(520px, 100%);
  max-height: 80vh;
  overflow-y: auto;
  padding: 0 1.5rem 1.4rem;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.7);
}
/* One-time nudge to install, above the greeting. Dismissing it is remembered
   on this device and it never returns; the profile row carries it after that. */
.install-strip {
  position: relative;
  display: flex; align-items: center; gap: 0.8rem;
  background: var(--surface);
  border: 1px solid color-mix(in srgb, var(--volt) 35%, transparent);
  border-radius: 14px;
  padding: 0.8rem 0.9rem;
  margin-bottom: 1.1rem;
}
.install-strip[hidden] { display: none; }
.install-strip .is-txt { flex: 1 1 auto; min-width: 0; line-height: 1.35; }
.install-strip .is-txt b { display: block; font-weight: 600; font-size: 0.9rem; }
.install-strip .is-txt span { color: var(--muted); font-size: 0.78rem; }
/* The x sits in the top-right corner, tucked into the padding, so the button
   can use the right edge and the title keeps its line. The button is layered
   above the x's hit area so a thumb on the pill never dismisses the strip. */
.install-strip .btn { white-space: nowrap; padding-inline: 0.85rem; margin-right: 0.6rem; position: relative; z-index: 1; }
.install-strip .is-x {
  position: absolute; top: 0; right: 0;
  width: 2rem; height: 1.7rem;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; color: var(--muted);
  font-size: 1.1rem; line-height: 1; cursor: pointer;
}
.install-strip .is-x:hover { color: var(--text); }
/* The sheet behind Show me: the taps to add the app by hand, numbered. The
   glyph next to step one is the browser's own three-dot button. */
.install-steps { list-style: none; counter-reset: step; display: grid; gap: 0.75rem; padding-bottom: 0.3rem; }
.install-steps li {
  counter-increment: step;
  display: grid; grid-template-columns: 26px 1fr; gap: 0.75rem; align-items: start;
}
.install-steps li::before {
  content: counter(step);
  width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.75rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.install-steps b { display: block; font-weight: 600; line-height: 1.7; }
.install-steps span { display: block; grid-column: 2; color: var(--muted); font-size: 0.8125rem; }
.install-steps .step-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 17px; border-radius: 4px; vertical-align: -3px; margin-left: 0.15rem;
  border: 1px solid rgba(125, 136, 255, 0.45); background: rgba(125, 136, 255, 0.14);
}
.install-steps .step-glyph svg { width: 12px; height: 12px; fill: var(--cobalt); display: block; }

/* A past night's photos inside its opened row: square thumbnails, lazy, the
   first eight then See all. Tapping one opens the full photo. */
.session-gallery { margin-top: 1rem; }
.gal-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.4rem; }
.gal-thumb { display: block; width: 100%; aspect-ratio: 1; overflow: hidden; border-radius: 10px; background: var(--bg-2); border: 0; padding: 0; cursor: pointer; }
.gal-thumb:focus-visible { outline: 2px solid var(--volt); outline-offset: 2px; }
/* The slideshow: one overlay per page, above the bottom bar and the modals.
   The photo fits the screen; arrows sit at the edges, the count at the foot. */
.lightbox { position: fixed; inset: 0; z-index: 300; background: rgba(6, 5, 4, 0.96); display: flex; align-items: center; justify-content: center; }
.lightbox[hidden] { display: none; }
.lightbox img { max-width: 100vw; max-height: 100vh; object-fit: contain; display: block; }
.lightbox button { position: absolute; background: none; border: 0; color: var(--text); cursor: pointer; font-size: 1.6rem; line-height: 1; padding: 0.6rem 0.9rem; min-width: 44px; min-height: 44px; opacity: 0.85; }
.lightbox button:hover { opacity: 1; color: var(--volt); }
.lightbox .lb-x { top: calc(0.4rem + env(safe-area-inset-top)); right: 0.6rem; font-size: 2rem; }
.lightbox .lb-prev { left: 0.2rem; top: 50%; transform: translateY(-50%); }
.lightbox .lb-next { right: 0.2rem; top: 50%; transform: translateY(-50%); }
.lightbox .lb-count { position: absolute; bottom: calc(1rem + env(safe-area-inset-bottom)); left: 0; right: 0; text-align: center; font-size: var(--mono-xs); letter-spacing: 0.18em; color: var(--muted); margin: 0; }
.gal-thumb[hidden] { display: none; }
.gal-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gal-all { display: block; margin-top: 0.6rem; }
@media (max-width: 480px) { .gal-grid { grid-template-columns: repeat(3, 1fr); } }

/* Ran but never confirmed. Collapses like a past run, but amber: unfinished
   business sitting above the history rather than a run on the record. */
.kicker-amber { color: var(--amber); }
.notin-card { border-color: color-mix(in srgb, var(--amber) 35%, transparent); }
.notin-card[open] summary b { color: var(--amber); }
.notin-card summary:hover b { color: var(--amber); }
.sum-status.is-asked { color: var(--amber); }

/* A row where the runner has asked to be confirmed: it sorts to the top of the
   roster and carries an amber edge, so a captain sees who is waiting on them. */
.roster-row.is-asked { border-left-color: var(--amber); background: color-mix(in srgb, var(--amber) 6%, transparent); }

/* The full calendar: one flat list, the page scrolls, month bands stick so
   you always know where you are. Date block left, title and tag right. */
.cal-filter { margin: 0 0 1.1rem; }
.cal-month {
  position: sticky; top: 0; z-index: 1;
  margin: 1.2rem 0 0.5rem; padding: 0.45rem 0;
  background: var(--bg);
}
.cal-month:first-of-type { margin-top: 0; }
.cal-row summary { display: flex; align-items: center; gap: 0.9rem; cursor: pointer; list-style: none; }
.cal-row summary::-webkit-details-marker { display: none; }
/* Whole-pixel basis and line box: 3.1rem (49.6px) with a 1.05 line-height put
   the centred date on a half pixel, and a heavy face rasterised across the grid
   looks soft. 3rem and 1.125 land on whole pixels at every root size we use. */
.cal-date {
  flex: 0 0 3rem; text-align: center; line-height: 1.125;
  font-family: var(--font-display); font-size: 1.5rem; color: var(--text);
  font-variant-numeric: tabular-nums;
  /* Archivo at 800 is already heavy; antialiased thins it on a dark ground and
     reads as blur at this size. Subpixel rendering keeps the strokes solid. */
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
}
.cal-date b { display: block; font-family: var(--font-body); font-size: var(--mono-xs); letter-spacing: 0.18em; color: var(--muted); font-weight: 600; }
.cal-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.cal-title { font-style: normal; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-row[open] .cal-title { white-space: normal; }
.cal-row .sum-status { margin-left: 0; font-size: 0.78rem; }
.cal-row .sum-status.is-race { color: var(--amber); }
.cal-row .sum-status.is-colab { color: var(--cobalt); }
.cal-weekly { margin-bottom: 1.1rem; }
.cal-weekly .run-meta { margin: 0; }
.cal-row .sum-status.is-open { color: var(--volt); }
.cal-row .sum-status.is-cancelled { color: var(--red); }
.cal-row .sum-status.is-done { color: var(--muted); }
.cal-row[open] summary { margin-bottom: 0.9rem; }
.cal-row .run-meta { margin-top: 0; }

/* Roster controls: find a name, narrow to a distance, break into groups. */
.roster-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.7rem 1rem; margin-bottom: 0.9rem; }
.roster-tools .field { flex: 1 1 14rem; margin: 0; }
.roster-tools .roster-filter { flex: 0 1 auto; gap: 0.4rem; }
.roster-tools .roster-filter .pill { padding: 0.35rem 0.85rem; font-size: 0.8125rem; min-width: 0; flex: 0 0 auto; }
.roster-group { display: flex; align-items: center; gap: 0.45rem; font-size: 0.8125rem; color: var(--muted); white-space: nowrap; cursor: pointer; }
.roster-group input { accent-color: var(--volt); width: 16px; height: 16px; }
/* A group heading is a band across the list, not a row that lost its columns:
   it takes the rows' side padding, sits a step lighter, and swaps the dashed
   row border for a solid hairline so the eye reads it as structure. Sticky, so
   you always know which distance you are looking at partway down a long group. */
.roster-head {
  margin: 0;
  padding: 0.6rem 1.5rem 0.45rem;
  background: #1C1A16;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  position: sticky;
  top: 0;
  z-index: 1;
}
.roster-head:first-child { border-top: 0; }
/* Desktop clamps the roster the way the other admin tables do, so the aid
   crew and photos below are not three screens away. Phones keep one honest
   page: a scroller inside a scrolling page traps flicks and hides the length. */
@media (min-width: 768px) {
  .roster-scroll { max-height: 62vh; overflow-y: auto; }
}
/* How they got in, next to the name: 19:32 - GPS, or 19:45 - AMEER. */
.roster-how { color: var(--muted); font-size: 0.78rem; letter-spacing: 0.06em; white-space: nowrap; }
@media (max-width: 600px) {
  .roster-tools .field { flex: 1 1 100%; }
  .roster-how { display: none; }
}

/* How the night splits across distances, under the run's tiles. Wraps on
   phones rather than squeezing. */
.dist-split {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.4rem;
  margin: 0.2rem 0 1.4rem;
  font-size: var(--mono-xs);
  letter-spacing: 0.18em;
  color: var(--muted);
  text-transform: uppercase;
}
.dist-split b { color: var(--text); font-size: 1.05rem; letter-spacing: 0; margin-right: 0.1rem; }

/* The pending queue is a table in spirit: name, when, distance, how far out,
   then the two actions. It needs more room than a profile card, so this one
   modal runs wider. */
.modal-card.modal-wide { width: min(760px, 100%); }
.pending-row { align-items: center; gap: 0.5rem; }
.pending-row b { flex: 1 1 8rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pending-row .pend-when { flex: 0 0 6.5rem; color: var(--muted); font-size: 0.8125rem; }
.pending-row .pend-km { flex: 0 0 3.5rem; font-size: 0.8125rem; }
.pending-row .pend-away { flex: 0 0 7rem; font-size: 0.8125rem; color: var(--muted); }
.pending-row .row-actions { flex: 0 0 auto; margin-top: 0; flex-basis: auto; }
.pending-group { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.today-group { display: flex; justify-content: space-between; align-items: center; gap: 0.8rem; margin: 1rem 0 0.3rem; }
.today-group .card-kicker { display: flex; gap: 0.35rem; min-width: 0; }
.today-venue { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.today-n { white-space: nowrap; color: var(--volt); }
.today-n::before { content: '\00B7\00A0'; }
/* Phones: the venue wraps rather than losing its name to an ellipsis, and
   the count takes its own line without a dot leading it. */
@media (max-width: 600px) {
  .today-group .card-kicker { flex-wrap: wrap; }
  .today-venue { white-space: normal; }
  .today-n::before { content: none; }
}
.today-group + .today-group { margin-top: 1.6rem; }
.today-split { margin: 0.5rem 0 0.4rem; padding: 0 0.2rem; }
/* .row wraps and sits on the baseline; a name and its distance stay on one
   line, the name breaking inside itself if it has to. */
.row.today-row { align-items: center; flex-wrap: nowrap; }
.row.today-row b { font-size: 1.05rem; flex: 1 1 auto; min-width: 0; }
.row.today-row .badge { margin-left: 0.4rem; vertical-align: middle; }
.row.today-row .today-km { flex: none; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--muted); }
/* Phones: the name takes its own line and the timestamp goes - how far out
   they are is what decides an approval, the time is desktop context. */
@media (max-width: 600px) {
  .pending-row { flex-wrap: wrap; }
  .pending-row b { flex: 1 1 100%; }
  .pending-row .pend-when { display: none; }
  .pending-row .pend-km { flex: 0 0 auto; }
  .pending-row .pend-away { flex: 1 1 auto; }
  .pending-row .row-actions { flex-basis: auto; }
}

/* One scroll region only: the card scrolls, nothing nested inside it does.
   The name and close button stay pinned while long histories scroll under. */
.modal-head {
  display: flex; justify-content: space-between; align-items: center;
  position: sticky; top: 0; z-index: 2;
  background: var(--surface);
  padding: 1.4rem 0 0.7rem;
  margin-bottom: 0.5rem;
}
.modal-close { font-size: 1.6rem; line-height: 1; color: var(--muted); }
.modal-close:hover { color: var(--volt); }
.row-actions { display: flex; gap: 0.5rem; flex-basis: 100%; justify-content: flex-end; margin-top: 0.4rem; }

.admin-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  align-items: start;
  margin-top: 1.2rem;
}
@media (max-width: 860px) {
  .admin-grid { grid-template-columns: 1fr; }
  /* Tiles share the full row on phones, whatever their count: two tiles get
     half each, three get thirds, more than three wrap at three per line. */
  .tiles { display: flex; flex-wrap: wrap; gap: 0.5rem; }
  .tile { flex: 1 1 30%; padding: 0.75rem 0.8rem; }
  .tile b { font-size: 1.5rem; }
  .tile span { font-size: 0.5625rem; letter-spacing: 0.1em; }
  .admin-head { align-items: flex-start; flex-direction: column; }
}

/* ── Hero ── */
.hero-min { text-align: center; padding: 1.2rem 0 1.3rem; }
.kicker {
  font-size: var(--mono-xs);
  font-weight: 500;
  letter-spacing: 0.28em;
  color: var(--volt);
  margin-bottom: 0.7rem;
}
.kicker a { color: var(--volt); text-decoration: none; }
.kicker a:hover { text-decoration: underline; text-underline-offset: 4px; }
h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.7rem, 6.5vw, 2.3rem);
  line-height: 1;
  letter-spacing: 0.015em;
  text-transform: uppercase;
  text-shadow: 0 4px 60px rgba(0, 0, 0, 0.55);
}
.sub { color: var(--muted); font-size: 0.9375rem; margin-top: 0.7rem; }

/* ── Cards ── */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 1.75rem 1.5rem;
  margin-bottom: 1rem;
}
.card-kicker {
  font-size: var(--mono-xs);
  letter-spacing: 0.24em;
  color: var(--muted);
  margin-bottom: 1rem;
}
.card-kicker:not(:first-child) { margin-top: 1.6rem; }

/* ── Fields ── */
.field { display: block; margin-bottom: 1.2rem; }
.field > span {
  display: block;
  font-size: var(--mono-xs);
  letter-spacing: 0.24em;
  color: var(--muted);
  margin-bottom: 0.55rem;
}
.field input {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  padding: 0.85rem 1rem;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.field input::placeholder { color: rgba(222, 231, 247, 0.48); }
.field input:focus {
  outline: none;
  border-color: var(--volt);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--volt) 18%, transparent);
}
.field input[type="time"], .field input[type="datetime-local"] { color-scheme: dark; }
.field select {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  padding: 0.85rem 1rem;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23F3EFE6' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  cursor: pointer;
}
.field select:focus { outline: none; border-color: var(--volt); box-shadow: 0 0 0 3px color-mix(in srgb, var(--volt) 18%, transparent); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
/* Two joined inputs under one label, e.g. date + time. Wraps on narrow screens.
   span.field-duo outranks the generic .field span caption rule. */
span.field-duo { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0; }
.field-duo > input:first-child, .field-duo > select:first-child { flex: 1 1 10rem; min-width: 0; }
.field-duo .duo-time { flex: 0 0 8.5rem; width: 8.5rem; text-align: center; }
select.duo-time { text-align: left; padding-right: 2.2rem; }
/* Time stepper: hour / minutes / am-pm as three compact dropdowns. */
span.time-trio { display: flex; gap: 0.4rem; flex: 0 0 auto; margin: 0; }
.time-trio select {
  width: auto;
  padding: 0.85rem 1.7rem 0.85rem 0.7rem;
  background-position: right 0.55rem center;
}
@media (max-width: 480px) { .field-row { grid-template-columns: 1fr; gap: 0; } }
.field textarea {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  padding: 0.85rem 1rem;
  resize: vertical;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.field textarea::placeholder { color: rgba(222, 231, 247, 0.48); }
.field textarea:focus { outline: none; border-color: var(--volt); box-shadow: 0 0 0 3px color-mix(in srgb, var(--volt) 18%, transparent); }

/* ── Website photo picker (weekly form) ── */
.photo-pick { display: flex; align-items: center; gap: 0.9rem; }
.photo-pick img {
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
}
.photo-pick .form-note { margin: 0; text-align: left; }
.field[hidden] { display: none; }
/* The hidden attribute always wins, even over display:grid/flex rules. */
[hidden] { display: none !important; }

/* ── Merch admin ── */
.item-actions { display: flex; justify-content: center; gap: 2rem; margin-top: 1.1rem; }
.merch-prod { display: flex; align-items: center; gap: 0.7rem; color: var(--text); text-decoration: none; }
.merch-prod:hover b { color: var(--volt); }
.merch-thumb {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
  flex: 0 0 auto;
}
.merch-thumb-empty { display: inline-block; background: var(--bg-2); }
.merch-actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.merch-actions form { display: inline-flex; }
.icon-btn {
  width: 30px;
  height: 30px;
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--muted);
  transition: border-color 0.18s, color 0.18s;
}
.icon-btn:hover:not(:disabled) { border-color: var(--volt); color: var(--volt); }
.icon-btn:disabled { opacity: 0.3; cursor: default; }
/* Phones get full 44pt touch targets on the reorder arrows. */
@media (max-width: 640px) {
  .icon-btn { width: 44px; height: 44px; border-radius: 10px; font-size: 1.05rem; }
}
.size-grid { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.size-cell { display: flex; flex-direction: column; gap: 0.4rem; width: 4.2rem; }
.pill.pill-sm { padding: 0.35rem 0.5rem; font-size: 0.8125rem; min-width: 0; }
/* Muted selected state for the compact size pills. */
.pill-wrap input:checked + .pill.pill-sm {
  background: color-mix(in srgb, var(--volt) 14%, transparent);
  border-color: color-mix(in srgb, var(--volt) 50%, transparent);
  color: var(--volt);
  font-weight: 600;
  box-shadow: none;
}
.size-qty {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.8125rem;
  padding: 0.4rem 0.5rem;
  text-align: center;
}
.size-qty::placeholder { color: rgba(222, 231, 247, 0.48); }
.size-qty:focus { outline: none; border-color: var(--volt); }
.merch-photos { display: flex; gap: 1rem; flex-wrap: wrap; }
.photo-slot[hidden] { display: none; }
.slot-prev[hidden] { display: none; }
.photo-slot { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; width: 130px; }
.slot-prev {
  width: 130px;
  height: 130px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
}
.photo-slot .form-note { margin: 0; text-align: left; }

/* Check-in state as words next to the card's time — clearer than an icon. */
.sum-status { font-style: normal; margin-left: 0.45rem; font-size: 0.85em; letter-spacing: 0.08em; }
.sum-status.is-ok { color: var(--volt); }
/* The distance is a fact like the time, so it stays muted beside it. Pending
   takes the whole next line and is the only colour in the row - the quiet
   inline version got skimmed past. */
.sum-km { font-style: normal; margin-left: 0.45rem; font-size: 0.85em; letter-spacing: 0.08em; }
.sum-status.is-pending {
  color: var(--cobalt);
  display: block;
  margin-left: 0;
  margin-top: 0.2rem;
  font-size: 1em;
  font-weight: 600;
}

/* The admin list row, shared by Weekly, Calendar and Past runs: the link is the
   row, and any action (Share, Duplicate, Pause) sits beside it as its own target
   rather than a link inside a link. The date is body type like everything else
   on the row; the public calendar's display-face day number is .cal-date, and
   these rows must not borrow it. */
.list-row { align-items: center; gap: 0.8rem; }
.list-main { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex: 1 1 auto; min-width: 0; text-decoration: none; flex-wrap: wrap; }
.list-main b { font-variant-numeric: tabular-nums; }
.list-row .badge { white-space: nowrap; }
.list-action { flex: none; white-space: nowrap; margin-left: auto; }

/* The run's card photo, as a banner above the details of an opened card. It
   is the same picture the website card uses. Lazy, so it costs nothing until
   a card is opened, and it never sits between the runner and the pills. */
.run-photo { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: 12px; margin-bottom: 0.9rem; background: var(--bg-2); }

/* A colab run says what it is before it lists its details. Prose, so it gets
   room to breathe under the label rows. */
.run-blurb {
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--text);
  margin: 0.2rem 0 0.4rem;
}

/* Admin calendar tab. Same row, badge and button vocabulary as the tabs
   beside it: the filters are outline badges, the list scrolls with the page,
   month kickers are light, and only specials wear a kind badge. */
.cal-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem; margin-bottom: 0.9rem; }
.cal-kinds { display: flex; gap: 0.5rem; }
.cal-kind {
  min-height: 32px; padding: 0.3rem 0.7rem;
  background: none; color: var(--muted); border-color: rgba(255, 255, 255, 0.22);
  cursor: pointer; transition: border-color 0.18s, color 0.18s;
}
.cal-kind:hover { border-color: color-mix(in srgb, var(--volt) 50%, transparent); color: var(--text); }
.cal-kind.is-active { color: var(--volt); border-color: var(--volt); }
.cal-hide { display: flex; align-items: center; gap: 0.45rem; font-size: 0.8125rem; color: var(--muted); white-space: nowrap; cursor: pointer; min-height: 32px; }
.cal-hide input { accent-color: var(--volt); width: 16px; height: 16px; }
.cal-count { margin-left: auto; font-size: var(--mono-xs); letter-spacing: 0.18em; color: var(--muted); text-transform: uppercase; }
.cal-band { margin: 1.3rem 1.5rem 0.3rem; padding-bottom: 0.45rem; border-bottom: 1px solid var(--line); }
.cal-band:first-child { margin-top: 0.9rem; }
.badge-race { color: var(--amber); border: 1px solid color-mix(in srgb, var(--amber) 50%, transparent); }
.badge-colab { color: var(--cobalt); border: 1px solid rgba(125, 136, 255, 0.55); }
@media (max-width: 600px) {
  .cal-count { margin-left: 0; flex-basis: 100%; }
}

.roster-name { cursor: pointer; }
.roster-name:hover { color: var(--volt); }
.roster-row { align-items: center; }
.roster-row b { flex: 1 1 auto; }
.roster-row .row-actions { flex-basis: auto; margin-top: 0; }

/* ── Run night photos (admin roster page) ── */
.session-photos { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-bottom: 1rem; }
.session-photos:empty { margin-bottom: 0; }
.session-photo { position: relative; width: 110px; height: 110px; }
.session-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
}
.np-x {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(6, 5, 4, 0.8);
  color: var(--text);
  font-size: 1rem;
  line-height: 1;
  border: 1px solid var(--line);
}
.np-x:hover { color: var(--red); border-color: color-mix(in srgb, var(--red) 50%, transparent); }
.np-move { top: auto; bottom: 4px; }
.np-move:hover { color: var(--volt); border-color: color-mix(in srgb, var(--volt) 50%, transparent); }
.np-left { left: 4px; right: auto; }
.np-right { right: 4px; }

/* ── Run picker (several runs open at once) ── */
.run-picker { margin-bottom: 1.1rem; }
.run-picker .pill { text-decoration: none; flex: 0 1 auto; }
.run-picker .pill.is-active {
  background: var(--volt);
  border-color: var(--volt);
  color: var(--on-volt);
  font-weight: 600;
}

/* ── Tabs (I'm running / Aid station) ── */
.reg-tabs {
  display: flex; gap: 0;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1.2rem;
}
.reg-tab {
  padding: 0.7rem 1.2rem;
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: 0.03em;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.18s, border-color 0.18s;
}
.reg-tab:hover { color: var(--text); }
.reg-tab.is-active { color: var(--volt); border-bottom-color: var(--volt); }
.reg-panel { animation: panelIn 0.4s var(--ease-out); }

.rule { border: 0; border-top: 1px dashed var(--line); margin: 1.5rem 0 1.4rem; }

/* ── Distance pills ── */
.pills { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.pill-wrap { position: relative; flex: 1 1 auto; display: flex; }
.pill-wrap input { position: absolute; opacity: 0; pointer-events: none; }
.pill-wrap .pill { width: 100%; }
.pill-wrap input:checked + .pill {
  background: var(--volt);
  border-color: var(--volt);
  color: var(--on-volt);
  font-weight: 600;
  box-shadow: 0 0 26px color-mix(in srgb, var(--volt) 25%, transparent);
}
.pill-wrap input:focus-visible + .pill { outline: 2px solid var(--volt); outline-offset: 3px; }
.idtabs { margin-bottom: 1.3rem; }
.idtabs .pill { font-size: 0.9rem; }
.pill {
  padding: 0.55rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--muted);
  transition: all 0.18s var(--ease-out);
  flex: 1 1 auto;
  text-align: center;
  min-width: 5.2rem;
}
.pill:hover { border-color: color-mix(in srgb, var(--volt) 50%, transparent); color: var(--text); transform: translateY(-2px); }
.pill:active { transform: translateY(1px); }
.pill.is-active {
  background: var(--volt);
  border-color: var(--volt);
  color: var(--on-volt);
  font-weight: 600;
  box-shadow: 0 0 26px color-mix(in srgb, var(--volt) 25%, transparent);
}

/* ── Buttons ── */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 600;
  font-size: 0.875rem;
  letter-spacing: 0.04em;
  text-decoration: none;
  padding: 0.6rem 1.4rem;
  border-radius: 999px;
  transition: transform 0.18s var(--ease-out), box-shadow 0.18s var(--ease-out), border-color 0.18s, color 0.18s;
}
.btn:active { transform: translateY(1px); }
.btn-volt { background: var(--volt); color: var(--on-volt); }
.btn-volt:hover { transform: translateY(-2px); box-shadow: 0 6px 32px color-mix(in srgb, var(--volt) 35%, transparent); }
.btn-ghost { border: 1px solid rgba(255, 255, 255, 0.32); color: var(--muted); }
.btn-ghost:hover { border-color: var(--volt); color: var(--volt); transform: translateY(-2px); }
.btn-sm { padding: 0.4rem 1rem; font-size: 0.8125rem; }
/* Held back rather than missing: a button that vanishes reads as broken. */
.btn:disabled { opacity: 0.4; cursor: default; transform: none; box-shadow: none; }
.btn-full { width: 100%; margin-top: 0.4rem; }

.link-btn { color: var(--muted); text-decoration: underline; text-underline-offset: 4px; font-size: 0.8125rem; }
.link-btn:hover { color: var(--volt); }
.inline-form { text-align: center; margin-top: 0.9rem; }

/* ── Returning runner ── */
.returning {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 1.2rem 1.5rem;
  margin-bottom: 1rem;
}
.returning summary { cursor: pointer; color: var(--muted); font-size: 0.9rem; }
.returning summary:hover { color: var(--volt); }
.returning form { margin-top: 1.2rem; }

/* ── Bib card (you're in) ── */
.bib-card {
  border: 1.5px dashed color-mix(in srgb, var(--volt) 60%, transparent);
  border-radius: 18px;
  padding: 2.25rem 2rem;
  text-align: center;
  background: var(--surface);
  margin-bottom: 1rem;
  animation: panelIn 0.5s var(--ease-out);
}
@keyframes panelIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.bib-kicker { font-size: var(--mono-xs); letter-spacing: 0.3em; color: var(--volt); margin-bottom: 1rem; }
.bib-num {
  font-family: var(--font-display);
  font-size: clamp(3rem, 14vw, 5rem);
  line-height: 1;
  color: var(--volt);
  text-shadow: 0 0 40px color-mix(in srgb, var(--volt) 35%, transparent);
  margin-bottom: 0.4rem;
}
.bib-num span { font-size: 0.38em; letter-spacing: 0.1em; }
.bib-name { font-weight: 600; font-size: 1.125rem; margin-bottom: 1.4rem; }
.bib-station {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 7vw, 2.6rem);
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--volt);
  text-shadow: 0 0 40px color-mix(in srgb, var(--volt) 35%, transparent);
  margin-bottom: 0.5rem;
}
.bib-code {
  font-size: var(--mono-xs);
  letter-spacing: 0.24em;
  color: var(--muted);
  border-top: 1px dashed var(--line);
  max-width: 280px;
  margin: 0 auto 1.2rem;
  padding-top: 1rem;
}
.bib-note { font-size: 0.875rem; color: var(--muted); }

/* ── Event meta (venue / aid stations / after) ── */
.run-meta { list-style: none; }
.run-meta li {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  font-size: 0.875rem;
  letter-spacing: 0.04em;
  padding: 0.5rem 0;
  border-bottom: 1px dashed var(--line);
  text-align: right;
}
.run-meta li:last-child { border-bottom: 0; }
.run-meta li span { color: var(--muted); font-size: var(--mono-xs); letter-spacing: 0.2em; text-align: left; white-space: nowrap; }
.run-meta li em { font-style: normal; }
.spots { color: var(--volt); font-variant-numeric: tabular-nums; }
.spots.is-full { color: var(--red); }

/* ── +Editor rows (distances, aid stations) ── */
.aid-row { display: flex; gap: 0.6rem; align-items: center; margin-bottom: 0.6rem; }
.aid-row select, .aid-row input {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.875rem;
  padding: 0.5rem 0.8rem;
}
.aid-row select { cursor: pointer; }
.aid-row .aid-type { flex: 0 0 auto; width: 78px; }
.aid-row input[type="number"] { width: 64px; }
.aid-row .aid-name { flex: 1 1 auto; min-width: 220px; }
/* No spinner arrows on km/number fields */
.aid-row input[type="number"]::-webkit-inner-spin-button,
.aid-row input[type="number"]::-webkit-outer-spin-button,
.field input[type="number"]::-webkit-inner-spin-button,
.field input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.aid-row input[type="number"], .field input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.aid-row select:focus, .aid-row input:focus {
  outline: none;
  border-color: var(--volt);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--volt) 18%, transparent);
}
.aid-del { color: var(--muted); font-size: 1.3rem; line-height: 1; padding: 0 0.3rem; }
.aid-del:hover { color: var(--red); }
#aidRows, #distRows { margin-top: 0.3rem; }

/* ── Geolocation status ── */
/* Volt while it waits: muted grey read as nothing happening, so runners
   thought the tap had died and the GPS wait went unnoticed. */
.geo-status {
  display: flex; align-items: center; gap: 0.55rem;
  font-size: var(--mono-xs);
  letter-spacing: 0.22em;
  color: var(--volt);
  margin-top: 0.9rem;
}
.geo-status i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--volt);
  animation: blink 1.6s steps(2, start) infinite;
}
@keyframes blink { 50% { opacity: 0.15; } }
.geo-status.is-on { color: var(--volt); }
.geo-status.is-on i { background: var(--volt); animation: none; }
/* Shown only when the browser reports a refusal. Cobalt like every other
   pending state, and it stays put: the runner needs to read it, leave the app
   to change a setting, and come back. */
.geo-blocked {
  border: 1px solid rgba(125, 136, 255, 0.4);
  border-radius: 12px;
  background: rgba(125, 136, 255, 0.07);
  padding: 0.85rem 0.95rem;
  margin-top: 0.9rem;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--muted);
}
.geo-blocked[hidden] { display: none; }
.geo-blocked p + p { margin-top: 0.5rem; }
.geo-blocked b { color: var(--text); }
.geo-blocked .gb-ios[hidden], .geo-blocked .gb-droid[hidden] { display: none; }

.geo-status.is-off { color: var(--cobalt); }
.geo-status.is-off i { background: var(--cobalt); animation: none; }

/* ── Status badges + pending state ── */
.badge {
  font-style: normal;
  font-size: var(--mono-xs);
  letter-spacing: 0.14em;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  vertical-align: middle;
}
.badge-ok { color: var(--text); border: 1px solid rgba(222, 231, 247, 0.34); }
.badge-pending { color: var(--cobalt); border: 1px solid rgba(125, 136, 255, 0.55); }
.badge-cancelled { color: var(--red); border: 1px solid color-mix(in srgb, var(--red) 50%, transparent); }
/* Filled, not outlined: a request is the one row state that wants answering. */
.badge-asked { background: var(--amber); color: var(--on-volt); font-weight: 600; }
.badge-vol { color: var(--moon, #9DB8FF); border: 1px solid rgba(157, 184, 255, 0.5); }
.badge-paused { color: var(--muted); border: 1px solid rgba(255, 255, 255, 0.28); }
.bib-card.is-pending { border-color: rgba(125, 136, 255, 0.6); }
.bib-card.is-pending .bib-kicker { color: var(--cobalt); }
.bib-card.is-pending .bib-num { color: var(--cobalt); text-shadow: 0 0 40px rgba(125, 136, 255, 0.35); }
.approve-form { flex-basis: 100%; text-align: right; margin-top: 0.3rem; }

/* ── No run / next run / tonight ── */
.next-run { text-align: center; }
.tonight-card { text-align: center; border-color: color-mix(in srgb, var(--volt) 30%, transparent); }
.tonight-card.is-cancelled { border-color: color-mix(in srgb, var(--red) 40%, transparent); }
.tonight-card.is-cancelled .next-run-title { text-decoration: line-through; color: var(--muted); }

/* Slim tonight bar on the dashboard */
.tonight-bar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; flex-wrap: wrap;
  padding: 0.9rem 1.5rem;
  border-color: color-mix(in srgb, var(--volt) 30%, transparent);
}
.tonight-bar.is-cancelled { border-color: color-mix(in srgb, var(--red) 40%, transparent); }
.tonight-bar.is-cancelled .tonight-title { text-decoration: line-through; color: var(--muted); }
.tonight-bar.is-done { border-color: var(--line); }
.tonight-bar.is-done .tonight-title { color: var(--muted); }
.tonight-title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.2;
}
.tonight-sub {
  font-family: var(--font-body);
  font-size: 0.8125rem;
  text-transform: none;
  letter-spacing: 0.02em;
  color: var(--muted);
  margin-left: 0.6rem;
}
.tonight-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.next-run-title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.row.is-tonight { border-left-color: var(--volt); background: color-mix(in srgb, var(--volt) 5%, transparent); }
.toolbar .btn + .btn { margin-left: 0.5rem; }

/* ── Volunteer sign-up list ── */
.vol-event summary {
  cursor: pointer;
  display: flex; align-items: baseline; gap: 0.7rem; flex-wrap: wrap;
  list-style: none;
}
.vol-event summary::-webkit-details-marker { display: none; }
.vol-event summary b { font-weight: 600; letter-spacing: 0.04em; }
.vol-event summary span { color: var(--muted); font-size: 0.8125rem; }
.vol-event summary:hover b { color: var(--volt); }
/* Open rows glow volt on every device: the highlight means "expanded". Touch
   screens keep hover styles stuck after a tap, so hover is desktop-only. */
.vol-event[open] summary b { color: var(--volt); }
@media (hover: none) {
  .vol-event:not([open]) summary:hover b { color: inherit; }
}
.vol-event[open] summary { margin-bottom: 0.9rem; }
/* My runs rows: the venue clips so the kms and time always hold one line;
   expanding the row lets the full venue wrap free. */
.sum-line { display: flex; align-items: baseline; min-width: 0; flex: 1 1 auto; }
.sum-line .sum-venue { font-style: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.sum-line .sum-status { flex: none; white-space: nowrap; }
.vol-event[open] .sum-line { flex-wrap: wrap; }
.vol-event[open] .sum-venue { white-space: normal; }
.vol-event .run-meta { margin-bottom: 1.1rem; }
.vol-in { color: var(--volt); text-align: left; margin: 0; }

/* ── Mini stats strip ── */
.stats-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin-bottom: 1rem;
}
.stats-strip.one { grid-template-columns: 1fr; }
.stats-strip.four { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 480px) { .stats-strip.four { grid-template-columns: repeat(2, 1fr); row-gap: 0.9rem; } }
.stats-strip .stat { border-left: 1px solid var(--line); padding-left: 0.9rem; }
.stats-strip .stat b {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.9rem, 8vw, 2.7rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  margin-bottom: 0.25rem;
}
.stats-strip .stat span { font-size: var(--mono-xs); letter-spacing: 0.18em; color: var(--muted); }
.stats-strip .stat-volt { border-left-color: var(--volt); }
.stats-strip .stat-volt b { color: var(--volt); text-shadow: 0 0 30px color-mix(in srgb, var(--volt) 30%, transparent); }
.stats-strip .stat-volt span { color: var(--volt); }

/* ── Consent + POPIA ── */
.consent-check {
  display: flex; align-items: flex-start; gap: 0.6rem;
  font-size: 0.875rem;
  color: var(--volt);
  margin-bottom: 1.1rem;
  cursor: pointer;
}
.consent-check.plain { color: var(--text); }
.consent-check input {
  width: 1.05rem; height: 1.05rem;
  margin-top: 0.15rem;
  accent-color: var(--volt);
  flex-shrink: 0;
}
.popia {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 0.8rem 1rem;
  margin-bottom: 0.9rem;
}
.popia summary { cursor: pointer; font-size: 0.8125rem; color: var(--muted); }
.popia summary:hover { color: var(--text); }
.popia p { font-size: 0.8125rem; color: var(--muted); margin-top: 0.7rem; line-height: 1.55; }

/* ── Notes + errors ── */
.form-note { font-size: 0.8125rem; color: var(--muted); text-align: center; margin-top: 1rem; }
.error {
  border: 1px solid color-mix(in srgb, var(--red) 50%, transparent);
  background: color-mix(in srgb, var(--red) 8%, transparent);
  color: #FFB3B3;
  border-radius: 12px;
  padding: 0.8rem 1.1rem;
  font-size: 0.875rem;
  margin-bottom: 1rem;
}

/* ── Admin lists ── */
.toolbar { text-align: center; margin-bottom: 1.2rem; }
.list { padding: 0.25rem 0; }
.row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  flex-wrap: wrap;
  padding: 0.95rem 1.5rem;
  border-bottom: 1px dashed var(--line);
  text-decoration: none;
  border-left: 2px solid transparent;
  transition: background-color 0.18s, border-color 0.18s;
}
.row:last-child { border-bottom: 0; }
a.row:hover { background: color-mix(in srgb, var(--volt) 5%, transparent); border-left-color: var(--volt); }
/* Share chip inside a row link: sits at the right edge, doesn't inherit the row's link look. */
.row .share-btn { margin-left: auto; font-style: normal; cursor: pointer; flex: none; }
.share-btn { cursor: pointer; }
/* Phones paint a grey RECTANGLE over tapped elements by default — ugly on
   round pills. The pills/buttons have their own :active press effect. */
* { -webkit-tap-highlight-color: transparent; }
/* Cancelled run notice: red-tinted card with a share for spreading the word. */
.cancel-card { border-color: color-mix(in srgb, var(--red) 40%, transparent); }
.cancel-card .card-kicker { color: color-mix(in srgb, var(--red) 90%, transparent); }
/* The card can be dismissed; the choice is remembered on this device. */
.cancel-card { position: relative; }
.cancel-card .cc-x {
  position: absolute; top: 0.7rem; right: 0.9rem;
  background: none; border: 0; color: var(--muted);
  font-size: 1.35rem; line-height: 1; padding: 0 0.2rem; cursor: pointer;
}
.cancel-card .cc-x:hover { color: var(--text); }
/* A cancelled night in the run history: kept, labelled, counted nowhere. */
.sum-status.is-cancelled { color: var(--red); }
/* Saved results hide their edit form behind a quiet toggle. */
.fix-result { margin-top: 0.8rem; }
.fix-result > summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
}
/* H:MM:SS result boxes: three compact equal cells that fit one line on a phone. */
.time-trio { display: flex; gap: 0.35rem; }
.time-trio input {
  width: 3.1em; min-width: 0; flex: 1 1 0;
  text-align: center;
  padding-left: 0.2rem; padding-right: 0.2rem;
  -moz-appearance: textfield;
}
.time-trio input::-webkit-outer-spin-button,
.time-trio input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* Runner card share link sits under the card content, quiet until needed. */
details.vol-event .link-btn.share-btn { display: block; margin-top: 0.9rem; }
/* "Map" chip after the meet spot: opens Google Maps pinned on the start. */
.map-link {
  display: inline-block;
  margin-left: 0.45rem;
  padding: 0 0.5rem;
  border: 1px solid var(--volt);
  border-radius: 999px;
  color: var(--volt);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
.map-link:hover { background: color-mix(in srgb, var(--volt) 12%, transparent); }
.row b { font-weight: 600; letter-spacing: 0.04em; }
.row span { color: var(--muted); font-size: 0.8125rem; letter-spacing: 0.04em; }

/* ── QR poster ── */
.poster { text-align: center; padding-top: 2.5rem; }
.poster img {
  width: min(78vw, 320px);
  border-radius: 18px;
  margin: 1.8rem auto;
  background: #fff;
  padding: 14px;
  border: 1.5px dashed color-mix(in srgb, var(--volt) 60%, transparent);
}
.poster .form-note a { color: var(--volt); }

/* ── Header actions: bell + sign in/profile share the auth button's spot ── */
.hdr-actions {
  position: absolute;
  right: 1.25rem; top: 50%;
  transform: translateY(-50%);
  display: flex; gap: 0.5rem; align-items: center;
}
.hdr-actions .auth-btn { position: static; transform: none; }
@media (max-width: 640px) {
  .hdr-actions { position: static; transform: none; flex: none; }
}
.bell-btn { position: relative; display: inline-flex; align-items: center; }
.bell-btn svg { display: block; }
.bell-dot {
  position: absolute;
  top: -0.45rem; right: -0.45rem;
  background: var(--volt); color: var(--on-volt);
  border-radius: 999px;
  font-style: normal; font-weight: 700;
  font-size: 0.625rem; line-height: 1.15rem;
  min-width: 1.15rem; height: 1.15rem;
  padding: 0 0.25rem;
  text-align: center;
}

/* ── Crew news (bell panel) ── */
.notice { padding: 0.85rem 1.6rem 0.85rem 0; border-bottom: 1px solid var(--line); text-align: left; position: relative; }
/* Dismiss: clears the notice from this bell for good. */
.notice-x {
  position: absolute;
  top: 0.55rem; right: -0.2rem;
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  padding: 0.3rem 0.45rem;
}
.notice-x:hover { color: var(--volt); }
.notice:last-child { border-bottom: none; padding-bottom: 0.2rem; }
.notice b { display: block; font-weight: 600; letter-spacing: 0.02em; }
.notice p { margin: 0.25rem 0 0; font-size: 0.875rem; color: var(--text); }
.notice span {
  display: block; margin-top: 0.35rem;
  color: var(--muted);
  font-size: var(--mono-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.notice span a { color: var(--volt); }
/* Meta row: the link (if any) on the left, the date and time right-aligned. */
.notice .notice-meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
}
.notice-meta em { font-style: normal; }
.notice.is-unread b::before {
  content: '';
  display: inline-block;
  width: 0.45rem; height: 0.45rem;
  border-radius: 50%;
  background: var(--volt);
  margin-right: 0.5rem;
  vertical-align: 0.1rem;
}

/* ── Profile push setting: status left, small switch right — reads as a
   setting row, not a page action. Log out stays the only full-width button. ── */
.push-row { display: flex; align-items: center; justify-content: space-between; gap: 0.9rem; }
.push-row .form-note { margin: 0; text-align: left; flex: 1 1 auto; }
.push-row .btn { flex: none; }

/* ── Sponsors: logo strip above the footer ── */
.sponsor-strip { margin-top: 2.8rem; text-align: center; }
.sponsor-logos {
  display: flex; flex-wrap: wrap;
  justify-content: center; align-items: center;
  gap: 1.3rem 2.2rem;
  margin-top: 1.1rem;
}
.sponsor-logos img {
  height: 34px; width: auto; max-width: 130px;
  object-fit: contain;
  opacity: 0.85;
  transition: opacity 0.2s;
}
.sponsor-logos a:hover img { opacity: 1; }
.sponsor-name { color: var(--muted); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; font-size: 0.8125rem; }
/* Admin list thumbs */
.sponsor-thumb { height: 28px; width: 60px; object-fit: contain; flex: none; }
.sponsor-thumb-empty { display: inline-block; background: var(--surface); border: 1px dashed var(--line); border-radius: 6px; }
.sponsor-row { align-items: center; gap: 0.9rem; }
.logo-prev { height: 44px; width: auto; max-width: 140px; object-fit: contain; }

/* ── Notify: runner picker ── */
.pick-list {
  max-height: 16rem; overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 12px;
  margin-top: 0.6rem;
}
.pick-row {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.55rem 0.9rem;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.pick-row:last-child { border-bottom: none; }
.pick-row b { font-weight: 600; }
.pick-row span { margin-left: auto; color: var(--muted); font-size: 0.8125rem; }
.pick-row input { accent-color: var(--volt); }
/* The roster picker puts an Add button where notify puts a phone number. */
.pick-row .add-btn { margin-left: auto; flex: none; }
.pick-row[hidden] { display: none; }

/* ── Add a member: the roster's picker window ──
   Three decisions stacked in one card — who they are, how far, which person —
   so each gets its own band with a rule between. Without the separators they
   read as one long undifferentiated column of controls. */
#addModal .add-group { padding-block: 1rem; border-top: 1px solid var(--line); }
#addModal .add-group:first-of-type { padding-top: 0.4rem; border-top: 0; }
#addModal .add-group .card-kicker { margin: 0 0 0.6rem; }
/* Distance pills size to their label instead of stretching to fill the row.
   Stretching left "Run 10 km" alone on a second line at phone width, spanning
   the full card, which reads as a mistake rather than a choice. */
#addModal #addDist { gap: 0.5rem; }
#addModal #addDist .pill {
  flex: 0 0 auto;
  min-width: 0;
  padding: 0.5rem 0.95rem;
  font-size: 0.875rem;
}
#addModal .search { width: 100%; margin: 0 0 0.6rem; }
#addModal .pick-list { margin-top: 0; }
/* form-note centres by default, which leaves these two adrift in a left-aligned
   card. Both are read as part of the flow above them, not as captions. */
#addModal .add-intro { text-align: left; margin: 0 0 0.2rem; }
#addModal #addNone { text-align: left; margin: 0.6rem 0 0; }
/* The Add buttons stay the app's normal volt button. The only change is that
   they do not lift on hover: the shared .btn raises 2px, and in a list that
   means every row jumps as the pointer crosses it. */
#addModal .add-btn:hover { transform: none; }
/* A row is a target, not just a line of text: give it room for a 44px tap and
   let a long name wrap rather than shoving the button off the edge. */
#addModal .pick-row { padding: 0.7rem 0.9rem; gap: 0.6rem; min-height: 3rem; }
#addModal .pick-row b { min-width: 0; overflow-wrap: anywhere; }
/* The modal card is itself a scroller, so an inner scrolling list nests one
   inside the other: a flick near the bottom scrolls the wrong thing and
   neither shows its full length. On phones the list runs at full height and
   the card does the scrolling; only from 768px, where the card has room to sit
   still, does the list get its own scroller and a fade to say so. */
#addModal .pick-wrap { position: relative; }
#addModal .pick-list { max-height: none; }
@media (min-width: 768px) {
  #addModal .pick-list { max-height: 17rem; overflow-y: auto; }
  #addModal .pick-wrap::after {
    content: '';
    position: absolute; left: 1px; right: 1px; bottom: 1px; height: 2.2rem;
    background: linear-gradient(to top, var(--surface), transparent);
    border-radius: 0 0 11px 11px;
    pointer-events: none;
  }
}
/* Who drifted, visible while you pick: the date carries it, the dot marks it. */
.pick-row.is-slipping span { color: var(--volt); }
.pick-row.is-slipping b::after {
  content: '';
  display: inline-block;
  width: 5px; height: 5px;
  margin-left: 0.4rem;
  border-radius: 50%;
  background: var(--volt);
  vertical-align: middle;
}
/* The count on the pill, so the audience says its own size. */
.pill i {
  font-style: normal;
  margin-left: 0.35rem;
  padding: 0.05rem 0.35rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
  font-size: 0.85em;
}
#pickSearch { margin-top: 0.9rem; width: 100%; }
/* ── Admin menu: text links across the top on desktop, a bottom bar on phones.
   Both show the same five sections with the current one lit; the top strip
   carries QR and a separated Sign out too. ── */
.admin-topnav { display: none; }
@media (min-width: 641px) {
  .admin-topnav {
    display: flex;
    align-items: center;
    gap: 1.2rem;
    flex-wrap: wrap;
    padding: 1.3rem 0 0;
  }
  .admin-topnav a,
  .admin-topnav .link-btn {
    color: var(--muted);
    text-decoration: none;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }
  .admin-topnav a:hover,
  .admin-topnav .link-btn:hover { color: var(--volt); }
  .admin-topnav a.is-active { color: var(--volt); }
  /* Sign out (and its divider) sits at the far right edge of the strip. */
  .admin-topnav .nav-sep { width: 1px; height: 0.95rem; background: var(--line); margin-left: auto; }
}

/* Bottom nav: the five admin sections, fixed in thumb reach. The spacer sits
   in the page flow so nothing hides behind the bar. Desktop never sees it. */
.admin-bottomnav, .bottomnav-pad { display: none; }
.mobile-only { display: none; }
@media (max-width: 640px) {
  .mobile-only { display: flex; }
  .admin-foot {
    flex-direction: column;
    align-items: center;
    margin-top: 3.2rem;
    margin-bottom: -1.2rem; /* tucks sign out right up against the footer */
  }
  .bottomnav-pad { display: block; height: 1.2rem; }
  /* The footer comes after the page content, so it needs its own clearance
     from the fixed bar or "Built by Scale Digital" hides underneath it. */
  body:has(.admin-bottomnav) .foot { margin-bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
  .admin-bottomnav {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    background: var(--surface);
    border-top: 1px solid var(--line);
    padding: 0.5rem 0.2rem calc(0.6rem + env(safe-area-inset-bottom));
    z-index: 80;
  }
  .admin-bottomnav a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    color: var(--muted);
    text-decoration: none;
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.2rem 0;
  }
  .admin-bottomnav svg { width: 20px; height: 20px; }
  .admin-bottomnav a.is-active { color: var(--volt); }
  .admin-bottomnav a { position: relative; }
  /* Pending check-ins waiting for a captain: a volt count on Home. */
  .admin-bottomnav .nav-dot {
    position: absolute;
    top: -0.2rem; right: calc(50% - 1.35rem);
    background: var(--volt); color: var(--on-volt);
    border-radius: 999px;
    font-style: normal; font-weight: 700;
    font-size: 0.5625rem; line-height: 1rem;
    min-width: 1rem; height: 1rem;
    padding: 0 0.2rem;
    text-align: center;
  }
}

/* ── Submitting: the tapped pill holds its lit state and its siblings fade;
   plain buttons (Sign me up, Sign in, Save result) dim and lock while the
   page responds so no tap ever looks dead. ── */
form.is-submitting .pills { pointer-events: none; }
form.is-submitting .pill:not(.is-active) { opacity: 0.35; }
form.is-submitting .btn { opacity: 0.55; pointer-events: none; }

/* ── Runner bottom nav: the pill tabs plus News and Profile, in thumb reach.
   Phones only; desktop keeps the pills and the corner buttons. ── */
.runner-bottomnav { display: none; }
@media (max-width: 640px) {
  .runner-bottomnav {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    background: var(--surface);
    border-top: 1px solid var(--line);
    padding: 0.5rem 0.2rem calc(0.6rem + env(safe-area-inset-bottom));
    z-index: 80;
  }
  .runner-bottomnav button, .runner-bottomnav a {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    color: var(--muted);
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.2rem 0;
    position: relative;
  }
  .runner-bottomnav svg { width: 20px; height: 20px; }
  .runner-bottomnav button.is-active { color: var(--volt); }
  .runner-bottomnav a { text-decoration: none; }
  .runner-bottomnav .nav-dot {
    position: absolute;
    top: -0.2rem; right: calc(50% - 1.35rem);
    background: var(--volt); color: var(--on-volt);
    border-radius: 999px;
    font-style: normal; font-weight: 700;
    font-size: 0.5625rem; line-height: 1rem;
    min-width: 1rem; height: 1rem;
    padding: 0 0.2rem;
    text-align: center;
  }
  /* The bar replaces the pill tabs and the corner buttons on phones, except
     the bell: notifications belong in the top right on both layouts, and the
     News tab below is the blog. */
  body:has(.runner-bottomnav) .hdr-actions { display: flex; }
  body:has(.runner-bottomnav) .hdr-actions .auth-btn { display: none; }
  body:has(.runner-bottomnav) .reg-tabs { display: none; }
  body:has(.runner-bottomnav) .foot { margin-bottom: calc(4.4rem + env(safe-area-inset-bottom)); }
}

/* ── Undo toast: act-then-undo for roster removes ── */
.undo-toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(1.4rem + env(safe-area-inset-bottom));
  background: #1C1A16;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.6rem 1.2rem;
  display: flex;
  gap: 1.1rem;
  align-items: center;
  font-size: 0.875rem;
  z-index: 90;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
}
.undo-btn { color: var(--volt); font-weight: 700; font-size: 0.75rem; letter-spacing: 0.1em; }
@media (max-width: 640px) {
  /* Sits above the bottom nav instead of behind it. */
  .undo-toast { bottom: calc(5rem + env(safe-area-inset-bottom)); }
}

/* Sent notifications: tap a row, the full message expands underneath. */
.sent-row { cursor: pointer; }
.sent-detail td { padding-top: 0; }
.sent-body { margin: 0.2rem 0 0.5rem; font-size: 0.875rem; }
.sent-body a { color: var(--volt); }

@media print {
  body { background: #fff; color: #000; }
  .grain, .no-print, .foot { display: none; }
  .kicker, .script-accent { color: #000; }
  .sub { color: #333; }
  h1 { text-shadow: none; }
  .poster img { border-color: #000; padding: 0; }
}

/* ── First visit to the captain panel: nothing on the books yet ── */
.welcome-card { border-color: color-mix(in srgb, var(--volt) 45%, transparent); }
.welcome-steps { margin: 0.8rem 0 0; padding-left: 1.3rem; display: grid; gap: 0.8rem; }
.welcome-steps li { line-height: 1.5; }
.welcome-steps li b { color: var(--text); }
/* A step already done: still listed, so the owner can see what is left. */
.welcome-steps li.is-done { color: var(--muted); }
.welcome-steps li.is-done b { color: var(--muted); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--text) 40%, transparent); }
.welcome-steps .btn { margin-top: 0.5rem; }
.welcome-steps a:not(.btn) { color: var(--volt); }

/* ── "?" help: a one-line explanation next to a label or heading, tap to read ── */
.help-btn {
  display: inline-grid; place-items: center;
  width: 18px; height: 18px; margin-left: 0.4rem; vertical-align: middle;
  border-radius: 50%; border: 1px solid var(--line); background: transparent;
  color: var(--muted); font: 600 0.7rem/1 var(--font-body); letter-spacing: 0; cursor: pointer;
  transition: border-color 120ms, color 120ms;
}
.help-btn:hover, .help-btn.is-on { border-color: var(--volt); color: var(--volt); }
.help-tip {
  display: block; margin: 0.35rem 0 0.6rem; padding: 0.55rem 0.8rem;
  border-left: 2px solid var(--volt); background: color-mix(in srgb, var(--volt) 6%, transparent);
  color: var(--muted); font-size: 0.8125rem; letter-spacing: 0; text-transform: none; line-height: 1.5;
}

/* ── Monthly leaderboard on the member home ── */
.board { list-style: none; margin: 0.4rem 0 0; padding: 0; counter-reset: place; }
.board li { display: flex; align-items: center; gap: 0.7rem; padding: 0.45rem 0; border-bottom: 1px solid var(--line); font-size: 0.9375rem; }
.board li:last-child { border-bottom: 0; }
.board li::before { counter-increment: place; content: counter(place); font-family: var(--font-display); font-size: 1.05rem; width: 1.6rem; color: var(--muted); }
.board li b { flex: 1; font-weight: 500; }
.board li em { font-style: normal; font-family: var(--font-display); font-size: 1.05rem; color: var(--volt); font-variant-numeric: tabular-nums; }
.board li.is-me { color: var(--volt); }
.board li.is-me b { font-weight: 700; }
.board-me { font-size: 0.8125rem; color: var(--muted); margin: 0.7rem 0 0; }
