/* NASTAR homepage.
 *
 * Loaded only on the homepage via layout.php's $pageStylesheet. It is
 * deliberately NOT part of theme/css/nastar.css: that file is a matched pair
 * with skiracing's theme_2026/css/nastar.css and must stay identical, so
 * page-specific rules cannot live there (architecture doc §12).
 *
 * Every colour, space and radius below is a token from nastar.css, so this
 * cannot drift from the approved theme.
 */

/* ------------------------------------------------------------- carousel */
.hc { position: relative; background: var(--nastar-blue-dark); overflow: hidden; }
.hc__slide { display: none; position: relative; }
.hc__slide.is-active { display: block; }
.hc__img { display: block; width: 100%; height: 340px; object-fit: cover; }

.hc__cap {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: var(--space-7) 0 var(--space-6);
  /* Three stops, not two: with a plain ramp the gold eyebrow sits where the
     overlay is still nearly transparent and washes out against bright snow. */
  background: linear-gradient(to top,
              rgba(12, 24, 48, .92) 0%,
              rgba(12, 24, 48, .78) 45%,
              rgba(12, 24, 48, 0) 100%);
}
/* A wrapper rather than `.hc__cap > *`: that selector ties with the title's
   own `margin: 0` on specificity and loses on source order, which silently
   kills the centering and leaves the caption misaligned with .container. */
.hc__capinner {
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding-inline: var(--space-4);
}
.hc__eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--nastar-gold);
  font: 700 12px/1 var(--font-heading);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.hc__title { margin: 0; font: 700 30px/1.15 var(--font-heading); }
.hc__title a { color: var(--white); text-decoration: none; }
.hc__title a:hover { text-decoration: underline; }

.hc__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  min-width: var(--tap-min);
  min-height: var(--tap-min);
  border: 0;
  background: rgba(12, 24, 48, .45);
  color: var(--white);
  font-size: 20px;
  cursor: pointer;
}
.hc__nav:hover { background: rgba(12, 24, 48, .75); }
.hc__nav--prev { left: 0; }
.hc__nav--next { right: 0; }
.hc__dots { position: absolute; right: var(--space-5); bottom: var(--space-3); display: flex; gap: var(--space-2); }
.hc__dot {
  width: 10px; height: 10px; padding: 0;
  border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .45);
  cursor: pointer;
}
.hc__dot.is-active { background: var(--nastar-gold); }

/* ----------------------------------------------------------- leaderboard */
.lb {
  border: 1px solid var(--gray-200);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  background: var(--white);
}

/* Three distinct states, per David's reference (2026-08-20):
     default  navy / white
     hover    lighter blue-grey / white, hovered item only
     active   gold / dark navy text, persistent
   The gap lets the container colour through as hairline dividers, which also
   separates the two rows the tabs wrap onto at phone widths. */
.lb__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
  background: var(--nastar-gold);
}
.lb__tab {
  flex: 1 1 auto;
  min-height: var(--tap-min);
  padding: var(--space-3) var(--space-4);
  border: 0;
  background: var(--nastar-blue-dark);
  color: var(--white);
  font: 700 14px/1 var(--font-heading);
  letter-spacing: .08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color .12s ease, color .12s ease;
}
@media (prefers-reduced-motion: reduce) {
  .lb__tab { transition: none; }
}

/* `:not([aria-pressed="true"])` is the whole behavioural rule: hover must
   never visually replace or obscure the selected family. Both the server-
   rendered path and home.js set aria-pressed, so keying off it (rather than a
   class) means the two paths cannot disagree about which tab looks active. */
.lb__tab:hover:not([aria-pressed="true"]) {
  background: var(--nastar-blue-light);
  color: var(--white);
}

.lb__tab[aria-pressed="true"] {
  /* Gold on navy text measures 5.08:1 — above the 4.5:1 needed at this size. */
  background: var(--nastar-gold);
  color: var(--nastar-blue-dark);
}

/* Keyboard users get an equivalent, and it stays visible on the gold fill. */
.lb__tab:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: -5px;
}
.lb__tab[aria-pressed="true"]:focus-visible { outline-color: var(--nastar-blue-dark); }

.lb__controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: end;
  padding: var(--space-4) var(--space-5);
  background: var(--gray-100);
  border-bottom: 1px solid var(--gray-200);
}
/* `min-width: 0` overrides the flex default of `auto`, which sizes an item to
   its min-content. A <select> measures that from its LONGEST OPTION, so the
   Adaptive family's classification names ("Adaptive Snowboard: Lower Limb
   Disability") pushed this control ~25px past the row on a 390px phone. */
.lb__ctl { display: flex; flex-direction: column; gap: 4px; flex: 1 1 200px; min-width: 0; }
/* `display: flex` above beats the UA stylesheet's [hidden] { display: none },
   so the hidden group selector stayed visible as an empty box. */
.lb__ctl[hidden] { display: none; }
.lb__ctl-label {
  font: 700 11px/1 var(--font-heading);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gray-500);
}
.lb__select {
  max-width: 100%;
  min-height: var(--tap-min);
  padding: 0 var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--gray-900);
  font: 15px/1 var(--font-body);
}
/* The no-JavaScript submit. home.js removes it once it takes over. */
.lb__go {
  min-height: var(--tap-min);
  padding: 0 var(--space-4);
  border: 1px solid var(--nastar-blue-dark);
  border-radius: var(--radius-sm);
  background: var(--nastar-blue-dark);
  color: var(--white);
  font: 700 14px/1 var(--font-heading);
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
}

