@import url('../fonts/fonts.css');

/* ============================================================
   Court Craft — Huish Tigers
   Black + orange, taken from the club logo and match flyers.
   Body: Maven Pro 500. Headings: Anton. Accents: Bangers brush.
   ============================================================ */

:root {
  /* The app is dark, so tell the browser: without this the date and time inputs draw their own
     calendar and clock icons in black, which are invisible on a dark field, and the native date
     picker itself opens in light mode. This also darkens select popups and scrollbars to match. */
  color-scheme: dark;

  --black: #08080a;
  --panel: #131317;
  --panel-2: #1b1b21;
  --panel-3: #232329;
  --line: rgba(255, 255, 255, 0.09);
  --line-strong: rgba(255, 255, 255, 0.18);
  --white: #ffffff;
  --muted: #b0b0ba;
  --muted-2: #9797a3;

  /* The club's colour, and the only place it is written down.
     Held as bare channel numbers so any transparency of it can be built with
     rgb(var(--brand-rgb) / 0.3) rather than another hardcoded rgba() that would ignore whatever
     colour the club has actually chosen. --brand-deep-rgb is the same hue a shade down, used for
     gradients and the tab bar rule; the app works both out from the one colour an admin picks and
     writes them onto :root at startup. The values here are the Huish orange, which is what a club
     that has never opened the branding screen gets. */
  --brand-rgb: 245 136 58;
  --brand-deep-rgb: 242 101 34;
  --orange: rgb(var(--brand-rgb));
  --flame: rgb(var(--brand-deep-rgb));
  --orange-soft: rgb(var(--brand-rgb) / 0.14);

  --bronze: #cd7f45;
  --silver: #c8cdd4;
  --gold: #f3b739;
  --platinum: #93e9f2;

  --font-body: 'Maven Pro', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-display: 'Anton', 'Arial Narrow', sans-serif;
  --font-brush: 'Bangers', var(--font-display);

  --radius: 16px;
  --radius-sm: 10px;
  --shell: 1180px;
  /* A comfortable reading measure, about 70 characters at the body size. */
  --measure: 62ch;
  --tap: 48px;
}

* { box-sizing: border-box; }

/* An author `display` beats the UA rule for [hidden], which silently un-hides anything the JS
   hides by attribute (e.g. the field that does not apply to the chosen scoring type). */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--black);
  color: var(--white);
  /* The sticky header changes height on scroll; scroll anchoring would fight that. */
  overflow-anchor: none;
}

body {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 18px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  /* Faint court glow, echoing the flame wash at the foot of the flyers. */
  background-image: radial-gradient(120% 60% at 50% 100%, rgb(var(--brand-deep-rgb) / 0.13), transparent 70%);
  background-attachment: fixed;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.98;
  margin: 0;
}

a { color: var(--orange); text-decoration: none; }
/* 16px keeps iOS from zooming the page when a field is focused. */
button, input, select { font-family: inherit; font-weight: inherit; font-size: inherit; }
button { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }

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

/* The shell's own gutter, exposed so a full-bleed row inside it can cancel it out.
   One width for every view. Only the coach board used to get the wide shell, which left every
   other page as a phone-sized column stranded in the middle of a desktop screen. */
.shell { --gut: 18px; max-width: var(--shell); margin: 0 auto; padding: 0 var(--gut) 108px; }

/* Prose does not want the extra room: past about 75 characters the eye loses the line coming back.
   So the shell widens and the reading column does not. Anything laid out as cards or a table uses
   the whole width; paragraphs and inputs stay at a measure you can actually read. */
.hero__sub,
.note-body,
.note--pad,
.field__error { max-width: var(--measure); }

@media (min-width: 760px) {
  /* Card-based content spreads out rather than stacking in one tall column. */
  .grid { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
  .outline { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 28px; align-items: start; }
  .tv-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
  .linkset { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
  .people { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 12px; align-items: start; }
  .person { max-width: none; }
  /* Only the writing is capped, not the whole section: the photo gallery and the link tiles want
     the room, and capping their container squeezed them into a column for no reason. */
  .club-section .note-editor,
  .club-section .note-body { max-width: var(--measure); }
  /* Anything that draws a border shares the column, so every right edge lines up: a card that
     stopped short of the rows above and the button below it just looked broken.
     What gets capped is the controls inside, because a name box a metre long looks broken too. */
  .card input[type='text'],
  .card input[type='url'],
  .card input[type='email'],
  .card input[type='password'],
  .card input[type='number'],
  .card input[type='date'],
  .card input[type='time'],
  .card select,
  .season-search input,
  .filterbar select { max-width: 420px; }
  /* Except where the box is the content: a bio or a note wants the room it is given. */
  .card textarea,
  .card .note-editor { max-width: var(--measure); }
}

@media (min-width: 1100px) {
  .outline { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* The account tag is the only thing in the bar you can tap, so it says so. */
.tag--me {
  text-decoration: none;
  cursor: pointer;
  border-color: var(--orange);
  min-height: 34px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* Never squashed: this is how a player reaches their own account, and a flex item with hidden
     overflow will happily shrink to zero width and vanish without any sign it was ever there. */
  flex: none;
}
.tag--me > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The arrow is what says "this opens something". Sized off the text so it never dominates it. */
.tag__go {
  flex: none;
  display: inline-flex;
  opacity: 0.75;
}
.tag__go svg { width: 15px; height: 15px; display: block; }
.tag--me:hover { background: var(--orange); color: var(--black); }

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  /* Respects the notch when the app is installed to the home screen. */
  padding: calc(8px + env(safe-area-inset-top)) 18px 8px;
  background: rgba(8, 8, 10, 0.92);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}

.topbar__logo {
  width: 114px;
  height: 114px;
  border-radius: 24px;
  display: block;
  flex: none;
}
.topbar__title {
  font-family: var(--font-display);
  font-size: 31px;
  letter-spacing: 0.02em;
  white-space: nowrap;
  min-width: 0;
  /* On a narrow phone the bar cannot hold the logo, the name and a player's own name and number.
     The product name is the part everyone can already see they are inside, so it is the one that
     gives way. Before this the account link was shrunk to nothing and simply disappeared. */
  overflow: hidden;
  text-overflow: ellipsis;
}
.topbar__title span { color: var(--orange); }
.topbar__spacer { flex: 1; }

/* Offline and waiting-to-send badges, so a queued score never looks like a lost one. */
.tag--offline {
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--line-strong);
  color: var(--muted);
}
.tag--waiting {
  background: rgb(var(--brand-deep-rgb) / 0.18);
  border-color: rgb(var(--brand-deep-rgb) / 0.45);
  color: var(--orange);
}

.tag {
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: 0.08em;
  padding: 5px 9px 4px;
  border-radius: 6px;
  background: var(--orange-soft);
  color: var(--orange);
  border: 1px solid rgb(var(--brand-rgb) / 0.3);
}



body[data-scrolled='true'] .topbar { padding-top: calc(6px + env(safe-area-inset-top)); padding-bottom: 6px; }
body[data-scrolled='true'] .topbar__logo { width: 46px; height: 46px; border-radius: 11px; }
body[data-scrolled='true'] .topbar__title { font-size: 24px; }

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

/* The hero is a title, and on three pages one line under it. Nothing else.
   It used to run to about 300px before the sub-nav appeared: a logo, a label saying which page you
   had opened, a huge word, and a sentence describing what you could already see. This is a closed
   app for one club, so none of that was telling anyone anything. */
.hero { position: relative; padding: 10px 0 6px; overflow: hidden; }
.hero__name {
  font-family: var(--font-brush);
  font-size: clamp(30px, 8.5vw, 42px);
  line-height: 0.92;
  color: var(--flame);
  transform: skewX(-7deg);
  transform-origin: left bottom;
  letter-spacing: 0.01em;
  margin: 1px 0 0;
}
/* Only a handful of pages still carry one, and only where it says something the page does not:
   the offline warning, a category's own blurb, the reflection's instructions. */
.hero__sub { color: var(--muted); font-size: 15px; line-height: 1.4; margin-top: 3px; }
.identity {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0 4px;
}
.identity span {
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.12em;
  color: var(--muted-2);
  padding: 4px 8px 3px;
  border: 1px solid var(--line);
  border-radius: 5px;
}
/* No hover here. These four words are the club's motto, not controls: nothing happens when you
   click one, so lighting them up under the pointer promises something that is not there. */

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

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
}

.section-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 26px 0 12px;
}
.section-title h2 { font-size: 22px; }
.section-title small { color: var(--muted-2); font-size: 15px; letter-spacing: 0.04em; }

.grid { display: grid; gap: 12px; }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Medal strip -------------------------------------------------- */

