/* ==========================================================================
   Perth Futsal Collective — page compositions
   ========================================================================== */

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

.hero {
  --band: clamp(2.5rem, 7vw, 7.5rem);
  /* The page gutter: 1.25rem until the shell hits its max width, then it grows. */
  --gutter: max(1.25rem, calc((100vw - var(--shell)) / 2));
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.5rem, 2rem + 8vw, 7.5rem);
}

/* The crimson column and rounded corner are lifted from the club's
   fixture graphics, where the shield sits in a red band down the left. */
.hero__band {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--band);
  background: linear-gradient(180deg, var(--crimson-600), var(--crimson-700));
  border-bottom-right-radius: clamp(2rem, 4vw, 4rem);
  z-index: 0;
}

.hero__band::after {
  content: "";
  position: absolute;
  right: -1px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: rgba(252, 227, 222, 0.18);
}

.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 4rem);
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  align-items: center;
  /* Clear the crimson band without letting it push content on wide screens,
     where the gutter already covers it. */
  padding-left: max(0px, calc(var(--band) + 1.75rem - var(--gutter)));
}

@media (max-width: 900px) {
  .hero__inner { grid-template-columns: 1fr; }
}

.hero__title {
  font-size: var(--step-4);
  line-height: 0.88;
  text-transform: uppercase;
  letter-spacing: -0.035em;
}

.hero__title span {
  display: block;
  font-weight: 400;
  color: var(--ink-soft);
  letter-spacing: -0.02em;
}

.hero__kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: rgba(21, 8, 38, 0.5);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin-bottom: 1.4rem;
}

.hero__lead {
  font-size: var(--step-1);
  color: var(--ink-soft);
  max-width: 44ch;
  margin-top: 1.5rem;
  line-height: 1.5;
}

.hero__cta { margin-top: 2.25rem; }

.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0 2.5rem;
  margin-top: 2.75rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
}

.hero__facts div { padding-block: 0.5rem; }

.hero__facts dt {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.hero__facts dd {
  margin: 0.2rem 0 0;
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* next-round card riding alongside the hero */
.hero__panel {
  align-self: stretch;
  display: flex;
  flex-direction: column;
}
.hero__panel > .next-card { flex: 1; }

.next-card {
  display: flex;
  flex-direction: column;
  align-self: stretch;
  background: linear-gradient(165deg, rgba(252, 227, 222, 0.1), rgba(252, 227, 222, 0.03));
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.next-card__head {
  padding: 1.1rem 1.35rem;
  background: var(--crimson-600);
  color: var(--cream);
}
.next-card__head p {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.85;
}
.next-card__head h2 {
  font-size: var(--step-1);
  text-transform: uppercase;
  margin-top: 0.2rem;
}

.next-card__list {
  padding: 0.5rem 0.4rem;
  flex: 1;
  display: grid;
  align-content: space-evenly;
}
.next-card__foot { padding: 0.9rem 1.35rem 1.25rem; }

/* -------------------------------------------------------------- fixture rows */

/* Seven columns, identical on Fixtures and Results so the two tabs line up:
   time | home | score | away | pitch | league | status.
   An upcoming game just leaves the status column empty. */
.fx {
  display: grid;
  grid-template-columns:
    4.6rem              /* time */
    minmax(0, 1fr)      /* home team */
    5rem                /* score */
    minmax(0, 1fr)      /* away team */
    4.6rem              /* pitch */
    8.5rem              /* league - "Mon Division A", "Wildcard round" */
    6.2rem;             /* status */
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.95rem;
  border-radius: var(--r);
  text-decoration: none;
  transition: background 0.16s;
}

.fx:hover { background: var(--surface); }
.fx + .fx { box-shadow: inset 0 1px 0 var(--line); }
/* The friendly played in place of a forfeit, under the forfeit itself. */
.fx__friendly {
  grid-column: 1 / -1;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--ink-soft);
}

.fx__time {
  font-size: 0.88rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  white-space: nowrap;
}

/* Teams and their scores share one type treatment, so a dimmed loser's score
   is as quiet as their name rather than shouting in bold. */
.fx__team,
.fx__score b {
  font-size: 0.94rem;
  font-weight: 600;
  color: var(--ink);
}

/* Name and strip square travel together. Both cells put the square on the
   side nearest the score, so the two strips sit either side of it and read
   as "this colour against that colour". */
.fx__team {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  min-width: 0;
}
.fx__team > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.fx__team--home {
  text-align: right;
  flex-direction: row-reverse;
  justify-content: flex-start;
}
.fx__team--away { text-align: left; }

/* The names are links to the team inside a row that is a link to the game,
   so they get their own affordance: underline on hover, and their own focus
   ring for keyboards. */
.fx__team:hover { text-decoration: underline; color: var(--cream); }
.fx__team:focus-visible {
  outline: 2px solid var(--crimson-400);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.fx__team.is-winner,
.fx__score b.is-winner { color: var(--cream); font-weight: 700; }

.fx__team.is-loser,
.fx__score b.is-loser { color: var(--ink-faint); font-weight: 600; }

.fx__score {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.35rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fx__score b { min-width: 1ch; text-align: center; }
.fx__score i { font-style: normal; color: var(--ink-faint); font-size: 0.8rem; }

.fx__score--empty i {
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.fx__pitch,
.fx__league {
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}
/* A long division or finals round name wraps onto a second line inside its
   own column rather than running under the status badge next to it. */
.fx__league {
  min-width: 0;
  white-space: normal;
  line-height: 1.35;
}

.fx__status { justify-self: end; }

/* Rows reflow on the width of their own container. Anything that holds a list
   of fixtures declares itself a container below. */
@container fx (max-width: 620px) {
  .fx {
    grid-template-columns: 4.2rem minmax(0, 1fr) 4.4rem minmax(0, 1fr);
    gap: 0.4rem 0.6rem;
  }
  .fx__pitch { grid-column: 2; }
  .fx__league { grid-column: 3; text-align: center; }
  .fx__status { grid-column: 4; justify-self: start; }
}

/* On a phone the row reads down instead of across: the two names get the
   whole width and the score sits beside them, which is how a fixture list
   reads on paper. Side by side, a name like "Balance Sheet Ballers" had
   about seven characters to live in. */
@container fx (max-width: 460px) {
  .fx {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.15rem 0.6rem;
    align-items: center;
  }
  .fx__time { grid-column: 1; grid-row: 1; }
  .fx__status { grid-column: 2; grid-row: 1; justify-self: end; }
  .fx__team--home {
    grid-column: 1;
    grid-row: 2;
    flex-direction: row;
    justify-content: flex-start;
    text-align: left;
  }
  .fx__team--away { grid-column: 1; grid-row: 3; }
  .fx__score {
    grid-column: 2;
    grid-row: 2 / span 2;
    justify-content: flex-end;
    align-self: center;
  }
  .fx__pitch { grid-column: 1; grid-row: 4; }
  .fx__league { grid-column: 2; grid-row: 4; text-align: right; }
  .fx__friendly { grid-row: 5; }
  /* Both names hold the full width, so neither is trimmed before the other. */
  .fx__team > span { white-space: normal; overflow: visible; }
  /* Two names above each other already read as a game, so the lone "v" on a
     game nobody has played yet is a letter taking up a column. A score still
     shows, because a score is the news. */
  .fx__score--empty { display: none; }
}

/* Wrappers that hold fixture rows, so the rows above can query their width. */
.panel__body, .next-card__list, .round-group, .fx-list {
  container: fx / inline-size;
}

/* round grouping */
.round-group + .round-group { margin-top: 2.5rem; }

.round-group__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  padding-bottom: 0.75rem;
  margin-bottom: 0.5rem;
  border-bottom: 2px solid var(--crimson-600);
}

.round-group__title {
  font-size: var(--step-1);
  text-transform: uppercase;
}

.round-group__date {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-faint);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.75rem;
}
.toolbar__spacer { margin-left: auto; }

/* ---- Admin members: the club's list of people ----------------------- */
.member {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1.6fr) auto auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface);
}
.member__panel { grid-column: 1 / -1; padding-top: 0.6rem; }
.member__who { display: grid; gap: 0.1rem; min-width: 0; }
.member__name { font-weight: 600; }
.member__meta {
  font-size: 0.74rem;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* On a phone the line under a name is an email address, and half an email
   address is no use to anybody ringing round. It wraps instead. */
@media (max-width: 560px) {
  .member__meta {
    white-space: normal;
    overflow-wrap: anywhere;
    text-overflow: clip;
  }
}
.member__teams { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.member__chip {
  font-size: 0.72rem;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
  white-space: nowrap;
}
.member__role {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
}
.member__role.is-referee { color: var(--warn); border-color: var(--warn); }
.member__role.is-admin { color: var(--crimson-400); border-color: var(--crimson-500); }

@media (max-width: 760px) {
  .member { grid-template-columns: 1fr auto; }
  .member__teams { grid-column: 1 / -1; }
}

/* -------------------------------------------------------------- instagram */

.ig-card {
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  background: var(--navy-700);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

.ig-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 1rem 1.15rem 0.75rem;
  background: var(--crimson-600);
}
.ig-card__head p {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blush);
}
.ig-card__handle {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--cream);
  text-decoration: none;
}
.ig-card__handle:hover { text-decoration: underline; }

.ig-card__stage { display: block; }

.ig-card__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
  background: var(--line);
}

/* The thumbnails are buttons, not links — they change what is playing. */
.ig-card__grid .ig-tile {
  border: 0;
  padding: 0;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.2s;
}
.ig-card__grid .ig-tile:hover { opacity: 0.85; }
.ig-card__grid .ig-tile.is-current {
  opacity: 1;
  outline: 2px solid var(--crimson-400);
  outline-offset: -2px;
}

/* The newest post, across the full width. The play mark is bigger here
   because the tile is, and a 12px triangle on a 400px square disappears. */
.ig-tile--feature { aspect-ratio: 1 / 1; border-bottom: 2px solid var(--line); }
.ig-tile--feature .ig-tile__play {
  right: 0.6rem;
  bottom: 0.5rem;
  font-size: 1.15rem;
}

.ig-tile {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--navy-800);
}
.ig-tile img,
.ig-tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.25s, opacity 0.25s;
}
.ig-tile:hover img,
.ig-tile:hover video { transform: scale(1.05); opacity: 0.85; }
.ig-tile__play {
  position: absolute;
  right: 0.35rem;
  bottom: 0.3rem;
  font-size: 0.7rem;
  color: var(--cream);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}

.ig-card__foot { padding: 0.85rem; }

/* ---- Questions -------------------------------------------------------- */
/* One question a line, opened by pressing it. Closed by default: the list is
   the point, and a wall of answers is the thing it replaces. */
.faq { display: grid; gap: 0.6rem; }

.faq__item {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  overflow: hidden;
}
.faq__item[open] { border-color: var(--line-strong); }

.faq__q {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1.1rem;
  font-weight: 600;
  font-size: 0.98rem;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: "+";
  margin-left: auto;
  font-size: 1.15rem;
  font-weight: 400;
  line-height: 1;
  color: var(--crimson-400);
  transition: transform 0.18s;
}
.faq__item[open] .faq__q::after { content: "−"; }
.faq__q:hover { background: var(--surface-hi); }

