/* tcl-theme/assets/css/form.css
 * TCL-574 — F2-04 multi-step form framework: shell chrome, field vocabulary, states.
 *
 * Visual spec is locked by the accepted design bundles (do NOT re-derive from scratch —
 * this file mirrors docs/wireframes/REG-04-details-and-kit/REG-04.dc.html for input/
 * checkbox/error treatments and REG-01/REG-05 for the rail + action bar). Every colour
 * comes from a var() in tokens.css. No new tokens, no raw hex anywhere in this file.
 *
 * ⚠️ THIS FILE USED TO SAY "No red/green/blue anywhere, including error states: an error is a
 * gold border plus helper text in the flow's own ink, never a colour of its own." ROUND 1
 * (2026-09-17) REVERSED THAT, on Noah's own words: "ensure that a red outline appears when its
 * not acceptable". An error is `--danger` now, read through `--flow-danger`, and it is the ONE
 * exception. Everything else in this file is still the five brand tokens and their ramps, and a
 * second status colour does not follow from this one. See the Error state block for why gold
 * was the wrong signal.
 *
 * Namespace: .tcl-form and its descendants only. This file does not touch .w-* or .lp-*.
 */

/* ============================================================
   TCL-805: THE FLOW'S ROLE LAYER, AND WHY IT EXISTS
   ============================================================
   Noah's staging feedback, item 5: "The black background on all the registration pages is
   unsightly, can we change it to a lighter color, like what we do on the body of the landing
   page? The text color can change to something else within our palate that's visible and
   clear." It applies to every flow at once, so it is done HERE and in inc/form-framework.php
   and nowhere per flow.

   THE MECHANISM IS ONE SET OF ROLE PROPERTIES, DEFINED ONCE AND REDEFINED ON DARK GROUND.
   Every rule below reads --flow-ink, --flow-ink-muted, --flow-surface and friends rather than
   naming a palette token directly. A container that keeps a dark fill (the header, a selected
   card, a notice panel, a filled roster slot) redefines those properties on itself, and custom
   properties inherit, so every descendant flips with it and no descendant needs a rule of its
   own. That is what keeps this change a re-mapping rather than a rewrite, and it is what makes
   "check every state" a finite job.

   EVERY VALUE IS A tokens.css TOKEN. Nothing here is a hex literal (deploy/lint.sh G2), and
   nothing here is a new brand colour: the accent is still Gold, the dark ground is still
   Forest and Deep Forest, and the light ground is --paper, the landing page's own body
   background.

   --flow-accent-ink IS GOLD READ FROM THE RAMP RATHER THAN A SECOND ACCENT. --gold on --paper
   is about 2.8:1, which fails 4.5:1 for anything a person has to read, so accent TEXT on the
   light ground takes --gold-600 while every accent FILL, border, pip and focus ring stays
   --gold. On the dark ground it is redefined back to --gold, where that contrast already
   works.
   ============================================================ */
.tcl-form,
body.tcl-flow-takeover {
  /* Ground. --paper is the landing page's body background (main.css line 44). */
  --flow-bg: var(--paper);
  --flow-surface: var(--white);
  --flow-surface-sunk: var(--sand-50);

  /* Ink. --ink-900 and --ink-500 both clear 4.5:1 on --paper. */
  --flow-ink: var(--ink-900);
  --flow-ink-muted: var(--ink-500);
  --flow-ink-placeholder: var(--ink-500);
  --flow-ink-disabled: var(--ink-400);
  --flow-display: var(--deep-forest);

  /* Lines. A card, an input and a panel take the Forest border; a hairline INSIDE one takes
     the lighter step so a rule between two rows does not read as a second card edge. */
  --flow-line-strong: var(--forest);
  --flow-line: var(--forest-200);
  --flow-track: var(--forest-200);

  /* The selected state: Forest fill, cream text. Unchanged from the dark build. */
  --flow-selected-bg: var(--forest);

  /* Accent. Fill stays --gold everywhere; accent TEXT on light takes the ramp's --gold-600. */
  --flow-accent-ink: var(--gold-600);

  --flow-disabled-bg: var(--ink-200);

  /* ⚠️ ROUND 1 (2026-09-17). THE ONE COLOUR THIS FLOW HAS THAT IS NOT A BRAND TOKEN, AND NOAH
     ASKED FOR IT BY NAME: "ensure that a red outline appears when its not acceptable".
     `--danger` is tokens.css's own status colour, not a new one, and it is read through a role
     property here so a container that ever puts a field on a dark ground can redefine it the way
     every other role above is redefined. None does today, which .herrors/ asserts. */
  --flow-danger: var(--danger);
}

/* Anything sitting on a Forest or Deep Forest ground redefines the ink roles, and every
   descendant follows. This is the whole of the dark-on-light handling. */
.tcl-form__header,
.tcl-notice--alarm,
.tcl-notice--welcome,
.tcl-roster__slot--filled,
.tcl-card:has(.tcl-card__radio:checked),
.tcl-season:has(.tcl-card__radio:checked) .tcl-season__card,
.tcl-league-row:has(.tcl-card__radio:checked),
.tcl-free-agent__row:has(.tcl-card__radio:checked),
.tcl-terms__card:has(.tcl-card__radio:checked) {
  --flow-ink: var(--cream);
  --flow-ink-muted: var(--forest-200);
  --flow-ink-disabled: var(--forest-300);
  --flow-accent-ink: var(--gold);
  --flow-line: var(--forest-500);
  --flow-line-strong: var(--forest-500);
}

/* ============================================================
   SHELL
   ============================================================ */
.tcl-form {
  --tcl-form-max: 560px;
  font-family: var(--font-ui);
  color: var(--flow-ink);
  background: var(--flow-bg);
}

.tcl-form__header {
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--gutter);
  border-bottom: 1px solid var(--flow-line);
}

/* TCL-805, Noah's item 4: "since the banner at the top has a see through background, it leads
   to an awkward thing where the logo is over the text. Give it an opaque background, same
   green as the containers below is fine, just make sure we have that white stroke around the
   TCL logo same as on the landing page."

   OPAQUE FOREST, AND NOTHING SCROLLS UNDER IT. The bar is position:sticky in takeover mode
   (see the takeover block at the foot of this file), so with a transparent fill the step
   behind it showed through and the mark sat on top of the copy. The class is on the element
   rather than being implied by the tag, so a harness can assert it on all four flows. It is
   declared AFTER the base rule so its border colour wins at equal specificity. */
.tcl-form__header--solid {
  background: var(--forest);
  border-bottom-color: var(--forest-700);
}

/* The eight-direction white outline main.css gives the landing page's nav mark, reused rather
   than re-invented. It is byte-identical to main.css line 197's own declaration, which the
   TCL-805 harness asserts across the two files, and #fff is the one hex deploy/lint.sh G2
   allows anywhere (achromatic literals carry no brand-drift risk). */
.tcl-form__mark--outlined {
  filter: drop-shadow(1px 0 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 1px 0 #fff) drop-shadow(0 -1px 0 #fff) drop-shadow(1px 1px 0 #fff) drop-shadow(-1px -1px 0 #fff) drop-shadow(1px -1px 0 #fff) drop-shadow(-1px 1px 0 #fff);
}

/* M-03 (TCL-618): the mark + wordmark lockup. ⚠️ ROUND 2 (2026-09-18), item 9: it IS a link now
   (see form-framework.php for the reversal and Noah's words). Nothing about the layout changes
   with the element, so the rule is unchanged apart from its own comment. */
.tcl-form__brand {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

/* ⚠️ ROUND 2 (2026-09-18), ITEM 9.1. THE MARK IS THE LANDING NAV'S OWN SIZE.
   Noah: "The logo is also smaller on the registration pages than it is on the main site. Fix
   that." main.css's `.w-nav__mark` is 52px and this was 28px, which is what he is comparing.
   The two are the same measurement now, which is the whole of the ruling.

   THE WORDMARK GOES WITH IT, and that is a judgement the ruling forced rather than one it made:
   the ruling names the mark, but a lockup whose mark nearly doubled while the word beside it did
   not is a broken lockup, and 52:28 is main.css's own pair (`.w-nav__mark` / `.w-nav__wordmark`).
   Matching the landing nav's lockup is the same instruction read one element wider.

   The header's own 64px height is unchanged and holds a 52px mark with room either side. */
.tcl-form__mark {
  height: 52px;
  width: auto;
  display: block;
}

.tcl-form__wordmark {
  height: 28px;
  width: auto;
  display: block;
}

/* ---------- Progress rail ----------
 * Three FIXED stages. The rail never changes length regardless of how many steps a
 * stage contains or which steps a condition hides — only the dot/bar states move.
 */
.tcl-form__rail {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}

.tcl-form__rail-item {
  display: flex;
  align-items: center;
}

.tcl-form__rail-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--forest-300);
  flex-shrink: 0;
}

.tcl-form__rail-bar {
  width: 96px;
  height: 4px;
  border-radius: 2px;
  background: var(--gold);
  flex-shrink: 0;
}

.tcl-form__rail-label {
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--flow-ink);
  white-space: nowrap;
}

/* Only the current stage shows a label + bar; the rest are bare dots. */
.tcl-form__rail-item[data-rail-state="pending"] .tcl-form__rail-label,
.tcl-form__rail-item[data-rail-state="done"] .tcl-form__rail-label {
  display: none;
}
.tcl-form__rail-item[data-rail-state="current"] .tcl-form__rail-dot {
  display: none;
}
.tcl-form__rail-item[data-rail-state="pending"] .tcl-form__rail-bar,
.tcl-form__rail-item[data-rail-state="done"] .tcl-form__rail-bar {
  display: none;
}
/* A completed stage keeps the gold treatment on its dot so progress reads at a glance,
   without growing the rail or adding a second colour. */
.tcl-form__rail-item[data-rail-state="done"] .tcl-form__rail-dot {
  background: var(--gold);
}

/* ---------- the header on a phone (Noah, 2026-10-29, iPhone screenshot) ----------
   At 375px the bar did not fit: the lockup is 105px, the rail is 258px (a 96px bar, LEAGUE
   DETAILS at 14px with 0.1em tracking, two dots and the gaps), and the two 20px gutters make
   403px. The brand link was the flex item that gave way, so the wordmark slid under the gold
   bar, which is what the screenshot shows.

   Two things, and both are measurements this theme already uses rather than new ones. The
   lockup takes the landing nav's own phone sizes (main.css, `.w-nav__mark` 46px and
   `.w-nav__wordmark` 24px in its 767px block), which is the same "same as the landing page"
   instruction TCL-805 applied at desktop width, and it may no longer shrink. The rail's bar
   drops to 32px and its label to --fs-caption, so the rail is about 180px. 20 + 94 + 8 + 180 +
   20 is 322px, which fits a 360px Android and a 375px iPhone with room to spare. Nothing about
   the rail's three stages, its states or its order changes: only its width on a phone. */