.medals { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.medal {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px 6px 10px;
  text-align: center;
}
.medal__count { font-family: var(--font-display); font-size: 28px; line-height: 1; }
.medal__label {
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: 0.1em;
  color: var(--muted-2);
  margin-top: 4px;
}
.medal--bronze .medal__count { color: var(--bronze); }
.medal--silver .medal__count { color: var(--silver); }
.medal--gold .medal__count { color: var(--gold); }
.medal--platinum .medal__count { color: var(--platinum); }
.medal--empty .medal__count { color: var(--muted-2); }

/* Category card ------------------------------------------------ */

.cat {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  text-align: left;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  color: var(--white);
  cursor: pointer;
  transition: border-color 0.18s, transform 0.18s;
}
.cat:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.cat__body { flex: 1; min-width: 0; }
.cat__name { font-family: var(--font-display); font-size: 21px; }
.cat__blurb {
  font-size: 15px;
  color: var(--muted);
  margin-top: 2px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.cat__chev { color: var(--muted-2); font-size: 22px; }

.ring { width: 54px; height: 54px; flex: none; position: relative; }
.ring svg { transform: rotate(-90deg); display: block; }
.ring__label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 15px;
}

/* The drill library as one outline: every section open, its drills indented under it, so the
   whole sheet is scannable without tapping into anything. The indent rail on the left is what
   carries the "these belong to that heading" reading once the header scrolls off. */
.outline { display: grid; gap: 4px; }
.outline__group { margin-top: 14px; }
.outline__head {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 2px 2px 10px;
}
.outline__headbody { flex: 1; min-width: 0; }
.outline__name {
  font-family: var(--font-display);
  font-size: 21px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.outline__blurb { font-size: 15px; color: var(--muted); margin-top: 2px; }
.outline__drills {
  display: grid;
  gap: 8px;
  margin-left: 14px;
  padding-left: 14px;
  border-left: 2px solid var(--line-strong);
}
.drill--nested { border-radius: var(--radius-sm); }
@media (max-width: 380px) {
  .outline__drills { margin-left: 6px; padding-left: 10px; }
}

/* Drill row ---------------------------------------------------- */

.drill {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 13px 14px;
  color: var(--white);
  cursor: pointer;
  transition: border-color 0.18s, background 0.18s;
}
.drill:hover { border-color: var(--line-strong); background: var(--panel-2); }
.drill__station {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--muted-2);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  min-width: 34px;
  padding: 5px 6px 4px;
  text-align: center;
  flex: none;
}
.drill__body { flex: 1; min-width: 0; }
.drill__name { font-family: var(--font-display); font-size: 18px; letter-spacing: 0.01em; }
.drill__meta { font-size: 15px; color: var(--muted-2); margin-top: 2px; }

/* Tier badge --------------------------------------------------- */

.badge {
  font-family: var(--font-brush);
  font-size: 17px;
  letter-spacing: 0.03em;
  padding: 4px 10px 2px;
  border-radius: 999px;
  color: var(--black);
  white-space: nowrap;
}
.badge--bronze { background: var(--bronze); color: #1a0f06; }
.badge--silver { background: var(--silver); }
.badge--gold { background: var(--gold); }
.badge--platinum { background: var(--platinum); }
.badge--none {
  background: transparent;
  border: 1px dashed var(--line-strong);
  color: var(--muted-2);
  font-family: var(--font-display);
  font-size: 14.5px;
  letter-spacing: 0.08em;
  padding: 5px 9px 4px;
}

/* ---------------------------------------------------------------- drill detail */

.player-frame {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--panel-2);
  aspect-ratio: 16 / 9;
}
.player-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
.player-frame--empty {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 20px;
  color: var(--muted-2);
  gap: 8px;
}
.player-frame--empty strong {
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--muted);
  letter-spacing: 0.06em;
}

.cue {
  border-left: 3px solid var(--orange);
  padding: 2px 0 2px 12px;
  margin: 16px 0;
  color: var(--white);
  font-size: 17px;
}

/* Tier ladder -------------------------------------------------- */

.ladder { display: grid; gap: 8px; }
.ladder__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--panel);
  border: 1px solid var(--line);
}
.ladder__row[data-earned='true'] { border-color: currentColor; background: var(--panel-2); }
.ladder__dot { width: 10px; height: 10px; border-radius: 50%; background: currentColor; flex: none; }
.ladder__name {
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.08em;
  flex: 1;
  color: var(--white);
}
.ladder__target { font-size: 15px; color: var(--muted); }
.ladder__tick { font-size: 15px; color: currentColor; }
.ladder__row--bronze { color: var(--bronze); }
.ladder__row--silver { color: var(--silver); }
.ladder__row--gold { color: var(--gold); }
.ladder__row--platinum { color: var(--platinum); }

/* Timer -------------------------------------------------------- */

.timer { text-align: center; padding: 6px 0 2px; }
.timer .ring { margin: 0 auto; }
.timer .ring svg { transform: rotate(-90deg); display: block; }
.timer__read {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 2px;
}
.timer__value {
  font-family: var(--font-display);
  font-size: 52px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.timer__hint {
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.12em;
  color: var(--muted-2);
}
.timer__actions { display: flex; gap: 10px; justify-content: center; margin-top: 16px; }

.btn {
  min-height: var(--tap);
  padding: 0 22px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--white);
  font-family: var(--font-display);
  font-size: 17px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.14s, background 0.18s, border-color 0.18s;
}
.btn:active { transform: scale(0.97); }
.btn--primary {
  background: linear-gradient(150deg, var(--orange), var(--flame));
  border-color: transparent;
  color: #1a0d04;
}
.btn--ghost { color: var(--muted); }
.btn--danger { color: #ff8f7a; border-color: rgba(255, 143, 122, 0.4); }
.btn--block { width: 100%; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* Log form ----------------------------------------------------- */

.field { display: block; margin-bottom: 12px; }
.field__label {
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.12em;
  color: var(--muted);
  display: block;
  margin-bottom: 6px;
}
.field input {
  width: 100%;
  min-height: var(--tap);
  padding: 0 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--panel-2);
  color: var(--white);
}
.field input::placeholder { color: var(--muted-2); }
.field--inline { display: flex; gap: 10px; align-items: flex-end; }
/* A field with a button beside it that must stay beside it, even on a narrow phone. */
.field--pair { display: flex; gap: 8px; align-items: stretch; }
.field--pair input { flex: 1 1 auto; min-width: 0; }
.field--pair > button { flex: 0 0 auto; }
.field--inline > * { flex: 1; }

.history { display: grid; gap: 6px; }
.history__row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  padding: 9px 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.history__value { font-family: var(--font-display); font-size: 18px; min-width: 62px; }
.history__when { color: var(--muted-2); font-size: 15px; flex: 1; }
.history__del {
  background: none;
  border: none;
  color: var(--muted-2);
  cursor: pointer;
  font-size: 22px;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  border-radius: 8px;
  flex: none;
}
.history__del:hover { color: #ff8f7a; }

/* ---------------------------------------------------------------- gate */

.gate {
  min-height: 100vh;
  min-height: 100dvh;   /* dvh keeps the panel centred as the mobile URL bar comes and goes */
  display: grid;
  place-items: center;
  padding: 28px 18px;
}
.gate__inner { width: 100%; max-width: 400px; }
.gate__logo { width: 92px; height: 92px; border-radius: 20px; display: block; margin: 0 auto 18px; }
.gate__title {
  font-family: var(--font-brush);
  font-size: 58px;
  line-height: 0.84;
  text-align: center;
  color: var(--flame);
  transform: skewX(-7deg);
  margin-bottom: 6px;
}
.gate__sub { text-align: center; color: var(--muted); font-size: 16px; margin-bottom: 24px; }

.tabs { display: flex; gap: 6px; background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: 4px; margin-bottom: 18px; }
.tabs button {
  flex: 1;
  min-height: 40px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
.tabs button[aria-selected='true'] { background: var(--panel-3); color: var(--white); }

.note { font-size: 15.5px; color: var(--muted-2); line-height: 1.45; }
.note--pad { margin-top: 14px; }

.alert {
  border-radius: var(--radius-sm);
  padding: 11px 13px;
  font-size: 16px;
  margin-bottom: 14px;
  border: 1px solid;
}
.alert--error { background: rgba(255, 92, 66, 0.1); border-color: rgba(255, 92, 66, 0.35); color: #ffb3a3; }
.alert--ok { background: rgb(var(--brand-rgb) / 0.1); border-color: rgb(var(--brand-rgb) / 0.35); color: var(--orange); }

/* ---------------------------------------------------------------- Huish TV */

.tv-grid { display: grid; gap: 18px; }

.tv-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.tv-card .player-frame { border: 0; border-radius: 0; }
.tv-card__body {
  padding: 14px 16px 16px;
  background: var(--panel-2);
  border-top: 1px solid var(--line);
}
.tv-card__topic {
  font-family: var(--font-display);
  font-size: 14.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--orange);
  display: block;
  margin-bottom: 4px;
}
.tv-card__title { font-family: var(--font-display); font-size: 23px; text-transform: none; letter-spacing: 0.01em; }
.tv-card__blurb { color: #c8c8d2; font-size: 16.5px; margin: 6px 0 0; }
.tv-card__credit { color: #a8a8b4; font-size: 15.5px; margin: 8px 0 0; }

/* ---------------------------------------------------------------- bottom nav */

.tabbar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  /* Light bar, brand rule along the top, so it reads as designed rather than accidental. */
  background: linear-gradient(180deg, #fdfdfe, #ebebef);
  border-top: 3px solid var(--flame);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.55);
  /* No gutter: each tab fills its share of the bar, so the active one runs edge to edge. */
  padding: 0 0 env(safe-area-inset-bottom);
}
.tabbar a {
  flex: 1;
  min-height: 60px;
  display: grid;
  place-items: center;
  gap: 3px;
  color: #2b2b33;
  font-family: var(--font-display);
  font-size: 19px;
  letter-spacing: 0.06em;
  border-radius: 0;
  position: relative;
  transition: background 0.18s ease, color 0.18s ease;
}
.tabbar a svg { transition: transform 0.18s ease; display: block; }
/* The icon sits in an inline span, whose line-height adds phantom space under the glyph. */
.tabbar a > span:first-child { line-height: 0; }

/* The live tab: full-bleed Tigers orange with a lift at the top edge. */
.tabbar a[aria-current='page'] {
  background: linear-gradient(180deg, var(--orange), var(--flame) 78%);
  color: #17130c;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.4), inset 0 -3px 10px rgba(0, 0, 0, 0.16);
}
.tabbar a[aria-current='page'] svg { transform: scale(1.08); }
.tabbar a[aria-current='page'] span:last-child { letter-spacing: 0.1em; }
.tabbar svg { width: 26px; height: 26px; }

/* ---------------------------------------------------------------- pulse + stats */

.pulse {
  display: flex;
  align-items: center;
  gap: 14px;
  background: linear-gradient(120deg, rgb(var(--brand-deep-rgb) / 0.16), rgb(var(--brand-rgb) / 0.04));
  border: 1px solid rgb(var(--brand-rgb) / 0.28);
  border-radius: var(--radius);
  padding: 15px 16px;
}
.pulse__num { font-family: var(--font-brush); font-size: 40px; line-height: 0.9; color: var(--orange); }
.pulse__text { font-size: 15.5px; color: var(--white); }
.pulse__text span { color: var(--muted); display: block; font-size: 15.5px; }

.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.stat { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 13px; text-align: center; }
.stat__num { font-family: var(--font-display); font-size: 26px; }
.stat__label { font-family: var(--font-display); font-size: 14px; letter-spacing: 0.1em; color: var(--muted-2); margin-top: 3px; }

/* ---------------------------------------------------------------- coach */

/* Sub-navigation, and filters, as two visibly different things ------------------
   The old version drew both as identical outlined pills in a wrapping row. On a phone the coach
   Squad page opened with sixteen of them stacked four rows deep before any content, and because
   "selected" was #232329 on #131317 nothing looked chosen. Two problems, two patterns:

   .subnav    moving between sections. One row that scrolls sideways and never wraps, no borders at
              all, the current section marked by orange text and a bar underneath. Height is fixed
              whatever the number of sections, so a page can never open with a wall of chrome.
   .filterbar narrowing what is on screen. Deliberately quieter and smaller than the sub-nav, so it
              reads as a setting rather than as somewhere to go. */

.subnav {
  display: flex;
  gap: 4px;
  margin: 6px 0 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* Bleeds to the screen edges so the row visibly runs off the side: that is the cue that there
     is more to scroll to. */
  padding: 0 var(--gut, 16px);
  margin-inline: calc(-1 * var(--gut, 16px));
  box-shadow: inset 0 -1px 0 var(--line);
  /* Held under the top bar, so switching section never means scrolling back up to find the row.
     The background is solid because content scrolls underneath it. */
  position: sticky;
  top: var(--topbar-h, 56px);
  z-index: 15;
  background: var(--black);
}
.subnav::-webkit-scrollbar { display: none; }
.subnav + * { margin-top: 16px; }
.subnav + .filterbar { margin-top: 16px; }

.subnav a,
.subnav button {
  flex: none;
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 3px solid transparent;
  padding: 12px 12px 10px;
  min-height: var(--tap);
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 1rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.subnav a:hover,
.subnav button:hover { color: var(--white); }
.subnav [aria-selected='true'],
.subnav [aria-current='page'] {
  color: var(--orange);
  border-bottom-color: var(--orange);
}

/* A sub-nav one level deeper, inside a card: same pattern, not sticky, and it does not bleed to
   the screen edges because it lives inside the card's own padding. */
.subnav--nested {
  position: static;
  padding: 0;
  margin-inline: 0;
  margin-top: 2px;
  background: none;
}

/* Filters. Smaller, no uppercase, and filled rather than outlined when active, so a glance tells
   you which of these is a place and which is a setting. */
/* The filter bar sits between the sub-nav and the content, and was almost touching both: 2px of
   air under a navigation rule, then 4px before a row of cards. It reads as its own band now. */
.filterbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin: 16px 0 14px;
}
.filterbar__label {
  font-size: 0.85rem;
  color: var(--muted-2);
  margin-right: 2px;
}
/* On a phone the word "Show" pushed the controls onto a second line all by itself. The controls
   say what they are; the label is a desktop nicety. */
@media (max-width: 430px) {
  .filterbar__label { display: none; }
  .filterbar select { max-width: 150px; }
}
.filterbar__set { display: inline-flex; gap: 4px; }
.filterbar button {
  appearance: none;
  min-height: 36px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--panel-2);
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.filterbar button:hover { color: var(--white); background: var(--panel-3); }
.filterbar button[aria-selected='true'] {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--black);
}
/* Over about four options a row of chips becomes the wall of pills this replaced, so those become
   a select instead: one control, one line, whatever the number of choices. */
.filterbar select {
  min-height: 36px;
  padding: 0 8px;
  border-radius: 10px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--white);
  font-family: var(--font-body);
  font-size: 0.9rem;
  max-width: 190px;
}

.coach-nav { display: flex; gap: 8px; margin: 18px 0 6px; flex-wrap: wrap; }
.chip {
  min-height: 44px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 15.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
/* A disabled chip has to look disabled, or it reads as a button that does not work. */
.chip:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  border-style: dashed;
}

.chip[aria-selected='true'] { background: var(--panel-3); color: var(--white); border-color: transparent; }
.chip__count {
  background: var(--flame);
  color: #1a0d04;
  border-radius: 999px;
  padding: 1px 7px 0;
  font-size: 14px;
}

.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); }