.faq__a {
  padding: 0 1.1rem 1rem;
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--ink-soft);
}
.faq__a a { color: var(--crimson-400); }

/* ---- Competition information ----------------------------------------- */
.rules-grid { display: grid; gap: var(--gap); }
@media (min-width: 60rem) { .rules-grid { grid-template-columns: 1fr 1fr; } }

.rules-block {
  padding: 1.4rem 1.5rem;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface);
}
.rules-block__title {
  font-size: var(--step-0);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--crimson-400);
  margin-bottom: 0.75rem;
}
.rules-list { margin: 0; padding-left: 1.1rem; display: grid; gap: 0.5rem; }
.rules-list li { font-size: 0.9rem; color: var(--ink-soft); line-height: 1.55; }
.rules-list li::marker { color: var(--crimson-500); }

/* ---- Socials page ---------------------------------------------------- */
.social-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 1.25rem;
  align-items: center;
}
/* Clear of the fixed header when a link lands on one card. */
.social-card { scroll-margin-top: 5.5rem; }
.social-card__when { display: grid; gap: 0.1rem; }
.social-card__day {
  font-size: var(--step-2);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink);
}
.social-card__time {
  font-size: var(--step-1);
  font-weight: 800;
  color: var(--warn);
  white-space: nowrap;
}
.social-card__body h3 { font-size: var(--step-0); text-transform: uppercase; }
.social-card__body p { font-size: 0.88rem; color: var(--ink-soft); margin-top: 0.2rem; }
/* Where it is: the venue is read at a glance, the street address under it. */
.social-card__where { display: grid; gap: 0.05rem; margin-top: 0.35rem !important; }
.social-card__where strong {
  font-size: var(--step-1);
  font-weight: 800;
  line-height: 1.15;
  color: var(--ink);
}
.social-card__where span { font-size: 0.86rem; color: var(--ink-soft); }
.social-card__price {
  font-size: var(--step-1);
  font-weight: 800;
  white-space: nowrap;
}
/* The full price while a special is on: there to be seen, and crossed out. */
.social-card__was {
  font-weight: 600;
  color: var(--ink-faint);
  margin-right: 0.15rem;
}
.social-strip__price s { font-weight: 600; color: var(--ink-faint); }
.social-card__price small {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The sign-up strip runs the card's full width, under the details. */
.social-card__coming {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.9rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--line);
}
.social-card__count {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--warn);
}
.social-card__names {
  flex-basis: 100%;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

@media (max-width: 700px) {
  .social-card { grid-template-columns: 1fr auto; }
  .social-card__body { grid-column: 1 / -1; }
}

/* -------------------------------------------------------------- social hour */

.social-strip {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 1.25rem;
  padding: 1.15rem 1.4rem;
  border-radius: var(--r-lg);
  border: 1px solid rgba(245, 184, 65, 0.35);
  background: linear-gradient(100deg, rgba(245, 184, 65, 0.14), rgba(245, 184, 65, 0.04));
}

.social-strip__price {
  margin-left: auto;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}

.social-strip__time {
  font-size: var(--step-1);
  font-weight: 800;
  color: var(--warn);
  font-variant-numeric: tabular-nums;
}

.social-strip h3 { font-size: var(--step-0); text-transform: uppercase; }
.social-strip p { font-size: 0.86rem; color: var(--ink-soft); }

@media (max-width: 700px) {
  .social-strip { grid-template-columns: 1fr; gap: 0.6rem; }
}

/* ------------------------------------------------------- entering a team */

/* Which season a team filling the form in would be joining. It sits above
   the form because "beginning 5th October" changes whether somebody fills
   it in at all. */
.intake-banner {
  margin-bottom: var(--gap);
  padding: 1.1rem 1.35rem;
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--crimson-600);
  border-radius: var(--r);
  background: var(--surface);
}
.intake-banner__season {
  margin: 0.35rem 0 0;
  font-size: var(--step-1);
  font-weight: 800;
  letter-spacing: -0.01em;
  text-transform: uppercase;
}

/* Two steps, and which one you are on. */
.stepline {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  list-style: none;
  margin: 0 0 1.6rem;
  padding: 0;
  font-size: 0.86rem;
  color: var(--ink-faint);
}
.stepline li { display: flex; align-items: center; gap: 0.5rem; }
.stepline li.is-current { color: var(--cream); font-weight: 700; }
.stepline li.is-done { color: var(--ink-soft); }
.stepline__num {
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
}
.stepline li.is-current .stepline__num {
  background: var(--crimson-600);
  border-color: transparent;
  color: var(--cream);
}

/* One squad member per block, with the vice-captain tick on the end. */
.roster-entry { display: grid; gap: 0.4rem; }
.roster-entry__row {
  display: grid;
  gap: 0 0.9rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  align-items: end;
  padding: 0.6rem 0;
}
.roster-entry__row + .roster-entry__row { border-top: 1px solid var(--line); }
.roster-entry__vice { align-self: center; white-space: nowrap; }

/* -------------------------------------------------------------- fees */

.fee-card { text-align: left; }

.fee-card__amount {
  font-size: var(--step-3);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 0.25rem;
}
.fee-card__amount small {
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-faint);
}

.fee-card h3 {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--crimson-400);
  margin-bottom: 0.9rem;
}

.fee-card p { font-size: 0.9rem; color: var(--ink-soft); }

.rule-list { list-style: none; padding: 0; display: grid; gap: 1.15rem; }

/* Direct children only. A list nested inside a rule — the waiver has one per
   clause — is not itself a numbered rule, and would otherwise be laid out
   into the 2.2rem column meant for the number. */
.rule-list > li {
  display: grid;
  grid-template-columns: 2.2rem minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}

/* Some of these lists are not sequences and carry no number; without one the
   first column is an empty gutter, so it goes. */
.rule-list > li:not(:has(> .num)) { grid-template-columns: minmax(0, 1fr); }

.rule-list .num {
  display: grid;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  background: var(--crimson-600);
  color: var(--cream);
  font-size: 0.85rem;
  font-weight: 800;
}

.rule-list h3 { font-size: var(--step-0); text-transform: uppercase; margin-bottom: 0.25rem; }
.rule-list p { font-size: 0.9rem; color: var(--ink-soft); }

/* -------------------------------------------------------------- ladders */

/* One league per block, stacked down the page. */
.ladder-block + .ladder-block { margin-top: var(--gap); }

.ladder-rules {
  font-size: 0.86rem;
  margin-bottom: var(--gap);
  padding: 0.7rem 1rem;
  border-radius: var(--r);
  background: var(--surface);
  border-left: 2px solid var(--crimson-500);
}

/* The team-detail page still uses a two-column layout. */
.ladder-layout {
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 2.4fr) minmax(0, 1fr);
  align-items: start;
}