@media (max-width: 767px) {
  .tcl-form__brand {
    flex-shrink: 0;
  }
  .tcl-form__mark {
    height: 46px;
  }
  .tcl-form__wordmark {
    height: 24px;
  }
  .tcl-form__rail {
    margin-left: var(--s-2);
  }
  .tcl-form__rail-bar {
    width: 32px;
  }
  .tcl-form__rail-label {
    font-size: var(--fs-caption);
    letter-spacing: 0.08em;
  }
}

/* ============================================================
   BODY / CONTENT COLUMN
   ============================================================ */
.tcl-form__body {
  padding: 0 var(--gutter);
}

.tcl-form__col {
  max-width: var(--tcl-form-max);
  margin: 0 auto;
  padding: var(--s-2) 0 var(--s-10);
}

.tcl-form__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

.tcl-form__eyebrow img {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--forest);
  padding: 4px;
  object-fit: cover;
}

.tcl-form__title {
  font-family: var(--font-norwester);
  font-weight: 400;
  line-height: 0.95;
  color: var(--flow-display);
  margin: 0 0 var(--s-8);
  font-size: clamp(32px, 6vw, 56px);
}

/* Round 1, item 9: "the team details should be the biggest thing on the page". On R4b the
   loudest element is a piece of DATA rather than the heading, so the step's H1 takes the small
   label treatment and sits above the team as its eyebrow. It is the same element, with the same
   focus target and the same announcement; only the type changes, and the team name below it
   takes the size this rule gives up. Nothing else selects on the step. */
.tcl-form__title--eyebrow {
  font-family: var(--font-ui);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-callout);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--flow-ink-muted);
  margin: 0 0 var(--s-3);
}

/* aria-live region: visually present but not shouting — kept in flow so sighted users
   also see step progress, per REG-04's "Your details" step 12px label pairing. */
.tcl-form__announce {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
  margin: 0 0 var(--s-4);
}

/* ============================================================
   FIELDS
   ============================================================ */
.tcl-field {
  margin-bottom: var(--s-5);
}

.tcl-field__label {
  display: block;
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
  color: var(--flow-ink);
  margin-bottom: var(--s-2);
}

.tcl-field__label-optional {
  font-size: 12px;
  font-weight: var(--fw-regular);
  color: var(--flow-ink-muted);
}

.tcl-field__helper {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
  margin-top: var(--s-2);
}

/* Base input chrome shared by text/tel/email/select. */
.tcl-input {
  width: 100%;
  height: 56px;
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  color: var(--flow-ink);
  font-size: var(--fs-body);
  font-family: var(--font-ui);
  padding: 0 var(--s-4);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.tcl-input::placeholder {
  color: var(--flow-ink-placeholder);
}

.tcl-input:focus-visible,
.tcl-input:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold);
}

select.tcl-input {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3e%3cpath d='M2 5L7 10L12 5' stroke='%23d7ccb3' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  padding-right: var(--s-8);
}

/* Tel field: the country code beside the number, matching REG-04's split control.
 *
 * Round 1 (2026-09-16). The code was a fixed span and is now a <select>, so the two share one
 * treatment: same padding, same divider, same height, same ink. The span survives for the one
 * state that still draws it (no mu-plugin, so no country list), and it must keep looking like
 * the select did, because a form that changes shape when a module is missing is a form nobody
 * can describe over the phone. */
.tcl-field__tel {
  display: flex;
  align-items: stretch;
  height: 56px;
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  overflow: hidden;
}

.tcl-field__tel-prefix,
.tcl-field__tel-country {
  display: flex;
  align-items: center;
  padding: 0 var(--s-3);
  border-right: 1px solid var(--flow-line);
  color: var(--flow-ink);
  font-size: var(--fs-body);
  flex-shrink: 0;
}

/* The select keeps the native control (its own listbox on a phone, the native keyboard
 * behaviour, the free accessibility) and loses only the chrome that would make it look like a
 * second field beside the number. Same reasoning page-register.php gives for using a real
 * <select> on R6 rather than building a bespoke listbox. */
/* ⚠️ W62 PUT 244 COUNTRIES IN THIS CONTROL, SO ITS WIDTH IS NOW CAPPED RATHER THAN LEFT TO THE
 * LONGEST LABEL. A native select sizes itself to its widest option, and "United States Virgin
 * Islands +1" would leave no room for the number beside it. The cap is a flex basis plus
 * `min-width: 0`, which lets the browser truncate the label it is showing and keeps the number
 * box the larger of the two.
 *
 * The option text stays "Country +Code" in that order, and the closed control shows the start of
 * it rather than the code alone. Showing the code alone means a custom listbox, and a custom
 * listbox loses the phone's own picker and the type-ahead that lets somebody find Belgium by
 * typing a B, which is the thing that makes a 244-entry list usable at all. */
.tcl-field__tel-country {
  height: 100%;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 44%;
  border-top: 0;
  border-bottom: 0;
  border-left: 0;
  border-radius: 0;
  background: transparent;
  font-family: inherit;
  text-overflow: ellipsis;
}

.tcl-field__tel .tcl-input {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  border-radius: 0;
  background: transparent;
}

.tcl-field__tel:has(.tcl-input:focus),
.tcl-field__tel:has(.tcl-field__tel-country:focus) {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold);
}

/* date_parts: three side-by-side selects. */
.tcl-field__date-parts {
  display: flex;
  gap: var(--s-2);
}
.tcl-field__date-parts .tcl-input {
  flex: 1;
  min-width: 0;
  font-size: 15px;
}

/* ---------- Error state ----------
 *
 * ⚠️ ROUND 1 (2026-09-17). THIS BLOCK USED TO READ "Gold border + cream helper text. Never a
 * distinct hue", and this file's own header said "No red/green/blue anywhere, including error
 * states". BOTH ARE REVERSED HERE, by Noah, in as many words: "For each input, ensure that a red
 * outline appears when its not acceptable, with an error message below the text box explaining
 * the issue."
 *
 * Gold was the wrong signal and the staging pass is what proved it: gold is this flow's ACCENT,
 * carried by the focus ring, the selected card, the pips and the Continue pill, so a gold border
 * on a refused box looks like the box you are in rather than the box that is wrong. Red is a
 * distinct hue on purpose now. `--danger` is a tokens.css token that has existed since the design
 * system was written and is not a new brand colour; it clears 4.5:1 on `--paper`, which is the
 * ground every field in every flow renders on.
 *
 * ⚠️ ONE DEFINITION, BECAUSE NO FIELD RENDERS ON THE DARK GROUND. The containers that redefine
 * the ink roles (the header, a selected card, a notice, a filled roster slot) hold no
 * `[data-field]`, which `.herrors/` asserts against all three rendered shells rather than
 * leaving as a reading of the markup. A container that ever puts a field on Forest has to
 * redefine `--flow-danger` with it, because `--danger` on Forest is about 1.8:1.
 *
 * The border goes to 2px, which changes no layout: `* { box-sizing: border-box }` is global in
 * main.css, so the extra pixel comes out of the padding box rather than pushing the field wider.
 */
.tcl-field[data-invalid="true"] .tcl-input,
.tcl-field[data-invalid="true"] .tcl-field__tel,
.tcl-team[data-invalid="true"] .tcl-input {
  border-color: var(--flow-danger);
  border-width: 2px;
}

/* The focus ring on a refused control is the SAME red, not the gold one. A gold ring inside a
   red border is two signals arguing on one box. */
.tcl-field[data-invalid="true"] .tcl-input:focus,
.tcl-field[data-invalid="true"] .tcl-input:focus-visible,
.tcl-team[data-invalid="true"] .tcl-input:focus,
.tcl-team[data-invalid="true"] .tcl-input:focus-visible,
.tcl-field[data-invalid="true"] .tcl-field__tel:focus-within {
  border-color: var(--flow-danger);
  box-shadow: 0 0 0 2px var(--flow-danger);
}

.tcl-field[data-invalid="true"] .tcl-field__helper {
  color: var(--flow-ink);
}

/* ---------- The message line ----------
 *
 * ONE RULE FOR EVERY FIELD TYPE, keyed on the attribute and the slot rather than on the wrapper
 * class, because ruling 1 puts this line on text, tel, email, date parts, textarea, cards, chips,
 * consent, checkgroup, repeater rows and the team-name box, and eleven selectors that have to
 * agree are eleven that can stop agreeing. It is `.tcl-field__helper` sized already, which is the
 * helper size ruling 1 asks for; all this adds is the colour.
 *
 * An empty `[data-field-alert]` is `display: none` so a field with nothing to say takes no
 * vertical space: every field carries the element now, and a column of empty lines would push a
 * step's fields apart for no reason. `:empty` is exact: form.js writes textContent and clears it
 * to '', so the element is genuinely empty rather than holding a space.
 */
[data-invalid="true"] [data-field-alert] {
  color: var(--flow-danger);
}

[data-field-alert]:empty {
  display: none;
}

/* ============================================================
   CONSENT CHECKBOX ROWS
   ============================================================ */
.tcl-consent {
  margin-bottom: var(--s-4);
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  cursor: pointer;
}

.tcl-consent__box {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: 1px solid var(--flow-line-strong);
  background-color: transparent;
  background-repeat: no-repeat;
  background-position: center;
  flex-shrink: 0;
  margin-top: 1px;
  padding: 0;
  cursor: pointer;
}

.tcl-consent__box:checked {
  background-color: var(--gold);
  border-color: var(--gold);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3e%3cpath d='M2 6L5 9L10 2.5' stroke='%2313100e' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
}

.tcl-consent__box:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-consent__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.tcl-consent__label {
  font-size: 15px;
  color: var(--flow-ink);
}