.lb__boardhead {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
  justify-content: space-between;
  padding: var(--space-5) var(--space-5) var(--space-3);
}
.lb__title { margin: 0; font-size: 20px; }
/* Which season is on screen, and whether it is finished. The season selector
   shows only the year, so this is not redundant with it. */
.lb__season {
  margin: 0;
  color: var(--gray-500);
  font: 700 11px/1 var(--font-heading);
  letter-spacing: .1em;
  text-transform: uppercase;
}

.lb__list { list-style: none; margin: 0; padding: 0 var(--space-5) var(--space-3); }
.lb__row {
  display: grid;
  grid-template-columns: 2.5rem 1fr auto;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--gray-200);
}
.lb__row--head {
  border-bottom: 2px solid var(--gray-300);
  font: 700 11px/1 var(--font-heading);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gray-500);
}
.lb__row:last-child { border-bottom: 0; }
.lb__rank { font: 700 17px/1 var(--font-heading); color: var(--nastar-blue); text-align: right; }
.lb__row--head .lb__rank { font-size: 11px; color: var(--gray-500); }
/* Content links are underlined, including inside data tables — the link is
   the point of the row (project instructions, "Links are how racers explore
   the data"). */
.lb__name { font-size: 16px; text-decoration: underline; }
.lb__row--head .lb__name { font-size: 11px; text-decoration: none; }
.lb__where { margin-top: 2px; color: var(--gray-500); font-size: 13px; }
/* Its own link now, so it carries its own underline rather than inheriting the
   name's. Deliberately quieter than the name: the racer is the primary target. */
.lb__where a { color: inherit; text-decoration: underline; }
.lb__where a:hover { color: var(--nastar-blue); }
.lb__val {
  font: 700 16px/1 var(--font-body);
  font-variant-numeric: tabular-nums;
  color: var(--gray-900);
  text-align: right;
}
.lb__row--head .lb__val { font-size: 11px; color: var(--gray-500); }

.lb__more { display: inline-block; padding: 0 var(--space-5) var(--space-5); font-size: 15px; }

/* ------------------------------------------------------------------ news */
.newsgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-5); }
.news { display: block; text-decoration: none; }
.news__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  margin-bottom: var(--space-3);
}
.news__title { font-size: 15px; line-height: 1.35; text-decoration: underline; }

/* --------------------------------------------------------------- mobile */
@media (max-width: 900px) {
  .newsgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .hc__img { height: 220px; }
  .hc__title { font-size: 22px; }
  .hc__cap { padding: var(--space-6) 0 var(--space-5); }
  .hc__dots { right: var(--space-4); }

  /* Tabs wrap onto two rows rather than scrolling sideways: nothing on this
     page may introduce horizontal overflow. */
  .lb__tab { flex: 1 1 33%; font-size: 12px; padding: var(--space-3) var(--space-2); }

  .lb__controls { padding: var(--space-3) var(--space-4); gap: var(--space-3); }
  .lb__ctl { flex: 1 1 100%; }
  .lb__go { width: 100%; }

  .lb__boardhead { padding: var(--space-4) var(--space-4) var(--space-2); }
  .lb__title { font-size: 18px; }
  .lb__list, .lb__more { padding-inline: var(--space-4); }

  /* Three columns is still the phone limit: rank, name, value. The hometown
     is NOT dropped any more, though — it is a real link to that town's racers,
     not decoration, and hiding it removed that navigation on phones entirely.
     It sits on its own line under the name inside the same column, so the row
     keeps three columns and grows by one small line. */
  .lb__row { grid-template-columns: 2rem 1fr auto; gap: var(--space-2); }
  .lb__where { font-size: 12px; }
  .lb__name, .lb__val { font-size: 15px; }

  .newsgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
  .news__title { font-size: 14px; }

}

/* ------------------------------------------ featured racer + lifetime club */
.eyebrow {
  margin: 0 0 var(--space-2);
  color: var(--nastar-blue);
  font: 700 12px/1 var(--font-heading);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.racers {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: var(--space-7);
  align-items: start;
}
.featured__name { margin: 0; font-size: 30px; }
.featured__where { margin: 0 0 var(--space-4); color: var(--gray-500); }
.featured__prose p { margin: 0 0 var(--space-3); }
.featured__stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  list-style: none;
  margin: var(--space-4) 0;
  padding: 0;
}
.featured__stats li { display: flex; flex-direction: column; }
.featured__stats strong { font: 700 22px/1 var(--font-heading); color: var(--nastar-blue-dark); }
.featured__stats span { color: var(--gray-500); font-size: 13px; }

/* Staff-only Featured Racer preview. Never rendered for the public, so it can
   afford to look like a tool rather than part of the design. Deliberately
   quiet: it sits under the eyebrow and must not compete with the racer's name.
   Tap targets stay >= 44px to satisfy the homepage's own check. */