@media (max-width: 900px) {
  .ladder-layout { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------------- fixture detail */

.detail-list {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.55rem 1.25rem;
  margin: 0;
  align-items: baseline;
}

.detail-list dt {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.detail-list dd { margin: 0; font-size: 0.94rem; font-weight: 600; }

/* -------------------------------------------------------------- teams */

.team-grid { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); }

.team-tile {
  display: grid;
  gap: 0.5rem;
  padding: 1.25rem;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  text-decoration: none;
  transition: transform 0.18s, border-color 0.18s, background 0.18s;
}
/* The admin tile holds a notes panel as well as the link, so the lift follows
   the link rather than the whole tile — hovering the notes button shouldn't
   make the card jump. */
.team-tile:hover,
.team-tile:has(.team-tile__link:hover) {
  transform: translateY(-3px);
  border-color: var(--crimson-500);
  background: var(--surface-hi);
}
.team-tile:has(.team-notes:not([hidden])) { transform: none; }

.team-tile__link {
  display: grid;
  gap: 0.5rem;
  text-decoration: none;
  color: inherit;
}

/* Notes — on referee match cards and on admin team tiles. */
.team-notes { display: grid; gap: 0.5rem; margin-top: 0.6rem; }
.team-notes__count { color: var(--ink-faint); }

.note-block { display: grid; gap: 0.5rem; margin-top: 0.5rem; }

.note-box {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border-radius: 0.6rem;
  border: 1px solid var(--line-strong);
  background: var(--navy-800);
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
  resize: vertical;
}
.note-box:focus { outline: 2px solid var(--crimson-500); outline-offset: 1px; }

/* Two notes at a glance; the rest scroll inside the same little box. */
.note-log { display: grid; gap: 0.4rem; max-height: 11rem; overflow-y: auto; }
.note-log__item {
  position: relative;
  display: grid;
  gap: 0.15rem;
  margin: 0;
  padding: 0.5rem 1.6rem 0.5rem 0.6rem;
  border-left: 2px solid var(--crimson-600);
  border-radius: 0.35rem;
  background: var(--surface);
}
.note-log__who {
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.note-log__body { font-size: 0.86rem; white-space: pre-wrap; }
.note-log__x {
  position: absolute;
  top: 0.25rem;
  right: 0.3rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.2rem;
}
.note-log__x:hover { color: var(--danger); }
.team-tile__name {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--step-1);
  text-transform: uppercase;
  letter-spacing: -0.02em;
}
.team-tile__meta { font-size: 0.76rem; color: var(--ink-faint); letter-spacing: 0.08em; text-transform: uppercase; }
.team-tile__record { font-size: 0.85rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

.team-hero {
  padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem);
  border-bottom: 1px solid var(--line);
  background: linear-gradient(140deg, rgba(168, 59, 75, 0.32), transparent 62%);
}

.team-hero__name {
  font-size: var(--step-3);
  text-transform: uppercase;
}

.stat-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  margin-top: 2rem;
}

.stat-strip div { background: var(--navy-800); padding: 0.9rem 1rem; }

.stat-strip dt {
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.stat-strip dd {
  margin: 0.15rem 0 0;
  font-size: var(--step-1);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.roster { display: grid; gap: 0.4rem; }

/* Shirt number, then the player, then whatever sits on the right — the goals
   they have scored on a team page, or the buttons a captain gets on the manage
   page. */
.roster__row {
  display: grid;
  grid-template-columns: 2.4rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.5rem 0.9rem;
  padding: 0.75rem 1rem;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--surface);
  container-type: inline-size;
}

/* Edit, Make captain and Remove come to about 270px. The squad sits in one
   half of a two-column page, so its rows are around 360px wide even on a large
   screen, and squeezing three buttons into what is left over pushed them out
   of their column and on top of the name. In a row that narrow they take a
   line of their own, right across it — including under the shirt number,
   without which Remove drops to a second line and the row grows by a third.

   Only rows that have buttons: a team page shows a goal count there instead,
   and that has always fitted. The question is asked of the row, since it is
   the page layout that makes it narrow rather than the screen. */
@container (max-width: 30rem) {
  .roster__row:has(> .btn-row) {
    grid-template-columns: 2.4rem minmax(0, 1fr);
  }
  .roster__row > .btn-row {
    grid-column: 1 / -1;
    justify-content: flex-start;
    gap: 0.4rem;
  }
}

.roster__num {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: var(--r-sm);
  background: var(--navy-600);
  font-size: 0.82rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.roster__name { font-weight: 600; }

/* An editing row drops the three-column grid and fills the width. */
.roster__row:has(.roster__edit) { display: block; }
.roster__edit { display: grid; gap: 0.25rem; }
.roster__edit .field { margin-bottom: 0.5rem; }
.roster__contact { font-size: 0.8rem; color: var(--ink-faint); }
.roster__contact a { text-decoration: none; }
.roster__contact a:hover { color: var(--crimson-400); }

/* -------------------------------------------------------------- fill-ins */

.shout {
  display: grid;
  gap: 1rem;
  padding: 1.35rem;
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  background: linear-gradient(150deg, rgba(168, 59, 75, 0.2), rgba(252, 227, 222, 0.03));
}

.shout__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}

.shout__team { font-size: var(--step-1); text-transform: uppercase; }
.shout__when { font-size: 0.86rem; color: var(--ink-soft); font-weight: 600; }
.shout__note { font-size: 0.9rem; color: var(--ink-soft); }

.shout__spots {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.spot-pips { display: inline-flex; gap: 0.25rem; }
.spot-pips i {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  border: 1.5px solid var(--live);
}
.spot-pips i.is-taken { background: var(--ink-faint); border-color: var(--ink-faint); }

/* -------------------------------------------------------------- fill-in offers */

.offer-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: center;
  padding: 0.6rem 0.8rem;
  border-radius: var(--r);
  background: var(--surface);
}

/* Offers are shown oldest first; the number makes that order obvious. */
.offer-row__order {
  display: grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--navy-600);
  font-size: 0.72rem;
  font-weight: 800;
}

.offer-row__name { font-weight: 600; font-size: 0.9rem; min-width: 0; }

@media (max-width: 620px) {
  .offer-row { grid-template-columns: auto minmax(0, 1fr); }
  .offer-row .btn-row { grid-column: 1 / -1; }
}

/* -------------------------------------------------------------- invite by name */

.invite {
  display: grid;
  gap: 0.5rem;
  padding: 0.7rem;
  border-radius: var(--r);
  border: 1px dashed var(--line-strong);
  margin-bottom: 0.7rem;
}

.invite__search {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: rgba(21, 8, 38, 0.6);
  color: var(--ink);
  font-size: 0.85rem;
}
.invite__search:focus { outline: none; border-color: var(--crimson-500); }

/* Bonds: find one team without scrolling the whole book. */
.bond-search {
  width: 100%;
  margin-top: 0.75rem;
  padding: 0.55rem 0.8rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: rgba(21, 8, 38, 0.6);
  color: var(--ink);
  font-size: 0.9rem;
}
.bond-search:focus { outline: none; border-color: var(--crimson-500); }

.invite__results { display: grid; gap: 0.2rem; }
.invite__results:empty { display: none; }

.invite__result {
  text-align: left;
  padding: 0.45rem 0.6rem;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.85rem;
  cursor: pointer;
}
.invite__result:hover:not(:disabled) { background: var(--surface-hi); }
.invite__result:disabled { opacity: 0.45; cursor: default; }

.invite__chips { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.invite__chips:empty { display: none; }

.invite__chip {
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  border: 1px solid var(--crimson-500);
  background: rgba(168, 59, 75, 0.25);
  color: var(--ink);
  font-size: 0.78rem;
  cursor: pointer;
}

/* -------------------------------------------------------------- match-day console */

.matchday { display: grid; gap: 1rem; }

.mdcard {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--navy-900);
}

/* The game on now: found for the referee rather than looked for. */
.mdcard.is-now { border-color: var(--crimson-500); box-shadow: 0 0 0 1px rgba(214, 69, 91, 0.3); }
.mdcard__now {
  display: block;
  padding: 0.3rem 0.9rem;
  background: var(--crimson-600);
  color: var(--cream);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.mdcard.is-live { border-color: var(--live); box-shadow: 0 0 0 1px rgba(52, 211, 153, 0.25); }
.mdcard.is-blocked { border-color: rgba(242, 88, 95, 0.5); }

.mdcard__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1rem;
  padding: 0.85rem 1.15rem;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.mdcard__time {
  font-size: 1.1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.mdcard__league { font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-faint); }
.mdcard__head .badge { margin-left: auto; }

/* Admin-only strip under the head: who has the whistle for this game. */
.mdcard__ref {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 1.15rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.mdcard__ref label {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.mdcard__ref select { flex: 1; min-width: 0; }

.mdcard__body { padding: 1.15rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.15rem; }

.scoreline {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 0.75rem;
}

.scoreline__team { display: grid; gap: 0.5rem; justify-items: center; text-align: center; }
.scoreline__name {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 700;
  font-size: 0.95rem;
}

/* The name in the team's strip. The outline keeps a black or navy strip from
   sinking into the dark card. */
.scoreline__name--strip {
  /* Every block the same: as wide as its half of the card and two lines
     tall, whether the name needs one line or two. */
  display: flex;
  box-sizing: border-box;
  width: 100%;
  height: calc(2.4em + 0.5rem + 2px);
  overflow: hidden;
  justify-content: center;
  text-align: center;
  padding: 0.25rem 0.45rem;
  border-radius: 0.4rem;
  border: 1px solid rgba(255, 255, 255, 0.35);
  line-height: 1.2;
  overflow-wrap: anywhere;
}
/* A name that wraps to two lines must not push its score buttons below the
   other team's: both sides take the taller name's height. */
.scoreline:has(.scoreline__name--strip) { align-items: stretch; }
.scoreline:has(.scoreline__name--strip) .scoreline__team { grid-template-rows: 1fr auto; }
.scoreline:has(.scoreline__name--strip) .scoreline__name { align-self: center; }
.scoreline:has(.scoreline__name--strip) .scoreline__vs { align-self: center; }

/* Who is in what, said out loud on a game that has not been played yet. */
.strip-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  margin-top: 0.9rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}
.scoreline__vs { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.14em; color: var(--ink-faint); }

.stepper {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem;
  border-radius: 999px;
  background: var(--surface-hi);
  border: 1px solid var(--line);
}

.stepper button {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 0;
  background: var(--navy-600);
  color: var(--ink);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, transform 0.12s;
}
.stepper button:hover { background: var(--crimson-600); }
.stepper button:active { transform: scale(0.94); }
.stepper button[disabled] { opacity: 0.35; pointer-events: none; }
.stepper button.is-waiting { opacity: 0.35; }

.stepper output {
  min-width: 2.75rem;
  text-align: center;
  font-size: 1.9rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* On a phone two full-size steppers are wider than the card, and the away
   team's plus button ran off its right edge. */
@media (max-width: 460px) {
  .scoreline { gap: 0.4rem; }
  .stepper { gap: 0.15rem; padding: 0.2rem; }
  .stepper button { width: 2.3rem; height: 2.3rem; }
  .stepper output { min-width: 2.2rem; }
}

/* Who scored, under the scoreline: home names to the left, away to the
   right, the way the score above them reads. */
.scorers {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: baseline;
  gap: 0.75rem;
  margin: -0.55rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-soft);
}
.scorers__side { text-align: center; }
.scorers__side:last-child { text-align: center; }
.scorers__label {
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The goal picker: shirt numbers big enough to hit courtside, one press
   each. Opened by the + on the scoreline and gone again the moment one is
   pressed, so it is never in the way of the next goal. */
.goalpick {
  display: grid;
  gap: 0.7rem;
  padding: 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--surface);
}
.goalpick__ask { margin: 0; font-weight: 700; font-size: 0.92rem; }
.goalpick__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));
  gap: 0.5rem;
}
.goalpick__who {
  display: grid;
  justify-items: center;
  gap: 0.15rem;
  padding: 0.6rem 0.35rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--navy-600);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  transition: background 0.15s, transform 0.12s;
}
.goalpick__who:hover { background: var(--crimson-600); }
.goalpick__who:active { transform: scale(0.96); }
.goalpick__no {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.goalpick__name {
  font-size: 0.72rem;
  color: var(--ink-soft);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.goalpick__who:hover .goalpick__name { color: var(--cream); }
.goalpick__foot { display: flex; gap: 0.5rem; justify-content: flex-end; }

.pay-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r);
  background: var(--surface);
  font-size: 0.88rem;
}
/* Let a long match label wrap inside its own column rather than pushing the
   amount onto a line of its own. */
.pay-row__team {
  font-weight: 600;
  margin-right: auto;
  flex: 1 1 9rem;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* -------------------------------------------------------------- assistant bar */

.assistant-bar {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: start;
  margin-top: 1.25rem;
  padding: 0.65rem 0.85rem;
  border-radius: var(--r);
  background: var(--navy-950);
  border: 1px solid var(--line-strong);
}
.assistant-bar__label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--crimson-400);
  padding-top: 0.65rem;
  white-space: nowrap;
}
.assistant-bar__body { min-width: 0; }
.assistant-bar__demo {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
}

/* In the bar the input and send button sit on one line. */
.chat__form--bar { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; align-items: start; }
.chat__form--bar .chat__input { min-height: 2.6rem; }
.chat__form--bar .chat__actions { display: contents; }
.chat__form--bar .chat__actions .faint { display: none; }
.assistant-bar .chat__log { margin-top: 0.6rem; margin-bottom: 0; }

/* -------------------------------------------------------------- admin assistant */

.chat__examples {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1rem;
}

.chat__example {
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  border: 1px dashed var(--line-strong);
  background: transparent;
  color: var(--ink-faint);
  font-size: 0.76rem;
  cursor: pointer;
  text-align: left;
  transition: color 0.15s, border-color 0.15s;
}
.chat__example:hover { color: var(--ink); border-color: var(--crimson-500); }

.chat__log {
  display: grid;
  gap: 0.6rem;
  max-height: 26rem;
  overflow-y: auto;
  margin-bottom: 1rem;
}
.chat__log:empty { display: none; }

.chat__msg {
  padding: 0.7rem 0.95rem;
  border-radius: var(--r);
  font-size: 0.9rem;
  max-width: 46ch;
  white-space: pre-wrap;
}
.chat__msg--you {
  justify-self: end;
  background: var(--crimson-600);
  color: var(--cream);
}
.chat__msg--bot { background: var(--surface-hi); }
.chat__msg--note {
  background: rgba(242, 88, 95, 0.12);
  border: 1px solid rgba(242, 88, 95, 0.4);
  color: var(--ink);
  max-width: none;
}
.chat__msg.is-thinking { color: var(--ink-faint); font-style: italic; }

.chat__proposal {
  padding: 1rem;
  border-radius: var(--r);
  border: 1px solid var(--crimson-500);
  background: rgba(168, 59, 75, 0.16);
  display: grid;
  gap: 0.75rem;
}

.chat__proposal-head {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--crimson-400);
}

.chat__plan { margin: 0; padding-left: 1.2rem; display: grid; gap: 0.4rem; font-size: 0.9rem; }
.chat__plan li.is-ok { color: var(--live); }
.chat__plan li.is-bad { color: var(--danger); }

.chat__form { display: grid; gap: 0.6rem; }