.tcl-consent__helper {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

.tcl-consent[data-invalid="true"] .tcl-consent__box {
  border-color: var(--flow-danger);
  border-width: 2px;
}

/* ---------- Round 1 (2026-09-17): a refused choice, on every cards variant ----------
 *
 * ONE RULE RATHER THAN SEVEN. `cards` has six physical variants (plain, season, entry,
 * league_row, chip, free_agent, payment_terms) and each draws its own option element:
 * `.tcl-card`, `.tcl-season__card`, `.tcl-entry__card`, `.tcl-league-row`, `.tcl-chip`,
 * `.tcl-free-agent__row`, `.tcl-terms__card`. What every one of them contains is the same
 * visually-hidden native radio, `.tcl-card__radio`, because they are all real radiogroups, so
 * `:has()` finds the option without this file holding a list of seven class names that a new
 * variant would have to be added to. `:has()` is already how a selected card is styled, a few
 * rules below, so no new browser requirement is introduced.
 *
 * A SELECTED option is excluded: once one is chosen the group is not refused any more, and a red
 * edge on the Forest fill of a chosen card would be the only red-on-dark in the flow. */
[data-field-type="cards"][data-invalid="true"] label:has(.tcl-card__radio:not(:checked)) {
  border-color: var(--flow-danger);
}

/* ============================================================
   SELECTABLE CARDS
   ============================================================ */
.tcl-cards {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  margin-bottom: var(--s-5);
}

@media (min-width: 768px) {
  .tcl-cards {
    flex-direction: row;
  }
}

/* Cards are <label> elements wrapping a visually-hidden native radio, so selection is a
   real form control (keyboard/screen-reader native, and a genuine name/value pair for
   whatever eventually POSTs this form) styled entirely through :has() / :checked. */
.tcl-card {
  position: relative;
  flex: 1;
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  cursor: pointer;
  text-align: left;
  color: var(--flow-ink);
  font-family: var(--font-ui);
}

.tcl-card__radio {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.tcl-card:has(.tcl-card__radio:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-card:has(.tcl-card__radio:checked) {
  border-color: var(--gold);
  background: var(--flow-selected-bg);
}

/* THL pricing A1. A card drawn but not on offer (a location with nothing priced yet): readable,
   visibly quieter, with the not-allowed cursor. The radio inside it is natively disabled. */
.tcl-card[aria-disabled="true"] {
  cursor: not-allowed;
  opacity: 0.55;
}

/* THL pricing A2. The single-plan lines on The House League's review step. */
.tcl-summary__plan-lines {
  margin-top: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.tcl-summary__plan-line {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 700;
  color: var(--flow-ink);
}

.tcl-card__title {
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-card__desc {
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

/* ============================================================
   M-03 (TCL-618) — CARD VARIANTS: season / league_row / chip / free_agent
   Every option below is still a <label> wrapping a native <input type="radio">, matching
   the plain .tcl-card mechanism above — only the layout differs per variant. Status
   badges carry no colour of their own (shared REG preamble): --gold text for the one
   selectable-adjacent case that needs emphasis, --cream at 70% + a --forest border for
   everything else. No red/green/blue anywhere in this block.
   ============================================================ */

/* ---------- season (R1) ---------- */
.tcl-season__card {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  cursor: pointer;
}

.tcl-season:has(.tcl-card__radio:checked) .tcl-season__card {
  border-color: var(--gold);
  background: var(--flow-selected-bg);
}

.tcl-season:has(.tcl-card__radio:focus-visible) .tcl-season__card {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-season__left {
  display: flex;
  align-items: center;
  gap: var(--s-4);
}

.tcl-season__badge {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background: var(--forest);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}

.tcl-season__badge img {
  height: 40px;
  width: auto;
}

.tcl-season__copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tcl-season__title {
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-season__tipoff,
.tcl-season__tbc {
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

.tcl-season__right {
  display: flex;
  align-items: center;
  justify-content: center;
}

.tcl-season__countdown {
  display: flex;
  gap: var(--s-5);
}

.tcl-season__unit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.tcl-season__unit strong {
  font-size: 32px;
  font-weight: var(--fw-bold);
  color: var(--flow-accent-ink);
  font-family: var(--font-ui);
}

.tcl-season__unit em {
  font-style: normal;
  font-size: var(--fs-micro);
  color: var(--flow-ink-muted);
  text-transform: capitalize;
}

.tcl-season__closed {
  font-size: var(--fs-subtitle);
  color: var(--flow-ink-muted);
}

@media (min-width: 768px) {
  .tcl-season__card {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* ---------- team-code bar (R0/R1, visual only until M-04) ---------- */
.tcl-code-bar {
  margin-top: var(--s-5);
  background: var(--flow-surface-sunk);
  border-radius: var(--r-md);
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.tcl-code-bar__copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tcl-code-bar__copy strong {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-code-bar__copy span {
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

/* Cream fill, not gold: prompt 1 asks for this to read as SECONDARY to the gold buttons
   above it on R0. It is a real route onto a roster, not a lesser one — but a third gold
   pill on the front door would make the choice look like three equal doors when two of
   them are cards and this one needs something a captain gave you. */
.tcl-code-bar__btn {
  height: 44px;
  padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  border: none;
  background: var(--forest);
  color: var(--cream);
  font-weight: var(--fw-semibold);
  font-family: var(--font-ui);
  cursor: pointer;
  white-space: nowrap;
}

.tcl-code-bar__btn:hover {
  background: var(--deep-forest);
}

@media (min-width: 768px) {
  .tcl-code-bar {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* ---------- league_row (R2) ---------- */
.tcl-league-list {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-6);
}

.tcl-league-filters {
  display: flex;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
  flex-wrap: wrap;
}

.tcl-chip-filter {
  height: 36px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  border: 1px solid var(--flow-line-strong);
  background: transparent;
  color: var(--flow-ink);
  font-size: var(--fs-callout);
  font-family: var(--font-ui);
  cursor: pointer;
}

.tcl-chip-filter[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--black);
  font-weight: var(--fw-semibold);
}

.tcl-league-rows {
  display: flex;
  flex-direction: column;
}

.tcl-league-empty {
  color: var(--flow-ink-muted);
  font-size: var(--fs-body);
  padding: var(--s-4) 0;
}

.tcl-league-row {
  border-top: 1px solid var(--flow-line);
  padding: var(--s-5) 0;
}

.tcl-league-row:first-child {
  border-top: none;
}

.tcl-league-row--inert {
  opacity: 0.5;
}

.tcl-league-row__main {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
  cursor: pointer;
}

.tcl-league-row--inert .tcl-league-row__main {
  cursor: not-allowed;
}

.tcl-league-row:has(.tcl-card__radio:checked) {
  background: var(--flow-selected-bg);
  border-radius: var(--r-md);
  margin: 0 calc(-1 * var(--s-3));
  padding-left: var(--s-3);
  padding-right: var(--s-3);
}

.tcl-league-row:has(.tcl-card__radio:focus-visible) .tcl-league-row__main {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-league-row__tile {
  width: 112px;
  height: 112px;
  border-radius: var(--r-md);
  background: var(--forest);
  flex-shrink: 0;
  display: flex;
  align-items: flex-end;
  padding: var(--s-2);
  box-sizing: border-box;
}

.tcl-league-row__tile-label {
  font-family: var(--font-norwester);
  font-weight: 400;
  font-size: 13px;
  line-height: 1.1;
  color: var(--flow-ink);
}

.tcl-league-row__mid {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: var(--s-1);
}

.tcl-league-row__title {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-league-row__check {
  display: none;
  color: var(--flow-accent-ink);
}

.tcl-league-row:has(.tcl-card__radio:checked) .tcl-league-row__check {
  display: inline;
}

.tcl-league-row__formal {
  font-size: var(--fs-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--flow-ink-muted);
}

.tcl-league-row__address {
  font-size: var(--fs-label);
  color: var(--flow-ink-muted);
}

.tcl-league-row__end {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  padding-top: var(--s-1);
}

.tcl-league-row__division {
  font-size: var(--fs-label);
  color: var(--flow-ink);
}

.tcl-league-row__price {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--flow-accent-ink);
}

.tcl-league-row__badge {
  height: 22px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  border: 1px solid var(--flow-line-strong);
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--flow-ink-muted);
}

.tcl-league-row__notify-toggle {
  margin-top: var(--s-3);
  background: none;
  border: none;
  color: var(--flow-accent-ink);
  font-size: var(--fs-callout);
  font-weight: var(--fw-medium);
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}

@media (max-width: 767px) {
  .tcl-league-row__tile {
    width: 72px;
    height: 72px;
  }
  .tcl-league-row__main {
    flex-wrap: wrap;
  }
  .tcl-league-row__end {
    align-items: flex-start;
    flex-direction: row;
    flex-wrap: wrap;
    padding-top: var(--s-2);
    margin-left: calc(72px + var(--s-4));
  }
}

/* ---------- notify capture (league_row coming-soon, chip no-times) ---------- */
.tcl-notify {
  margin-top: var(--s-4);
  padding: var(--s-4);
  background: var(--flow-surface-sunk);
  border-radius: var(--r-md);
}

.tcl-notify[hidden] {
  display: none;
}

.tcl-notify__row {
  display: flex;
  gap: var(--s-2);
}

.tcl-notify__phone {
  flex: 1;
  height: 44px;
}

.tcl-notify__btn {
  height: 44px;
  padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  border: none;
  background: var(--gold);
  color: var(--black);
  font-weight: var(--fw-semibold);
  font-family: var(--font-ui);
  cursor: pointer;
  flex-shrink: 0;
}

.tcl-notify__helper {
  margin: var(--s-2) 0 0;
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

/* ---------- chip (R3 day/time schedule) ---------- */
.tcl-schedule__chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}

.tcl-schedule__chips[hidden] {
  display: none;
}

.tcl-chip {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--flow-line-strong);
  cursor: pointer;
  position: relative;
}

.tcl-chip:has(.tcl-card__radio:checked) {
  background: var(--gold);
  border-color: var(--gold);
}

.tcl-chip:has(.tcl-card__radio:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-chip__day {
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-chip:has(.tcl-card__radio:checked) .tcl-chip__day {
  color: var(--black);
}

.tcl-chip__time {
  font-size: var(--fs-micro);
  color: var(--flow-ink-muted);
}

.tcl-chip:has(.tcl-card__radio:checked) .tcl-chip__time {
  color: var(--black);
  opacity: 0.7;
}

.tcl-schedule__empty[hidden] {
  display: none;
}

.tcl-schedule__empty p {
  font-size: var(--fs-body);
  color: var(--flow-ink-muted);
  margin: 0 0 var(--s-3);
}

/* ---------- free_agent (R3) ----------
   Two division sections when no league has been chosen, and ONE card for the chosen league
   once R2 has been answered, which is round 1 item 11 and is what a visitor actually sees.
   The single card needs no layout of its own: it is the same row, without a section heading
   above it and without the second section that contradicted the visitor's own answer. */
.tcl-division-section {
  margin-bottom: var(--s-6);
}

.tcl-division-section__heading {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
  margin: 0 0 var(--s-3);
}

.tcl-division-section__info {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--flow-line-strong);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--flow-ink-muted);
  cursor: help;
}

.tcl-free-agent__row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-4);
  cursor: pointer;
}

.tcl-free-agent__row:has(.tcl-card__radio:checked) {
  border-color: var(--gold);
  background: var(--flow-selected-bg);
}

.tcl-free-agent__row:has(.tcl-card__radio:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-free-agent__icon {
  font-size: 20px;
  color: var(--flow-accent-ink);
  flex-shrink: 0;
}

.tcl-free-agent__copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tcl-free-agent__eyebrow {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

.tcl-free-agent__title {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

/* M-09 (TCL-624). Choosing the row above IS the consent this states — see W30. Caption-sized
   and quieter than the eyebrow/title, but never hidden or truncated. */
.tcl-free-agent__note {
  margin-top: 2px;
  font-size: var(--fs-caption);
  line-height: var(--lh-callout);
  color: var(--flow-ink-muted);
}

/* ============================================================
   REPEATER
   ============================================================ */
.tcl-repeater__row {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  margin-bottom: var(--s-4);
  position: relative;
}

.tcl-repeater__row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--s-4);
}

.tcl-repeater__row-label {
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-repeater__remove {
  background: none;
  border: none;
  color: var(--flow-accent-ink);
  font-size: var(--fs-caption);
  font-weight: var(--fw-medium);
  cursor: pointer;
  padding: var(--s-1) var(--s-2);
}

.tcl-repeater__remove:hover {
  color: var(--flow-ink);
}

.tcl-repeater__add {
  background: none;
  border: none;
  color: var(--flow-accent-ink);
  font-size: 15px;
  font-weight: var(--fw-medium);
  cursor: pointer;
  padding: var(--s-2) 0;
  text-decoration: underline;
}

.tcl-repeater__add:hover {
  color: var(--flow-ink);
}

.tcl-repeater__add:disabled {
  color: var(--flow-ink-disabled);
  text-decoration: none;
  cursor: not-allowed;
}

/* B-01b-i (TCL-687). The group's own helper line: the same size, the same muted cream and
 * the same top margin as .tcl-field__helper, so a group refusal reads as the same kind of
 * thing a field refusal does. It carries the rule the group enforces ("At least one child,
 * and no more than six on one form.") so the invalid state below has something to turn
 * cream. The one addition is an explicit line-height, because this line runs to two lines at
 * 375px where a field helper rarely does. */
.tcl-repeater__helper {
  font-size: var(--fs-caption);
  line-height: var(--lh-callout);
  color: var(--flow-ink-muted);
  margin-top: var(--s-2);
}

/* The group-level error state. Gold border on the rows, cream on the helper, which is the same pair of
 * moves .tcl-field[data-invalid="true"] makes, never a distinct hue (form.css's own rule at
 * the Error state block above). The wrapper is what carries [data-invalid] because a repeater
 * has no single control to mark, and with zero rows it has no control at all. */
.tcl-repeater[data-invalid="true"] .tcl-repeater__row {
  border-color: var(--flow-danger);
}
.tcl-repeater[data-invalid="true"] .tcl-repeater__helper {
  color: var(--flow-ink);
}
/* Focus lands here when the group is refused (form.js's validateStep), and the wrapper is a
 * div with tabindex="-1". Suppress the UA outline: the gold border and the cream helper are
 * the treatment, and an outline on a full-width group reads as a second, different error. */
.tcl-repeater:focus {
  outline: none;
}

/* ============================================================
   BAND PREVIEW (B-02, TCL-584)
   ============================================================
   The derived band, shown back inside the child's own row before anything is confirmed
   (AC8). It sits at the foot of the row it belongs to, so a parent reads the date of birth
   they typed and the band it produced without moving their eyes off one card.

   It is NOT styled as a field: there is no control, nothing to fill and nothing to get
   wrong, so it takes no border, no input geometry and none of the [data-invalid] treatment.
   A hairline above it and a quieter label is enough to say "this is the answer to what you
   just typed" rather than "this is another question".

   Four states, keyed off data-band-status, and only one of them is a band. The other three
   are all quieter than the answer, because "we need one more thing" and "we will follow up"
   must never read as loudly as a band a parent is meant to check. NOTHING here is red or
   error-toned: an out-of-range date of birth is accepted (thl-decisions.md Q6) and a form
   that scolds a parent for their child's age is the exact failure D9 is about. */
.tcl-band {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--flow-line);
}

/* TCL-805, Noah's item 3. The label and the value read as ONE sentence now
   ("Qualified age group: 6-9 co-ed"), so the uppercase display transform goes: a line that is
   specified to read exactly a certain way must not be re-cased on its way to the screen. */
.tcl-band__label {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink-muted);
}

/* TCL-805, ruling 4b. The affordance beside an out-of-range year. It renders only in the
   `outside` state (assets/js/form.js toggles `hidden`), and it opens a conversation with the
   staff number the flow's own "Lost your code?" row already uses. */
.tcl-band__wa {
  min-height: 44px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  border: 1px solid var(--flow-line-strong);
  background: transparent;
  color: var(--flow-ink);
  font-family: var(--font-ui);
  font-size: var(--fs-callout);
  font-weight: var(--fw-semibold);
  cursor: pointer;
}

.tcl-band__wa:hover {
  border-color: var(--gold);
}

.tcl-band__wa[hidden] {
  display: none;
}

.tcl-band__value {
  font-size: var(--fs-callout);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-callout);
  color: var(--flow-accent-ink);
  flex: 1 1 auto;
  min-width: 0;
}

/* The three non-answers. Muted cream, regular weight: present, readable, and visibly not
   the same kind of thing as a band. */
.tcl-band[data-band-status="empty"] .tcl-band__value,
.tcl-band[data-band-status="need_sex"] .tcl-band__value,
.tcl-band[data-band-status="outside"] .tcl-band__value,
.tcl-band[data-band-status="unconfigured"] .tcl-band__value {
  color: var(--flow-ink-muted);
  font-weight: var(--fw-regular);
  font-size: var(--fs-caption);
}

/* ============================================================
   ACTION BAR: the form's own footer, at the foot of every step
   ============================================================
   ⚠️ ROUND 1, ITEM 5, AND THIS IS THE CAUSE RATHER THAN THE SYMPTOM.

   Noah, on the application form at /join-us/<slug>/: "The modal to apply has no navigation from
   the first page, how can I continue beyond 'about you'? Even if you did configure a way and it
   wasn't a miss, the fact that I can't figure it out means its not dummy proof, it needs to be
   clear, like a 'continue' pill button at the bottom".

   The markup was never missing: inc/form-framework.php has rendered `[data-form-actions]` with
   a Back and a Continue inside every `.tcl-form` since TCL-574, and form.js shows it on every
   step. What was wrong is THIS RULE. `position: fixed` was written for the full-bleed takeover,
   where the form IS the page and the viewport's bottom edge is the form's own foot (REG-01's
   shared preamble: "Bottom action bar. Fixed to the viewport bottom"), and it was never scoped
   to it. On /join-us/<slug>/ and /apply/ the form is one block inside an ordinary page, so the
   bar was welded to the window instead: on screen from the moment the page loaded, over the job
   description, over the site footer, and never at the foot of the form a person was filling in.
   Whatever a consent banner or anything else bottom-anchored happens to be doing, nothing is at
   the end of the last field, which is where somebody looks for Continue.

   So the bar is now IN FLOW by default, at the foot of the form, and the takeover block at the
   end of this file pins it to the viewport exactly as before. The two registration flows are
   unchanged: they are takeovers on every step. */
.tcl-form__actions {
  background: var(--flow-surface);
  border-top: 1px solid var(--flow-line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-height: 72px;
  padding: var(--s-4) var(--gutter);
  box-sizing: border-box;
}

/* TCL-805, Noah's item 9: "Back button should have a pill too". It is the GHOST variant of
   the Continue pill rather than a second filled one: same height, same radius, same row, a
   Forest border and Forest text on the light ground. A second gold pill would make the two
   read as equal choices, and only one of them moves the registration forward. */
.tcl-form__back {
  height: 48px;
  padding: 0 28px;
  border-radius: var(--r-pill);
  border: 1px solid var(--flow-line-strong);
  background: transparent;
  color: var(--flow-display);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  font-family: var(--font-ui);
}

.tcl-form__back:hover {
  border-color: var(--gold);
  color: var(--flow-display);
}

.tcl-form__back:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-form__back[hidden] {
  display: none;
}

.tcl-form__primary {
  height: 48px;
  padding: 0 28px;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  border: none;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  font-family: var(--font-ui);
}

.tcl-form__primary:hover {
  background: var(--gold-500);
}

/* aria-disabled, not disabled, so the pill stays focusable and can announce why. */
.tcl-form__primary[aria-disabled="true"] {
  background: var(--flow-disabled-bg);
  color: var(--flow-ink-disabled);
  cursor: not-allowed;
}

.tcl-form__secondary {
  background: none;
  border: none;
  color: var(--flow-ink-muted);
  font-size: 15px;
  cursor: pointer;
  padding: var(--s-3);
  font-family: var(--font-ui);
}

/* ============================================================
   INTERSTITIAL
   ============================================================ */
.tcl-interstitial {
  position: fixed;
  inset: 0;
  background: var(--flow-bg);
  z-index: 50;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--gutter);
  box-sizing: border-box;
}

.tcl-interstitial[hidden] {
  display: none;
}

.tcl-interstitial__inner {
  max-width: var(--tcl-form-max);
  margin: 0 auto;
  width: 100%;
}

.tcl-interstitial__title {
  font-family: var(--font-norwester);
  font-weight: 400;
  line-height: 0.98;
  color: var(--flow-display);
  font-size: clamp(30px, 5vw, 48px);
  margin: 0 0 var(--s-5);
}

.tcl-interstitial__body {
  font-size: var(--fs-body);
  color: var(--flow-ink);
  line-height: 1.5;
  margin: 0 0 var(--s-10);
}

.tcl-interstitial__primary {
  width: 100%;
  height: 52px;
  border-radius: 26px;
  background: var(--gold);
  color: var(--black);
  border: none;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  margin-bottom: var(--s-4);
  font-family: var(--font-ui);
}

.tcl-interstitial__secondary {
  width: 100%;
  background: none;
  border: none;
  color: var(--flow-ink-muted);
  font-size: 15px;
  cursor: pointer;
  padding: var(--s-3);
  font-family: var(--font-ui);
}

/* ============================================================
   THE MODAL INTERSTITIAL (round 1, item 5)
   ============================================================
   Noah: "The "The House League Might Be a Better Fit" Message is a new screen and the buttons
   look too small for the text. It should be a pop up modal, graying out the screen behind it,
   with an appropriately sized pill for the button below."

   ⚠️ SCOPED TO `--modal`, AND THAT IS THE POINT. R8's confirmation and R9's four state screens
   render into the same overlay element and must keep the full-bleed treatment above: each of
   them IS the whole screen, with nothing behind it to grey out. Only a step whose config says
   `display: modal` gets these rules, and assets/js/form.js removes the class on every other
   paint so the overlay cannot keep a presentation from the last thing shown in it.

   The scrim is 60% Deep Forest, written as the rgb triple of --deep-forest (#0a302b) so the
   file carries no hex (G2) and no fifth brand colour. tokens.css's own shadows are the same
   triple at lower alphas, so this is the palette's own shadow colour at the weight a scrim
   needs. */
.tcl-interstitial--modal {
  background: rgba(10, 48, 43, 0.6);
  justify-content: center;
  align-items: center;
}

.tcl-interstitial--modal .tcl-interstitial__inner {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-6);
  max-width: 420px;
  box-shadow: var(--shadow-lg);
  box-sizing: border-box;
}

.tcl-interstitial--modal .tcl-interstitial__title {
  font-size: var(--fs-title);
  margin-bottom: var(--s-4);
}

.tcl-interstitial--modal .tcl-interstitial__body {
  margin-bottom: var(--s-6);
}

/* BOTH PILLS ARE THE CONTINUE PILL'S SIZE AND BOTH ARE FULL WIDTH.
   The weighting toward The House League is carried by the FILL, gold against the ghost, rather
   than by making the secondary smaller, which is what "the buttons look too small for the text"
   was about. The ghost is the same treatment .tcl-form__back takes (W58 ruling 3), for the same
   reason: only one of the two moves the registration forward. */
.tcl-interstitial--modal .tcl-interstitial__primary,
.tcl-interstitial--modal .tcl-interstitial__secondary {
  display: block;
  width: 100%;
  height: 48px;
  border-radius: var(--r-pill);
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  font-family: var(--font-ui);
  line-height: 48px;
  padding: 0 28px;
  text-align: center;
  text-decoration: none;
  box-sizing: border-box;
  cursor: pointer;
}

.tcl-interstitial--modal .tcl-interstitial__primary {
  background: var(--gold);
  color: var(--black);
  border: 1px solid var(--gold);
  margin-bottom: var(--s-3);
}

.tcl-interstitial--modal .tcl-interstitial__secondary {
  background: transparent;
  border: 1px solid var(--flow-line-strong);
  color: var(--flow-display);
}

.tcl-interstitial--modal .tcl-interstitial__primary:focus-visible,
.tcl-interstitial--modal .tcl-interstitial__secondary:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* ============================================================
   RESUME BAR
   ============================================================ */
.tcl-resume {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  margin: var(--s-5) 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

@media (min-width: 768px) {
  .tcl-resume {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.tcl-resume[hidden] {
  display: none;
}

.tcl-resume__text {
  font-size: 15px;
  color: var(--flow-ink);
}

.tcl-resume__actions {
  display: flex;
  gap: var(--s-3);
}

.tcl-resume__primary {
  height: 44px;
  padding: 0 20px;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  border: none;
  font-size: var(--fs-callout);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  font-family: var(--font-ui);
}

.tcl-resume__secondary {
  height: 44px;
  padding: 0 20px;
  border-radius: var(--r-pill);
  background: none;
  border: 1px solid var(--flow-line-strong);
  color: var(--flow-ink);
  font-size: var(--fs-callout);
  cursor: pointer;
  font-family: var(--font-ui);
}

/* ============================================================
   DEMO-ONLY STUB SUBMIT RESULTS (F2-05 will replace this block)
   ============================================================ */
.tcl-form__demo-results {
  margin-top: var(--s-8);
  padding: var(--s-5);
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-lg);
}

.tcl-form__demo-results[hidden] {
  display: none;
}

.tcl-form__demo-results h2 {
  font-size: var(--fs-label);
  color: var(--flow-ink);
  margin: 0 0 var(--s-3);
}

.tcl-form__demo-results pre {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--flow-ink);
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
}

/* Honeypot: visually hidden, not display:none (matches how screen readers/bots treat
   the two differently — display:none is skipped by some crawlers' heuristics). */
.tcl-form__hp {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   RESPONSIVE — 375px vs 1280px action bar behaviour
   ============================================================ */
@media (max-width: 767px) {
  .tcl-form__actions {
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-3);
    height: auto;
    padding: var(--s-3) var(--gutter) var(--s-5);
  }
  /* TCL-805. Back is a pill now, so on a phone it takes the same full width as Continue and
     sits under it, rather than being a centred word of its own size. */
  .tcl-form__back {
    order: 1;
    align-self: stretch;
    width: 100%;
  }
  .tcl-form__primary {
    order: 2;
    width: 100%;
  }
  .tcl-form__body {
    padding: 0 var(--gutter);
  }
}

@media (min-width: 1280px) {
  .tcl-form__col {
    max-width: var(--tcl-form-max);
  }
}

/* ============================================================
   TAKEOVER SHELL — M-03 (TCL-618)
   Scoped to body.tcl-flow-takeover, set by tcl_flow_set_takeover( true ) in functions.php
   BEFORE get_header() runs (page-register.php's flow branch). Every rule above this block
   already governs .tcl-form unconditionally, including the ?tcl_form_demo= harnesses,
   which render inside ordinary site chrome and never carry this body class — this block
   only adds what full-bleed takeover needs on top of the shared shell: the page
   background behind .tcl-form's own black fill, the R1/R2-width content column (1040px,
   wider than the 560px .tcl-form__col default tuned for R5/R6's single-column forms),
   and the sticky top bar.
   ============================================================ */
body.tcl-flow-takeover {
  background: var(--flow-bg);
  margin: 0;
}

/* Sticky, NOT fixed. The WP admin bar (visible only on the ?tcl_flow=preview path, which
   is admin-only) is itself position:fixed at the real viewport top and makes WordPress
   add `margin-top: 32px` to <html> (46px under the 782px breakpoint) — a SECOND
   position:fixed element pinned to top:0 would render UNDER that 32px band instead of
   below it, which is exactly what main.css's `.admin-bar .w-nav { top: 32px }` rule
   exists to correct for the site nav. `sticky` sidesteps the whole problem: it
   participates in normal flow first, so it already starts right after the admin bar's
   reserved space, and only pins once its resting position scrolls past. A signed-out
   visitor has no admin bar, so this is a no-op difference for them. */
body.tcl-flow-takeover .tcl-form__header {
  position: sticky;
  top: 0;
  z-index: 30;
}

/* ---------- the action bar, pinned, and ONLY here ----------
   Round 1, item 5. This is the half of the bar that belongs to the takeover: the flow is the
   whole page, so the viewport's bottom edge IS the foot of the form and a bar pinned there is
   the REG-01 preamble's "Bottom action bar. Fixed to the viewport bottom... Page content must
   never be hidden behind the bar". The padding on .tcl-form is what keeps the second half of
   that sentence true, and it belongs here for the same reason: in flow the bar takes its own
   space and a reserve underneath it would be a gap.

   Every value below is the one the unscoped rule carried, so a takeover renders as it did.

   Complianz's cookie-banner CSS is not declared anywhere in this theme; the plugin sets its
   own z-index, far above anything a theme file would pick, so 40 already clears it without
   this file guessing at Complianz's number. Do NOT raise this z-index for takeover: the
   requirement is "stays below", and the untouched value already satisfies it; raising it is
   what would risk the action bar sitting OVER the consent banner instead. */
body.tcl-flow-takeover .tcl-form {
  /* Room for the fixed 72px action bar plus a little breathing space. */
  padding-bottom: calc(72px + var(--s-6));
}

body.tcl-flow-takeover .tcl-form__actions {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
}

/* The bar's desktop geometry, and it is behind a breakpoint because this block sits AFTER the
   responsive one: at 375px the stacked full-width treatment above is what a takeover has always
   rendered, and a height and a padding declared here unguarded would silently undo it. */
@media (min-width: 768px) {
  body.tcl-flow-takeover .tcl-form__actions {
    height: 72px;
    padding: 0 var(--gutter-lg);
  }
}

/* ---------- page padding: 375px 20px gutters, 1280px 1040px centred column ---------- */
body.tcl-flow-takeover .tcl-form__header,
body.tcl-flow-takeover .tcl-form__body {
  padding-left: 20px;
  padding-right: 20px;
}

body.tcl-flow-takeover .tcl-form__col {
  max-width: 1040px;
  padding-top: var(--s-6);
}

@media (min-width: 1280px) {
  body.tcl-flow-takeover .tcl-form__header,
  body.tcl-flow-takeover .tcl-form__body {
    padding-left: calc((100% - 1040px) / 2);
    padding-right: calc((100% - 1040px) / 2);
  }
}

/* ---------- the closed-state message (M-03, no dead end — links back to home) ---------- */
.tcl-flow-closed {
  min-height: 100vh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  max-width: 480px;
  margin: 0 auto;
  padding: var(--s-10) 20px;
}

.tcl-flow-closed__mark {
  height: 40px;
  width: auto;
  margin: 0 auto var(--s-6);
}

.tcl-flow-closed__title {
  font-family: var(--font-norwester);
  font-weight: 400;
  line-height: 0.98;
  color: var(--flow-display);
  font-size: clamp(28px, 5vw, 40px);
  margin: 0 0 var(--s-4);
}

.tcl-flow-closed__body {
  font-size: var(--fs-body);
  color: var(--flow-ink-muted);
  margin: 0 0 var(--s-8);
}

.tcl-flow-closed__home {
  display: inline-block;
  height: 48px;
  line-height: 48px;
  padding: 0 28px;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  font-weight: var(--fw-semibold);
  text-decoration: none;
}

.tcl-flow-closed__home:hover {
  background: var(--gold-500);
  color: var(--black);
}

/* ============================================================
   M-08 (TCL-623) — R9, the shared state-screen shape
   ============================================================
   Two callers: page-register.php's tcl_form_render_state_screen() (server-rendered, <a>
   actions) and assets/js/form.js's renderStateScreen() (client-rendered inside
   .tcl-interstitial, <button> actions). Same classes either way — see both files' own notes
   on why they cannot share one implementation but must share one look.
   ============================================================ */
.tcl-state {
  min-height: 100vh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  max-width: 480px;
  margin: 0 auto;
  padding: var(--s-10) 20px;
}

/* form.js paints .tcl-state inside .tcl-interstitial, which is already a fixed full-viewport
   layer — a second min-height:100vh there would only ever double up harmlessly, but the
   client variant does not need it, so it is dropped there via this override hook. */
.tcl-interstitial .tcl-state {
  min-height: 0;
}

.tcl-state__icon {
  width: 64px;
  height: 64px;
  margin: 0 auto var(--s-6);
  color: var(--flow-ink-muted);
}

.tcl-state__title {
  font-family: var(--font-norwester);
  font-weight: 400;
  line-height: 0.98;
  color: var(--flow-display);
  font-size: clamp(28px, 5vw, 40px);
  margin: 0 0 var(--s-4);
}

.tcl-state__body {
  font-size: var(--fs-body);
  color: var(--flow-ink-muted);
  margin: 0 0 var(--s-8);
}

.tcl-state__actions {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  width: 100%;
}

/* ⚠️ ROUND 1, ITEM 6: "Back to Join Us button is not properly aligned", AND THIS IS WHY.
 *
 * Both pills are 100% wide, so the widths always matched. What did not match was the text
 * inside them: the primary carries `padding: 0 28px` and the secondary carried none, so on the
 * application confirmation, whose block is left-aligned (.tcl-confirm-done), one label started
 * 28px in and the one under it started at the pill's own edge. `text-align: center` on both,
 * and the same padding on both, makes them one stack of identical pills wherever they are
 * painted: centred inside .tcl-state, which centres its own text, and centred here too. */
.tcl-state__primary {
  display: inline-block;
  width: 100%;
  box-sizing: border-box;
  height: 48px;
  line-height: 48px;
  padding: 0 28px;
  text-align: center;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  font-weight: var(--fw-semibold);
  text-decoration: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--fs-body);
}

.tcl-state__primary:hover {
  background: var(--gold-500);
  color: var(--black);
}

.tcl-state__secondary {
  display: inline-block;
  width: 100%;
  box-sizing: border-box;
  background: none;
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-pill);
  height: 48px;
  line-height: 46px;
  padding: 0 28px;
  text-align: center;
  color: var(--flow-ink);
  text-decoration: none;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--fs-body);
}

.tcl-state__secondary:hover {
  border-color: var(--gold);
}

/* ============================================================
   M-04 (TCL-619) — R0's entry cards, the code modal, R4's team panel
   ============================================================
   Same rules as everything above: every colour is a var() from tokens.css, no raw hex, and
   no red/green/blue anywhere including errors — an error is a gold border plus cream helper
   text (see .tcl-team[data-invalid]) and never a colour of its own.
   ============================================================ */

/* ---------- R0: the two entry cards ---------- */
.tcl-entry {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: 1fr;
}

.tcl-entry__card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-6);
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  cursor: pointer;
}

/* Card A carries "very slightly more weight" (prompt 1) and card B must not read as
   secondary or disabled — so the difference is a hairline, not an opacity or a fill. */
.tcl-entry__card--primary {
  border-color: var(--deep-forest);
}

.tcl-entry:has(.tcl-card__radio:checked) .tcl-entry__card:has(.tcl-card__radio:checked) {
  border-color: var(--gold);
}

.tcl-entry__card:has(.tcl-card__radio:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-entry__head {
  font-size: 28px;
  line-height: 1.1;
  font-weight: var(--fw-bold);
  color: var(--flow-ink);
}

.tcl-entry__sub {
  font-size: var(--fs-body);
  color: var(--flow-ink-muted);
}

/* The design specifies a 4:3 photographic region here. There is no approved photography for
   these two states in the repo, and inventing one would be a made-up product fact (D17), so
   the tile carries the mark on the forest surface — the same device R2's venue rows use for
   a venue with no photo. Aspect ratio is kept so the real image drops straight in. */
.tcl-entry__art {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  margin: var(--s-2) 0;
  background: var(--forest);
  border-radius: var(--r-sm);
  overflow: hidden;
}

.tcl-entry__art img {
  height: 56px;
  width: auto;
  opacity: 0.55;
}

/* Round 1 (2026-09-16): the approved photos for the two cards landed, so the tile shows one
   edge to edge when the config names it, and the mark treatment above stays for a card without.

   ⚠️ ROUND 2 (2026-09-18), ITEM 1. THE WHOLE FIGURE SHOWS, LETTERBOXED, AND THE FRAME DOES NOT
   MOVE. Noah: "Bad crop on Run solo picture, can we find a way to zoom out to show all of him,
   even if the picture has different dimensions? We can fill the container with the same black to
   expand on the background if the zoomed out version of the picture doesn't fit the frame anymore."

   `cover` fills a 4:3 tile by cropping whatever does not fit, which is what took the top of his
   head off. `contain` fits the whole image inside the same tile and leaves the remainder showing
   the tile's own fill, so the fill becomes the letterbox and it is `--black` rather than the
   `--forest` the no-photo treatment uses: the photos are shot on black and a forest surround would
   read as a border around the picture rather than as more of it.

   THE 4:3 FRAME IS UNCHANGED, deliberately. Both cards keep the same height whatever their images
   are, so a re-export at a different aspect ratio drops straight in and moves no layout. */
.tcl-entry__art--photo {
  background: var(--black);
}

.tcl-entry__art--photo img {
  height: 100%;
  width: 100%;
  object-fit: contain;
  opacity: 1;
}

.tcl-entry__btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  font-weight: var(--fw-bold);
}

.tcl-entry__card:hover .tcl-entry__btn {
  background: var(--gold-500);
}

@media (min-width: 768px) {
  .tcl-entry {
    grid-template-columns: 1fr 1fr;
  }
}

/* ---------- the code-entry modal ---------- */
.tcl-code-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-5);
}

.tcl-code-modal[hidden] {
  display: none;
}

.tcl-code-modal__scrim {
  position: absolute;
  inset: 0;
  background: rgba(19, 16, 14, 0.7);
}

.tcl-code-modal__panel {
  position: relative;
  width: 100%;
  max-width: 420px;
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.tcl-code-modal__close {
  position: absolute;
  top: var(--s-2);
  right: var(--s-2);
  width: 44px;
  height: 44px;
  border: 0;
  background: none;
  color: var(--flow-ink);
  font-size: var(--fs-h2);
  line-height: 1;
  cursor: pointer;
}

.tcl-code-modal__title {
  margin: 0;
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-code-modal__label {
  font-size: var(--fs-label);
  font-weight: var(--fw-medium);
  color: var(--flow-ink);
}

/* Uppercase is a DISPLAY transform only. The value the client sends is whatever was typed;
   the mu-plugin's normalizer is the sole judge of a code, and it strips separators and
   uppercases server-side (W21). Transforming here so the two disagree is how a "case doesn't
   matter" promise quietly stops being true. */
.tcl-code-modal__input {
  height: 56px;
  padding: 0 var(--s-4);
  background: var(--flow-surface);
  border: 1.5px solid var(--flow-line-strong);
  border-radius: var(--r-sm);
  color: var(--flow-ink);
  font-family: var(--font-ui);
  font-size: var(--fs-h2);
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.tcl-code-modal__input:focus,
.tcl-code-modal__input:focus-visible {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(181, 139, 56, 0.18);
}

.tcl-code-modal__help,
.tcl-code-modal__error {
  margin: 0;
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

/* An error is gold, never red — the palette has five tokens and no semantic status colours. */
.tcl-code-modal__error {
  color: var(--flow-accent-ink);
}

.tcl-code-modal__error[hidden] {
  display: none;
}

.tcl-code-modal__submit {
  height: 48px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  font-family: var(--font-ui);
  font-weight: var(--fw-bold);
  font-size: var(--fs-body);
  cursor: pointer;
}

.tcl-code-modal__submit[aria-disabled="true"] {
  background: var(--flow-disabled-bg);
  color: var(--flow-ink-disabled);
  cursor: default;
}

.tcl-code-modal__link {
  align-self: center;
  min-height: 44px;
  border: 0;
  background: none;
  color: var(--flow-ink-muted);
  font-family: var(--font-ui);
  font-size: var(--fs-callout);
  text-decoration: underline;
  cursor: pointer;
}

.tcl-code-modal__recovery {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--flow-line);
}

.tcl-code-modal__recovery[hidden] {
  display: none;
}

.tcl-code-modal__recovery p {
  margin: 0;
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

.tcl-code-modal__wa {
  height: 44px;
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-pill);
  background: none;
  color: var(--flow-ink);
  font-family: var(--font-ui);
  font-weight: var(--fw-semibold);
  cursor: pointer;
}

/* ---------- R4: the team panel ---------- */
.tcl-team {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

/* ⚠️ Round 1, item 9. R4b's team name IS the screen's largest element, at the size the step
   H1 gave up, in the same display face. It is a <p> rather than a heading because it is the
   team's data and the heading above it is still the step's title; the size is the hierarchy. */
.tcl-team__name {
  margin: 0;
  font-family: var(--font-norwester);
  font-weight: 400;
  line-height: 0.95;
  color: var(--flow-display);
  font-size: clamp(32px, 6vw, 56px);
}

/* The league line, directly under the name and quieter than it. `.tcl-team` is a flex column
   with its own gap, so this carries no margin of its own. Empty when the team resolved with no
   league to name, which renders as nothing rather than as a stray separator. */
.tcl-team__league {
  margin: 0;
  font-size: var(--fs-subtitle);
  color: var(--flow-ink-muted);
}

.tcl-team__league:empty {
  display: none;
}

.tcl-team__eyebrow {
  margin: 0;
  font-size: var(--fs-label);
  color: var(--flow-ink-muted);
}

.tcl-team__eyebrow[hidden] {
  display: none;
}

.tcl-team__lead {
  margin: 0;
  font-size: var(--fs-body);
  color: var(--flow-ink-muted);
}

.tcl-team__create {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

.tcl-team__create[hidden] {
  display: none;
}

/* Round 1 (2026-09-17). The border and the ring moved into the shared Error state block above,
   so the team-name box is refused in exactly the same red as every other control. */
.tcl-team[data-invalid="true"] .tcl-field__helper {
  color: var(--flow-ink);
}

.tcl-team__go {
  height: 48px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  font-family: var(--font-ui);
  font-weight: var(--fw-bold);
  font-size: var(--fs-body);
  cursor: pointer;
}

.tcl-team__go[aria-disabled="true"] {
  background: var(--flow-disabled-bg);
  color: var(--flow-ink-disabled);
  cursor: default;
}

.tcl-team__share[hidden] {
  display: none;
}

.tcl-team__share {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
}

.tcl-team__delegation {
  margin: 0;
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

/* THE SHARE BLOCK IS THE LOUDEST ELEMENT ON THE SCREEN (prompt 3). The WhatsApp pill is 56px
   and the action bar's Continue is 48px — that ordering is the design's, and it is the whole
   inversion this screen exists for. Do not equalise them. */
.tcl-share {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.tcl-share__wa {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  height: 56px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--gold);
  color: var(--black);
  font-family: var(--font-ui);
  font-weight: var(--fw-bold);
  font-size: 17px;
  cursor: pointer;
}

.tcl-share__wa:hover {
  background: var(--gold-500);
}

.tcl-share__wa-glyph {
  font-size: var(--fs-subtitle);
  line-height: 1;
}

.tcl-share__copy {
  height: 48px;
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-pill);
  background: none;
  color: var(--flow-ink);
  font-family: var(--font-ui);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-body);
  cursor: pointer;
}

.tcl-share__url {
  margin: 0;
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
  overflow-wrap: anywhere;
}

.tcl-share__copied {
  margin: 0;
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--flow-accent-ink);
}

.tcl-share__copied[hidden] {
  display: none;
}

/* The code block is SECONDARY: a bordered box, not a filled card, so it cannot compete with
   the share block above it. The code itself is the one identity-face moment on this screen
   and the design specifies it — 40px, letter-spaced, gold. */
.tcl-teamcode {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-sm);
  padding: var(--s-5);
}

.tcl-teamcode__label,
.tcl-teamcode__help {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

.tcl-teamcode__value {
  font-family: var(--font-norwester);
  font-weight: 400;
  font-size: var(--fs-display);
  line-height: 1;
  letter-spacing: 0.15em;
  color: var(--flow-accent-ink);
}

/* ============================================================
   M-07 (TCL-622) — R8, "You're in"
   ============================================================
   Renders inside .tcl-interstitial (see .tcl-interstitial__title above, reused verbatim for
   the H1). .tcl-share / .tcl-teamcode above are reused as-is for the team block; nothing
   here restyles them.
   ============================================================ */
.tcl-confirm-done {
  display: flex;
  flex-direction: column;
  gap: var(--s-5);
  text-align: left;
}

.tcl-confirm-done__ref-label {
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--flow-ink-muted);
}

.tcl-confirm-done__ref-value {
  margin: calc(var(--s-2) * -1) 0 0;
  font-family: var(--font-norwester);
  font-weight: 400;
  font-size: var(--fs-title);
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--flow-accent-ink);
}

.tcl-confirm-done__sent {
  margin: 0;
  font-size: var(--fs-callout);
  line-height: var(--lh-callout);
  color: var(--flow-ink-muted);
}

.tcl-confirm-done__owed {
  margin: 0;
}

.tcl-confirm-done__wa {
  width: 100%;
  height: 56px;
  border-radius: 28px;
  background: var(--gold);
  color: var(--black);
  border: none;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  font-family: var(--font-ui);
}

.tcl-confirm-done__wa:hover {
  background: var(--gold-500);
}

.tcl-confirm-done__free-agent {
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--flow-ink);
}

/* B-03b (TCL-681). The House League's confirmation reads as a short letter rather than as a
   receipt: a heading, a list, and body lines between the panels R7 and R8 already style. Three
   classes, all built from existing tokens, and no new colour. */
.tcl-confirm-done__heading {
  margin: 0;
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--flow-ink-muted);
}

.tcl-confirm-done__line {
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--flow-ink);
}

.tcl-confirm-done__list {
  margin: calc(var(--s-3) * -1) 0 0;
  padding: 0 0 0 var(--s-5);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--flow-ink);
}