/* Sideways-scrolling squad board -------------------------------- */

.board-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 8px;
}
.board-bar__hint { font-size: 15.5px; color: var(--muted-2); }
.board-bar__arrows { display: flex; gap: 8px; flex: none; }

.board-nav {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid var(--line-strong);
  background: var(--panel-2);
  color: var(--white);
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1;
  padding-bottom: 4px;
  cursor: pointer;
  transition: background 0.18s, opacity 0.18s, border-color 0.18s;
}
.board-nav:hover { background: var(--panel-3); border-color: var(--orange); }
.board-nav[disabled] { opacity: 0.28; cursor: default; }
.board-nav[disabled]:hover { background: var(--panel-2); border-color: var(--line-strong); }

.board-scroll { position: relative; }
.board-scroll__viewport {
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  /* Keep the scrollbar on screen: macOS would otherwise hide it until you scroll. */
  scrollbar-color: var(--orange) var(--panel-3);
  scrollbar-width: auto;
}
.board-scroll__viewport::-webkit-scrollbar { height: 14px; }
.board-scroll__viewport::-webkit-scrollbar-track {
  background: var(--panel-3);
  border-radius: 999px;
  margin: 0 10px 3px;
}
.board-scroll__viewport::-webkit-scrollbar-thumb {
  background: var(--orange);
  border-radius: 999px;
  border: 4px solid var(--panel-3);
  min-width: 44px;
}
.board-scroll__viewport::-webkit-scrollbar-thumb:hover { background: var(--flame); }

/* Fades that tell you there is more table in that direction. */
.board-scroll::before,
.board-scroll::after {
  content: '';
  position: absolute;
  top: 1px;
  bottom: 16px;
  width: 44px;
  pointer-events: none;
  z-index: 2;
  transition: opacity 0.2s;
}
.board-scroll::before {
  left: 1px;
  border-radius: var(--radius) 0 0 0;
  background: linear-gradient(to right, var(--panel), rgba(19, 19, 23, 0));
}
.board-scroll::after {
  right: 1px;
  border-radius: 0 var(--radius) 0 0;
  background: linear-gradient(to left, var(--panel), rgba(19, 19, 23, 0));
}
.board-scroll[data-at-start='true']::before { opacity: 0; }
.board-scroll[data-at-end='true']::after { opacity: 0; }
table.board { border-collapse: collapse; width: 100%; font-size: 15px; }
table.board th, table.board td { padding: 9px 10px; text-align: left; white-space: nowrap; border-bottom: 1px solid var(--line); }
table.board thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--panel-2);
  font-family: var(--font-display);
  font-size: 14.5px;
  letter-spacing: 0.07em;
  color: var(--muted);
  font-weight: 400;
}
table.board thead th:first-child {
  left: 0;
  z-index: 3;
}
table.board tbody th {
  position: sticky;
  left: 0;
  background: var(--panel);
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 400;
  letter-spacing: 0.02em;
  z-index: 1;
  box-shadow: 1px 0 0 var(--line);
}
table.board td { text-align: center; color: var(--muted-2); }
table.board tr:hover td, table.board tr:hover th { background: var(--panel-2); }
.board-station {
  display: block;
  color: var(--orange);
  font-size: 15px;
  letter-spacing: 0.04em;
}
.cell { display: inline-grid; place-items: center; gap: 1px; }
.cell__dot { width: 9px; height: 9px; border-radius: 50%; }
.cell__val { font-size: 14.5px; font-variant-numeric: tabular-nums; }
.cell--bronze { color: var(--bronze); }
.cell--silver { color: var(--silver); }
.cell--gold { color: var(--gold); }
.cell--platinum { color: var(--platinum); }
.cell--none { color: var(--muted-2); }

.feed { display: grid; gap: 8px; }
.feed__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.feed__row[data-new='true'] { border-color: rgb(var(--brand-rgb) / 0.4); background: rgb(var(--brand-rgb) / 0.06); }
.feed__who { font-family: var(--font-display); font-size: 17px; min-width: 74px; }
.feed__what { flex: 1; min-width: 0; font-size: 15.5px; }
.feed__what span { color: var(--muted-2); display: block; font-size: 15px; }

.codes { display: grid; gap: 6px; }
.code-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 13px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 16px;
}
/* The name needs room before it will share a line. Without a floor it was squeezed to one word
   per line by the squad picker and the number box sitting next to it, which turned a player row
   into a nine-line paragraph on a phone. Below this width the whole row stacks instead. */
.code-row__name { font-family: var(--font-display); font-size: 17px; flex: 1 1 170px; min-width: 150px; }
.code-row { flex-wrap: wrap; row-gap: 8px; }
/* An empty slot is still a flex item, and its gap pushed the row's last button in from the edge.
   It only exists once a passphrase has been issued into it. */
.code-row__phrase:empty { display: none; }
/* Both words buttons reserve the same width, so a row with "New words" does not sit a few pixels
   out of line with the rows saying "Issue words". */
.code-row .chip { min-width: 116px; justify-content: center; }
.code-row .chip--danger { color: #e8988a; border-color: rgba(232, 152, 138, 0.4); }
.code-row .chip--danger:hover { background: rgba(232, 152, 138, 0.12); border-color: #e8988a; }
/* When it does have something in it, it belongs on its own line under the controls. */
.code-row__phrase { flex: 1 0 100%; }
.code-row select { min-height: var(--tap); }
.code-row__code {
  font-family: var(--font-display);
  letter-spacing: 0.14em;
  color: var(--orange);
  background: var(--orange-soft);
  border: 1px solid rgb(var(--brand-rgb) / 0.3);
  min-height: 44px;
  padding: 4px 12px 3px;
  border-radius: 8px;
  cursor: pointer;
  flex: none;
}
.code-row__done { font-size: 15px; color: var(--muted-2); font-family: var(--font-display); letter-spacing: 0.08em; }

/* Drill manager -------------------------------------------------- */

.manage-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-bottom: 8px;
}
.manage-row[data-retired='true'] { opacity: 0.55; }
.manage-row__body { flex: 1; min-width: 0; }
.manage-row__meta { font-size: 15px; color: var(--muted-2); margin-top: 2px; }
.manage-row__targets { display: flex; gap: 6px; flex: none; }

.target-chip {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.04em;
  border: 1px solid currentColor;
  border-radius: 6px;
  padding: 4px 7px 3px;
}

.manage-grid { display: grid; grid-template-columns: 90px 1fr; gap: 10px; }
.manage-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.manage-grid .field { margin-bottom: 0; }

select {
  width: 100%;
  min-height: var(--tap);
  padding: 0 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--panel-2);
  color: var(--white);
}
select + input:not([hidden]) { margin-top: 8px; }