.chat__input {
  width: 100%;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: rgba(21, 8, 38, 0.6);
  color: var(--ink);
  font-size: 0.95rem;
  resize: vertical;
}
.chat__input:focus { outline: none; border-color: var(--crimson-500); }

.chat__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* -------------------------------------------------------------- week ahead */

.week-row {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr) auto;
  gap: 0.9rem;
  align-items: center;
  padding: 0.6rem 0.8rem;
  border-radius: var(--r);
  background: var(--surface);
  font-size: 0.9rem;
}

.week-row__time { font-weight: 700; font-variant-numeric: tabular-nums; }
.week-row__teams { min-width: 0; font-weight: 600; }

.week-row__controls { display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; }
.week-row__select { padding-block: 0.35rem; font-size: 0.8rem; }
.week-row__select:disabled { opacity: 0.5; }

@media (max-width: 760px) {
  .week-row { grid-template-columns: 4.5rem minmax(0, 1fr); }
  .week-row__controls { grid-column: 1 / -1; justify-content: flex-start; }
}

/* Small caps sublabel used under a time on the admin screens. */
.fx__court {
  display: block;
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* -------------------------------------------------------------- admin chrome */

/* ---- Admin grid: pitches across, kick-off times down ---------------- */
.grid-toolbar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.75rem;
  font-size: 0.84rem;
  color: var(--ink-soft);
}

/* The pitch stepper, sat on the grid toolbar beside the night picker. */
.pitch-steps {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
}


.pitch-step {
  width: 1.9rem;
  height: 1.9rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.pitch-step:hover:not(:disabled) {
  background: var(--surface-hi);
  border-color: var(--crimson-500);
}
.pitch-step:disabled { opacity: 0.35; cursor: default; }
.pitch-steps__count { min-width: 1ch; text-align: center; }
.pitch-steps__note { font-size: 0.76rem; color: var(--ink-faint); }

@media (max-width: 560px) {
  /* The toolbar wraps on a phone; keep the stepper together and let it start
     the second line rather than trailing off the end of the first. */
  .grid-toolbar { flex-wrap: wrap; }
  .pitch-steps { margin-left: 0; gap: 0.5rem; }
  /* Big enough to hit with a thumb. Admins rearrange a night on a phone at
     the courts, which is why the grid takes taps as well as drags. */
  .pitch-step { width: 2.6rem; height: 2.6rem; font-size: 1.15rem; }
}

/* A confirmation that has to be pressed to go on: the team entry form. */
.confirm-shade {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 1rem;
  overflow-y: auto;
  background: rgba(8, 4, 16, 0.82);
}
.confirm-dialog {
  width: min(30rem, 100%);
  padding: 1.6rem 1.4rem 1.4rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--navy-900, #14172b);
  color: var(--ink);
  text-align: center;
}
.confirm-dialog p { margin: 0 0 0.8rem; }
.confirm-dialog__tick {
  display: grid;
  place-items: center;
  width: 3.4rem;
  height: 3.4rem;
  margin: 0 auto 0.9rem;
  border-radius: 50%;
  background: #1f9d55;
  color: #fff;
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1;
}
.confirm-dialog__title {
  margin: 0 0 0.8rem;
  font-size: var(--step-2);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}
.confirm-dialog__mail { font-size: 0.88rem; color: var(--ink-soft); overflow-wrap: anywhere; }
.confirm-dialog .btn { margin-top: 0.4rem; }

.grid-wrap { overflow-x: auto; padding-bottom: 0.5rem; }
/* The board, and beside it the teams still waiting for a game. The board
   keeps its own sideways scroll, so the list never gets pushed off screen. */
.grid-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 13rem;
  gap: 1rem;
  align-items: start;
}
.grid-spare {
  /* Follows the admin down a long night, clear of the site's own header. */
  position: sticky;
  top: 5.5rem;
  max-height: calc(100vh - 6.5rem);
  overflow-y: auto;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface);
  font-size: 0.84rem;
}
/* The Edit mode bar along the bottom must not sit over the end of the list. */
body.has-live-bar .grid-spare { max-height: calc(100vh - 10.5rem); }
.grid-spare__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.grid-spare__count {
  min-width: 1.5rem;
  padding: 0.1rem 0.4rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  text-align: center;
  color: var(--ink-soft);
}
.grid-spare__group + .grid-spare__group { margin-top: 0.7rem; }
.grid-spare__league {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.25rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}
.grid-spare__list { margin: 0; padding: 0; list-style: none; }
.grid-spare__list li { padding: 0.2rem 0; border-top: 1px solid var(--line); }
.grid-spare__list li:first-child { border-top: 0; }
.grid-spare__none { margin: 0; color: var(--ink-soft); }
@media (max-width: 900px) {
  .grid-layout { grid-template-columns: 1fr; }
  .grid-spare { position: static; max-height: none; }
}
.grid-board {
  display: grid;
  grid-template-columns: 4.5rem repeat(var(--pitches, 2), minmax(11rem, 1fr));
  gap: 0.4rem;
  min-width: min-content;
}
/* The night in five-minute rows. Rows are thin and gap-free, so a
   game - a block as long as a game runs - takes about the height a square
   does on the normal board. Quarter hours carry a time and a firmer line. */
.grid-board--fine {
  grid-template-rows: auto repeat(var(--rows), 1.1rem);
  row-gap: 0;
}
.grid-fine__time {
  font-size: 0.72rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  line-height: 1;
  transform: translateY(-0.35rem);
}
.grid-fine__slot {
  border-top: 1px dashed rgba(252, 227, 222, 0.05);
  cursor: pointer;
}
.grid-fine__slot.is-quarter { border-top: 1px solid var(--line); }
.grid-fine__slot:hover { background: rgba(252, 227, 222, 0.04); }
.grid-holding .grid-fine__slot:hover,
.grid-fine__slot.is-target { background: rgba(214, 69, 91, 0.35); }
.grid-cell--fine {
  position: relative;
  z-index: 1;
  margin: 1px 0;
  align-content: start;
  overflow: hidden;
}
.grid-cell--fine .grid-cell__v { display: none; }
.grid-cell--fine { gap: 0.3rem; padding: 0.45rem 0.5rem; }
.grid-nudge {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.3rem;
}
.grid-nudge__time {
  font-size: 0.78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.grid-nudge__step {
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.2);
  color: var(--ink);
  font: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
}
.grid-nudge__step:hover:not(:disabled) { border-color: var(--crimson-500); }
.grid-nudge__step:disabled { opacity: 0.4; }

.grid-head {
  padding: 0.4rem 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.grid-head__ref {
  display: block;
  width: 100%;
  max-width: 14rem;
  margin-top: 0.3rem;
  padding: 0.3rem 0.4rem;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--line);
  border-radius: 0.45rem;
}
.grid-time {
  display: flex;
  align-items: center;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 0.86rem;
  color: var(--ink-soft);
}
.grid-cell {
  display: grid;
  gap: 0.25rem;
  padding: 0.55rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface);
}
/* One colour per league, so a night reads as blocks rather than a wall of
   names. The tint is on the cell; the team chips take the matching line
   colour so they still stand out as the thing you drag. */
.grid-cell.lg-1 { background: var(--lg-1); border-color: var(--lg-1-line); }
.grid-cell.lg-2 { background: var(--lg-2); border-color: var(--lg-2-line); }
.grid-cell.lg-3 { background: var(--lg-3); border-color: var(--lg-3-line); }
.grid-cell.lg-4 { background: var(--lg-4); border-color: var(--lg-4-line); }
.grid-cell.lg-5 { background: var(--lg-5); border-color: var(--lg-5-line); }
.grid-cell.lg-6 { background: var(--lg-6); border-color: var(--lg-6-line); }

.grid-cell.lg-1 .grid-team { border-color: var(--lg-1-line); }
.grid-cell.lg-2 .grid-team { border-color: var(--lg-2-line); }
.grid-cell.lg-3 .grid-team { border-color: var(--lg-3-line); }
.grid-cell.lg-4 .grid-team { border-color: var(--lg-4-line); }
.grid-cell.lg-5 .grid-team { border-color: var(--lg-5-line); }
.grid-cell.lg-6 .grid-team { border-color: var(--lg-6-line); }
.grid-cell .grid-team { background: rgba(21, 8, 38, 0.45); }

.grid-key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.9rem;
  margin: 0 0 0.9rem;
  font-size: 0.76rem;
  color: var(--ink-soft);
}
.grid-key__item { display: inline-flex; align-items: center; gap: 0.4rem; }
.grid-key__swatch {
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 0.25rem;
  border: 1px solid var(--line-strong);
}
.grid-key__swatch.lg-1 { background: var(--lg-1); border-color: var(--lg-1-line); }
.grid-key__swatch.lg-2 { background: var(--lg-2); border-color: var(--lg-2-line); }
.grid-key__swatch.lg-3 { background: var(--lg-3); border-color: var(--lg-3-line); }
.grid-key__swatch.lg-4 { background: var(--lg-4); border-color: var(--lg-4-line); }
.grid-key__swatch.lg-5 { background: var(--lg-5); border-color: var(--lg-5-line); }
.grid-key__swatch.lg-6 { background: var(--lg-6); border-color: var(--lg-6-line); }
.grid-cell--empty:hover { color: var(--crimson-500); border-color: var(--crimson-500); cursor: pointer; }
.grid-cell--empty {
  align-content: center;
  justify-items: center;
  color: var(--ink-faint);
  border-style: dashed;
}
/* Four tracks, so the grip sits in the middle of the square no matter how
   long the league's name is: name to the left, grip centred, then change
   the teams and take the game off, both to the right. */
.grid-cell__top {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: center;
  gap: 0.3rem;
}
.grid-cell__top > .grid-cell__league { justify-self: start; }
.grid-cell__top > .grid-cell__grip { justify-self: center; }
.grid-cell__top > .grid-cell__edit,
.grid-cell__top > .grid-cell__x { justify-self: end; }
.grid-cell__grip {
  flex: 0 0 auto;
  padding: 0 0.2rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 0.8rem;
  line-height: 1;
  cursor: grab;
}
.grid-cell__grip:hover { color: var(--ink); }
/* Beside the grip: take this game off the board. Quiet until wanted. */
.grid-cell__x {
  flex: 0 0 auto;
  padding: 0 0.2rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 0.75rem;
  line-height: 1;
  cursor: pointer;
}
.grid-cell__x:hover { color: var(--crimson-400); }
/* The round as a board, for anyone: pitches across, kick-offs down. The
   club pins this version up at the courts, so the site can show it too. It
   carries what the list carries and nothing else - time, teams, pitch and
   division. */
.pubgrid__wrap { overflow-x: auto; padding-bottom: 0.25rem; }
.pubgrid {
  display: grid;
  grid-template-columns: auto repeat(var(--pitches), minmax(8.5rem, 1fr));
  gap: 0.4rem;
  min-width: min-content;
}
/* The clock down the side in five-minute steps: games on two pitches often
   start five minutes apart, and a row for each kick-off left the board full
   of holes. Each step is a thin row, and a game is as many of them tall as
   it runs, so what you see is what the night looks like. */