.featured__admin {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
  font-size: 13px;
  color: var(--gray-500);
}
.featured__admin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border: 1px solid var(--gray-300, #cbd2d9);
  border-radius: 4px;
  text-decoration: none;
  color: var(--nastar-blue-dark);
  line-height: 1;
}
.featured__admin-btn:hover,
.featured__admin-btn:focus-visible { background: var(--gray-100, #f0f3f6); }
.featured__admin-state { font-variant-numeric: tabular-nums; }
.featured__admin-state em { font-style: normal; text-transform: uppercase; letter-spacing: .04em; font-size: 11px; }
.featured__admin-state em.is-preview { color: var(--nastar-blue-dark); font-weight: 700; }
.featured__admin-reset {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--nastar-blue-dark);
}
.featured__admin-note { margin-left: auto; font-size: 11px; color: var(--gray-400, #9aa5b1); }
@media (max-width: 700px) {
  .featured__admin-note { margin-left: 0; flex-basis: 100%; }
}

.club { border-left: 4px solid var(--nastar-gold); padding-left: var(--space-5); }
.club__head { margin: 0 0 var(--space-2); font-size: 22px; }
.club__intro { margin: 0 0 var(--space-5); color: var(--gray-700); font-size: 15px; }
.club__group + .club__group { margin-top: var(--space-5); }
.club__lvl {
  margin: 0 0 var(--space-2);
  font: 12px/1 var(--font-heading);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gray-500);
}
.club__lvl strong { font-size: 18px; color: var(--nastar-gold-dark); }
.club__list { list-style: none; margin: 0; padding: 0; }
.club__list li { padding: var(--space-2) 0; border-bottom: 1px solid var(--gray-200); break-inside: avoid; }
.club__list li:last-child { border-bottom: 0; }
.club__list a { text-decoration: underline; }
.club__where { display: block; color: var(--gray-500); font-size: 13px; }
/* The 30+ group runs far taller than the Featured Racer beside it otherwise. */
.club__group--wide .club__list { column-count: 2; column-gap: var(--space-5); }

/* --------------------------------------------------------- recent races */
/* Two columns, but grid's default row-wise flow keeps reading order
   chronological: 1-2 on the first line, 3-4 on the next. A column-wise
   layout would put race 4 beside race 1. */
.races { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--space-7); }
.race {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr) auto;
  gap: var(--space-3);
  align-items: baseline;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--gray-200);
  text-decoration: none;
}
.race__date { color: var(--gray-500); font-size: 13px; font-weight: 700; }
.race__name { display: block; text-decoration: underline; }
.race__resort { display: block; color: var(--gray-500); font-size: 13px; }
.race__n { color: var(--gray-500); font-size: 13px; white-space: nowrap; }

/* --------------------------------------------------------------- guides */
/* RETAINED, UNUSED BY THIS PAGE. The "New to NASTAR?" row these styled was
   removed 2026-08-26 when the onboarding band took over the job. Kept rather
   than deleted because Homepage::guides() is intact and /start is the page
   these cards belong on; MOVE THIS BLOCK to /start's stylesheet when that page
   is built, rather than leaving it loading on every homepage view forever. */
/* auto-fit rather than a fixed 3: at intermediate widths a hard 3-column grid
   collapsing to 2 leaves one orphan card on its own row. */
.guides { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--space-5); }
.guide {
  display: block;
  padding: var(--space-5);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius);
  background: var(--white);
  text-decoration: none;
}
.guide:hover { box-shadow: var(--shadow); }
.guide__title {
  display: block;
  font: 700 17px/1.25 var(--font-heading);
  color: var(--nastar-blue-dark);
  text-decoration: underline;
}

/* ------------------------------------------------- own row, when signed in */
.lb__row--me {
  background: rgba(234, 175, 29, .16);
  box-shadow: inset 3px 0 0 var(--nastar-gold);
}