/* Passphrase reveal, shown once for the coach to copy into Spond ------- */

.passphrase {
  flex: 1 1 100%;
  margin-top: 10px;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--orange-soft);
  border: 1px solid rgb(var(--brand-rgb) / 0.35);
  display: grid;
  gap: 8px;
  justify-items: start;
}
.passphrase__words {
  font-family: var(--font-display);
  font-size: 27px;
  letter-spacing: 0.02em;
  color: var(--orange);
  user-select: all;
}

/* ---------------------------------------------------------------- toast */

.toast {
  position: fixed;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%) translateY(14px);
  z-index: 60;
  background: var(--panel-3);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  padding: 11px 20px;
  font-size: 16px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s, transform 0.22s;
  max-width: min(92vw, 420px);
  text-align: center;
}
.toast[data-show='true'] { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast strong { font-family: var(--font-brush); font-size: 19px; letter-spacing: 0.03em; }

/* Tier celebration ------------------------------------------- */

.reveal {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: grid;
  place-items: center;
  background: rgba(4, 4, 6, 0.86);
  backdrop-filter: blur(4px);
  padding: 24px;
  text-align: center;
}
.reveal__tier {
  font-family: var(--font-brush);
  font-size: clamp(56px, 18vw, 104px);
  line-height: 0.86;
  transform: skewX(-7deg);
  animation: pop 0.5s cubic-bezier(0.2, 1.5, 0.4, 1);
}
.reveal__label { font-family: var(--font-display); font-size: 16px; letter-spacing: 0.18em; color: var(--muted); }
.reveal__value { font-family: var(--font-display); font-size: 24px; margin-top: 6px; }
@keyframes pop {
  from { transform: skewX(-7deg) scale(0.4); opacity: 0; }
  to { transform: skewX(-7deg) scale(1); opacity: 1; }
}

.empty { text-align: center; color: var(--muted-2); padding: 30px 12px; font-size: 16px; }

.back {
  background: none;
  border: none;
  min-height: 44px;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 15.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 14px 0 4px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.back:hover { color: var(--white); }

.row-between { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.mt { margin-top: 16px; }
.mt-lg { margin-top: 26px; }

/* Phones: the header has to fit 375px without pushing the page sideways. */
@media (max-width: 460px) {
  .topbar { gap: 10px; padding-left: 14px; padding-right: 14px; }
  .topbar__logo { width: 84px; height: 84px; border-radius: 18px; }
  .topbar__title { font-size: 26px; }
  body[data-scrolled='true'] .topbar__logo { width: 42px; height: 42px; border-radius: 10px; }
  body[data-scrolled='true'] .topbar__title { font-size: 22px; }
  .shell { padding-left: 14px; padding-right: 14px; }
  .manage-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field--inline { flex-wrap: wrap; }
  .field--inline > * { flex: 1 1 100%; }
  .medals { gap: 6px; }
  .medal { padding: 10px 4px 8px; }
  .stat__num { font-size: 23px; }
}

@media (min-width: 720px) {
  .hero__name { font-size: 66px; }
  .medals { gap: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ------------------------------------------------------------------ season record
   Awards, self reflection and the Habits Review. Coach side is dense by nature: three of these
   are paper documents with a lot of rows, so the job is to keep them scannable on a phone
   without pretending they are smaller than they are. */

.season-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  margin-top: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  text-align: left;
  color: var(--white);
  font: inherit;
  cursor: pointer;
}
.season-row[aria-selected='true'] { border-color: var(--orange); background: var(--orange-soft); }
/* A floor on the name, and the row wraps rather than crushing it. Without this the six award
   dots squeezed "Asher 24 / 0/6 awards" into one word per line. */
.season-row { flex-wrap: wrap; row-gap: 8px; }
.season-row__body { flex: 1 1 160px; min-width: 145px; }
.season-row__dots { display: flex; gap: 4px; flex-shrink: 0; }

.award-dot {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  background: var(--panel-3);
  color: var(--muted-2);
  border: 1px solid var(--line);
}
.award-dot[data-tier='bronze'] { background: rgba(205, 127, 69, 0.2); color: var(--bronze); border-color: var(--bronze); }
.award-dot[data-tier='silver'] { background: rgba(200, 205, 212, 0.2); color: var(--silver); border-color: var(--silver); }
.award-dot[data-tier='gold'] { background: rgba(243, 183, 57, 0.2); color: var(--gold); border-color: var(--gold); }

.award {
  padding: 14px;
  margin-top: 10px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.tier-picker { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }

.checks { margin-top: 10px; }
.check {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 0;
  border-top: 1px solid var(--line);
  font-size: 15px;
}
.check__mark { width: 16px; color: var(--muted-2); font-weight: 700; }
.check[data-met='true'] .check__mark { color: var(--orange); }
.check__label { flex: 1; min-width: 0; }
.check__score { color: var(--muted-2); font-size: 15px; white-space: nowrap; }

.criteria { margin-top: 12px; }
.criteria > summary { cursor: pointer; color: var(--orange); font-size: 15px; padding: 4px 0; }
.criteria__row { padding: 10px 0; border-top: 1px solid var(--line); }
.criteria__name { font-family: var(--font-display); font-size: 16px; margin-bottom: 6px; }
.criteria__name small { display: block; color: var(--muted-2); font-family: var(--font-body); font-size: 14.5px; }
.criteria__cell { margin-top: 6px; }
.criteria__tier { font-family: var(--font-display); font-size: 15px; letter-spacing: 0.04em; }
.criteria__cell ul { margin: 2px 0 0; padding-left: 18px; }
.criteria__cell li { font-size: 15.5px; color: var(--muted); }

/* Self reflection: the player's number, the coach's picker, and the gap between them. */
.reflect {
  padding: 12px 0;
  border-top: 1px solid var(--line);
}
.reflect__text { font-size: 16.5px; margin-bottom: 8px; }
.reflect__scores { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.reflect__mine { color: var(--muted-2); font-size: 15px; white-space: nowrap; }
.reflect__gap {
  font-family: var(--font-display);
  font-size: 14.5px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--panel-3);
  color: var(--muted);
}
.reflect__gap[data-sign='same'] { color: var(--orange); }

.score-picker { display: flex; gap: 6px; }
.score {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 18px;
  cursor: pointer;
}
.score[aria-selected='true'] { background: var(--orange); border-color: var(--orange); color: var(--black); }

/* Habits review: one season window at a time, so the grade buttons always have a heading and
   nothing needs to scroll sideways on a phone. */
.habits { margin-top: 12px; }
.habits__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}
.habits__label { flex: 1; min-width: 0; font-size: 16.5px; }
.habits__label small {
  display: block;
  margin-top: 3px;
  color: var(--muted-2);
  font-size: 15px;
}
.habits__cat {
  margin-top: 14px;
  padding: 6px 0 4px;
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--orange);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.habits__cell { display: flex; gap: 6px; flex-shrink: 0; }
.grade {
  width: 54px;
  padding: 11px 0;
  border-radius: 10px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--white);
  /* Body font, not the condensed display face: two letters at a small size need the room. */
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.03em;
  cursor: pointer;
}
.grade[aria-selected='true'] { background: var(--orange); border-color: var(--orange); color: var(--black); }

/* The thing a coach needs to read before typing about a child. */
.notice {
  padding: 12px 14px;
  border-radius: 12px;
  background: rgb(var(--brand-rgb) / 0.1);
  border: 1px solid var(--orange);
  font-size: 15px;
}
.notice strong { display: block; font-family: var(--font-display); margin-bottom: 4px; color: var(--orange); }

/* On a phone the award title and its three tier chips fight over one row, and the chips wrap
   two-and-one. Stack them instead so the tiers always read as a single set of three. */
@media (max-width: 460px) {
  .award > .row-between {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .tier-picker .chip { flex: 1; text-align: center; padding-left: 8px; padding-right: 8px; }
}

/* On a phone the three grade buttons and a wrapping habit name squeeze each other into an
   unreadable column. Give the buttons their own full-width row underneath instead: bigger tap
   targets, and the habit name gets the whole line. */
@media (max-width: 520px) {
  .habits__row {
    flex-direction: column;
    align-items: stretch;
    gap: 9px;
  }
  .habits__cell { width: 100%; }
  .habits__cell .grade { flex: 1; width: auto; font-size: 17px; padding: 12px 0; }
}

/* Season record search. Sticks under the header so it stays reachable with a long squad list. */
.season-search { position: sticky; top: 0; z-index: 2; padding: 8px 0; background: var(--black); }
.season-search input {
  width: 100%;
  padding: 12px 14px;
  font-size: 17px;
  border-radius: 12px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--white);
}
.season-search input::placeholder { color: var(--muted-2); }
.season-search input:focus { outline: 2px solid var(--orange); outline-offset: 1px; }

/* Inline field errors on the sign-in screen. */
.field__error {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 15px;
  color: #ffb4a2;
}
.field__fix {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--orange-soft);
  border: 1px solid var(--orange);
  color: var(--orange);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
}
.field input[aria-invalid='true'] { border-color: #ffb4a2; }

/* Manage drills row on a phone. Station, name, four target chips and an Edit button will not sit
   on one 375px line: the name ends up one word per row. Stack it instead, the same way the habits
   rows are stacked, so the drill name gets a full line and the targets get their own. */
@media (max-width: 560px) {
  .manage-row {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas:
      'station body'
      'targets targets'
      'edit    edit';
    align-items: start;
    gap: 6px 12px;
    row-gap: 10px;
  }
  .manage-row > .drill__station { grid-area: station; align-self: center; }
  .manage-row__body { grid-area: body; align-self: center; }
  .manage-row__targets { grid-area: targets; flex-wrap: wrap; }
  .manage-row > .chip { grid-area: edit; justify-self: start; }
}

/* Short labels must never break across lines. The chip row already wraps chip-by-chip, so a chip
   splitting into "Squad / board" is always wrong, and a sign-up code split over two lines is
   unreadable as a code. */
.chip,
.tag,
.target-chip,
.grade,
.score,
.badge,
.badge--none,
.code-row__code,
.board-station,
.drill__station,
.award-dot { white-space: nowrap; }

/* An awarded tier should look like the award. Unselected reads as an outline in the tier colour;
   selected fills with it. All three tier colours are light, so the text goes black on top: that
   clears 6.6:1 on bronze, the darkest of them. */
.chip--tier[data-tier='bronze'] { color: var(--bronze); border-color: rgba(205, 127, 69, 0.5); }
.chip--tier[data-tier='silver'] { color: var(--silver); border-color: rgba(200, 205, 212, 0.5); }
.chip--tier[data-tier='gold'] { color: var(--gold); border-color: rgba(243, 183, 57, 0.5); }

.chip--tier[aria-selected='true'] { color: var(--black); font-weight: 700; }
.chip--tier[data-tier='bronze'][aria-selected='true'] { background: var(--bronze); border-color: var(--bronze); }
.chip--tier[data-tier='silver'][aria-selected='true'] { background: var(--silver); border-color: var(--silver); }
.chip--tier[data-tier='gold'][aria-selected='true'] { background: var(--gold); border-color: var(--gold); }

/* Activity: the player filter, and the name as a shortcut to filter by that player. */
.feed-filter { display: flex; flex-direction: column; gap: 6px; }
.feed-filter select {
  width: 100%;
  padding: 12px 14px;
  font-size: 1rem;
  border-radius: 12px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--white);
}
.feed__who--link {
  background: none;
  border: none;
  padding: 0;
  text-align: left;
  color: var(--orange);
  font: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: rgb(var(--brand-rgb) / 0.4);
  text-underline-offset: 3px;
}
.feed__who--muted { color: var(--muted-2); }

/* The sign-up code is a button that copies. Make that visible rather than a hidden trick. */
.code-row__code { display: inline-flex; align-items: center; gap: 8px; }
.code-row__value { letter-spacing: 0.14em; }
.code-row__copy { display: inline-flex; width: 16px; opacity: 0.8; }
.code-row__copy svg { width: 100%; height: auto; }
.code-row__label { font-family: var(--font-body); font-weight: 700; letter-spacing: 0; opacity: 0.85; }
.code-row__code[data-copied='true'] {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--black);
}

/* Section chips are links now, so stop them looking like link text. */
.coach-nav a.chip { text-decoration: none; }

/* Habits review header: window picker on the left, the key on the right, both above the columns. */
.habits-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-top: 4px;
}
.habits-key {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  padding: 10px 12px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.habits-key__title {
  font-family: var(--font-display);
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.habits-key__item { display: flex; align-items: center; gap: 8px; }
.habits-key__swatch {
  display: grid;
  place-items: center;
  min-width: 42px;
  padding: 6px 0;
  border-radius: 9px;
  background: var(--panel-3);
  border: 1px solid var(--line-strong);
  color: var(--white);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
}
.habits-key__text { display: flex; flex-direction: column; line-height: 1.25; }
.habits-key__text strong { font-size: 15px; }
.habits-key__text small { color: var(--muted-2); font-size: 14px; }

/* Season record: who is picked, once the list has collapsed. */
.season-picked {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  margin-top: 8px;
  background: var(--orange-soft);
  border: 1px solid var(--orange);
  border-radius: 14px;
}
.season-picked__body { flex: 1; min-width: 0; }

/* Coach notes: a box you can actually write in, with the two bits of formatting that get used. */
.note-field {
  padding: 14px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.note-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
}
.note-editor,
.note-input {
  width: 100%;
  min-height: 220px;
  padding: 14px;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--white);
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  resize: vertical;
}
.note-editor:focus, .note-input:focus { outline: 2px solid var(--orange); outline-offset: 1px; }
.note-field__foot { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
.note-body {
  margin-top: 6px;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px dashed var(--line-strong);
  border-radius: 12px;
}
.note-body p { margin: 0 0 8px; }
.note-body p:last-child { margin-bottom: 0; }
.note-body__list { margin: 0 0 8px; padding-left: 20px; }
.note-body__list li { margin-bottom: 4px; }
.note-body strong { color: var(--white); font-weight: 700; }

/* ------------------------------------------------------------------ global type scale
   Two presses of ctrl/cmd + in Chrome is 125%, and that is the size the club wants as default.
   `zoom` reproduces it exactly, layout and spacing included, rather than only growing text inside
   boxes that stay the same size, which is what breaks rows. */
body { zoom: 1.25; }

/* Recent attempts row: value, drill, tier badge and time. At the larger default scale that is
   more than a narrow phone can fit on one line, so let it wrap rather than push the page sideways.
   The drill name shrinks first, and the badge and time drop to a second line only if they must. */
.history__row { flex-wrap: wrap; }
.history__when { min-width: 0; }
@media (max-width: 560px) {
  .history__value { min-width: 52px; }
}

/* ------------------------------------------------------------------ games */

.game-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 12px 14px;
  margin-top: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 4px solid var(--line-strong);
  border-radius: 14px;
  text-align: left;
  color: var(--white);
  font: inherit;
}
.game-row[aria-selected='true'] { border-color: var(--orange); background: var(--orange-soft); }
.game-row[data-result='won'] { border-left-color: #5fd08a; }
.game-row[data-result='lost'] { border-left-color: #e07a6a; }
.game-row[data-result='drew'] { border-left-color: var(--muted-2); }
.game-row__when { flex: none; min-width: 92px; }
.game-row__when strong { display: block; font-family: var(--font-display); font-size: 1rem; }
.game-row__when small { color: var(--muted-2); font-size: 0.85rem; }
.game-row__who { flex: 1; min-width: 0; }

.game-score {
  flex: none;
  padding: 6px 10px;
  border-radius: 10px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1rem;
  background: var(--panel-3);
  white-space: nowrap;
}
.game-score[data-result='won'] { background: rgba(95, 208, 138, 0.18); color: #7ee0a2; }
.game-score[data-result='lost'] { background: rgba(224, 122, 106, 0.18); color: #f0998b; }
.game-score--tbc { background: none; color: var(--muted-2); font-weight: 500; }

.game-links { display: flex; flex-direction: column; gap: 8px; }
.game-link {
  display: flex;
  flex-direction: column;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--orange);
  text-decoration: none;
}
.game-link strong { font-size: 1rem; }
.game-link small { color: var(--muted-2); font-size: 0.85rem; }

.travel-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px 14px;
  margin-top: 10px;
}
.travel-grid__label { color: var(--muted-2); }
.travel-grid__value { font-weight: 700; }

/* Squad picking: one row per player, four states. */
/* Picking a squad, as a board rather than a list.
   23 players as full-width rows was most of a phone screen of scrolling for a job a coach does in
   a car park. Tiles put the whole squad in view at once, shirt number first, which is how a team
   sheet is read. */
/* A location field and the button that opens it, on one line. The button keeps its width and the
   input takes the rest, so the three of them line up down the form. */
.field__open {
  flex: none;
  text-decoration: none;
  gap: 6px;
}
.field__open[aria-disabled='true'] {
  opacity: 0.4;
  pointer-events: none;
}
.field__open-icon { display: block; width: 15px; }

/* The notes box and the line above it share a width, so the block reads as one thing rather than
   a full-width banner sitting on a narrower box. */
.card textarea + *,
.note--pad + textarea { max-width: var(--measure); }

/* A fixture row: the whole left side opens the game, the two buttons on the right do the jobs a
   coach wants without opening it at all. */
.game-row__open {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 14px;
  text-align: left;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  padding: 0;
  cursor: pointer;
}
.game-row__quick { display: flex; align-items: center; gap: 6px; flex: none; }

/* On a phone there is not room for the date, the fixture, the status badge and two buttons on one
   line: they crushed into each other, with the icons landing on top of the badge. The row becomes
   two lines instead, the fixture across the top and the buttons under it on the right. */
@media (max-width: 560px) {
  .game-row { flex-wrap: wrap; row-gap: 10px; }
  .game-row__open { flex: 1 1 100%; flex-wrap: wrap; gap: 4px 10px; }
  /* Date and status share the top line, the fixture gets a line to itself underneath. Sharing one
     line left about 80px for the opponent, so "vs Bristol" came out three words tall. */
  .game-row__when { min-width: 0; }
  .game-row__who { flex: 1 1 100%; order: 3; }
  .game-row .game-score { margin-left: auto; }
  .game-row__quick { margin-left: auto; }
}
.chip--icon {
  width: 42px;
  min-height: 42px;
  padding: 0;
  justify-content: center;
}
.chip__glyph { display: block; width: 19px; }

/* Newer / Older either side of where you are in the log. */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.pager .chip:disabled { opacity: 0.4; cursor: not-allowed; }

.squad-grid {
  display: grid;
  /* 64px is chosen against the phone, not the desktop: inside the game card there is about 240px
     of layout width, so this is the largest tile that still gives three columns instead of two. */
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 7px;
  margin-top: 10px;
}
.squad-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 66px;
  padding: 8px 4px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--white);
  font: inherit;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.squad-tile:hover { border-color: var(--line-strong); background: var(--panel-2); }
.squad-tile:active { transform: scale(0.97); }
.squad-tile__num {
  font-family: var(--font-display);
  font-size: 1.3rem;
  line-height: 1;
}
.squad-tile__name {
  font-size: 0.72rem;
  line-height: 1.15;
  color: var(--muted);
  overflow-wrap: anywhere;
}
/* Picked is unmistakable at a glance across a whole board of them. */
.squad-tile[aria-pressed='true'] {
  background: var(--orange);
  border-color: var(--orange);
  color: var(--black);
}
.squad-tile[aria-pressed='true'] .squad-tile__name { color: rgba(8, 8, 10, 0.75); }
.squad-tile[aria-pressed='true']:hover { background: var(--flame); border-color: var(--flame); }

.squad-pick {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}
.squad-pick__body { flex: 1; min-width: 0; }
.squad-pick__actions { display: flex; gap: 6px; flex-wrap: wrap; flex: none; }
.squad-pick[data-status='selected'] { background: rgba(95, 208, 138, 0.06); }
.squad-pick[data-status='injured'],
.squad-pick[data-status='sick'],
.squad-pick[data-status='absent'] { opacity: 0.7; }

.score-head {
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  font-family: var(--font-display);
  font-size: 1.1rem;
}
.score-head[data-result='won'] { border-color: #5fd08a; }
.score-head[data-result='lost'] { border-color: #e07a6a; }

.stat-row {
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 8px;
  margin-top: 8px;
}
.stat-cell { display: flex; flex-direction: column; gap: 4px; }
.stat-cell span { color: var(--muted-2); font-size: 0.85rem; }
.stat-cell input {
  width: 100%;
  padding: 10px;
  font-size: 1rem;
  text-align: center;
  border-radius: 10px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--white);
}


/* Picking who travels, inside the game form. */
.pick-squad { margin-top: 8px; }
.pick-squad__bulk { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
.pick-player {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 6px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--white);
  font: inherit;
  font-size: 1rem;
  text-align: left;
  cursor: pointer;
}
.pick-player[aria-pressed='true'] {
  border-color: #5fd08a;
  background: rgba(95, 208, 138, 0.12);
}
.pick-player__tick {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  color: var(--black);
  font-weight: 700;
}
.pick-player[aria-pressed='true'] .pick-player__tick { background: #5fd08a; border-color: #5fd08a; }
.pick-player__name { flex: 1; min-width: 0; }
.pick-player__flag { color: var(--gold); font-size: 0.85rem; white-space: nowrap; }
.pick-player[data-unavailable='true'] .pick-player__name { color: var(--muted); }

@media (max-width: 560px) {
  .game-row { flex-wrap: wrap; }
  .game-row__when { min-width: 100%; }
  /* One line per player, even on a phone. This list is 23 names long, and a rule that put the
     button on its own row made each one three times as tall as it needed to be: picking a squad
     became a long scroll instead of a column you can thumb down.
     The button shrinks instead of wrapping, and the row keeps a comfortable tap height. */
  .squad-pick { flex-wrap: nowrap; gap: 8px; }
  .squad-pick__actions { flex-wrap: nowrap; width: auto; }
  .squad-pick__actions .chip {
    min-height: 40px;
    padding: 0 10px;
    font-size: 13px;
    letter-spacing: 0.04em;
    white-space: nowrap;
  }
  .squad-pick .drill__name { font-size: 17px; }
  .squad-pick .manage-row__meta { font-size: 13px; }
  /* A label like "Back by (rough)" leaves the value almost no room, and a venue name ends up one
     word per line. Stack them so each gets the full width. */
  .travel-grid { grid-template-columns: 1fr; gap: 2px; }
  .travel-grid__label { margin-top: 8px; }
}

/* Topbar at the larger default scale. On a phone the row wants logo + title + squad label +
   avatar in 300 units and cannot have it, so the title used to shrink its box without shrinking
   its text and print straight over the label.
   The squad or Coach label goes: the page heading underneath already says which it is. The offline
   and "waiting to send" badges stay, because those are the ones you actually need to see. */
.topbar__title { min-width: 0; }
@media (max-width: 560px) {
  /* Three things have to fit across a phone: the club badge, the product name and the player's own
     name. This used to hide the last of those, on the grounds that a squad label repeated what the
     page heading already said. It now carries their name and number, which is how they know whose
     account they are opening, so instead the badge comes down to a size that leaves room for both.
     A 114px badge was a third of the screen width before anything else was drawn. */
  .topbar__title { font-size: 22px; }
  .topbar__logo { width: 56px; height: 56px; border-radius: 13px; }
  .tag--me { font-size: 14px; padding: 0 9px; }
  /* Nine pixels short of fitting the name in full, which is the whole difference between
     "CourtCraft" and "CourtCr...". Taken off the gaps rather than the type. */
  .topbar { gap: 8px; padding-left: 12px; padding-right: 12px; }
}

/* The date and time picker glyphs.
   `color-scheme: dark` above already tells the browser to draw its own controls light, and an
   invert filter on top of that turned them straight back to black, which is what made them look
   unchanged. So no filter: instead the glyph is replaced with our own in the club orange, which
   does not depend on how any particular browser paints its default. Firefox ignores this
   pseudo-element and follows color-scheme, which it supports. */
input[type='date']::-webkit-calendar-picker-indicator,
input[type='time']::-webkit-calendar-picker-indicator {
  width: 22px;
  height: 22px;
  padding: 0;
  margin-left: 6px;
  cursor: pointer;
  opacity: 0.9;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 20px 20px;
}
input[type='date']::-webkit-calendar-picker-indicator {
  background-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23f5883a'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'><rect%20x='3'%20y='5'%20width='18'%20height='16'%20rx='2'/><path%20d='M8%203v4M16%203v4M3%2011h18'/></svg>");
}
input[type='time']::-webkit-calendar-picker-indicator {
  background-image: url("data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23f5883a'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'><circle%20cx='12'%20cy='12'%20r='9'/><path%20d='M12%207v5l3.5%202'/></svg>");
}
input[type='date']:hover::-webkit-calendar-picker-indicator,
input[type='time']:hover::-webkit-calendar-picker-indicator { opacity: 1; }

input[type='date'],
input[type='time'] { color: var(--white); font-family: var(--font-body); font-size: 1rem; }

/* Base styling for every form control, not just the ones inside a .field label. Anything outside
   one used to fall back to the browser default, which on a dark page means a white box: the
   coach notes outside a .field label were doing exactly that. Element-level specificity on
   purpose, so the components with their own look (.stat-cell input, .note-input, the search box)
   still win. */
input, select, textarea {
  min-height: var(--tap);
  padding: 0 14px;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--white);
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
}
textarea { padding: 12px 14px; line-height: 1.55; }
input::placeholder, textarea::placeholder { color: var(--muted-2); }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 1px;
}

/* Two equal columns for a pair of fields. .manage-grid is 90px + rest, which is right for
   "Station / Name" and wrong for anything else: it was making Squad 90px wide and the away score
   full width. */
.form-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.form-pair .field { margin-bottom: 0; }
.score-pair { display: flex; gap: 12px; align-items: flex-end; }
.score-pair .field { margin-bottom: 0; }
.score-pair input { width: 110px; text-align: center; font-size: 1.15rem; }
@media (max-width: 560px) {
  .form-pair { grid-template-columns: 1fr; }
}

/* Post-save summary. */
.saved-banner {
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(95, 208, 138, 0.12);
  border: 1px solid #5fd08a;
  margin-bottom: 12px;
}
.saved-banner strong {
  display: block;
  font-family: var(--font-display);
  color: #7ee0a2;
  margin-bottom: 2px;
}
.summary-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 14px;
  margin-top: 4px;
}
.summary-grid__label,
.summary-grid__value { padding: 7px 0; border-bottom: 1px solid var(--line); }
.summary-grid__label { color: var(--muted-2); }
.summary-grid__value { font-weight: 700; }
.summary-grid__value--todo { color: var(--muted-2); font-weight: 500; font-style: italic; }
.summary-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 14px; }