.pubgrid--fine {
  grid-template-rows: auto repeat(var(--rows), 0.42rem);
  gap: 0 0.4rem;
  align-items: stretch;
}
.pubgrid__tick {
  display: flex;
  align-items: center;
  padding-right: 0.5rem;
  font-size: 0.68rem;
  color: var(--ink-faint);
  white-space: nowrap;
}
.pubgrid__tick.is-quarter { color: var(--ink-soft); }
.pubgrid__lane { border-top: 1px solid transparent; }
.pubgrid__lane.is-quarter { border-top-color: var(--line); }
.pubgrid--fine .pubgrid__cell {
  margin: 1px 0;
  padding: 0.35rem 0.4rem;
  align-content: center;
  overflow: hidden;
}
.pubgrid__at {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--ink-faint);
}
.pubgrid__corner { display: block; }
.pubgrid__head {
  padding: 0.35rem 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: center;
}
.pubgrid__time {
  display: flex;
  align-items: center;
  padding-right: 0.5rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink-soft);
  white-space: nowrap;
}
.pubgrid__cell {
  display: grid;
  gap: 0.1rem;
  justify-items: center;
  padding: 0.6rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  text-align: center;
  transition: background 0.15s, border-color 0.15s;
}
.pubgrid__cell:hover { background: var(--surface-hi); border-color: var(--line-strong); }
.pubgrid__cell.is-empty {
  border-style: dashed;
  background: none;
  pointer-events: none;
}
.pubgrid__team { font-size: 0.82rem; font-weight: 600; line-height: 1.2; }
.pubgrid__v {
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
/* "v" dead centre, the league number at the right-hand end of its line. */
.pubgrid__mid {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  justify-self: stretch;
}
.pubgrid__mid .pubgrid__v { grid-column: 2; }
.pubgrid__lg {
  grid-column: 3;
  justify-self: end;
  padding: 0.1rem 0.3rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.6rem;
  font-weight: 700;
  line-height: 1;
  color: var(--ink-soft);
}
.pubgrid__league {
  margin-top: 0.15rem;
  font-size: 0.68rem;
  color: var(--ink-faint);
}

/* A square the draw cannot have: socials on a pitch, a club night. Striped
   rather than coloured, so it reads as "not a game" at a glance. */
.grid-block {
  position: relative;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 0.15rem;
  padding: 0.4rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-sm);
  background: repeating-linear-gradient(
    135deg,
    var(--surface) 0 8px,
    var(--surface-hi) 8px 16px);
  color: var(--ink-soft);
  text-align: center;
  overflow: hidden;
}
.grid-block__label {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--ink);
}
.grid-block__time { font-size: 0.68rem; color: var(--ink-faint); }
.grid-block__x {
  position: absolute;
  top: 0.15rem;
  right: 0.25rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 0.7rem;
  line-height: 1;
  cursor: pointer;
}
.grid-block__x:hover { color: var(--crimson-400); }

/* Change who is playing in this game. */
.grid-cell__edit {
  flex: 0 0 auto;
  padding: 0 0.2rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 0.75rem;
  line-height: 1;
  cursor: pointer;
}
.grid-cell__edit:hover { color: var(--ink); }
.grid-cell.is-held {
  outline: 2px solid var(--crimson-400);
  outline-offset: 1px;
}
.grid-cell.is-target {
  outline: 2px dashed var(--live);
  outline-offset: 1px;
}
.grid-cell__league {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.grid-cell__v { font-size: 0.66rem; color: var(--ink-faint); text-align: center; }
.grid-cell__score { font-size: 0.72rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }

.grid-team {
  width: 100%;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: 0.5rem;
  background: var(--navy-700);
  color: var(--ink);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  text-align: left;
  cursor: grab;
}
.grid-team:hover { border-color: var(--crimson-500); }
.grid-team.is-picked {
  background: var(--crimson-600);
  border-color: var(--crimson-400);
  color: var(--cream);
  cursor: grabbing;
}
.grid-team.is-target { border-color: var(--live); background: var(--surface-hi); }

/* ---- Admin breakdown: time slots per team --------------------------- */
.bd-table { display: grid; gap: 0.25rem; overflow-x: auto; }
.bd-row {
  display: grid;
  grid-template-columns: minmax(9rem, 1.6fr) repeat(auto-fit, minmax(3rem, 1fr));
  grid-auto-flow: column;
  grid-auto-columns: minmax(3rem, 1fr);
  gap: 0.3rem;
  align-items: center;
  padding: 0.45rem 0.6rem;
  border-radius: 0.5rem;
  background: var(--surface);
  font-size: 0.84rem;
}
/* The reason a team is flagged is the point of the row, so it wraps rather
   than being cut to "too many la". */
.bd-row > span { min-width: 0; overflow-wrap: anywhere; }

.bd-row--head {
  background: none;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.bd-team { display: grid; gap: 0.05rem; min-width: 0; }
.bd-team__name { font-weight: 600; }
.bd-team__league { font-size: 0.68rem; color: var(--ink-faint); }
.bd-slot {
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.bd-slot.is-late { color: var(--warn); font-weight: 700; }
.bd-slot--total { font-weight: 700; color: var(--ink); }
.bd-flag {
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: right;
  white-space: nowrap;
}
/* "Too many late games" is the reason the row is flagged, so on a narrow
   screen it wraps onto two lines rather than being cut to "too many la". */
@media (max-width: 700px) {
  .bd-flag { white-space: normal; overflow-wrap: anywhere; }
}
.bd-flag.is-warn { color: var(--danger); }
.bd-flag.is-ok { color: var(--live); }

/* Referee: one game per screen, swiped between. Scroll snapping does the
   gesture work, so there is no touch handling to get wrong. */
body.is-locked { overflow: hidden; }

.md-full {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: var(--navy-900);
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}
.md-full__bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--line);
}
.md-full__count {
  flex: 1 1 auto;
  text-align: center;
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.md-full__arrow,
.md-full__close {
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.md-full__arrow:hover,
.md-full__close:hover { background: var(--surface-hi); }

.md-full__track {
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.md-full__track::-webkit-scrollbar { display: none; }

.md-full__slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  overflow-y: auto;
  padding: 0.75rem;
  -webkit-overflow-scrolling: touch;
}

.md-full__dots {
  display: flex;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.6rem;
}
.md-full__dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 999px;
  background: var(--line-strong);
}
.md-full__dot.is-on { background: var(--crimson-500); }

/* Ticking players off on the sideline. */
.roster__player input[type="checkbox"] {
  flex: 0 0 auto;
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--crimson-500);
}
label.roster__player { cursor: pointer; }
.roster__add { margin-top: 0.5rem; display: grid; gap: 0.35rem; }
.roster__search {
  flex: 1 1 8rem;
  min-width: 0;
  padding: 0.4rem 0.55rem;
  border-radius: 0.5rem;
  border: 1px solid var(--line-strong);
  background: var(--navy-800);
  color: var(--ink);
  font: inherit;
  font-size: 0.82rem;
}
.roster__results { display: grid; gap: 0.15rem; }
.roster__hit {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.82rem;
  text-align: left;
  cursor: pointer;
}
.roster__hit:hover { border-color: var(--crimson-500); }

/* Referee match day: both squads, so the ref can check who is on court.
   Its own class - .roster belongs to the squad lists on team pages, and
   these two-column rules once leaked onto them. */
.md-roster {
  display: grid;
  gap: 0.75rem;
  margin-top: 0.5rem;
  padding: 0.75rem;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
  background: var(--surface);
}
@media (min-width: 30rem) { .md-roster { grid-template-columns: 1fr 1fr; } }

.roster__team {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.4rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.roster__count { color: var(--ink-faint); font-weight: 600; }
.roster__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.1rem; }
.roster__player {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.1rem;
  font-size: 0.88rem;
  border-bottom: 1px solid var(--line);
}
.roster__player:last-child { border-bottom: 0; }
.roster__no {
  flex: 0 0 1.5rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--ink-faint);
  text-align: right;
}
.roster__name { flex: 1 1 auto; }
.roster__tag {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.1rem 0.35rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
}
.roster__tag--fillin { color: var(--warn); border-color: var(--warn); }

/* The admin season name is a button: press it to move the whole site to
   another season. It has to keep looking like the h1 it sits inside. */
.season-h1 { margin: 0; }

.season-switch__wrap { position: relative; display: inline-block; }

.season-switch {
  display: inline-flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  text-align: left;
}
.season-switch:hover { color: var(--cream); }
.season-switch__caret {
  font-size: 0.4em;
  line-height: 1;
  color: var(--ink-soft);
  transform: translateY(-0.15em);
}
.season-switch[aria-expanded="true"] .season-switch__caret { color: var(--crimson-400); }

.season-menu {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.4rem);
  left: 0;
  min-width: min(20rem, 80vw);
  padding: 0.35rem;
  border: 1px solid var(--line-strong);
  border-radius: 0.9rem;
  background: var(--navy-700);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
  display: grid;
  gap: 0.15rem;
}

.season-menu__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 0;
  border-radius: 0.6rem;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  text-align: left;
  cursor: pointer;
}
.season-menu__item:hover { background: var(--surface-hi); }
.season-menu__item.is-current { color: var(--cream); cursor: default; }
.season-menu__flag {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--live);
  white-space: nowrap;
}
.season-menu__note,
.season-menu__link {
  padding: 0.55rem 0.75rem;
  font-size: 0.84rem;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink-soft);
}
.season-menu__link {
  border-top: 1px solid var(--line);
  margin-top: 0.15rem;
  text-decoration: none;
  display: block;
}
.season-menu__link:hover { color: var(--ink); }

.admin-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 1.25rem;
}

/* The rooms inside a group: a quieter second row under the main tabs. */
.admin-tabs--sub { margin-top: 0.6rem; }
.admin-tab--sub { padding: 0.35rem 0.8rem; font-size: 0.82rem; }

.admin-tab {
  /* The tab sits on one line with whatever it carries - a caret, or the
     number saying something is waiting - so a badge cannot drag its text
     off the centre line. */
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.5rem 1rem;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-soft);
  font-size: 0.86rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.admin-tab .badge { margin: 0 !important; line-height: 1; }
.admin-tab:hover { color: var(--ink); background: var(--surface-hi); }
.admin-tab.is-active {
  background: var(--crimson-600);
  border-color: var(--crimson-500);
  color: var(--cream);
}

/* Where new rounds come from: how many, starting when, for which divisions.
   Folded away behind one button, because most visits to this page are to
   fix a game rather than to make a week. */
.seed-panel {
  margin-bottom: 1.1rem;
  padding: 1rem 1.15rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--surface);
}
.seed-panel__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}
.seed-panel__row + .seed-panel__row { margin-top: 0.75rem; }
.seed-panel__row > label { font-size: 0.86rem; color: var(--ink-soft); }

.input-inline {
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--navy-700);
  color: var(--ink);
  font: inherit;
  font-size: 0.86rem;
}