.tcl-confirm-done__link,
/* Round 2 (2026-09-18), ruling 15: the CV prompt's mailto address, in the same accent every other
   link in this block takes. The role property resolves to --gold-600 on the light ground, which is
   W58 ruling 1's whole arrangement, so no colour is named here. */
.tcl-confirm-done__cv a {
  color: var(--flow-accent-ink);
}

.tcl-confirm-done__lost {
  margin: 0;
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
  text-align: center;
}

.tcl-confirm-done__lost-link {
  width: auto;
  padding: 0 0 0 var(--s-2);
  color: var(--flow-ink);
  text-decoration: underline;
}

/* The roster panel. 375px collapses it to one line plus a bar; 1280px moves it beside the
   share and code blocks (see the media query at the foot of this block). The invite list is
   S-02 and is deliberately absent — the launch layout closes up without it. */
.tcl-roster {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.tcl-roster__line {
  margin: 0;
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

.tcl-roster__bar {
  height: 4px;
  border-radius: 2px;
  background: var(--flow-track);
  overflow: hidden;
}

.tcl-roster__bar span {
  display: block;
  height: 100%;
  background: var(--gold);
}

/* Hidden at 375px: the line and the bar already answer "how full is this". */
.tcl-roster__slots {
  display: none;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: var(--s-2);
}

.tcl-roster__slot {
  height: 44px;
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-sm);
  display: flex;
  align-items: center;
  padding: 0 var(--s-3);
  font-size: var(--fs-callout);
  color: var(--flow-ink-disabled);
}

.tcl-roster__slot--filled {
  border-color: var(--forest-500);
  background: var(--forest);
  color: var(--flow-ink);
}

@media (min-width: 1024px) {
  .tcl-team__share {
    display: grid;
    grid-template-columns: 3fr 2fr;
    grid-template-areas:
      "share roster"
      "code roster"
      "delegation roster";
    gap: var(--s-5) var(--s-6);
    align-items: start;
  }

  .tcl-team__share > .tcl-share { grid-area: share; }
  .tcl-team__share > .tcl-teamcode { grid-area: code; }
  .tcl-team__share > .tcl-team__delegation { grid-area: delegation; }
  .tcl-team__share > .tcl-roster { grid-area: roster; }

  .tcl-roster__slots {
    display: flex;
    flex-direction: column;
    margin-top: var(--s-3);
  }
}

/* ============================================================
   M-05 (TCL-620) — R5 DETAILS AND R6 KIT
   ============================================================
   Mirrors docs/wireframes/REG-04-details-and-kit/REG-04.dc.html. Every value is a token or
   a layout literal; no new colour, no raw hex, no identity typeface below the H1.
   ============================================================ */

/* ---------- the waiver link inside a consent helper ----------
 * Gold, underlined, and it is the ONLY link the consent block carries. A consent row that
 * cannot point at the document it consents to is asking for agreement to something unread.
 */
.tcl-consent__link {
  color: var(--flow-accent-ink);
  text-decoration: underline;
}

.tcl-consent__link:hover,
.tcl-consent__link:focus-visible {
  color: var(--flow-ink);
}

/* ---------- live character counter ----------
 * Sits inside the existing helper line ("4/12 · This is printed on the back."), so it
 * inherits the helper's colour and needs no rule of its own beyond a tabular figure width —
 * without it the sentence after the counter shifts sideways on every keystroke.
 */
.tcl-field__counter {
  font-variant-numeric: tabular-nums;
}

/* ---------- half-width field pair ----------
 * R6's `1st choice` / `2nd choice` backup numbers, which the accepted design draws side by
 * side. Deliberately narrow: prompt 4 forbids paired form fields on R5 outright and R5 uses
 * none. Two adjacent .tcl-field--inline siblings pair themselves; an odd one out simply sits
 * at half width, which is correct for a two-character number field anyway.
 */
.tcl-field--inline {
  display: inline-block;
  width: calc(50% - var(--s-2));
  vertical-align: top;
}

.tcl-field--inline + .tcl-field--inline {
  margin-left: var(--s-3);
}

/* ---------- static copy block ----------
 * Used for R6's intro paragraph and for the caption above the backup-number pair. Caption
 * weight, because in both places it is describing the controls beneath it rather than being
 * one of them.
 */
.tcl-field--static {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
  line-height: 1.5;
  margin-bottom: var(--s-4);
}

/* ROUND 1, ITEM 9. THE ONE STATIC VARIANT: the heading over a group of questions.
 *
 * Noah asked that the two question sets on the coaching application read as two distinct
 * questions. A `cards` field draws no visible label of its own, so a heading above each set is
 * what does it: display face, the flow's display ink, and a rule under it so the group has a
 * visible top edge. It is the same weight the rest of the flow gives a heading inside a step
 * and it introduces no colour. */
.tcl-field--static-group {
  font-size: var(--fs-subtitle);
  font-weight: var(--fw-semibold);
  color: var(--flow-display);
  line-height: 1.25;
  margin-top: var(--s-6);
  margin-bottom: var(--s-3);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--flow-line);
}