@media (max-width: 900px) {
  .racers { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
  .club { border-left: 0; border-top: 4px solid var(--nastar-gold); padding: var(--space-5) 0 0; }
  .races { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 640px) {
  .featured__name { font-size: 26px; }
  /* Two columns and no hometown: one name per line made the section ~600px
     longer for no legibility gain. */
  .club__group .club__list { column-count: 2; column-gap: var(--space-4); }
  .club__where { display: none; }
  .club__list li { padding: 6px 0; }
  .guides { grid-template-columns: minmax(0, 1fr); }
}

/* Featured Racer photo is optional; the layout only becomes two-column when
   an editor has actually supplied one. */
.featured__body--photo { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: var(--space-5); }
.featured__photo { display: block; width: 100%; height: auto; border-radius: var(--radius); }
@media (max-width: 640px) {
  .featured__body--photo { grid-template-columns: minmax(0, 1fr); }
  .featured__photo { max-width: 240px; }
}

/* Guide cards show the article's own image when it has one. Cards without an
   image sit in the same grid and simply have no media — the row must not
   depend on every guide having artwork. */
.guide--image { padding: 0; overflow: hidden; }
.guide__img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
.guide--image .guide__title { display: block; padding: var(--space-4) var(--space-5); }

/* --------------------------------------------------- racer photo (camera) */
/* The name+camera share one line; the hometown sits on its own beneath, as its
   own link. Three independent controls in one column, and the row stays the
   same height it was when the hometown lived inside the name link. */
.lb__who { display: flex; flex-direction: column; min-width: 0; }
.lb__wholine { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; }
.lb__wholine .lb__name { min-width: 0; }

.lb__cam {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px of hit area from a 16px icon, without changing the line box:
     the padding is absorbed by a negative margin. */
  width: var(--tap-min);
  height: var(--tap-min);
  margin: calc(var(--tap-min) / -2 + 8px) calc(var(--tap-min) / -2 + 8px);
  padding: 0;
  border: 0;
  background: none;
  color: var(--gray-500);
  cursor: pointer;
}
.lb__cam svg { width: 16px; height: 16px; fill: currentColor; }
.lb__cam:hover, .lb__cam[aria-expanded="true"] { color: var(--nastar-blue); }
.lb__cam:focus-visible { outline: 2px solid var(--nastar-blue); outline-offset: -12px; border-radius: var(--radius-sm); }

.racerpop {
  position: absolute;
  z-index: 50;
  width: min(320px, calc(100vw - 16px));
  padding: var(--space-2);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius);
  background: var(--white);
  box-shadow: var(--shadow-lg);
}
.racerpop[hidden] { display: none; }
.racerpop__img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 60vh;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--gray-100);
}
.racerpop.is-loading .racerpop__img { min-height: 120px; }
.racerpop__cap {
  margin: var(--space-2) 0 0;
  font: 700 13px/1.2 var(--font-heading);
  color: var(--gray-700);
  text-align: center;
}
.racerpop__close {
  position: absolute;
  top: 0; right: 0;
  width: var(--tap-min); height: var(--tap-min);
  border: 0;
  background: none;
  color: var(--gray-700);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
@media (hover: hover) {
  /* The close control is for touch, where there is nothing to hover away to. */
  .racerpop__close { display: none; }
}

/* ------------------------------------------------- NASTAR action button
 * The established NASTAR action language, taken from skiracing's own
 * `.record-claim` ("This is me") on the 2026 race-record header: gold, dark
 * text, 44px, hovering to gold-dark. Reimplemented here in the shared theme's
 * tokens rather than importing skiracing's stylesheet — same visual language,
 * no cross-site CSS coupling. It also matches the leaderboard's own selected
 * tab, so the page has one action colour rather than two.
 */
.btn-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: 6px var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--nastar-gold);
  color: var(--gray-900);
  font: 700 14px/1.25 var(--font-heading);
  letter-spacing: .04em;
  text-decoration: none;
  white-space: nowrap;
}
/* The arrow is part of NASTAR's action-button language (record-claim,
   record-nudge), so it is spaced rather than glued to the label, and nudges
   on hover the way a "go here" affordance should. aria-hidden: it is
   decoration, and the label already says where it goes. */
.btn-action__arrow { margin-left: var(--space-2); transition: transform .12s ease; }
.btn-action:hover { background: var(--nastar-gold-dark); color: var(--white); text-decoration: none; }
.btn-action:hover .btn-action__arrow { transform: translateX(2px); }
@media (prefers-reduced-motion: reduce) { .btn-action__arrow { transition: none; } .btn-action:hover .btn-action__arrow { transform: none; } }
.btn-action:focus-visible { outline: 3px solid var(--nastar-blue-dark); outline-offset: 2px; }
.btn-action:active { transform: translateY(1px); }
@media (prefers-reduced-motion: reduce) { .btn-action:active { transform: none; } }

/* ------------------------------------------------- Lifetime Club portraits
 * The 40+ tier shows faces; 30+ shows a camera icon. Same control underneath,
 * so both open the same preview — the difference is only whether the image is
 * on the page already, which is affordable at two racers.
 */
.club__group--faces .club__list li { display: flex; align-items: center; gap: var(--space-3); }
.club__member { display: flex; flex-direction: column; min-width: 0; }
.club__nameline { display: flex; align-items: baseline; gap: var(--space-1); min-width: 0; }

.club__face {
  /* Overrides .lb__cam's icon sizing: this control IS the portrait. */
  width: 56px;
  height: 56px;
  margin: 0;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--gray-100);
  box-shadow: 0 0 0 2px var(--nastar-gold);
}
.club__face img {
  /* Racers upload action shots, not headshots, and one of the two 40+ photos
     is actually TWO images stacked in one 928x1815 file — a centre crop landed
     exactly in the white gap between them and rendered as an empty circle.
     Biasing to the top of the frame lands on the subject in both a landscape
     action shot and a stacked one, since a skier is rarely at the very bottom.
     Not bulletproof for arbitrary uploads; with two racers it is the right
     trade, and the full image is one click away. */
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}
.club__face:hover, .club__face[aria-expanded="true"] { box-shadow: 0 0 0 3px var(--nastar-gold-dark); }
.club__face:focus-visible { outline: 3px solid var(--nastar-blue-dark); outline-offset: 2px; }

/* The camera in the 30+ list sits on a normal line, so it does not need the
   leaderboard's negative-margin trick. */
.club__list .lb__cam:not(.club__face) { width: 28px; height: 28px; margin: 0; }
.club__list .lb__cam:not(.club__face) svg { width: 14px; height: 14px; }

/* ------------------------------------------------- onboarding/action band
 * The band between the carousel and the leaderboard. Its job is described in
 * app/templates/pages/home.php: turn intent into the two acts that make
 * somebody a NASTAR racer.
 *
 * Full-bleed navy, reversed type, and deliberately NO photography. Three
 * reasons, all about the band immediately above it: photography would compete
 * with the carousel a few pixels away; a white or grey `.section` would read as
 * a fourth content block instead of a turn in the page; and dark image -> dark
 * band -> white data gives the page a rhythm rather than an alternating stripe.
 *
 * HEIGHT BUDGET, and it is the reason for the three-column layout. At 1440x900
 * the header (132px) plus carousel (340px) end at 472px, so the band has ~430px
 * of the first screen. Stacking the proposition above the two steps measured
 * 499px: it emptied the right half of the band AND put the leaderboard
 * entirely below the fold. Running proposition / step 1 / step 2 across one
 * grid instead keeps the band near 300px, so the top of the leaderboard still
 * shows: the signal that the page continues. If this section grows, that
 * peek-through is what it is spending.
 *
 * Every colour, space and radius is a nastar.css token, so the band cannot
 * drift from the approved theme.
 */