/* Editable fixtures grid. */
.afx {
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr) 1.5rem minmax(0, 1fr) 6rem 9rem;
  gap: 0.6rem;
  align-items: center;
  padding: 0.6rem 0.8rem;
  border-radius: var(--r);
  background: var(--surface);
}
.afx + .afx { margin-top: 0.4rem; }
.afx__vs { text-align: center; color: var(--ink-faint); font-weight: 700; font-size: .8rem; }
.afx select, .afx input {
  width: 100%;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--navy-700);
  color: var(--ink);
  font-size: 0.84rem;
}
.afx input[type=time] { font-variant-numeric: tabular-nums; }
.afx__played { opacity: 0.6; }
/* A forfeited game: nobody played it, so the club can still move it or put
   another team in. Marked rather than locked. */
.afx--forfeit { outline: 2px dotted var(--warn); outline-offset: 2px; }
.grid-cell--forfeit { outline: 2px dotted var(--warn); outline-offset: -2px; }
.grid-cell__flag {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--warn);
}
.afx__played select, .afx__played input { pointer-events: none; }

/* The empty game under the last one on the seeding screen: dashed, quiet,
   plainly a space to fill rather than a game that exists. */
.afx--blank {
  background: transparent;
  border: 1px dashed var(--line-strong);
}
.afx--blank select, .afx--blank input { color: var(--ink-soft); }
/* Take out a game added by hand. Sits in the row's right margin so it never
   pushes the fields around. */
.afx { position: relative; }
.afx:has(.afx__x) { padding-right: 2.2rem; }
.afx__x {
  position: absolute;
  top: 50%;
  right: 0.55rem;
  transform: translateY(-50%);
  padding: 0.2rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 0.8rem;
  line-height: 1;
  cursor: pointer;
}
.afx__x:hover { color: var(--crimson-400); }

@media (max-width: 800px) {
  .afx { grid-template-columns: 4.5rem minmax(0,1fr) minmax(0,1fr); }
  .afx__vs { display: none; }
  .afx > *:nth-child(5), .afx > *:nth-child(6) { grid-column: span 1; }
}

/* -------------------------------------------------------------- admin schedule */

.sched-row {
  display: grid;
  grid-template-columns: 5rem minmax(0, 1fr) auto;
  gap: 1rem;
  align-items: center;
  padding: 0.85rem 1rem;
  border-radius: var(--r);
  background: var(--surface);
}

.sched-row__time {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-size: 0.95rem;
}

.sched-row__teams { display: grid; justify-items: start; min-width: 0; }
.sched-row__teams strong { font-size: 0.95rem; }

.sched-row__controls { display: flex; gap: 0.5rem; flex-wrap: wrap; justify-content: flex-end; }

@media (max-width: 760px) {
  .sched-row { grid-template-columns: 1fr; gap: 0.6rem; }
  .sched-row__controls { justify-content: flex-start; }
}

/* -------------------------------------------------------------- match clock */

.clock {
  display: grid;
  gap: 0.85rem;
  justify-items: center;
  padding: 1rem;
  border-radius: var(--r-lg);
  background: var(--navy-950);
  border: 1px solid var(--line);
}

.clock__time {
  font-size: clamp(3rem, 2rem + 8vw, 4.5rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  transition: color 0.2s;
}

.clock.is-running .clock__time { color: var(--cream); }
.clock.is-warning .clock__time { color: var(--warn); }

.clock.is-over {
  border-color: rgba(242, 88, 95, 0.6);
  background: rgba(242, 88, 95, 0.1);
}
.clock.is-over .clock__time {
  color: var(--danger);
  animation: clock-flash 1.1s ease-in-out infinite;
}

@keyframes clock-flash {
  50% { opacity: 0.45; }
}

.clock__controls {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Thumb-sized, because this is used one-handed courtside. */
.clock__btn {
  min-width: 8rem;
  padding-block: 0.9rem;
  font-size: 1rem;
}

/* -------------------------------------------------------------- dashboard */

.dash-head {
  padding-block: clamp(2rem, 1.5rem + 3vw, 3.5rem);
  border-bottom: 1px solid var(--line);
  background: linear-gradient(130deg, rgba(168, 59, 75, 0.28), transparent 60%);
}

.dash-head h1 { font-size: var(--step-3); text-transform: uppercase; }
.admin-head__shell {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* The season name on the left, the Edit mode button on the right, and the
   assistant bar straight underneath. */
.admin-head__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  justify-content: space-between;
}
.admin-head__editslot {
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}
.admin-head__memberview {
  font-size: 0.92rem;
  font-weight: 600;
  padding: 0.6rem 1rem;
}
.admin-head__shell .assistant-bar { margin-top: 0; }

.admin-head__editmode {
  font-size: 0.92rem;
  font-weight: 600;
  padding: 0.6rem 1rem;
  --btn-bg: #f59e0b !important;
  --btn-fg: #1f2937 !important;
  --btn-bd: #d97706 !important;
  box-shadow: none !important;
}

.admin-head__editmode:hover {
  --btn-bg: #d97706 !important;
}



.dash-grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  align-items: start;
}

@media (max-width: 940px) {
  .dash-grid { grid-template-columns: 1fr; }
}

.mini-list { display: grid; gap: 0.5rem; }

.mini-list__row {
  display: grid;
  gap: 0.15rem;
  padding: 0.75rem 0.9rem;
  border-radius: var(--r);
  background: var(--surface);
  font-size: 0.88rem;
}
.mini-list__row strong { font-size: 0.94rem; }
.mini-list__row .when { color: var(--ink-faint); font-size: 0.8rem; }

/* One line per season: its name, the way into its settings, and whether it
   is the one players are looking at. The live one is marked down the side
   rather than by a word in the middle of the name. */
.season-list { display: grid; gap: 0.5rem; }

.season-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: center;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r);
  background: var(--surface);
  border-left: 3px solid transparent;
}
.season-row.is-live { border-left-color: var(--live); }
.season-row__name { flex: 1 1 8rem; min-width: 0; font-size: 0.94rem; }
.season-row__acts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
  margin-left: auto;
}

.season-row__x {
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 0.9rem;
  line-height: 1;
  padding: 0.35rem 0.4rem;
  border-radius: 0.4rem;
  cursor: pointer;
}
.season-row__x:hover { color: var(--ink); background: var(--navy-800); }

@media (max-width: 520px) {
  .season-row__name { flex: 1 1 100%; }
  .season-row__acts { margin-left: 0; width: 100%; }
}

.notif {
  position: relative;
  display: grid;
  gap: 0.2rem;
  /* Room down the right for the ✕, so a long subject never runs under it. */
  padding: 0.8rem 2.1rem 0.8rem 0.9rem;
  border-radius: var(--r);
  background: var(--surface);
  border-left: 2px solid transparent;
  font-size: 0.86rem;
}

/* One message off the list. Sat in the corner rather than in the row of
   buttons underneath: it is not an answer to the message, it is the end of
   it. */
.notif__x {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  width: 1.6rem;
  height: 1.6rem;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink-faint);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.notif__x:hover { background: var(--crimson-600); color: var(--cream); }
.notif__x[disabled] { opacity: 0.4; pointer-events: none; }
.notif.is-unread { border-left-color: var(--crimson-500); background: var(--surface-hi); }
/* The subject is the line people scan; a size difference alone did not
   separate it from the message underneath. */
.notif strong { text-decoration: underline; text-underline-offset: 3px; }
.notif__meta { font-size: 0.72rem; color: var(--ink-faint); letter-spacing: 0.06em; text-transform: uppercase; }

.money-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-radius: var(--r);
  background: var(--surface);
}
.money-row__label { margin-right: auto; }
.money-row__amount { font-weight: 800; font-variant-numeric: tabular-nums; font-size: 1.05rem; }

.kpi-grid { display: grid; gap: 1px; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); background: var(--line); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
.kpi { background: var(--navy-900); padding: 1.15rem; }
.kpi dt { font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-faint); }
.kpi dd { margin: 0.3rem 0 0; font-size: var(--step-2); font-weight: 800; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- auth + forms pages */

.auth-wrap {
  display: grid;
  place-items: center;
  padding-block: clamp(2.5rem, 2rem + 4vw, 5rem);
}

.auth-card {
  width: min(100%, 28rem);
  padding: clamp(1.5rem, 1.2rem + 1.5vw, 2.5rem);
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  background: var(--navy-900);
  box-shadow: var(--shadow-lg);
}

.auth-card h1 { font-size: var(--step-2); text-transform: uppercase; margin-bottom: 0.4rem; }
.auth-switch { margin-top: 1.25rem; font-size: 0.88rem; color: var(--ink-soft); text-align: center; }
.auth-switch button {
  border: 0;
  background: none;
  color: var(--crimson-400);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.demo-logins {
  margin-top: 1.25rem;
  padding: 0.9rem 1rem;
  border-radius: var(--r);
  border: 1px dashed var(--line-strong);
  font-size: 0.78rem;
  color: var(--ink-faint);
  display: grid;
  gap: 0.3rem;
}
.demo-logins button {
  border: 0;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
  text-align: left;
  padding: 0;
  font-size: 0.78rem;
}
.demo-logins button:hover { color: var(--crimson-400); }

.form-page { width: min(100%, 46rem); margin-inline: auto; }

/* ==========================================================================
   Photography
   Shots of the club's own nights at Dorrien Gardens, carried across from the
   site they ran before this one. Each sits behind a scrim built from the
   palette, so the photo reads as ground rather than as a picture pasted on,
   and type over it stays legible whatever the shot is doing. The image itself
   comes in as --photo, set where the layer is used.
   ========================================================================== */

.photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: var(--photo-focus, center);
  background-repeat: no-repeat;
  /* The club's photos are lit by hall floodlights, which run hot and green.
     Pulling the saturation back lets them sit next to the crimson. */
  filter: saturate(0.7);
  background-image:
    linear-gradient(180deg, rgba(21, 8, 38, 0.66) 0%, rgba(28, 15, 49, 0.82) 55%,
                    var(--navy-800) 100%),
    var(--photo);
}

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

/* Weighted to the left, where the headline and the crimson band are: the
   photo is close to full strength out on the right where nothing sits. */
.hero__photo {
  background-image:
    linear-gradient(90deg, rgba(21, 8, 38, 0.95) 0%, rgba(21, 8, 38, 0.78) 42%,
                    rgba(21, 8, 38, 0.38) 100%),
    linear-gradient(0deg, var(--navy-800) 1%, rgba(36, 21, 70, 0) 42%),
    var(--photo);
  background-position: center 42%;
}

@media (max-width: 900px) {
  /* Stacked, the text runs the full width, so the left-weighted wash no
     longer lines up with anything. Even it out instead. */
  .hero__photo {
    background-image:
      linear-gradient(180deg, rgba(21, 8, 38, 0.8) 0%, rgba(21, 8, 38, 0.66) 45%,
                      var(--navy-800) 100%),
      var(--photo);
  }
}

/* -- page banners -------------------------------------------------------- */

.page-banner {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3rem, 2rem + 4vw, 5.5rem);
  border-bottom: 1px solid var(--line);
}

.page-banner > .shell { position: relative; z-index: 1; }