/* The first one on a step is the step's own first thing, so it does not push itself away from
   the title above it. */
.tcl-field--static-group:first-child { margin-top: 0; }

/* The first static block on a split step is the step's lede, not a caption. */
.tcl-split__fields > .tcl-field--static:first-child {
  font-size: var(--fs-body);
  color: var(--flow-ink);
  margin-bottom: var(--s-6);
}

/* ---------- split step: art beside the fields ----------
 * Stacked art-first on a phone at reduced height; two columns from 1024px with the image
 * region taking the larger share, per prompt 4's "image left at about 55%".
 */
.tcl-split {
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

.tcl-split__art {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

/* The standing treatment for photography that does not exist yet — the same mark-backed tile
 * R0's entry cards and R2's venue rows use. Never a stand-in product shot: the Season 4
 * jersey artwork does not exist and inventing one would be a made-up product fact (D17).
 */
.tcl-split__art-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 200px;
  border-radius: var(--r-lg);
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  overflow: hidden;
}

.tcl-split__art-tile img {
  width: 72px;
  height: auto;
  opacity: 0.5;
}

.tcl-split__art-caption {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

.tcl-split__fields {
  min-width: 0;
}

@media (min-width: 1024px) {
  /* A split step is the one place the flow uses the full column rather than the 560px form
   * measure — the measure exists to keep a single column of inputs readable, and here the
   * inputs are only half of what is on screen.
   */
  .tcl-form__col:has(.tcl-split) {
    max-width: 1040px;
  }

  .tcl-split {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--s-10);
  }

  .tcl-split__art {
    flex: 0 0 55%;
    max-width: 55%;
  }

  .tcl-split__art-tile {
    height: 420px;
  }

  .tcl-split__fields {
    flex: 1;
  }
}

/* ==========================================================================
   M-06 (TCL-621) — R7, the payment intent screen
   ==========================================================================
   docs/DESIGN_PROMPTS.md prompt 5 R7 + docs/wireframes/REG-05-confirm-and-states/.

   [PENDING DESIGN SYSTEM] Two sizes the prompt names are not on the type scale, and both
   are rounded UP to the nearest token rather than hardcoded:

     prompt 18px/700 (the D18 warning's first line)  -> --fs-subtitle (20px)
     prompt 28px/700 (the MoMo merchant code)        -> --fs-title    (32px)

   Rounding up rather than down is deliberate on both. The warning exists to be the loudest
   thing on the screen, so a size error must not make it quieter; the merchant code is
   transcribed by hand into a phone, so a size error must not make it harder to read. The
   prompt's own relationship (code larger than the warning line) is preserved. Confirm both
   with the CPO, or add 18px/28px to tokens.css.
   ========================================================================== */

/* ---------- the two-column confirm layout ---------- */

.tcl-confirm {
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

.tcl-confirm__actions {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

/* ---------- left column: the summary card ---------- */

.tcl-summary {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-6);
}

.tcl-summary__facts,
.tcl-summary__totals {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.tcl-summary__fact {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.tcl-summary__label {
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--flow-ink-muted);
}

.tcl-summary__value {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--flow-ink);
}

.tcl-summary__rule {
  height: 1px;
  border: 0;
  background: var(--flow-line);
  margin: var(--s-6) 0;
}

/* The totals table. Three rows and a fourth for the amount due, and there is deliberately no
 * rule, class or slot for a tax, subtotal or discount line: prompt 5 states the registration
 * price is the whole price, and a table that CAN render a line the business does not have is
 * a line somebody eventually fills in.
 */
.tcl-summary__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
}

.tcl-summary__total-label {
  font-size: var(--fs-callout);
  color: var(--flow-ink-muted);
}

.tcl-summary__total-value {
  margin: 0;
  font-size: var(--fs-callout);
  color: var(--flow-ink);
  text-align: right;
}

.tcl-summary__total--due {
  margin-top: var(--s-2);
}

.tcl-summary__total--due .tcl-summary__total-label {
  color: var(--flow-ink);
}

.tcl-summary__total--due .tcl-summary__total-value {
  font-size: var(--fs-subtitle);
  line-height: var(--lh-subtitle);
  font-weight: 700;
  color: var(--flow-accent-ink);
}

/* A row whose value the flow could not resolve renders nothing at all rather than an empty
 * label — an unexplained blank beside "TEAM" reads as data loss on the confirm screen.
 */
.tcl-summary__fact[hidden],
.tcl-summary__total[hidden] {
  display: none;
}

/* ---------- right column 1: the payment-terms toggle ---------- */

.tcl-terms {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-3);
}