@media (max-width: 560px) {
  .summary-grid { grid-template-columns: 1fr; gap: 0; }
  .summary-grid__label { border-bottom: none; padding-bottom: 0; }
  .summary-grid__value { padding-top: 2px; }
  .summary-actions .btn, .summary-actions .chip { flex: 1 1 100%; text-align: center; }
}

/* Coach controls on a Huish TV card. */
.tv-card__admin { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
.tv-card[data-retired='true'] { opacity: 0.6; }
.tv-card[data-retired='true'] .tv-card__title::after {
  content: ' (hidden)';
  color: var(--muted-2);
  font-family: var(--font-body);
  font-size: 0.85rem;
}

/* Overview: a player's name carries their average award level as a background, so a coach can
   scroll the board and see who needs a word without reading a single number.
   The tier colours are all light, so the text goes black on top: bronze is the darkest and still
   clears 6.6:1. No colour at all means nothing logged yet, which is exactly the group a coach is
   looking for and is why the "not signed up" line could go. */
table.board tbody th.board-name { color: var(--white); }
table.board tbody th.board-name[data-tier='bronze'],
table.board tbody th.board-name[data-tier='silver'],
table.board tbody th.board-name[data-tier='gold'],
table.board tbody th.board-name[data-tier='platinum'] { color: var(--black); }
table.board tbody th.board-name[data-tier='bronze'] { background: var(--bronze); }
table.board tbody th.board-name[data-tier='silver'] { background: var(--silver); }
table.board tbody th.board-name[data-tier='gold'] { background: var(--gold); }
table.board tbody th.board-name[data-tier='platinum'] { background: var(--platinum); }
/* The row hover rule would otherwise wash the tier colour out. */
table.board tr:hover th.board-name[data-tier='bronze'] { background: var(--bronze); }
table.board tr:hover th.board-name[data-tier='silver'] { background: var(--silver); }
table.board tr:hover th.board-name[data-tier='gold'] { background: var(--gold); }
table.board tr:hover th.board-name[data-tier='platinum'] { background: var(--platinum); }

/* The average row. Deliberately unlike a player row: it is a summary, not somebody. */
table.board tfoot tr.board-average th,
table.board tfoot tr.board-average td {
  border-top: 2px solid var(--orange);
  border-bottom: none;
  background: var(--panel-3);
  padding-top: 12px;
  padding-bottom: 12px;
}
table.board tfoot tr.board-average th {
  position: sticky;
  left: 0;
  z-index: 1;
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--orange);
}
.cell--avg {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.15;
  color: var(--white);
  font-weight: 700;
}
.cell__of { color: var(--muted-2); font-size: 0.75rem; font-weight: 500; }