@media (max-width: 700px) {
  /* Narrow enough that the lead paragraph runs right across the photo rather
     than beside it, so the wash has to work harder. */
  .page-banner .photo {
    background-image:
      linear-gradient(180deg, rgba(21, 8, 38, 0.78) 0%, rgba(28, 15, 49, 0.88) 55%,
                      var(--navy-800) 100%),
      var(--photo);
  }
}

/* A plain list of statements, each ticked. Used for the waiver, where every
   line is something the reader is agreeing to rather than a bullet point. */
.tick-list { list-style: none; display: grid; gap: 0.45rem; margin-top: 0.5rem; }
.tick-list li {
  position: relative;
  padding-left: 1.4rem;
  color: var(--ink-soft);
  font-size: 0.92rem;
}
.tick-list li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--crimson-400);
  font-weight: 700;
}

/* Keeps a run of the headline exactly as it is written, against the uppercase
   the rest of the title takes. An <em> so it still means something with the
   styles off; the slant is not wanted. */
.hero__title-asis { text-transform: none; font-style: normal; }

/* The socials door list: one person per row, phone number tappable. */
.roll-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem 1rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--line);
}
.roll-row:last-child { border-bottom: 0; }
.roll-row__name { font-weight: 700; }
.roll-row__extras { color: var(--warn); font-weight: 800; }
.roll-row__phone { font-variant-numeric: tabular-nums; }
.roll-row__when { margin-left: auto; font-size: 0.76rem; color: var(--ink-faint); }
/* Everybody on the booking, each with a tick for who turned up. */
.roll-row__people {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.6rem;
}
.roll-row__person {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  font-size: 0.86rem;
  cursor: pointer;
}
.roll-row__person:has(input:checked) { border-color: var(--live); background: rgba(52, 211, 153, 0.1); }

/* How many they are bringing: four small pills, the chosen one lit. */
.social-card__bringing { display: flex; align-items: center; gap: 0.35rem; }
.bring-pick {
  min-width: 2.1rem;
  height: 2.1rem;
  padding: 0 0.4rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink-soft);
  font-weight: 700;
  cursor: pointer;
}
.bring-pick:hover:not(:disabled) { border-color: var(--crimson-500); }
.bring-pick.is-on {
  background: var(--crimson-600);
  border-color: var(--crimson-500);
  color: var(--cream);
}

/* ==========================================================================
   Finals brackets
   Columns left to right, one per round; a match is two stacked slots.
   space-around per column keeps later rounds sitting between the matches
   that feed them without drawing connector lines.
   ========================================================================== */

.bracket-wrap { overflow-x: auto; padding-bottom: 0.5rem; }
.bracket { display: flex; gap: 1.25rem; min-width: min-content; }
.bracket-round {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  /* From the top, not floated down the column: the matches line up across
     rounds, and the header row does the aligning. */
  justify-content: flex-start;
  min-width: 13rem;
}

/* One header per column, the same height in every column — name on the
   first line, date on the second — so the boxes below all start level,
   date or no date, picker or plain text. */