/* A league that takes no deposit renders ONE card, full width, and no toggle affordance at
 * all — see W27 ruling 5. A disabled second card would advertise a payment option this
 * league does not offer.
 */
.tcl-terms--single {
  grid-template-columns: 1fr;
}

.tcl-terms__card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--flow-line-strong);
  background: transparent;
  cursor: pointer;
}

.tcl-terms__card:has(.tcl-card__radio:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-terms__card:has(.tcl-card__radio:checked) {
  background: var(--flow-selected-bg);
  border: 2px solid var(--gold);
  /* The 1px the border gained is taken back from the padding so a selected card does not
   * shift its neighbour. */
  padding: calc(var(--s-4) - 1px);
}

.tcl-terms__heading {
  font-size: var(--fs-callout);
  font-weight: 700;
  color: var(--flow-ink);
}

.tcl-terms__amount {
  font-size: var(--fs-subtitle);
  line-height: var(--lh-subtitle);
  font-weight: 700;
  color: var(--flow-ink);
}

.tcl-terms__sub {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

/* ---------- right column 2: the D18 warning ----------
 * THE LOUDEST ELEMENT ON THE SCREEN, AND STRUCTURALLY SO. Prompt 5: "If a registrant can
 * leave this screen believing they already have a place, the screen has failed." That is why
 * this is a full-width panel with its own vertical space and a two-part heading/body split,
 * rather than helper text under a total. Nothing else in the flow gets the gold left edge.
 */

.tcl-notice {
  border-radius: var(--r-md);
  padding: var(--s-5);
}

.tcl-notice--alarm {
  background: var(--forest);
  border-left: 2px solid var(--gold);
  margin: var(--s-2) 0;
}

/* B-02 (TCL-721). The welcome panel: the same structure, one weight down, and a gold TITLE
 * rather than a gold edge on a louder ground. The distinction is the point of the variant
 * existing at all, see TCL_FORM_NOTICE_VARIANTS: an under-18 welcome drawn in the payment
 * warning's treatment would tell somebody that being sixteen is a problem. */
.tcl-notice--welcome {
  background: var(--deep-forest);
  border: 1px solid var(--forest);
  border-left: 3px solid var(--gold);
  margin: var(--s-4) 0;
}

.tcl-notice--welcome .tcl-notice__title {
  font-size: var(--fs-callout);
  line-height: var(--lh-callout);
  font-weight: var(--fw-semibold);
  color: var(--flow-accent-ink);
}

.tcl-notice__title {
  margin: 0 0 var(--s-2);
  font-size: var(--fs-subtitle);
  line-height: var(--lh-subtitle);
  font-weight: 700;
  color: var(--cream);
}

.tcl-notice__body {
  margin: 0;
  font-size: var(--fs-callout);
  line-height: var(--lh-callout);
  color: var(--cream);
}

/* Round 2 (2026-09-18), ruling 14: the link a notice may carry. Both notice variants redefine
   --flow-accent-ink to --gold on themselves (the dark-ground block at the head of this file), so
   this reads correctly on the Deep Forest panel without naming a colour. */
.tcl-notice__link {
  color: var(--flow-accent-ink);
  text-decoration: underline;
}

/* ---------- right column 3: the MoMo panel ---------- */

.tcl-momo {
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-5);
}

.tcl-momo__heading {
  margin: 0 0 var(--s-3);
  font-size: var(--fs-callout);
  font-weight: 700;
  color: var(--flow-ink);
}

.tcl-momo__code-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-3);
}