/* The admin coach's activity log. */
.log { margin-top: 8px; }
.log-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.log-row__who {
  flex: none;
  min-width: 96px;
  font-family: var(--font-display);
  font-size: 0.95rem;
  color: var(--orange);
}
.log-row__what { flex: 1; min-width: 0; }
.log-row__what small { display: block; color: var(--muted-2); font-size: 0.85rem; margin-top: 2px; }
.log-row__when { flex: none; color: var(--muted-2); font-size: 0.85rem; white-space: nowrap; }
@media (max-width: 560px) {
  .log-row { flex-wrap: wrap; gap: 4px 10px; }
  .log-row__who { min-width: 0; }
  .log-row__when { width: 100%; }
}

/* Reflection scores read as a level: picking 4 lights 1 to 4. The chosen number itself is marked
   so it is still obvious which one was tapped. */
.score[data-exact='true'] { box-shadow: inset 0 0 0 2px var(--black); }

/* Habits review: traffic lights. Emerging is where the work is, excelling is there.
   Black text on all three, which clears 6.6:1 on the darkest of them. */
.grade[aria-selected='true'][data-grade='EM'],
.habits-key__swatch[data-grade='EM'] { background: #e07a6a; border-color: #e07a6a; color: var(--black); }
.grade[aria-selected='true'][data-grade='ES'],
.habits-key__swatch[data-grade='ES'] { background: var(--gold); border-color: var(--gold); color: var(--black); }
.grade[aria-selected='true'][data-grade='EX'],
.habits-key__swatch[data-grade='EX'] { background: #5fd08a; border-color: #5fd08a; color: var(--black); }
/* Unselected still hints at the colour, so the key and the buttons match at a glance. */
.grade[data-grade='EM'] { border-color: rgba(224, 122, 106, 0.45); }
.grade[data-grade='ES'] { border-color: rgba(243, 183, 57, 0.45); }
.grade[data-grade='EX'] { border-color: rgba(95, 208, 138, 0.45); }

/* The coach note editor. Formatted as you type; stored as plain text. */
.note-editor { overflow-y: auto; cursor: text; }
/* Return in a contenteditable produces a <p> in some situations and a bare <div> in others,
   depending on where the caret was. Styling only the <p> meant one Return gave you an 8px gap and
   the next gave you none, which is the uneven spacing this fixes. Both are paragraphs here. */
.note-editor p,
.note-editor div { margin: 0 0 8px; }
.note-editor p:last-child,
.note-editor div:last-child { margin-bottom: 0; }
.note-editor ul { margin: 0 0 8px; padding-left: 22px; }
.note-editor li { margin-bottom: 4px; }
.note-editor strong { color: var(--white); font-weight: 700; }
.note-editor:empty::before,
.note-editor p:only-child:empty::before {
  content: 'Start typing. Use B for bold and the list button for bullets.';
  color: var(--muted-2);
}

/* Tiger's TV: squad tag first, topic second. */
.tv-card__tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.tv-card__topic--soft { color: var(--muted-2); border-color: var(--line); }

/* A player's name in the Players list opens their own page. */
.code-row__name--link { color: var(--white); text-decoration: none; }
.code-row__name--link:hover { color: var(--orange); }

/* The per-player page. */
.award-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.dash-game {
  padding: 12px 14px;
  margin-top: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.dash-game__head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.dash-game__head strong { flex: 1; min-width: 0; }
.dash-stats { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.dash-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 54px;
  padding: 6px 8px;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 10px;
}
.dash-stat strong { font-family: var(--font-display); font-size: 1.1rem; }
.dash-stat small { color: var(--muted-2); font-size: 0.75rem; }

.dash-head { padding: 4px 0 10px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.dash-head h2 {
  font-family: var(--font-display);
  font-size: 1.6rem;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  margin-bottom: 2px;
}

/* Club Info. */
.club-section { margin-top: 16px; }
.club-section h2 {
  font-family: var(--font-display);
  font-size: 1.4rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 8px;
}
/* Somewhere to go: paying the fees, buying the kit. Big tap targets, because on the fees page the
   whole point of the screen is the link. */
.linkset { display: grid; gap: 10px; margin-top: 16px; }
.linktile {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  color: var(--white);
  text-decoration: none;
  min-height: var(--tap);
  transition: border-color 0.18s, background 0.18s;
}
.linktile:hover { border-color: var(--orange); background: var(--panel-2); }
/* White behind the thumbnail on purpose: the kit is black, and a product shot of it on the app's
   own near-black panel would be a black square. */
.linktile__pic {
  flex: none;
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  padding: 4px;
  background: #ffffff;
  border-radius: 10px;
}
.linktile__pic img { display: block; max-width: 100%; max-height: 100%; }
.linktile__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.linktile__label {
  font-family: var(--font-display);
  font-size: 1.25rem;
  letter-spacing: 0.01em;
}
.linktile__note { font-size: 0.9rem; line-height: 1.35; color: var(--muted); }
/* Top right, not centred with the text: the mark belongs to the tile as a whole, and the eye reads
   a corner badge as "about this thing" rather than as part of the sentence. */
.linktile__out {
  flex: none;
  align-self: flex-start;
  display: block;
  width: 20px;
  height: 20px;
  color: var(--orange);
}
.linktile:hover .linktile__out { color: var(--white); }

/* For a screen reader only: it cannot see the icon above. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The admin coach's list of them. */
.linkrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}
.linkrow__body { flex: 1; min-width: 0; }
.linkrow { flex-wrap: wrap; }
.linkrow__thumb {
  flex: none;
  width: 44px;
  height: 44px;
  object-fit: contain;
  background: #ffffff;
  border-radius: 8px;
  padding: 2px;
}

/* One photograph in the admin coach's list: thumbnail, caption, and the buttons that move or
   remove it. */
.photorow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.photorow__thumb {
  flex: none;
  width: 64px;
  height: 48px;
  object-fit: cover;
  border-radius: 8px;
  background: var(--black);
}
.photorow__body { flex: 1; min-width: 140px; }
.photorow__acts { display: flex; gap: 6px; flex-wrap: wrap; }
.photorow__acts .chip { min-height: 38px; padding: 0 11px; font-size: 14px; }
.linkrow__label { font-family: var(--font-display); font-size: 1.05rem; }
.linkrow__url { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.82rem; }

/* Old club photographs. Scaled to fit rather than cropped: the set mixes portrait and landscape,
   and a crop takes the ball out of the action shots. */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 14px;
}
.gallery__item {
  display: block;
  margin: 0;
  padding: 0;
  width: 100%;
  text-align: left;
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  color: inherit;
  font: inherit;
  cursor: zoom-in;
  transition: border-color 0.18s;
}
.gallery__item:hover { border-color: var(--line-strong); }
/* The corner marker is what tells you the photo opens. Without it a tappable picture reads as
   decoration and nobody tries it. */
.gallery__zoom {
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: rgba(8, 8, 10, 0.72);
  border: 1px solid var(--line-strong);
  color: var(--white);
  font-size: 15px;
  line-height: 1;
}
.gallery__img {
  display: block;
  width: 100%;
  height: 190px;
  object-fit: contain;
  background: var(--black);
}
.gallery__caption {
  display: block;
  padding: 8px 10px 10px;
  font-size: 0.86rem;
  line-height: 1.35;
  color: var(--muted);
}

/* Full screen photo -------------------------------------------- */

/* Fixed to the viewport rather than appended inside the scrolling shell, so the page behind cannot
   drag the photo off screen. The body scroll is frozen while it is open for the same reason. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  /* Room at the top for the close button, so it never sits on top of the photograph. */
  padding: 64px 16px 16px;
  /* Fully opaque, not a dark veil: the page behind is a wall of text and a bright tab bar, and any
     of it showing through fights the photograph. */
  background: var(--black);
  animation: lightbox-in 0.14s ease-out;
}
@keyframes lightbox-in { from { opacity: 0; } to { opacity: 1; } }
body.is-lightboxed { overflow: hidden; }

/* Sized by flex rather than in vh. The shell sets zoom on the body for the global type scale,
   which multiplies every vh by that factor, so a photo measured in vh overflows the screen. The
   overlay is already exactly the viewport, so letting the photo take whatever is left after the
   caption and the bar is both simpler and correct at any zoom. */
.lightbox__stage {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  max-width: 100%;
  cursor: default;
}
.lightbox__img {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  max-width: 100%;
  object-fit: contain;
  border-radius: 12px;
  background: var(--black);
}
.lightbox__caption,
.lightbox__bar { flex: none; }
.lightbox__caption {
  max-width: 34rem;
  text-align: center;
  font-size: 1rem;
  line-height: 1.4;
  color: var(--white);
}
.lightbox__bar {
  display: flex;
  align-items: center;
  gap: 14px;
}
.lightbox__counter {
  font-family: var(--font-display);
  font-size: 1rem;
  letter-spacing: 0.04em;
  color: var(--muted);
  min-width: 5.5rem;
  text-align: center;
}
.lightbox__step,
.lightbox__close {
  display: grid;
  place-items: center;
  width: var(--tap);
  height: var(--tap);
  border-radius: 50%;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  color: var(--white);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.lightbox__step:hover,
.lightbox__close:hover { background: var(--panel-3); border-color: var(--orange); }
.lightbox__close {
  position: absolute;
  top: 12px;
  right: 12px;
  font-size: 18px;
}
@media (max-width: 420px) {
  .lightbox { padding: 60px 12px 12px; }
  .lightbox__caption { font-size: 0.94rem; }
}

.person {
  display: flex;
  gap: 12px;
  padding: 12px 14px;
  margin-top: 8px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.person--edit { display: block; }
.person__initials {
  display: grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--orange);
  color: var(--black);
  font-family: var(--font-display);
  font-size: 1.1rem;
}
.person__body { flex: 1; min-width: 0; }
.person__name { font-family: var(--font-display); font-size: 1.15rem; }
.person__role { color: var(--orange); font-size: 0.9rem; margin-bottom: 4px; }

/* Picking three words, first time in. */
.phrase-card {
  display: block;
  width: 100%;
  padding: 14px;
  margin-bottom: 10px;
  text-align: left;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  color: var(--white);
  font: inherit;
  cursor: pointer;
}
.phrase-card[aria-pressed='true'] { border-color: var(--orange); background: var(--orange-soft); }
/* Tiles on the left, the story in the space to their right.
   Wrapping rather than a media query, because the same card appears in a narrow sign-in column and
   in the much wider app shell: below its 200px minimum the story drops onto its own line and takes
   the full width, which is what it used to do anyway. A width query would have to know which of
   the two it was in. */
.phrase-card__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}
.phrase-card__story {
  /* 180px is chosen against the app shell, not the screen: the three tiles are 280px and the
     widest card is about 500px of layout space, so this fits beside them there and cannot fit in
     the ~370px sign-in column, which is exactly the split we want. Sized in CSS pixels, which the
     shell's zoom then scales up, so do not compare these numbers to a screenshot. */
  flex: 1 1 180px;
  min-width: 170px;
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: 0;
  color: var(--muted);
}
.phrase-card__story strong { color: var(--white); font-weight: 700; }
.phrase-card[aria-pressed='true'] .phrase-card__story { color: var(--white); }

/* One question per screen. The step line and the question are the two things a player should read
   before anything else, so they get the top of the card and real size. */
.wizard { padding-bottom: 18px; }
.wizard__step {
  font-family: var(--font-display);
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--orange);
  margin-top: 10px;
}
.wizard__ask {
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1.15;
  margin: 4px 0 8px;
}
.wizard__done {
  font-family: var(--font-display);
  font-size: 1.1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold);
  margin-top: 10px;
}
.wizard input[type='text'] { margin-top: 6px; }
.wizard .btn + .btn { margin-top: 10px; }