.bracket-round__head {
  min-height: 3.4rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 0.3rem;
}
.bracket-round__name {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.bracket-match {
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  overflow: hidden;
}
.bracket-match--champ { border-color: var(--warn); }
.bracket-match__name {
  padding: 0.3rem 0.7rem 0;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.round-sizer { display: flex; gap: 0.3rem; justify-content: center; }
.bracket-slot {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.7rem;
  background: var(--surface);
  cursor: pointer;
}
.bracket-slot + .bracket-slot { border-top: 1px solid var(--line); }
.bracket-slot.is-empty { cursor: default; color: var(--ink-faint); }
/* An empty first-round slot on the admin board takes a click: it offers the
   teams that have no game in the round yet. */
.bracket-slot.is-open { cursor: pointer; }
.bracket-slot.is-open:hover { background: var(--surface-hi); color: var(--ink-soft); }
.bracket-slot.is-picked { outline: 2px solid var(--crimson-400); outline-offset: -2px; }
.bracket-slot:hover:not(.is-empty) { background: var(--surface-hi); }
.bracket-slot__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.88rem;
  font-weight: 600;
}
.bracket-slot__actions { display: flex; gap: 0.25rem; }
.bracket-btn {
  width: 1.6rem;
  height: 1.6rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
  font-size: 0.8rem;
}
.bracket-btn:hover { border-color: var(--crimson-500); color: var(--cream); }

/* The public board is for reading, not pressing. */
.bracket-slot--still { cursor: default; }
.bracket-slot--still:hover { background: var(--surface); }

/* Teams with no first-round game, waiting to be dragged in. */
.bench-team {
  padding: 0.35rem 0.7rem;
  border: 1px dashed var(--line-strong);
  border-radius: 999px;
  background: none;
  color: var(--ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: grab;
}
.bench-team:hover { border-color: var(--crimson-500); color: var(--cream); }
.bench-team.is-picked { outline: 2px solid var(--crimson-400); }
.bracket-slot.is-target { outline: 2px dashed var(--warn); outline-offset: -2px; }

/* Round dates: read-only text on the public board, a picker on the admin's. */
.bracket-round__date {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--warn);
}
.bracket-round__pick {
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.78rem;
  color-scheme: dark;
}

/* The rest of the week's games, plainly separated from the knockout: a
   dashed border where the bracket's are solid, and a label saying what
   these are — friendlies, not finals. */
.friendly-block {
  margin-top: 1.1rem;
  padding: 0.8rem 1rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r);
  display: grid;
  gap: 0.4rem;
}
.friendly-block__tag {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.friendly-block__week { font-size: 0.84rem; color: var(--ink-soft); }
.friendly-block__week strong { color: var(--ink); }
.friendly-block__date { color: var(--warn); font-weight: 700; }

/* Group tabs are buttons, not links: they open the row beneath, nothing
   else, so they carry a caret to say so. */
.admin-tab--group { cursor: pointer; font-family: inherit; }
.admin-tab__caret { margin-left: 0.3rem; font-size: 0.7em; opacity: 0.7; }

/* The money glance on each team tile: bond state and this week's fee. */
.team-tile__money {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

/* A fixtures-editor row whose referee is booked twice at that time. */
.afx--clash { outline: 1px solid var(--danger); outline-offset: 2px; border-radius: var(--r-sm); }

/* A week-ahead row whose referee is booked twice at that time. */
.week-row--clash {
  border: 1px solid var(--danger);
  border-radius: var(--r-sm);
}

/* A season row that opens that season's settings. */
button.mini-list__row--press {
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
button.mini-list__row--press:hover { background: var(--surface-hi); }

/* Dates on the season page: type in the field, or press for the calendar. */
.date-wrap { display: flex; gap: 0.35rem; align-items: stretch; }
.date-wrap input { flex: 1; min-width: 0; }
.date-pop {
  padding: 0 0.6rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  cursor: pointer;
  font-size: 0.95rem;
}
.date-pop:hover { border-color: var(--crimson-500); }

/* A league name on the builder: press it and the draw below points at it. */
.lg-chip {
  padding: 0.25rem 0.65rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.84rem;
  cursor: pointer;
}
.lg-chip:hover { border-color: var(--crimson-500); color: var(--cream); }
.lg-chip.is-on {
  background: var(--crimson-600);
  border-color: var(--crimson-500);
  color: var(--cream);
}

/* The fixtures editor's submit strip, and the rows with unsaved edits. */
.save-bar {
  position: sticky;
  bottom: 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1rem;
  padding: 0.7rem 1rem;
  border: 1px solid var(--warn);
  border-radius: var(--r);
  background: var(--navy-900);
  box-shadow: var(--shadow);
}
.afx--dirty { outline: 1px dashed var(--warn); outline-offset: 2px; border-radius: var(--r-sm); }

/* A week-ahead row with unsaved edits. */
.week-row--dirty { outline: 1px dashed var(--warn); outline-offset: 2px; border-radius: var(--r-sm); }


/* The home page's social strips are doors to the Socials page. */
a.social-strip--link {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
a.social-strip--link:hover {
  border-color: var(--crimson-500);
  background: var(--surface-hi);
}

/* A finals game in any fixture list: an amber edge and its round name where
   the league code would sit. */
.fx--final {
  border-left: 3px solid var(--warn);
  background: linear-gradient(90deg, rgba(245, 184, 65, 0.08), transparent 45%);
}
.fx__finals-tag {
  color: var(--warn);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.35;
}

/* Rounds − + on a board's header: how deep this division's knockout runs. */
.round-depth { display: inline-flex; align-items: center; gap: 0.3rem; }
.round-depth__label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The front-page announcement: the admins' own words, said loudly -
   a band the whole width of the page, sitting centred in the air between
   the site header above and the hero content below. */
.hero__announce {
  position: relative;
  z-index: 2;
  /* Lift into the hero's own top padding, leaving the same air above and
     below the band. */
  margin: calc(clamp(3.5rem, 2rem + 8vw, 7.5rem) / -2 - 1.4rem) 0
          clamp(1.75rem, 1rem + 4vw, 3.75rem);
  padding: 0.8rem 1.25rem;
  background: var(--crimson-600);
  color: var(--cream);
  text-align: center;
  font-weight: 800;
  font-size: clamp(0.95rem, 0.8rem + 0.8vw, 1.3rem);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  box-shadow: 0 8px 26px rgba(20, 10, 40, 0.35);
}

/* Competition info: the numbers people want first, spread across the page. */
.info-facts {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  gap: 1rem 2.5rem;
  margin: 0 auto 2rem;
  max-width: 56rem;
  text-align: center;
  padding: 1rem 1.5rem;
  border: 1px solid var(--line);
  border-radius: 1rem;
}
.info-facts dt {
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.info-facts dd {
  margin-top: 0.3rem;
  font-weight: 800;
  font-size: 1.25rem;
}

/* Team badges: uploaded by the teams themselves. */
.team-badge__preview {
  display: block;
  width: 7rem;
  height: 7rem;
  object-fit: contain;
  border-radius: 0.75rem;
  background: rgba(252, 227, 222, 0.06);
  padding: 0.4rem;
}
.team-hero__badge {
  width: 5.5rem;
  height: 5.5rem;
  object-fit: contain;
  margin-bottom: 0.75rem;
}

/* The public Teams grid: the crest is the tile, with the name and the
   leagues centred underneath. */
.team-tile--crest {
  justify-items: center;
  align-content: start;
  gap: 0.6rem;
  padding: 1.5rem 1.25rem 1.35rem;
  text-align: center;
}
.team-tile--crest .team-tile__name {
  display: block;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.team-tile__crest {
  width: 7.5rem;
  height: 7.5rem;
  margin-bottom: 0.35rem;
  object-fit: contain;
}
.team-tile__crest--blank {
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 3px solid var(--strip, var(--line-strong));
  background: var(--surface-hi);
  color: var(--ink-soft);
  font-size: 2.2rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}
.team-tile__leagues {
  display: grid;
  gap: 0.15rem;
  font-size: 0.74rem;
  color: var(--ink-faint);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* A team's uploaded badge sits atop its tile. */
.team-tile__badge {
  width: 3.5rem;
  height: 3.5rem;
  object-fit: contain;
  justify-self: start;
}

/* On the public finals board a team with a badge stands as the badge,
   name underneath. The admin board keeps its compact rows. */
.bracket-slot--badged {
  display: grid;
  justify-items: center;
  gap: 0.4rem;
  padding-block: 0.7rem;
  text-align: center;
}
.bracket-slot__badge {
  width: 4rem;
  height: 4rem;
  object-fit: contain;
}
.bracket-slot__tag {
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* The whistle on each grid square. */
.grid-cell__ref {
  width: 100%;
  margin-top: 0.15rem;
  padding: 0.25rem 0.35rem;
  border-radius: 0.45rem;
  border: 1px solid var(--line);
  background: rgba(0, 0, 0, 0.25);
  color: var(--ink-soft);
  font-size: 0.72rem;
}
.grid-cell__ref.is-doubled {
  border-color: var(--danger, #e0564f);
  color: var(--danger, #e0564f);
}

/* Admin > Games > Payments */
.payrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.7rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--line);
}
.payrow__team { flex: 1 1 10rem; font-weight: 700; }
.payrow__amount { font-variant-numeric: tabular-nums; }
.payrow__act { min-width: 6.5rem; display: flex; gap: 0.4rem; flex-wrap: wrap; justify-content: flex-end; }

/* Solo player form */
/* A session on the Solo player page: its price, and its own button. */
.solo-social { flex-wrap: wrap; gap: 0.5rem 0.9rem; align-items: center; }
.solo-social .money-row__label { flex: 1 1 14rem; }
.solo-nights { display: grid; gap: 0.5rem; margin-top: 0.4rem; }
.solo-night {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
  font-size: 0.92rem;
}
.solo-night:has(input:checked) { border-color: var(--crimson-500); }

/* The club's note to the referee, pinned under a team on match day. */
.refnote {
  margin-top: 0.3rem;
  padding: 0.45rem 0.7rem;
  border-left: 3px solid var(--warn, #e0b34f);
  border-radius: 0 0.45rem 0.45rem 0;
  background: rgba(224, 179, 79, 0.1);
  font-size: 0.84rem;
}
.refnote strong { color: var(--warn, #e0b34f); }
.refnote__edit, .refnote__add {
  border: 0;
  background: none;
  color: var(--ink-faint);
  cursor: pointer;
  font-size: 0.8rem;
  padding: 0.1rem 0.3rem;
}
.refnote__add { margin-top: 0.25rem; }
.refnote__add:hover, .refnote__edit:hover { color: var(--cream); }
.refnote__input {
  flex: 1;
  font-size: 0.85rem;
}

/* The adjustable clock's extra controls. */
.clock__controls + .clock__controls { margin-top: 0.5rem; }
/* Before the game is started the big button starts the game, and its label
   can be long ("Start (fees outstanding)"): it gets a row to itself. */
.clock--kickoff .clock__controls { flex-wrap: wrap; justify-content: center; }
.clock--kickoff .clock__controls > .btn--go { order: -1; flex: 1 1 100%; }
.clock__nudge {
  min-width: 4.6rem;
  padding-block: 0.9rem;
  font-variant-numeric: tabular-nums;
}
/* The three clock buttons in a row are wider than a phone's card. */
@media (max-width: 460px) {
  .clock__controls { gap: 0.4rem; }
  .clock__btn { min-width: 6.5rem; }
  .clock__nudge { min-width: 4rem; }
}
.clock__set {
  width: 6.5rem;
  padding: 0.7rem 0.6rem;
  font-size: 1.05rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* ---- Booking a socials spot ------------------------------------------ */
.social-book {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.6rem;
}
.social-book__heads {
  height: 2.1rem;
  padding: 0 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--ink);
  font-weight: 700;
}
/* Name and email only show to somebody signed out, and take the full width
   so the two fields sit under the button rather than squeezing it. */
.social-book__who {
  flex-basis: 100%;
  display: grid;
  gap: 0.5rem;
  grid-template-columns: 1fr;
}
/* Fixed columns, so the friends' boxes line up under the details above. */
@media (min-width: 560px) {
  .social-book__who { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
  .social-book__who { grid-template-columns: repeat(4, 1fr); }
}
.social-book--form { flex-basis: 100%; }
/* The price and the button that pays it, together at the foot of the form. */
.social-book__pay {
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem .9rem;
}
.social-book__cost { color: var(--ink-soft); font-size: .85rem; }
@media (max-width: 560px) {
  .social-book__pay .btn { width: 100%; justify-content: center; }
}
.social-book__mine {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}

/* Lost ball: the venue map with a pin for every ball nobody has collected. */
.lostball { max-width: 34rem; margin: 0 auto; }
.lostball__map {
  position: relative;
  aspect-ratio: 496 / 646;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: var(--navy-950);
  cursor: crosshair;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
}
.lostball__img { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.lostball__pins { position: absolute; inset: 0; }
.lostball__pin {
  position: absolute;
  width: 1.7rem;
  height: 1.7rem;
  margin: -2.05rem 0 0 -0.85rem;      /* the point of the pin is the spot */
  padding: 0;
  border: 2px solid var(--cream);
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  transform-origin: 50% 50%;
  background: var(--crimson-500);
  color: var(--cream);
  cursor: pointer;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.55);
}
.lostball__pin > span {
  display: block;
  transform: rotate(45deg);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.45rem;
}
.lostball__pin.is-selected { background: var(--warn); color: #1c0f31; z-index: 2; }
.lostball__pin.is-draft { background: var(--live); color: #1c0f31; pointer-events: none; z-index: 3; }
.lostball__after { display: grid; gap: 0.6rem; margin-bottom: 0.8rem; }
.lostball__hint { margin: 0.6rem 0; text-align: center; font-size: 0.86rem; color: var(--ink-soft); }
.lostball__note {
  width: 100%;
  margin-bottom: 0.6rem;
  padding: 0.65rem 0.8rem;
  border-radius: 10px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.lostball .btn-row .btn { flex: 1 1 auto; }
.lostball__list { margin-top: 1.1rem; display: grid; gap: 0.5rem; }
.lostball__row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  font-size: 0.86rem;
}
.lostball__row.is-selected { border-color: var(--warn); }
.lostball__row.is-done { opacity: 0.6; }
.lostball__num {
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--crimson-500);
  color: var(--cream);
  text-align: center;
  font-weight: 700;
  font-size: 0.78rem;
  line-height: 1.6rem;
}
.lostball__row.is-done .lostball__num { background: var(--live); color: #1c0f31; }
.lostball__what { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.lostball-full__body { overflow-y: auto; padding: 0.75rem; }
.lostball-full__title { font-size: 0.95rem; text-transform: uppercase; letter-spacing: 0.08em; }

/* A game on a team's own page: time, score, opponent and their colour, pitch,
   league. The opponent's name wraps rather than being cut short. */
.tfx {
  display: grid;
  grid-template-columns: 4.8rem 3rem minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.3rem 0.75rem;
  padding: 0.7rem 0.95rem;
  border-radius: var(--r);
  text-decoration: none;
  color: inherit;
}
.tfx:hover { background: var(--surface); }
.tfx + .tfx { box-shadow: inset 0 1px 0 var(--line); }
.tfx__time { display: grid; line-height: 1.25; white-space: nowrap; }
.tfx__time b { font-size: 0.88rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.tfx__time small { font-size: 0.7rem; color: var(--muted, inherit); opacity: 0.7; }
.tfx__score { font-weight: 700; font-size: 0.94rem; text-align: center; font-variant-numeric: tabular-nums; }
.tfx__score--empty { font-weight: 400; opacity: 0.45; text-transform: uppercase; font-size: 0.78rem; }
.tfx__score.is-won { color: var(--good, #5fd3a0); }
.tfx__score.is-lost { opacity: 0.6; }
.tfx__opponent { display: flex; align-items: center; gap: 0.45rem; font-size: 0.94rem; font-weight: 600; min-width: 0; }
.tfx__opponent > span:first-child { overflow-wrap: anywhere; }
.tfx__pitch, .tfx__league {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; opacity: 0.7; white-space: nowrap;
}
@media (max-width: 640px) {
  .tfx { grid-template-columns: 4.4rem 2.6rem minmax(0, 1fr) auto; }
  .tfx__pitch { grid-column: 3; }
  .tfx__league { grid-column: 4; }
  .tfx__opponent { grid-column: 3 / -1; }
}

/* The clock at nought: Half time / Full time flashing where the numbers
   were, pressed once to stop it, then Reset. */
.clock__call {
  font: inherit;
  font-size: clamp(2.2rem, 1.4rem + 6vw, 3.4rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--danger);
  background: none;
  border: 2px solid currentColor;
  border-radius: var(--r-lg);
  padding: 1.1rem 1.4rem;
  width: 100%;
  cursor: pointer;
  animation: clock-flash 1.1s ease-in-out infinite;
}
.clock__call[hidden] { display: none; }
.clock.is-acked .clock__call { animation: none; color: var(--cream); }
.clock.is-acked { border-color: var(--line); background: var(--navy-950); }

/* Admin > Teams > Ladder points and byes: one line per bye or change, with
   its buttons underneath. */
.plain-list { list-style: none; margin: .4rem 0 .8rem; padding: 0; display: grid; gap: .6rem; font-size: .85rem; }
.plain-list li { display: grid; gap: .3rem; }
.ladder-hand { display: grid; gap: .4rem; margin: .6rem 0; }
.ladder-hand .input-inline { width: 100%; }

/* A block is picked up and put down like a game. */
.grid-block { cursor: grab; }
.grid-block.is-held { outline: 2px solid var(--crimson-400); outline-offset: 1px; }

/* Admin > Socials: the form for a new session, or one being edited, set
   apart from the list of sessions around it. */
.social-form {
  margin-top: 0.9rem;
  padding: 1rem 1rem 0.2rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
}

/* The discount code box on a socials booking. */
.social-code { flex-basis: 100%; }
.social-code__open {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-soft);
  font: inherit;
  font-size: .85rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.social-code__open:hover { color: var(--ink); }
.social-code__row { display: flex; align-items: center; gap: .5rem; max-width: 22rem; }
.social-code__row[hidden] { display: none; }
.social-code__row input {
  flex: 1;
  min-width: 0;
  height: 2.75rem;
  padding: 0 .9rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: rgba(21, 8, 38, 0.6);
  color: var(--ink);
  font-size: .9rem;
  text-transform: uppercase;
}
.social-code__row input::placeholder { color: var(--ink-faint); }
.social-code__row input:focus {
  outline: none;
  border-color: var(--crimson-500);
  background: rgba(21, 8, 38, 0.85);
}
.social-code__note { display: block; font-size: .8rem; margin-top: .25rem; }
.social-code__note.is-good { color: var(--live); }
.social-code__note.is-bad { color: var(--danger); }

/* The season button under the Fixtures heading, for looking back. */
.season-pick { display: flex; align-items: center; flex-wrap: wrap; gap: .6rem; margin-top: .6rem; }
.season-switch--page {
  align-items: center;
  padding: .45rem .8rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  font-size: .95rem;
  font-weight: 700;
}
.season-switch--page .season-switch__caret { font-size: .7em; transform: none; }