.start {
  background: var(--nastar-blue-dark);
  color: var(--white);
  padding-block: var(--space-6);
}
/* Proposition first, then the two acts, reading left to right. The first
   column is wider because it carries the only sentence on the band. */
.start__grid {
  display: grid;
  grid-template-columns: 1.15fr 1fr 1fr;
  gap: var(--space-6) var(--space-8);
  align-items: start;
}
.start__intro { min-width: 0; }
.start__head {
  margin: 0 0 var(--space-2);
  color: var(--white);
  font: 700 30px/1.15 var(--font-heading);
}
.start__lede { margin: 0 0 var(--space-3); font-size: 17px; line-height: 1.5; color: rgba(255,255,255,.92); }
/* Chrome-style undecorated until hover: this is a signpost, not prose. Gold
   carries the "there is more this way" meaning the rest of the page uses. */
.start__learn { color: var(--nastar-gold); font-weight: 600; text-decoration: none; }
.start__learn:hover { color: var(--nastar-gold); text-decoration: underline; }

/* A hairline before each step, so the band reads as one proposition and TWO
   separate acts rather than three columns of similar-looking text. Without it
   "Find NASTAR racing near you" and "Get your NASTAR ID" run together at a
   glance, and the numbered badges have to carry the whole distinction on their
   own. The rule sits in the gutter (negative margin equal to half the gap), so
   it separates without stealing column width. */
.start__step {
  min-width: 0;
  padding-left: var(--space-5);
  border-left: 1px solid rgba(255,255,255,.2);
  margin-left: calc(var(--space-5) * -1);
}
.start__stephead {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin: 0 0 var(--space-2);
  color: var(--white);
  font: 700 19px/1.2 var(--font-heading);
}
/* The step number is a wayfinding mark, not content, and is aria-hidden in the
   markup, because "1 Find NASTAR racing near you" is not a heading anyone
   needs read to them. */
.start__num {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--nastar-gold);
  color: var(--nastar-blue-dark);
  font: 700 16px/1 var(--font-heading);
}
.start__stepbody {
  margin: 0 0 var(--space-4);
  font-size: 15px;
  line-height: 1.5;
  color: rgba(255,255,255,.88);
}

/* --- step 1: the state selector --------------------------------------- */
.start__find { margin: 0 0 var(--space-3); }
.start__ctl-label {
  display: block;
  margin-bottom: var(--space-1);
  color: rgba(255,255,255,.75);
  font: 700 11px/1 var(--font-heading);
  letter-spacing: .1em;
  text-transform: uppercase;
}
/* nowrap: at desktop the column is ~335px, and letting the button wrap to its
   own line cost ~55px of band height for no gain. It wraps again below 780px,
   where the button is full width by design. */
.start__findrow { display: flex; flex-wrap: nowrap; gap: var(--space-3); }
/* `min-width: 0` for the same reason as .lb__ctl: a flex item defaults to
   min-content, and a <select> measures that from its longest option
   ("Massachusetts", "New Hampshire"), which pushes the row past a 390px
   viewport. */
.start__select {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 100%;
  min-height: var(--tap-min);
  padding: 0 var(--space-3);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--gray-900);
  /* 16px, not 15: iOS zooms the page on focus for anything smaller. */
  font: 16px/1 var(--font-body);
}
.start__go {
  flex: 0 0 auto;
  min-height: var(--tap-min);
  padding: 0 var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--nastar-gold);
  color: var(--gray-900);
  font: 700 14px/1 var(--font-heading);
  letter-spacing: .04em;
  cursor: pointer;
}
.start__go:hover { background: var(--nastar-gold-dark); color: var(--white); }
.start__go:focus-visible, .start__select:focus-visible { outline: 3px solid var(--nastar-gold); outline-offset: 2px; }
.start__more { display: inline-block; color: rgba(255,255,255,.85); font-size: 14px; text-decoration: underline; }
.start__more:hover { color: var(--white); }

/* --- the two secondary lines ------------------------------------------ */
/* Visually secondary is the design, not an oversight: these are real needs,
   but giving them the weight of the two steps would turn the most valuable
   space on the site into a support directory. */
.start__aside {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid rgba(255,255,255,.22);
}
.start__asideline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  font-size: 14px;
  color: rgba(255,255,255,.8);
}
.start__asideline + .start__asideline { margin-top: var(--space-2); }
.start__asideline strong { color: var(--white); font-weight: 600; }
/* Underlined: these are content links, and on this background colour alone is
   not a reliable signal (project instructions, "Links are how racers explore
   the data"). */
.start__asideline a { color: var(--white); text-decoration: underline; }
.start__asideline a:hover { color: var(--nastar-gold); }

/* Three columns need real width. Below this the proposition takes the full
   row and the two steps sit side by side under it — the layout that measured
   499px at 1440px, which is fine here because the fold is no longer the
   binding constraint at tablet heights. */