.tcl-momo__code {
  font-size: var(--fs-title);
  line-height: var(--lh-title);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--flow-accent-ink);
}

/* The not-yet-set state. Body face, cream, NOT the code treatment above — it must be
 * impossible to mistake this for a number to dial. The Copy affordance is not rendered at all
 * in this state (see tcl_form_render_momo()), so there is nothing to copy the phrase with.
 */
.tcl-momo__code-pending {
  font-size: var(--fs-body);
  font-style: italic;
  color: var(--flow-ink-muted);
}

.tcl-momo__copy {
  min-height: 44px;
  padding: 0 var(--s-4);
  border-radius: var(--r-pill);
  border: 1px solid var(--flow-line-strong);
  background: transparent;
  color: var(--flow-ink);
  font-size: var(--fs-label);
  font-weight: 700;
  cursor: pointer;
}

.tcl-momo__copy:hover {
  border-color: var(--gold);
}

.tcl-momo__copy:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-momo__amount {
  margin: var(--s-4) 0 0;
  font-size: var(--fs-body);
  font-weight: 700;
  color: var(--flow-ink);
}

.tcl-momo__steps {
  margin: var(--s-4) 0 0;
  padding-left: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.tcl-momo__step {
  font-size: var(--fs-callout);
  line-height: var(--lh-callout);
  color: var(--flow-ink);
}

@media (min-width: 1024px) {
  /* Same reasoning as the split step: the 560px form measure exists to keep one column of
   * inputs readable, and R7 is not one column of inputs.
   */
  .tcl-form__col:has(.tcl-confirm) {
    max-width: 1040px;
  }

  .tcl-confirm {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--s-10);
  }

  /* Summary left at about 40%, actions right — prompt 5. */
  .tcl-summary {
    flex: 0 0 40%;
    max-width: 40%;
    position: sticky;
    top: var(--s-6);
  }

  .tcl-confirm__actions {
    flex: 1;
  }
}