/* A tappable set of words. The bar across the foot is a label on the card, not a button of its
   own: the whole card is the button, so one tap picks the set and moves the player on. A pill
   floating under the tiles looked like a second, separate control and sat in dead space. */
.phrase-card--pick { display: block; text-align: left; padding-bottom: 0; }
.phrase-card__use {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 14px;
  padding: 12px 2px 2px;
  border-top: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--orange);
  pointer-events: none;
}
.phrase-card__chev { font-size: 1.3rem; line-height: 1; }
.phrase-card--pick:hover { border-color: var(--orange); background: var(--panel-2); }
.phrase-card--pick:hover .phrase-card__use { color: var(--white); }

/* The set being confirmed. Not a button, so nothing about it invites another tap. */
.phrase-card--shown {
  display: block;
  border-color: var(--orange);
  background: var(--orange-soft);
  cursor: default;
}
.phrase-card--shown .phrase-card__word { background: var(--orange); color: var(--black); }
.phrase-card--shown .phrase-card__story { color: var(--white); }

.phrase-card__words { display: flex; flex-wrap: wrap; gap: 8px; }
.phrase-card__word {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--panel-3);
  font-family: var(--font-display);
  font-size: 1.3rem;
  letter-spacing: 0.02em;
}
.phrase-card__pic { width: 64px; height: 64px; object-fit: contain; border-radius: 8px; }
/* The emoji is sized to match the artwork slot exactly, so a word that later gets a drawn picture
   does not change the size of the card. line-height 1 keeps the glyph centred in its box. */