@media (max-width: 1080px) {
  .start__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .start__intro { grid-column: 1 / -1; max-width: 62ch; }
  /* Step 1 now starts a row instead of following the proposition, so its rule
     would hang off the left edge of the band with nothing to divide. (It
     currently lands just outside the viewport, which is luck, not design.) */
  .start__grid > .start__step:nth-child(2) {
    padding-left: 0;
    margin-left: 0;
    border-left: 0;
  }
}

@media (max-width: 640px) {
  /* Fully stacked. Step 1 stays first: "where can I race" is the question a
     newcomer actually arrives with. */
  .start__grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
  /* A vertical rule means nothing in a single column; the steps are separated
     by the gap and their own numbers instead. */
  .start__step { padding-left: 0; margin-left: 0; border-left: 0; }
  /* These two are standalone links on their own line, not links inside a
     sentence, so on touch they get the project's --tap-min like any other
     control. Measured 19px and 22px before this. */
  .start__learn,
  .start__more {
    display: inline-flex;
    align-items: center;
    /* inline-flex collapses the whitespace before the arrow span, so the gap
       puts it back. */
    gap: var(--space-1);
    min-height: var(--tap-min);
  }
  /* Stacked one per line, each needs room to be tapped without hitting its
     neighbour. The padding IS the separation, so the flex gap goes to zero
     rather than paying for the same space twice. */
  .start__asideline { flex-direction: column; gap: 0; }
  .start__asideline a { padding-block: var(--space-2); }
  .start__head { font-size: 26px; }
  .start__lede { font-size: 16px; }
  /* Full-width button under a full-width select, rather than a narrow stub
     squeezed beside it on a phone. */
  .start__findrow { flex-wrap: wrap; }
  .start__select { flex: 1 1 100%; }
  .start__go { flex: 1 1 100%; }
}
/* --------------------------------------- the authenticated band (.start--me)
 * Same navy band, same tokens, same width as the anonymous onboarding band --
 * a racer moving between logged-out and logged-in must not feel they changed
 * site. What changes is the internal structure: a stat line wants to be
 * horizontal, so this is three short rows rather than three prose columns.
 *
 * It is a compact personal dashboard and is allowed to be one. The rule it
 * answers to is space, not category: everything here has to earn its height,
 * because the height it takes comes off the leaderboard's peek above the fold.
 * verify-homepage.js enforces that as a number (<= 380px at desktop) rather
 * than leaving it to judgement.
 */
.start--me .container > * + * { margin-top: var(--space-4); }

/* Two columns from 641px up: the comparison table on the left, the ways onward
   on the right. Before this the table's name column ran to 865px of empty navy
   while the band grew downwards -- the width was already there, it just was
   not being spent. One column on a phone, in source order. */
.me__grid { display: grid; gap: var(--space-4); }
/* Capped so the numbers stay next to the names they belong to, and so the
   Buddies line beneath lines up with the table's right edge. Left to fill the
   column, the name cell ran to ~330px and each row became two things at
   opposite ends of a stripe -- the opposite of reading across. Wider than the
   phone viewport, so it does nothing there. */
.me__main { max-width: 30rem; }
.me__main > * + *,
.me__aside > * + * { margin-top: var(--space-3); }
@media (min-width: 641px) {
  .me__grid {
    /* The left column is the table's own max-width, not a fraction: the table
       is capped at 30rem, so a 1.2fr left column was reserving ~220px of navy
       nobody could use while the right column wrapped its links to a second
       line. Everything left over goes to the right, which is the column that
       actually varies. */
    grid-template-columns: minmax(0, 30rem) minmax(0, 1fr);
    gap: var(--space-4) var(--space-6);
    align-items: start;
  }
}

/* The identity line: greeting, NASTAR ID and Log out on one baseline, grouped
   at the left. They belong together -- space-between put the logout 800px away
   from the name it applies to. */
.me__top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-5);
}
/* Hugs the greeting above it. The season label is a direct child of the
   container now that the ID moved up into the identity line, so it needs to
   beat `.start--me .container > * + *`'s 16px rhythm on specificity. */
.start--me .container > .me__seasonlabel { margin-top: var(--space-1); }
.me__seasonlabel {
  margin: var(--space-1) 0 0;
  color: var(--nastar-gold);
  font: 700 12px/1.2 var(--font-heading);
  letter-spacing: .12em;
  text-transform: uppercase;
}
/* The NASTAR ID. It was 13px muted grey alone at the far right, labelled
   "NASTAR #", and was easy to miss -- and it is the identifier a racer is asked
   for at a resort and logs in with. */