/* ============================================================
   B-02 (TCL-721): TEXTAREA WITH A LIVE WORD COUNT
   ============================================================
   The G-03 README's sequence, drawn in the palette this file already has: the counter reads
   from an empty box, turns as it nears the cap and counts down, and over the cap the border,
   the count and the bar all move together and the message says how many words to cut.

   IT MOVES TO GOLD, NOT TO A NEW COLOUR. This file's opening rule is that there is no red,
   green or blue anywhere, error states included, and the artboard's amber is the gold token
   read through a different name. So the "over" treatment is the same gold every other refusal
   on this form uses, and what distinguishes it is the message beside it rather than a hue this
   palette does not have.
   ============================================================ */
.tcl-textarea__input {
  height: auto;
  min-height: 132px;
  line-height: var(--lh-body);
  padding: var(--s-3) var(--s-4);
  resize: vertical;
  display: block;
}

.tcl-textarea__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}

.tcl-textarea__message {
  flex: 1;
  min-width: 0;
}

.tcl-textarea__count {
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink-muted);
  white-space: nowrap;
  margin-top: var(--s-2);
  /* Tabular figures so the number does not jog the line as it changes. */
  font-variant-numeric: tabular-nums;
}

.tcl-textarea__bar {
  height: 3px;
  border-radius: 2px;
  background: var(--flow-track);
  margin-top: var(--s-2);
  overflow: hidden;
}

.tcl-textarea__bar span {
  display: block;
  height: 3px;
  border-radius: 2px;
  background: var(--gold);
}

/* Near the cap and over it. `data-count-state` is set by form.js on every keystroke. */
.tcl-textarea[data-count-state="near"] .tcl-textarea__count,
.tcl-textarea[data-count-state="over"] .tcl-textarea__count,
.tcl-textarea[data-count-state="near"] .tcl-textarea__message,
.tcl-textarea[data-count-state="over"] .tcl-textarea__message {
  color: var(--flow-accent-ink);
}

.tcl-textarea[data-count-state="over"] .tcl-input {
  border-color: var(--gold);
}

/* ============================================================
   B-02 (TCL-721): CHECKGROUP, ITS METER AND ITS FOOTER LINE
   ============================================================
   Three statements of the same requirement before it is ever a refusal: the meter with its
   pips and its count, the hint under them, and the footer line that sits immediately above the
   action bar. See tcl_form_render_checkgroup() for why the footer line lives inside the field.

   THE METER IS STICKY, which is the G-03 README's own word for it: on a phone the nine slots
   are taller than the viewport, so a meter that scrolled away would leave somebody choosing
   with no idea how many they had.
   ============================================================ */
.tcl-checkgroup {
  margin-bottom: var(--s-5);
}

.tcl-checkgroup__meter {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  margin-bottom: var(--s-4);
}

.tcl-checkgroup[data-met="true"] .tcl-checkgroup__meter,
.tcl-checkgroup[data-invalid="true"] .tcl-checkgroup__meter {
  border-color: var(--flow-danger);
  border-width: 2px;
}

.tcl-checkgroup__meter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin-bottom: var(--s-2);
}

.tcl-checkgroup__meter-title {
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  color: var(--flow-ink);
}

.tcl-checkgroup__meter-count {
  font-size: var(--fs-caption);
  color: var(--flow-ink);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.tcl-checkgroup__pips {
  display: flex;
  gap: var(--s-1);
}

.tcl-checkgroup__pip {
  flex: 1;
  height: 5px;
  border-radius: 3px;
  background: var(--flow-track);
}

.tcl-checkgroup__pip[data-on="true"] {
  background: var(--gold);
}

.tcl-checkgroup__hint {
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--flow-ink-muted);
  margin: var(--s-2) 0 0;
}

.tcl-checkgroup[data-met="true"] .tcl-checkgroup__meter-title,
.tcl-checkgroup[data-invalid="true"] .tcl-checkgroup__hint {
  color: var(--flow-danger);
}

.tcl-checkgroup__options {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-2);
}

.tcl-checkgroup__note,
.tcl-checkgroup__footer {
  font-size: var(--fs-caption);
  line-height: var(--lh-caption);
  color: var(--flow-ink-muted);
  margin: var(--s-4) 0 0;
}

.tcl-checkgroup[data-invalid="true"] .tcl-checkgroup__footer {
  color: var(--flow-ink);
}

/* One slot. A real native checkbox inside a label, styled the way the consent box already is,
   so the whole row is the hit target and the keyboard and screen-reader behaviour is free. */
.tcl-check {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 56px;
  padding: var(--s-3) var(--s-4);
  background: var(--flow-surface);
  border: 1px solid var(--flow-line-strong);
  border-radius: var(--r-md);
  cursor: pointer;
}

.tcl-check:has(.tcl-check__box:checked) {
  border-color: var(--gold);
}

.tcl-check:has(.tcl-check__box:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.tcl-check__box {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: 1px solid var(--flow-line-strong);
  background-color: transparent;
  background-repeat: no-repeat;
  background-position: center;
  flex-shrink: 0;
  padding: 0;
  cursor: pointer;
}

.tcl-check__box:checked {
  background-color: var(--gold);
  border-color: var(--gold);
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3e%3cpath d='M2 6L5 9L10 2.5' stroke='%2313100e' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
}

.tcl-check__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-width: 0;
}

.tcl-check__label {
  font-size: 15px;
  color: var(--flow-ink);
}

.tcl-check:has(.tcl-check__box:checked) .tcl-check__label {
  color: var(--flow-accent-ink);
}

.tcl-check__desc {
  font-size: var(--fs-caption);
  color: var(--flow-ink-muted);
}

.tcl-checkgroup[data-invalid="true"] .tcl-check {
  border-color: var(--flow-danger);
}

@media (min-width: 768px) {
  /* Two columns once there is room. Mobile first at 375px is the primary artboard, and nine
     rows in one column is the right shape there; the desktop form still does not sprawl,
     because .tcl-form__col's own measure bounds it. */
  .tcl-checkgroup__options {
    grid-template-columns: 1fr 1fr;
  }
}