.phrase-card__emoji {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  font-size: 44px;
  line-height: 1;
}
.phrase-card__words { flex-wrap: nowrap; }
@media (max-width: 400px) {
  .phrase-card__word { padding: 8px; font-size: 1.15rem; }
  .phrase-card__emoji { width: 52px; height: 52px; font-size: 36px; }
}
.phrase-card[aria-pressed='true'] .phrase-card__word { background: var(--orange); color: var(--black); }
.phrase-card__hint { margin-top: 8px; color: var(--muted-2); font-size: 0.9rem; }

/* Who's who pictures. */
/* The portrait is meant to be looked at, so it gets real space.
   Side by side on a wide screen; stacked on a phone, where a column narrow enough to sit beside the
   text would leave the picture smaller than it was. `contain`, never `cover`: cropping a portrait
   to fill a tall box slices the face in half, which is exactly what it did at first. */
.person { align-items: stretch; }
.person__pic {
  flex: none;
  width: 180px;
  align-self: stretch;
  min-height: 180px;
  border-radius: 14px;
  overflow: hidden;
  background: radial-gradient(120% 90% at 50% 100%, rgb(var(--brand-rgb) / 0.16), transparent 70%),
              linear-gradient(180deg, var(--panel-2), var(--panel-3));
}
.person__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center bottom;
}
.person__initials {
  width: 100%;
  height: 100%;
  border-radius: 0;
  font-size: 2rem;
}
.person__picrow { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
/* An empty picture slot. The initials block fills its parent and is solid orange, which as a
   placeholder reads as a filled-in field rather than an empty one waiting for a photo. */
.person__pic--empty {
  display: grid;
  place-items: center;
  color: var(--muted-2);
  font-size: 2rem;
  line-height: 1;
}
.person--edit .person__pic { width: 120px; min-height: 120px; align-self: flex-start; }

@media (max-width: 620px) {
  .person { flex-direction: column; }
  .person__pic { width: 100%; height: 240px; min-height: 0; align-self: auto; }
  .person--edit .person__pic { width: 120px; height: 120px; }
}

/* Awards are a statement of fact, not a control.
   They used to reuse the tier chip: a filled bronze block with heavy condensed black caps on top,
   which vibrates to read and looks tappable when it does nothing. Now the colour is the outline and
   the text, on the card background, and there is no pointer or hover. */
.award-badge {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid currentColor;
  cursor: default;
}
.award-badge strong {
  font-family: var(--font-display);
  font-size: 1rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.award-badge small {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.9;
}
.award-badge[data-tier='bronze'] { color: var(--bronze); }
.award-badge[data-tier='silver'] { color: var(--silver); }
.award-badge[data-tier='gold'] { color: var(--gold); }
.award-badge[data-tier='platinum'] { color: var(--platinum); }

/* Action rows wrap on a phone. Three buttons like "Save changes / Cancel / Hide from players" do
   not fit across 300 units at the larger type scale, and the third was running off the edge. */
.timer__actions { flex-wrap: wrap; }
@media (max-width: 560px) {
  .timer__actions { justify-content: flex-start; }
  .timer__actions > .btn, .timer__actions > .chip { flex: 1 1 auto; }
}

/* Four tabs, not three. "Account" was being clipped at the right edge, so the labels give up a
   little letter-spacing and size rather than the bar giving up a tab. */
@media (max-width: 560px) {
  .tabbar a { font-size: 17px; letter-spacing: 0.02em; }
  .tabbar a span:last-child { padding: 0 2px; }
}
@media (max-width: 380px) {
  .tabbar a { font-size: 15.5px; letter-spacing: 0; }
}

/* Hover ---------------------------------------------------------
   The club is on iPads and phones, where hover does not exist and a hover style applied anyway
   sticks to whatever was tapped last, so every rule here sits behind (hover: hover). Coaches do
   use the board and the roster on a laptop, and a control that stays flat under the pointer reads
   as decoration rather than something you can press.

   The move is always the same and always small: the surface lifts, the border firms up, the text
   goes to full white. Nothing changes size, so no row reflows under the pointer. Anything already
   pressed, selected or disabled is left alone, because those states already say what they are. */
@media (hover: hover) and (pointer: fine) {
  .btn:hover:not(:disabled) {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.34);
  }
  .btn--primary:hover:not(:disabled) {
    background: linear-gradient(150deg, #ff9a4d, #ff7433);
    border-color: transparent;
  }
  .btn--ghost:hover:not(:disabled) { color: var(--white); }
  .btn--danger:hover:not(:disabled) {
    background: rgba(255, 143, 122, 0.12);
    border-color: rgba(255, 143, 122, 0.65);
  }

  .chip:hover:not(:disabled):not([aria-selected='true']) {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.34);
    color: var(--white);
  }
  /* A tier chip carries its own colour, so it brightens rather than going white over the top. */
  .chip--tier:hover:not(:disabled):not([aria-selected='true']) {
    background: rgba(255, 255, 255, 0.05);
    color: inherit;
  }

  .tabs button:hover:not([aria-selected='true']) {
    background: rgba(255, 255, 255, 0.05);
    color: var(--white);
  }

  /* Form controls. A field that reacts to the pointer is the cheapest way of saying it is a field
     and not a label, which matters most on the roster where selects sit inside dense rows. */
  input:hover:not(:disabled):not([readonly]),
  select:hover:not(:disabled),
  textarea:hover:not(:disabled):not([readonly]) {
    border-color: rgba(255, 255, 255, 0.28);
  }

  /* Rows that open something. The whole row is the target, so the whole row answers. */
  .code-row:hover,
  .manage-row:hover,
  .log-row:hover {
    background: rgba(255, 255, 255, 0.03);
  }
  /* A new entry already carries an orange wash, so it is left as it is rather than washed twice. */
  .feed__row:hover:not([data-new='true']) { background: rgba(255, 255, 255, 0.03); }

  /* The tab bar is the one light surface in the app, so it darkens rather than brightens: white
     text on a near-white bar is invisible. The active tab is already full orange and is left be. */
  .tabbar a:not([aria-current='page']):hover {
    background: rgba(23, 19, 12, 0.07);
    color: #000;
  }
  a:hover { text-decoration-color: currentColor; }
}

/* Branding, the admin coach's own screen ------------------------- */

.brand-logo { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
/* The badge is shown on the dark bar it will actually sit on, at the size it will actually be,
   so a crest with a white background is obvious here rather than a surprise in the top bar. */
.brand-logo__frame {
  flex: none;
  width: 96px;
  height: 96px;
  border-radius: 20px;
  overflow: hidden;
  background: var(--black);
  border: 1px solid var(--line-strong);
  display: grid;
  place-items: center;
}
.brand-logo__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.brand-spec {
  margin: 10px 0 0;
  padding-left: 18px;
  color: var(--muted-2);
  font-size: 15px;
  line-height: 1.5;
}
.brand-spec li { margin-bottom: 3px; }

.brand-colour { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* A colour input draws its own chrome, which on a dark page is a small grey box with the colour
   hidden inside it. Stripped back so the swatch itself is the control. */
.brand-colour input[type='color'] {
  flex: none;
  width: 62px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: none;
  cursor: pointer;
}
.brand-colour input[type='color']::-webkit-color-swatch-wrapper { padding: 3px; }
.brand-colour input[type='color']::-webkit-color-swatch { border: none; border-radius: 7px; }
.brand-colour .note { flex: 1 1 260px; margin: 0; }