.me__id {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
  white-space: nowrap;
}
.me__idlabel {
  color: rgba(255,255,255,.65);
  font: 600 11px/1 var(--font-body);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.me__idval {
  color: var(--white);
  font: 700 20px/1 var(--font-heading);
  letter-spacing: .04em;
}
/* Deliberately a quiet text link, not a control. The shared account bar above
   already carries a LOGOUT on every page of both sites; this repeats it because
   that bar sits above the carousel and is as easy to overlook as the ID was,
   but it must never look like one of the band's own actions. */
.me__logout {
  flex: 0 0 auto;
  color: rgba(255,255,255,.8);
  font-size: 14px;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.me__logout:hover { color: var(--nastar-gold); }

/* --------------------------------------------------- the comparison table
 * The racer's own season, then up to three buddies', in one set of columns.
 * The whole value is reading DOWN a column, so every cell in it is aligned on
 * the same grid and the numerals are tabular -- a proportional 1 is narrower
 * than a 4 and quietly destroys the alignment this exists for.
 *
 * The card treatment this replaced used 30px numerals in a five-column grid.
 * It measured 80px at desktop and wrapped to two rows (131px) at 390px and
 * three (187px) at 360px, which is what made the band too tall on a phone.
 * The whole table now costs less than the old strip did.
 */
.me__compare {
  width: 100%;
  margin: 0;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.me__compare th,
.me__compare td {
  padding: 5px var(--space-3) 5px 0;
  text-align: right;
  white-space: nowrap;
}
/* The name column carries the row and takes whatever is left. */
.me__compare th[scope="row"],
.me__compare thead th:first-child {
  width: 99%;
  padding-right: var(--space-4);
  text-align: left;
  white-space: normal;
}
.me__compare thead th {
  border-bottom: 1px solid rgba(255,255,255,.22);
  color: rgba(255,255,255,.72);
  font: 600 12px/1.2 var(--font-body);
  letter-spacing: .04em;
}
.me__compare tbody th,
.me__compare tbody td {
  border-bottom: 1px solid rgba(255,255,255,.12);
  font: 400 17px/1.25 var(--font-body);
  color: rgba(255,255,255,.92);
}
.me__compare tbody tr:last-child th,
.me__compare tbody tr:last-child td { border-bottom: 0; }
.me__compare tbody th { font-weight: 600; }
/* The racer's own row is the anchor everything else is read against, so it is
   the one row in white at full weight. */
.me__row--self th,
.me__row--self td {
  color: var(--white);
  font-weight: 700;
  border-bottom-color: rgba(255,255,255,.22);
}
/* Buddy names are links into their race record -- underlined, because on this
   ground colour alone is not a link signal (project instructions, "Links are
   how racers explore the data"). */
.me__compare tbody th a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.me__compare tbody th a:hover { color: var(--nastar-gold); }

/* The Buddies line under the table: label left, action right, one line. */
.me__buddies {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  font-size: 14px;
  color: rgba(255,255,255,.8);
}
.me__buddieslabel { font-weight: 600; }
/* The invitation runs as a sentence rather than a label/action pair, so it
   reads as an offer instead of a heading over an empty table. */
.me__buddies--invite { justify-content: flex-start; font-size: 15px; }
.me__buddies--invite strong { color: var(--white); }

/* Racer account actions -- the quietest thing in the band. Small, wrapping,
   underlined because they are links on a coloured ground where colour alone is
   not a link signal (project instructions, "Links are how racers explore the
   data"). They sit in the right-hand column, which was ~92px shorter than the
   left one, so
   most of their height comes out of space the band was already paying for:
   measured 351 -> 363px at desktop, and 88px on a phone. */
.me__tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.me__tools a {
  color: rgba(255,255,255,.85);
  font-size: 14px;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.me__tools a:hover { color: var(--nastar-gold); }
/* Every tool link wraps its label in a span so the label and the qualifier are
   two real flex items. Left as a bare text node the label became an anonymous
   flex item that wrapped INDEPENDENTLY of the note, interleaving them into
   "Register a family (signs / member you out)" at 360px. */
.me__tools a { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); }
/* The qualifier on "Register a family member". Muted and smaller so it reads as
   a warning about the link rather than as part of its name, and it never
   splits: at narrow widths it drops whole onto its own line. */
.me__toolnote { color: rgba(255,255,255,.6); font-size: 12px; white-space: nowrap; }

/* The bridge into the leaderboard. Gold, because it is the one line in the
   band asking the racer to look at something else on the page. */
.me__bridge { margin: 0; font-size: 15px; }
.me__bridge a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--nastar-gold);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.me__bridge a:hover { color: var(--white); }

.me__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-5);
}
.me__where { margin: 0; font-size: 15px; color: rgba(255,255,255,.88); }
.me__where strong { color: var(--white); }
/* The invitation back, for a racer whose most recent season is not this one.
   Gold because it is the one thing on the band asking them to do something. */
.me__where .me__nudge { display: inline-block; color: var(--nastar-gold); }
.me__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); }
.me__link { color: var(--white); font-size: 14px; text-decoration: underline; }
.me__link:hover { color: var(--nastar-gold); }

/* The selector is a quiet afterthought for a racer who is mid-season, and the
   lead action for one who has not raced this season yet. */
.me__find { max-width: 520px; }
.me__find--lead { max-width: 100%; }
.me__find--lead .start__findrow { max-width: 520px; }

@media (max-width: 640px) {
  /* The table has to survive 360px, where the container leaves 328px. Division
     is the column that goes: it is the only word-valued one, it is the widest,
     and for the racer themselves the bridge sentence below already names their
     division. The four numeric columns stay, because they are the comparison.
     Measured at 360px: name 100px + four columns inside the remainder. */
  .me__c-div { display: none; }
  .me__compare th,
  .me__compare td { padding-right: var(--space-2); font-size: 15px; }
  .me__compare thead th { font-size: 11px; }
  .me__compare tbody th,
  .me__compare tbody td { font-size: 15px; }
  .me__compare th[scope="row"],
  .me__compare thead th:first-child { padding-right: var(--space-2); }

  /* "Your badges" and the buddies action sit beside a 44px button, so they
     need the same tap height; measured 22px before this. */
  .me__link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-height: var(--tap-min);
  }
  .me__buddies { justify-content: flex-start; }
  .me__foot { flex-direction: column; align-items: flex-start; }
  .me__actions { width: 100%; }
  .me__bridge a { min-height: var(--tap-min); }
  /* A fixed two-column grid rather than a wrapping row. Left to wrap, the four
     labels landed two/one/one at 360px -- three rows, 132px -- because
     "Register a family member" is wide enough to strand the one after it. Two
     columns is deterministic at every phone width: always two rows, 88px, with
     a long label wrapping inside its own cell instead of pushing the next one
     down. Same 44px tap height the rest of the band's links get. */
  .me__tools {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 var(--space-3);
  }
  .me__tools a { align-items: center; min-height: var(--tap-min); }
  /* Every block in the band is closer together on a phone, where the band is
     one column and the leaderboard is a long way down. Tightened again on
     2026-08-27 when the identity line and the account actions landed: four
     top-level children at 12px each was 36px of rhythm inside a band that is
     already most of a phone screen. */
  .start--me .container > * + * { margin-top: var(--space-2); }
  /* The NASTAR ID rides with the season label instead of taking its own row. */
  /* Left to wrap naturally, the ID fitted beside the greeting and pushed Log
     out onto a third line of its own -- 90px for three short things. */
  .me__top {
    flex-direction: row;
    flex-wrap: wrap;
    /* Centre, not baseline: Log out is a 44px tap target here, and baseline
       alignment made the line as tall as that box PLUS the offset needed to
       line its text up with the ID's. */
    align-items: center;
    gap: var(--space-1) var(--space-4);
  }
  /* The greeting takes its own line so the ID and Log out share the next one. */
  .me__top .start__head { flex: 1 1 100%; }
  /* Log out is a tap target here like every other link in the band. */
  .me__logout { display: inline-flex; align-items: center; min-height: var(--tap-min); }
  .me__idval { font-size: 18px; }
  /* The state selector and its button share a row here, unlike the anonymous
     band's, which stays full-width. This one is a quiet third action under a
     band that now carries a comparison table; it does not get 115px. */
  .me__find .start__findrow { flex-wrap: nowrap; }
  .me__find .start__select { flex: 1 1 auto; min-width: 0; }
  .me__find .start__go { flex: 0 0 auto; }
}
/* ============================================================ resorts & clubs
 * NASTAR's second audience. Navy like the band, against the white leaderboard
 * above and the grey Featured Racer below -- the page's existing way of saying
 * "this block is for a different kind of visitor". It renders in every auth
 * state, which is the fix for the thing it replaces: a single line in the
 * anonymous band's aside that vanished the moment anyone logged in.
 */
.hosts {
  background: var(--nastar-blue-dark);
  color: var(--white);
  /* A hard gold seam at the top. In the ANONYMOUS order this section sits
     directly under the navy onboarding band, and without it the two run
     together into one continuous blue area -- which loses the whole point,
     because a resort operator scanning the page has to see where the racers'
     block ends and theirs begins. It reads as deliberate in the logged-in order
     too, where the section follows the white leaderboard. */
  border-top: 3px solid var(--nastar-gold);
  /* Tighter than `.section`'s 48px. This block has to be unmissable, not big:
     it sits below a leaderboard that is over 1,000px tall, so every pixel it
     does not spend is a pixel closer to being on the same screen as the thing
     above it. */
  padding-block: var(--space-6);
}
.hosts__head {
  margin: 0;
  color: var(--white);
  font: 700 30px/1.15 var(--font-heading);
}
.hosts__lede {
  margin: var(--space-2) 0 var(--space-5);
  font-size: 17px;
  color: rgba(255,255,255,.9);
}
/* Two equal paths: neither audience is the secondary one. Equal columns are
   also what makes the split readable at a glance -- an unequal grid would read
   as a main action with a footnote. */
.hosts__paths {
  display: grid;
  gap: var(--space-5) var(--space-6);
}
@media (min-width: 721px) {
  .hosts__paths { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Heading and call to action, nothing else. The explanatory paragraph each
   tile used to carry restated what the destination says on arrival; removing it
   is what makes the higher anonymous placement affordable for the racers who
   scroll past it. Row at desktop -- with two short items a column left a tall
   tile mostly empty. */
.hosts__path {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-5);
  padding: var(--space-4) var(--space-5);
  border: 1px solid rgba(255,255,255,.28);
  border-radius: var(--radius);
  background: rgba(255,255,255,.05);
}
/* The visitor's own words, at heading weight: "We want to offer NASTAR" /
   "We already run NASTAR" is instantly sortable in a way that a description of
   each programme is not. */
.hosts__pathhead {
  margin: 0;
  color: var(--nastar-gold);
  font: 700 21px/1.2 var(--font-heading);
}

@media (max-width: 640px) {
  .hosts__head { font-size: 26px; }
  .hosts__lede { font-size: 16px; margin-bottom: var(--space-5); }
  .hosts__path { padding: var(--space-4); }
  .hosts__pathhead { font-size: 19px; }
  /* Stacked and full-width on a phone, like the band's own buttons. */
  .hosts__path { flex-direction: column; align-items: stretch; }
  .hosts__path .btn-action { text-align: center; }
}
