/* @source website/src/css/00-tokens.css */
/* ============================================================================
   THE SULLIVANS DIVISION USNSCC - DESIGN TOKENS
   Single source of truth. No component may hard-code a value that lives here.
   Direction (ADR-007): institutional editorial restraint. Photography carries
   the emotion; type and grid carry the credibility.
   Contrast (ADR-008): every foreground/background pair below meets WCAG 2.2 AA.
   ========================================================================= */

:root {
  /* --- Typography -----------------------------------------------------------
     Self-hosted variable faces, no third-party request (better CSP + privacy).
     Display: Libre Franklin, the American civic grotesque - poster authority.
     Text:    Public Sans, the U.S. Web Design System typeface - the face of
              federal government sites, which is what a congressionally
              chartered program should read like. */
  --font-display: "Libre Franklin", "Libre Franklin Fallback", Arial, Helvetica, sans-serif;
  --font-text: "Public Sans", "Public Sans Fallback", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Poster face, scoped to the marines-style run on the homepage (76-poster.css).
     Overpass is Red Hat's Highway Gothic revival, SIL OFL, the same lineage as
     the licensed Expressway that marines.com uses. */
  --font-poster: "Overpass", "Libre Franklin", "Libre Franklin Fallback", Arial, Helvetica, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  /* Fluid type scale, 1.25 minor third at mobile opening to 1.333 at desktop.
     Every step pairs a size with the line-height that belongs to it. */
  --text-2xs: 0.6875rem;   --leading-2xs: 1.45;
  --text-xs: 0.775rem;     --leading-xs: 1.5;
  --text-sm: 0.875rem;     --leading-sm: 1.55;
  --text-base: 1rem;       --leading-base: 1.65;
  --text-md: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);   --leading-md: 1.6;
  --text-lg: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);     --leading-lg: 1.45;
  --text-xl: clamp(1.5rem, 1.3rem + 1vw, 2rem);           --leading-xl: 1.3;
  --text-2xl: clamp(1.875rem, 1.5rem + 1.9vw, 2.75rem);   --leading-2xl: 1.18;
  --text-3xl: clamp(2.25rem, 1.7rem + 2.8vw, 3.75rem);    --leading-3xl: 1.08;
  --text-4xl: clamp(2.75rem, 1.9rem + 4.2vw, 5rem);       --leading-4xl: 1.02;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-black: 800;

  --tracking-tight: -0.02em;
  --tracking-snug: -0.011em;
  --tracking-normal: 0;
  --tracking-wide: 0.04em;
  --tracking-caps: 0.12em;

  /* Readable measure. Institutional copy stays inside 65-75 characters. */
  --measure: 68ch;
  --measure-narrow: 54ch;
  --measure-wide: 82ch;

  /* --- Color ---------------------------------------------------------------
     Semantic names only. Never reference a raw ramp value in a component. */
  --navy-950: #050f1f;
  --navy-900: #071326;
  --navy-800: #0a1d3a;
  --navy-700: #0c2b5a;
  --navy-600: #124178;
  --blue-500: #1d5cb8;
  --blue-100: #e7f0ff;
  --blue-050: #f2f7ff;

  --red-800: #9c0e26;
  --red-700: #c41230;
  --red-600: #d81c3c;
  --red-100: #fbe9ec;  /* light red ground, About comparison (comment 53) */

  --gold-600: #a97f16;
  --gold-500: #d6a938;
  --gold-200: #f4e3b6;

  --gray-900: #12181f;
  --gray-700: #38424f;
  --gray-600: #4c5766;  /* 7.0:1 on --paper. The AA-safe muted text value. */
  --gray-400: #8b95a3;
  --gray-200: #d8dee6;
  --gray-100: #eaeef3;
  --paper: #f6f8fb;
  --white: #ffffff;

  /* Semantic surface + text roles */
  --surface: var(--paper);
  --surface-raised: var(--white);
  --surface-sunken: var(--gray-100);
  /* The product page's photograph ground and option tiles: a warm neutral,
     as the Patagonia reference, so no product shot reads blue (ruling 12). */
  --surface-product: #f1f0ee;
  --surface-inverse: var(--navy-900);
  --surface-inverse-raised: var(--navy-800);

  --ink: var(--gray-900);           /* 16.1:1 on --paper */
  --ink-secondary: var(--gray-700); /* 9.4:1  on --paper */
  --ink-muted: var(--gray-600);     /* 7.0:1  on --paper - AA at every size */
  --ink-inverse: var(--white);
  --ink-inverse-muted: #c3ccd8;     /* 9.6:1 on --navy-900 */

  --accent: var(--red-700);         /* 7.4:1 on white. Emphasis and CTA only. */
  --accent-hover: var(--red-800);
  --accent-on-dark: #ff6b83;        /* 5.6:1 on --navy-900 */
  --honor: var(--gold-500);         /* Rare. Honors and highlights. */
  --honor-on-light: #8f6a10;        /* 4.96:1 on white. Raw gold is 2.19:1 and fails AA. */

  --line: rgba(10, 29, 58, 0.14);
  --line-strong: rgba(10, 29, 58, 0.28);
  --line-inverse: rgba(255, 255, 255, 0.18);
  /* Legacy aliases. legacy.css still references these; migrate and delete. */
  --blue-700: var(--navy-600);
  --muted: var(--ink-muted);

  --focus-ring: var(--blue-500);
  --focus-ring-inverse: var(--gold-500);

  /* --- Space ---------------------------------------------------------------
     One 4px-based scale. Section rhythm is deliberately varied by choosing
     different steps, never by inventing new values. */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs: 0.75rem;
  --space-sm: 1rem;
  --space-md: 1.5rem;
  --space-lg: 2rem;
  --space-xl: 3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;
  --space-4xl: 8rem;
  --section-y: clamp(3.5rem, 8vw, 7rem);
  --section-y-tight: clamp(2.5rem, 5vw, 4rem);
  --gutter: clamp(1.125rem, 4vw, 3rem);

  /* --- Layout -------------------------------------------------------------- */
  --max: 1520px;         /* widened 2026-09-27: desktop sides read as empty at 1180 */
  --max-wide: 1760px;
  --max-text: 46rem;

  /* --- Radius, border, shadow ---------------------------------------------- */
  --radius-xs: 3px;
  --radius-sm: 5px;
  --radius: 8px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  /* Ghost button ground. Transparent on light surfaces; the inverted-surface
     block in 02-base.css gives it a translucent white so the button still
     reads over the hero video. */
  --button-ghost-bg: transparent;

  --border: 1px solid var(--line);
  --border-strong: 1px solid var(--line-strong);

  --shadow-sm: 0 1px 2px rgba(7, 19, 38, 0.08), 0 2px 6px rgba(7, 19, 38, 0.06);
  --shadow: 0 24px 70px rgba(7, 19, 38, 0.18);
  --shadow-lg: 0 32px 90px rgba(7, 19, 38, 0.24);
  --shadow-header: 0 12px 34px rgba(0, 0, 0, 0.22);

  /* --- Z-index ladder -------------------------------------------------------
     Named, ordered, and total. z-index-by-guess contributed to BUG-001, so a
     raw numeric z-index anywhere in the stylesheet now fails the gate. */
  --z-behind: -2;
  --z-below: -1;
  --z-base: 0;
  --z-raised: 1;
  --z-raised-2: 2;
  --z-sticky: 100;
  --z-announce: 200;
  --z-header: 300;
  --z-nav-drawer: 400;
  --z-float: 500;
  --z-overlay: 700;
  --z-modal: 800;
  --z-drawer: 850;
  --z-toast: 900;
  --z-skip-link: 1000;

  /* --- Motion ---------------------------------------------------------------
     Minimal and functional (design-system.md). Nothing bounces. */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --duration-fast: 130ms;
  --duration: 200ms;
  --duration-slow: 320ms;

  /* Scroll entrances, copied from occasionswny.com on Camilo's instruction
     (ADR-036), made quicker after his 2026-09-27 review. */
  --ease-scroll: cubic-bezier(0.25, 0.46, 0.45, 0.94);
  --scroll-rise: 160px;

  /* Runtime-controlled. main.js owns this; nothing else may set it. */
  --header-height: 84px;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0.01ms;
    --duration: 0.01ms;
    --duration-slow: 0.01ms;
  }
}


/* @source website/src/css/01-fonts.css */
/* ============================================================================
   SELF-HOSTED VARIABLE FONTS (ADR-007)
   Served from our own origin: no third-party request, which keeps the CSP tight
   and sends no visitor data to a font CDN. Both families are SIL Open Font
   License 1.1, which permits self-hosting and redistribution.
   ========================================================================= */

/* Libre Franklin - display. Chosen by Camilo 2026-09-01 over Newsreader and
   Source Serif 4. The unit's voice is a recruiting poster, not an editorial
   page, and Franklin is the American civic/poster grotesque. It also happens to
   be 29 KB against Newsreader's 132 KB. */
@font-face {
  font-family: "Libre Franklin";
  font-style: normal;
  font-weight: 100 900;
  font-stretch: normal;
  font-display: swap;
  src: url("./assets/fonts/libre-franklin-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Overpass - the poster face for the homepage recruiting run. Red Hat's
   revival of the FHWA Highway Gothic series, SIL OFL, one variable file. */
@font-face {
  font-family: "Overpass";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./assets/fonts/overpass-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Public Sans - text and interface. The U.S. Web Design System typeface. */
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./assets/fonts/public-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("./assets/fonts/public-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Public Sans";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url("./assets/fonts/public-sans-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================================
   METRIC-MATCHED FALLBACKS
   font-display: swap paints a fallback first, then swaps. On a slow connection
   the real face cannot beat first paint no matter how early it is preloaded, so
   the only way to stop the swap moving the page is to make the fallback occupy
   the same space.

   Measured in-browser against the real faces at 100px, same sample string:
     Public Sans vs system-ui   112.03%   <- this was the whole problem
     Public Sans vs Arial       103.49%
     Libre Franklin vs Arial   100.61%   <- remeasured 2026-09-01 on the swap

   system-ui being 12% narrower changed how many lines the lede and the button
   row occupied, which moved everything below them. size-adjust corrects the
   width so the line count matches; our line-heights come from tokens, so the
   line box height is already fixed independently of the font's own metrics.
   ========================================================================= */
@font-face {
  font-family: "Public Sans Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 103.49%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Libre Franklin Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 100.61%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}


/* @source website/src/css/02-base.css */
/* ============================================================================
   BASE - element defaults built only from tokens.
   ========================================================================= */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-height) + var(--space-sm));
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--text-base);
  line-height: var(--leading-base);
  letter-spacing: var(--tracking-normal);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
video,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

/* Focus is always visible and never removed. WCAG 2.2 AA (ADR-008). */
:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

/* --- Headline system -------------------------------------------------------
   Display serif, tight tracking, deliberate scale. This is where the site's
   credibility is earned, not in decoration. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--ink);
  text-wrap: balance;
  margin: 0 0 var(--space-md);
}

h1 { font-size: var(--text-3xl); line-height: var(--leading-3xl); }
h2 { font-size: var(--text-2xl); line-height: var(--leading-2xl); }
h3 { font-size: var(--text-lg);  line-height: var(--leading-lg); letter-spacing: var(--tracking-snug); }
h4 { font-size: var(--text-md);  line-height: var(--leading-md); letter-spacing: var(--tracking-snug); }

h5, h6 {
  font-family: var(--font-text);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-2xs);
}

p {
  margin: 0 0 var(--space-md);
  max-width: var(--measure);
  text-wrap: pretty;
}

/* The eyebrow: small, spaced, uppercase. Used instead of decorative badges. */
.eyebrow {
  font-family: var(--font-text);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-sm);
}

.lede {
  font-size: var(--text-md);
  line-height: var(--leading-md);
  color: var(--ink-secondary);
  max-width: var(--measure);
}

/* --- Utilities ------------------------------------------------------------- */
.u-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.u-measure { max-width: var(--measure); }
.u-measure-narrow { max-width: var(--measure-narrow); }

.skip-link {
  position: fixed;
  left: var(--space-sm);
  top: var(--space-xs);
  z-index: var(--z-skip-link);
  transform: translateY(-160%);
  background: var(--white);
  color: var(--navy-900);
  padding: var(--space-2xs) var(--space-xs);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  font-weight: var(--weight-semibold);
  transition: transform var(--duration) var(--ease-out);
}

.skip-link:focus {
  transform: translateY(0);
}

/* --- Inverted surfaces ------------------------------------------------------
   Dark sections redefine the ink ROLES rather than overriding colour on each
   element inside them. Anything written in terms of var(--ink) is then correct
   on a dark background automatically, including components added later.

   This is the fix for a real regression: .hero set `color: white` and relied on
   h1 inheriting it. An explicit `h1 { color: var(--ink) }` beats inheritance no
   matter how low its specificity, so the hero headline turned near-black on a
   dark video. Redefining the token fixes the whole class of bug at once.

   Custom properties resolve where they are declared, so --muted is redefined
   here too; inheriting the alias alone would carry the light-surface value in. */
/* Every dark surface belongs in this list. Two were missing (.callout and
   .chart-section) and had per-element `color: white` overrides instead, which is
   the exact pattern the block below exists to replace: it also meant --focus-ring
   stayed on its light-surface value over navy, at 2.9:1. */
.u-on-dark,
.hero,
.announce-bar,
.site-header,
.site-footer,
.join-plate,
.callout,
.chart-section,
.rh-closing,
.lightbox,
.gal-viewer,
/* The poster run of 2026-09-26. Each also carries u-on-dark in the markup and is listed
   here so the roles do not depend on the class surviving an edit. */
.poster-cta,
.film,
.film-frame,
.creed,
.route-panel,
.train-band,
/* Covered at runtime only because its markup happens to carry u-on-dark. Listed
   so the styling does not depend on someone remembering the utility class. */
.about-close,
/* The pressed topic chip on Resources (round 3). */
.rh-chip[aria-pressed="true"],
/* The receipt printer on the cart page after payment: decorative and holds nothing focusable. */
.receipt-terminal {
  --ink: var(--white);
  --ink-secondary: var(--ink-inverse-muted);
  --ink-muted: var(--ink-inverse-muted);
  --muted: var(--ink-inverse-muted);
  --accent: var(--accent-on-dark);
  --button-ghost-bg: rgba(255, 255, 255, 0.14);
  --line: var(--line-inverse);
  --line-strong: rgba(255, 255, 255, 0.42);
  /* The focus ring is an ink role too: gold reads 8.5:1 on navy and 2.1:1 on
     white, so it has to swap with the surface like every other role here. */
  --focus-ring: var(--focus-ring-inverse);
  color: var(--ink);
}

/* A light island inside a dark section inherits the inverted roles, so its body
   copy turns #c3ccd8 on white: 1.62:1. The three .chart-card panels did exactly
   that the moment .chart-section joined the list above. This restores the
   light-surface roles for any such island rather than re-colouring each element,
   which is the same argument as the block above, pointed the other way. */
.u-on-light,
.chart-card {
  --ink: var(--gray-900);
  --ink-secondary: var(--gray-700);
  --ink-muted: var(--gray-600);
  --muted: var(--ink-muted);
  --accent: var(--red-700);
  --button-ghost-bg: transparent;
  --line: rgba(10, 29, 58, 0.14);
  --line-strong: rgba(10, 29, 58, 0.28);
  --focus-ring: var(--blue-500);
  color: var(--ink);
}

/* Utility spacing + the classes that replaced the last inline style attributes,
   so the CSP can ship without style-src-attr 'unsafe-inline'. */
.u-mt-md { margin-top: var(--space-md); }
.u-mt-lg { margin-top: var(--space-lg); }
.map-embed { border: 0; border-radius: var(--radius); }


/* @source website/src/css/50-legacy.css */
/* ============================================================================
   LEGACY STYLESHEET
   The original hand-written CSS, kept intact and appended after the token,
   font, and base layers so rule order and cascade are unchanged. Rules move
   out of here into real components as pages are rebuilt; nothing new is
   added here.
   ========================================================================= */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  font-weight: 800;
}

.brand span {
  display: grid;
  line-height: 1.1;
}

.brand small {
  margin-top: 5px;
  color: rgba(255, 255, 255, 0.78);
  font-size: 0.76rem;
  font-weight: 700;
  text-transform: uppercase;
}

.primary-nav {
  display: flex;
  align-items: center;
  gap: 6px;
}

.primary-nav a {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius);
  padding: 0 13px;
  color: rgba(255, 255, 255, 0.88);
  font-size: 0.92rem;
  font-weight: 750;
}

.primary-nav a:hover,
.primary-nav a:focus-visible,
.primary-nav a[aria-current="page"] {
  background: rgba(255, 255, 255, 0.12);
  color: var(--white);
}

/* You are here: a gold box with a soft glow on the current page (2026-09-27). */
.primary-nav a[aria-current="page"] {
  box-shadow: inset 0 0 0 1.5px var(--gold-500), 0 0 14px rgba(214, 169, 56, 0.35);
}

.primary-nav .nav-login {
  margin-left: 6px;
  background: var(--red-700);
  color: var(--white);
}

.nav-toggle {
  display: none;
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.1);
  color: var(--white);
}

.nav-toggle span {
  display: block;
  width: 22px;
  height: 2px;
  margin: 5px auto;
  background: currentColor;
}

.hero {
  position: relative;
  /* Full screen on load, review round 1 comment 4. svh, not vh: on iOS vh is
     the tall viewport, so the hero would sit under the URL bar and the CTA
     would be off screen until the user scrolls. */
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  align-items: end;
  overflow: hidden;
  color: var(--white);
  background: var(--navy-950);
}

.hero-media,
.hero-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero-media {
  object-fit: cover;
  opacity: 0.9;
  filter: brightness(1.1);
}

.hero-overlay {
  background:
    linear-gradient(90deg, rgba(7, 19, 38, 0.82) 0%, rgba(7, 19, 38, 0.44) 50%, rgba(7, 19, 38, 0.08) 100%),
    linear-gradient(0deg, rgba(7, 19, 38, 0.72) 0%, rgba(7, 19, 38, 0) 55%),
    linear-gradient(rgba(180, 20, 40, 0.1), rgba(180, 20, 40, 0.1));
}

.hero-content {
  position: relative;
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto 0 clamp(24px, 6vw, 80px);
  padding: 160px 0 90px;
  max-width: 780px;
}

.hero h1,
.page-hero h1 {
  max-width: 840px;
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(2.6rem, 5.8vw, 5.8rem);
  line-height: 0.95;
  letter-spacing: 0;
  white-space: nowrap;
}

.hero-copy {
  max-width: 670px;
  margin: 24px 0 0;
  color: rgba(255, 255, 255, 0.86);
  font-size: clamp(1.05rem, 2vw, 1.24rem);
}

.hero-subtitle {
  margin: 12px 0 0;
  color: rgba(255, 255, 255, 0.9);
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(1.45rem, 3vw, 2.45rem);
  font-style: italic;
}

.hero-actions,
.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.hero-actions {
  margin-top: 34px;
}

.button {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--radius);
  padding: 0 18px;
  font: inherit;
  font-weight: 850;
  cursor: pointer;
  transition:
    transform 160ms ease,
    box-shadow 160ms ease,
    background 160ms ease;
}

.button:hover,
.button:focus-visible {
  transform: translateY(-1px);
}

.button.primary {
  background: var(--red-700);
  color: var(--white);
  box-shadow: 0 14px 28px rgba(196, 18, 48, 0.28);
}

/* Token-driven so it is correct on BOTH surfaces. It used to hardcode white
   text on translucent white, which meant every light-background page needed its
   own override; three of those had accumulated and a fourth was about to. */
.button.secondary {
  background: var(--button-ghost-bg);
  color: var(--ink);
  border: 1px solid var(--line-strong);
}

.button.secondary:hover,
.button.secondary:focus-visible {
  border-color: var(--ink);
}

.section {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: clamp(72px, 9vw, 116px) 0;
}

.intro-section {
  padding-top: clamp(42px, 5vw, 66px);
  padding-bottom: clamp(34px, 5vw, 56px);
}

.intro-top {
  display: grid;
  grid-template-columns: 1fr minmax(280px, 420px);
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
  margin-bottom: clamp(28px, 4vw, 48px);
}

.section-heading {
  max-width: 730px;
}

h2 {
  margin: 0;
  color: var(--navy-950);
  font-family: Georgia, "Times New Roman", serif;
  font-size: clamp(2rem, 4vw, 3.6rem);
  line-height: 1.04;
}

h3 {
  margin: 0 0 10px;
  color: var(--navy-900);
  font-size: 1.08rem;
  line-height: 1.25;
}

p {
  color: var(--muted);
}

.page-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr);
  gap: clamp(28px, 5vw, 70px);
  align-items: center;
}

/* The "what cadets gain" panel was deleted in review round 1 (comment 15), so
   the intro is a single measured column of prose rather than a two-up. */
.intro-grid {
  display: block;
  max-width: var(--measure-wide);
}

.intro-copy p:first-child {
  margin-top: 0;
  color: var(--navy-900);
  font-size: 1.15rem;
}

.media-band {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: min(var(--max-wide), calc(100% - 36px));
  margin: 14px auto 0;
}

.media-band figure {
  position: relative;
  aspect-ratio: 4 / 3;
  min-height: 0;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--navy-900);
}

.media-band img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 420ms ease;
}

.media-band figcaption {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 16px;
  border-radius: var(--radius);
  background: rgba(7, 19, 38, 0.76);
  color: var(--white);
  padding: 12px 14px;
}

.media-band figcaption span {
  display: block;
  color: var(--gold-500);
  font-size: 0.76rem;
  font-weight: 950;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.media-band figcaption strong {
  display: block;
  margin-top: 4px;
  color: var(--white);
  font-size: 0.98rem;
  line-height: 1.25;
}

.media-band figure:hover img,
.media-band figure:focus-within img {
  transform: scale(1.05);
}

.recruit-section {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  gap: clamp(26px, 5vw, 60px);
  align-items: start;
}

.recruit-grid {
  display: grid;
  gap: 14px;
}

.recruit-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "title action"
    "text action";
  column-gap: 18px;
  row-gap: 6px;
  align-items: center;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--white);
  box-shadow: 0 18px 46px rgba(7, 19, 38, 0.08);
}

.recruit-card h3 {
  grid-area: title;
  margin: 0;
  font-size: clamp(1.2rem, 1.6vw, 1.45rem);
}

.recruit-card p {
  grid-area: text;
  margin: 0;
  color: var(--ink);
}

.recruit-card a {
  grid-area: action;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius);
  background: var(--navy-900);
  color: var(--white);
  padding: 0 14px;
  font-weight: 900;
  white-space: nowrap;
}

.callout {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 24px;
  padding: clamp(34px, 5vw, 54px);
  border-radius: var(--radius);
  background: var(--navy-900);
}

.callout h2,
.callout p {
  color: var(--white);
}

.callout p {
  max-width: 740px;
  color: rgba(255, 255, 255, 0.78);
}

.join-callout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 0.58fr);
  align-items: center;
}

/* Manual edit, comment 38: he pushed the supporting line 11px down off the
   heading. Kept as spacing on the paragraph rather than a transform so the
   gap survives a reflow at any width. */
.join-callout p:last-of-type {
  margin-top: calc(var(--space-xs) + 11px);
}

.join-callout .button {
  min-height: 64px;
  width: min(100%, 280px);
  justify-self: center;
  font-size: 1.08rem;
}

.roadmap-page .site-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.cart-preview .button {
  width: 100%;
  margin-top: 8px;
}

.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 34px clamp(18px, 4vw, 48px);
  background: var(--navy-950);
  color: var(--white);
}

.site-footer p {
  margin: 4px 0 0;
  color: rgba(255, 255, 255, 0.66);
}

.site-footer a {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  color: rgba(255, 255, 255, 0.8);
  font-weight: 750;
}

/* ── Announcement Banner ── */
/* ── Nav CTA ── */
.nav-cta {
  margin-left: 4px;
  background: var(--gold-500) !important;
  color: var(--navy-950) !important;
  font-weight: 900;
  border-radius: var(--radius);
}

/* ── Hero Video ── */
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.9;
  filter: brightness(1.12) saturate(1.05);
}

.hero-fallback {
  display: none;
}

/* No src means the video was never worth its bytes here (see main.js), or it
   failed to load. Either way the hero still needs a background, so hide the
   video element and let the poster image behind it show through. */
.hero-video:not([src]),
.hero-video[src=""] {
  display: none;
}

.hero:has(.hero-video:not([src])) .hero-fallback,
.hero:has(.hero-video[src=""]) .hero-fallback {
  display: block;
}

/* ── Age Split Section ── */
.age-split-section {
  background: var(--paper);
}

.age-split-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 36px;
}

.age-card {
  padding: 36px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--white);
  box-shadow: 0 18px 46px rgba(7,19,38,0.08);
  position: relative;
}

.nlcc-card {
  border-top: 5px solid var(--blue-700);
}

.sea-card {
  border-top: 5px solid var(--red-700);
}

.age-badge {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 5px 14px;
  font-size: 0.76rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 14px;
}

.nlcc-card .age-badge {
  background: var(--blue-100);
  color: var(--blue-700);
}

.sea-card .age-badge {
  background: rgba(196,18,48,0.08);
  color: var(--red-700);
}

.age-card h3 {
  font-size: 1.45rem;
  color: var(--navy-950);
  margin: 0 0 4px;
}

.age-abbr {
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 16px;
}

.age-card > p:not(.age-abbr) {
  color: var(--muted);
  margin-bottom: 18px;
}

.age-card ul {
  list-style: none;
  margin: 0 0 28px;
  padding: 0;
  display: grid;
  gap: 10px;
}

.age-card li {
  padding-left: 22px;
  position: relative;
  color: var(--navy-900);
  font-weight: 700;
  font-size: 0.95rem;
}

.age-card li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 10px;
  height: 2px;
  background: var(--red-700);
}

.nlcc-card li::before { background: var(--blue-700); }

/* ── Where We Meet ── */
.where-grid {
  display: grid;
  grid-template-columns: minmax(280px, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(24px, 4vw, 48px);
  align-items: start;
  margin-top: 36px;
}

.where-info {
  display: grid;
  gap: 14px;
}

.where-card {
  padding: 22px 24px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 18px 46px rgba(7,19,38,0.08);
}

.where-card span {
  display: block;
  color: var(--red-700);
  font-size: 0.74rem;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 6px;
}

.where-card strong {
  display: block;
  color: var(--navy-900);
  font-size: 1rem;
  line-height: 1.4;
  margin-bottom: 8px;
}

/* A standalone card CTA, not a link inline in a sentence, so it gets a real
   target rather than 2.5.8's inline-link exception. */
.where-card a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--blue-700);
  font-weight: 850;
  font-size: 0.9rem;
}

.map-embed {
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 18px 46px rgba(7,19,38,0.12);
}

/* ── Footer Upgrade ── */
.site-footer {
  display: grid;
  grid-template-columns: 1fr auto auto;
  grid-template-areas:
    "brand nav social"
    "copy copy copy";
  gap: 20px 40px;
  padding: 40px clamp(18px, 4vw, 48px) 28px;
  background: var(--navy-950);
  color: var(--white);
}

.footer-brand {
  grid-area: brand;
  display: flex;
  align-items: center;
  gap: 12px;
}

.footer-brand img {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255,255,255,0.9);
  object-fit: contain;
  flex-shrink: 0;
}

.footer-brand strong {
  display: block;
  color: var(--white);
  font-size: 0.95rem;
}

.footer-brand p {
  margin: 3px 0 0;
  color: rgba(255,255,255,0.55);
  font-size: 0.8rem;
}

.footer-social {
  grid-area: social;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  padding-top: 4px;
}

.footer-social a {
  color: rgba(255,255,255,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.16);
  transition: background 160ms ease, color 160ms ease;
}

.footer-social a:hover {
  background: rgba(255,255,255,0.1);
  color: var(--white);
}

/* The global focus ring lives in 02-base.css and reads --focus-ring, which dark
   surfaces redefine. A hard-coded colour here overrode it site-wide and put a
   2.19:1 ring on every light page. Deleted 2026-08-26; the gate now bans it. */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition: none !important;
  }

  .hero-video {
    display: none;
  }

  .hero-fallback {
    display: block;
  }

  .hero {
    background:
      linear-gradient(rgba(7, 19, 38, 0.6), rgba(7, 19, 38, 0.6)),
      url("./assets/images/cadets-aboard-ship.webp") center / cover;
  }}

/* Below 1280px the nav is the header row plus the burger drawer. Those rules
   moved to 89-final-header.css (final UI round, 2026-11-06). */

@media (max-width: 940px) {
  .age-split-grid { grid-template-columns: 1fr; }
  .where-grid { grid-template-columns: 1fr; }
  .intro-top { grid-template-columns: 1fr; }
  .site-footer {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "brand brand"
      "nav social"
      "copy copy";
  }

  .intro-grid,
  .recruit-section,
  .page-hero,
  .leadership-hero{
    grid-template-columns: 1fr;
  }

  .media-band,
  .command-board,
  .blueprint {
    grid-template-columns: 1fr 1fr;
  }

  .primary-command{
    grid-column: auto;
    grid-row: auto;
  }

  .blueprint-line {
    display: none;
  }

  .callout,
  .site-footer {
    align-items: flex-start;
    flex-direction: column;
  }

  .join-callout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(260px, 0.58fr);
    align-items: center;
  }}

/* ── Gold Button ── */
.button.gold {
  background: var(--gold-500);
  color: var(--navy-950);
  box-shadow: 0 14px 28px rgba(214, 169, 56, 0.28);
}
.button.gold:hover,
.button.gold:focus-visible {
  background: #bf9520;
}

/* ── Nav Social Icons ── */
.nav-social {
  display: flex;
  align-items: center;
  gap: 1px;
  margin: 0 4px;
  padding: 0 8px;
  border-left: 1px solid rgba(255,255,255,0.16);
  border-right: 1px solid rgba(255,255,255,0.16);
}
.nav-social a {
  width: 32px;
  height: 32px;
  min-height: unset;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: rgba(255,255,255,0.68);
}
.nav-social a:hover,
.nav-social a:focus-visible {
  background: rgba(255,255,255,0.12);
  color: var(--white);
}
.nav-social svg { width: 15px; height: 15px; flex-shrink: 0; }

/* ── Footer Redesign ── */
.site-footer {
  display: block;
  background: var(--navy-950);
  color: var(--white);
  padding: 0;
}

.footer-inner {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1.4fr;
  gap: 44px;
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: 56px 0 40px;
}

.footer-brand {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  grid-column: auto;
}

.footer-brand img {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(255,255,255,0.9);
  object-fit: contain;
  flex-shrink: 0;
  margin-top: 3px;
}

.footer-brand-text strong {
  display: block;
  color: var(--white);
  font-size: 1rem;
  line-height: 1.2;
}

.footer-brand-text p {
  margin: 5px 0 0;
  color: rgba(255,255,255,0.5);
  font-size: 0.82rem;
  line-height: 1.55;
}

.footer-col-title {
  display: block;
  margin: 0 0 14px;
  color: rgba(255,255,255,0.9);
  font-size: 0.72rem;
  font-weight: 950;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.footer-col-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.footer-col-nav a {
  min-height: 32px;
  display: inline-flex;
  align-items: center;
  color: rgba(255,255,255,0.6);
  font-size: 0.88rem;
  font-weight: 700;
  padding: 2px 0;
  transition: color 160ms ease;
}

.footer-col-nav a:hover { color: var(--white); }

.footer-social {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.footer-bottom {
  border-top: 1px solid rgba(255,255,255,0.1);
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: 18px 0 26px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

/* ── Chart Your Course Section ── */
.chart-section {
  background: var(--navy-900);
  padding: clamp(60px, 8vw, 100px) 0;
}

.chart-inner {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
}

.chart-section .eyebrow { color: var(--gold-500); }

.chart-section h2 {
  color: var(--white);
  margin: 0 0 42px;
}

.chart-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.chart-card {
  background: var(--white);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 20px 56px rgba(0,0,0,0.28);
  display: flex;
  flex-direction: column;
}

.chart-card img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.chart-card-body {
  padding: 22px 24px 18px;
  flex: 1;
}

.chart-card-body h3 {
  font-size: 1.18rem;
  color: var(--navy-950);
  margin: 0 0 8px;
}

.chart-card-body p {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.55;
}

.chart-card-cta {
  display: block;
  min-height: 48px;
  margin: 0 24px 24px;
  border-radius: var(--radius);
  background: var(--gold-500);
  color: var(--navy-950);
  font-weight: 900;
  font-size: 0.95rem;
  text-align: center;
  line-height: 48px;
  transition: background 160ms ease, transform 160ms ease;
}

.chart-card-cta:hover {
  background: #bf9520;
  transform: translateY(-1px);
}

/* ── Responsive: New Sections ── */
@media (max-width: 940px) {
  .chart-grid{ grid-template-columns: 1fr 1fr; }
  .footer-inner {
    grid-template-columns: 1fr 1fr;
    gap: 30px;
  }
  .footer-brand { grid-column: span 2; }
  .footer-bottom { flex-direction: column; align-items: flex-start; gap: 14px; }}

@media (max-width: 640px) {
  .age-card { padding: 24px; }
  .where-grid { grid-template-columns: 1fr; }
  .site-footer {
    grid-template-columns: 1fr;
    grid-template-areas: "brand" "nav" "social" "copy";
  }
  .footer-social { flex-direction: row; align-items: flex-start; }

  .site-header {
    padding: 12px 16px;
  }

  .brand small {
    display: none;
  }

  .hero {
    min-height: 88dvh;
  }

  .hero-content {
    width: min(100% - 28px, var(--max));
    padding-bottom: 70px;
  }

  .hero h1,
  .page-hero h1 {
    font-size: clamp(1.6rem, 9vw, 3.7rem);
    white-space: normal;
  }

  .page-hero h1 {
    font-size: clamp(2.1rem, 12vw, 3.25rem);
  }

  .section,
  .page-hero {
    width: min(100% - 28px, var(--max));
  }

  .media-band,
  .command-board,
  .blueprint {
    width: min(100% - 28px, var(--max));
    grid-template-columns: 1fr;
  }

  .leadership-hero,
  .roadmap-hero{
    width: min(100% - 28px, var(--max));
    padding-top: 128px;
  }

  .roadmap-hero h1 {
    font-size: clamp(2.15rem, 12vw, 3.35rem);
  }

  .leadership-copy h1 {
    font-size: clamp(2.05rem, 11vw, 3.2rem);
  }

  .media-band figure {
    aspect-ratio: 4 / 3;
  }

  .recruit-card {
    grid-template-columns: 1fr;
    grid-template-areas:
      "num"
      "title"
      "text"
      "action";
  }

  .recruit-card a {
    justify-content: center;
  }

  .join-callout {
    grid-template-columns: 1fr;
  }

  .page-hero {
    padding-top: 120px;
  }

  .chart-grid{ grid-template-columns: 1fr; }
  .footer-inner {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 36px 0 28px;
  }
  .footer-brand { grid-column: auto !important; }
  .footer-social { flex-direction: column; }}
.rh-hero .eyebrow { color: var(--gold-500); }
.rh-connect .eyebrow { color: var(--gold-500); }

/* ===== DEFINITIVE OVERRIDES ===== */

/* Logo nav */
/* Logo footer */
.footer-brand img {
  width: 130px !important;
  height: 130px !important;
  object-fit: contain !important;
  background: transparent !important;
  border-radius: 0 !important;
  flex-shrink: 0 !important;
}
.footer-brand {
  grid-area: auto !important;
  align-items: flex-start !important;
  gap: 20px !important;
}

/* Footer column titles */
.footer-col-title {
  color: #c6a22c !important;
  font-size: 0.8rem !important;
  font-weight: 900 !important;
  letter-spacing: 0.16em !important;
  text-transform: uppercase !important;
  padding-bottom: 10px !important;
  margin-bottom: 16px !important;
  border-bottom: none !important;
  text-decoration: underline !important;
  text-underline-offset: 5px !important;
  text-decoration-color: #c6a22c !important;
  display: block !important;
}

/* Footer social — plain text links, no icons */
.footer-social {
  display: flex !important;
  flex-direction: column !important;
  gap: 8px !important;
  margin-top: 4px !important;
}
.footer-social a {
  color: rgba(255,255,255,0.75) !important;
  font-size: 0.9rem !important;
  font-weight: 500 !important;
  text-decoration: none !important;
  text-transform: none !important;
  letter-spacing: 0 !important;
  display: block !important;
  padding: 2px 0 !important;
  width: auto !important;
}
.footer-social a:hover { color: #fff !important; text-decoration: underline !important; }

/* Footer grid */
.footer-inner {
  grid-template-columns: 1.5fr 0.9fr 0.9fr 1.1fr !important;
}

/* Nav social icons. Desktop row only: below 1280px the drawer styles its own
   social row in 89-final-header.css. */
@media (min-width: 1280px) {
.nav-social {
  display: flex !important;
  align-items: center !important;
  gap: 4px !important;
}
.nav-social a {
  width: 40px !important;
  height: 40px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 50% !important;
  color: rgba(255,255,255,0.8) !important;
  text-decoration: none !important;
  transition: color 160ms ease !important;
}
.nav-social a:hover { color: #fff !important; }
.nav-social svg { width: 20px !important; height: 20px !important; display: block !important; }
}

/* Sticky join */

@media (max-width: 640px) {
  .footer-inner { grid-template-columns: 1fr 1fr !important; gap: 24px !important; }}
@media (max-width: 480px) {
  .footer-inner { grid-template-columns: 1fr !important; }}

/* ===== STORE V2: Product cards, modal{
  display: flex !important;
  flex-direction: column !important;
  background: #fff;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 12px rgba(0,0,0,0.08);
  transition: box-shadow 180ms ease, transform 180ms ease;
}

/* Image wrap — bigger, white{
  position: relative;
  background: #ffffff;
  cursor: pointer;
  overflow: hidden;
  flex-shrink: 0;
}
/* ── Product Modal ──────────────────────────────── */
#product-modal[hidden] { display: none !important; }
#modal-img {
  width: 100%;
  max-height: 300px;
  object-fit: contain;
  display: block;
}
#modal-img-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #888;
  margin-top: 8px;
}

@keyframes shake {
  0%,100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }}

#cart-items {
  flex: 1;
  overflow-y: auto;
  padding: 16px 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
#cart-total { font-size: 1.3rem; color: #0a1f4e; }

/* ── Toast ──────────────────────────────────────── */
/* ================================================================
   STORE V3 — bigger images, lower text, envelopes, detail overlay,
   cart page + checkout page
   ================================================================ */

/* ── Product cards: image fills the box{
  height: 320px !important;
  padding: 12px !important;
}

/* ── Envelopes (dues): front-facing{ overflow: hidden; background: #fff; }
.field-row { display: flex; gap: 16px; flex-wrap: wrap; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; flex: 1; min-width: 160px; }
.field span { font-size: 0.82rem; font-weight: 700; color: #3a4150; }
.field input,
.field textarea {
  border: 1px solid #cfd5df;
  border-radius: 8px;
  padding: 11px 13px;
  font-size: 0.95rem;
  font-family: inherit;
  color: #0a0f1e;
  background: #fff;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: #0a1f4e;
  box-shadow: 0 0 0 3px rgba(10,31,78,0.12);
}

/* ── Responsive: cart + checkout ── */
@media (max-width: 560px) {
  .field-row { flex-direction: column; gap: 0; }}

/* ================================================================
   FINAL — Logo (no white, bigger, crisp) + Footer layout
   Appended last so it wins the cascade.
   ================================================================ */

/* Nav logo: transparent patch (white background removed), shown in full */
/* Footer brand block: logo middle-left, much bigger, text beside it */
.footer-inner {
  grid-template-columns: 2.4fr 1fr 1fr 1.2fr !important;
  align-items: start !important;
}
.footer-brand {
  display: flex !important;
  align-items: center !important;
  gap: 22px !important;
  grid-column: auto !important;
}
.footer-brand img {
  width: 152px !important;
  height: 152px !important;
  border-radius: 0 !important;
  object-fit: contain !important;
  object-position: center !important;
  background: transparent !important;
  clip-path: none !important;
  flex-shrink: 0 !important;
  margin: 0 !important;
}
.footer-brand-text strong { font-size: 1.18rem !important; }

/* Footer column titles: gold, bold, underlined, pushed right group */
.footer-col-title {
  color: #d6a938 !important;
  font-size: 0.84rem !important;
  font-weight: 900 !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase !important;
  text-decoration: underline !important;
  text-decoration-color: #d6a938 !important;
  text-underline-offset: 6px !important;
  text-decoration-thickness: 2px !important;
  margin: 0 0 16px !important;
  border-bottom: none !important;
  display: block !important;
}

/* Footer social: icon + name text links (kill old circular icon styling) */
.footer-social { align-items: flex-start !important; }
.footer-social a {
  width: auto !important;
  height: auto !important;
  border: 0 !important;
  border-radius: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 10px !important;
  justify-content: flex-start !important;
  color: rgba(255,255,255,0.72) !important;
  padding: 3px 0 !important;
}
.footer-social a svg {
  width: 17px !important;
  height: 17px !important;
  flex-shrink: 0 !important;
  display: block !important;
}
.footer-social a:hover {
  background: transparent !important;
  color: #fff !important;
}
.footer-social a:hover span { text-decoration: underline; }

@media (max-width: 860px) {
  .footer-inner { grid-template-columns: 1.6fr 1fr 1fr !important; }
  .footer-brand { grid-column: 1 / -1 !important; margin-bottom: 8px; }}
@media (max-width: 640px) {
  .footer-inner { grid-template-columns: 1fr 1fr !important; gap: 28px !important; }
  .footer-brand { grid-column: 1 / -1 !important; }
  .footer-brand img { width: 120px !important; height: 120px !important; }}
@media (max-width: 480px) {
  .footer-inner { grid-template-columns: 1fr !important; }}

/* ================================================================
   Resource Hub — closing CTA band (replaces two stacked CTAs)
   ================================================================ */
.rh-closing {
  background: var(--navy-900, #0a1830);
  margin: 0;
  padding: clamp(56px, 8vw, 88px) 24px;
}
.rh-closing-inner {
  width: min(760px, 100%);
  margin: 0 auto;
  text-align: center;
}
.rh-closing .eyebrow { color: var(--gold-500, #d6a938); }
.rh-closing h2 {
  color: #fff;
  font-size: clamp(1.8rem, 3.4vw, 2.6rem);
  margin: 10px 0 16px;
  line-height: 1.15;
}
.rh-closing p {
  color: rgba(255,255,255,0.72);
  font-size: 1.02rem;
  line-height: 1.65;
  margin: 0 auto 30px;
  max-width: 600px;
}
.rh-closing-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
}

/* ================================================================
   Contact page (rebuilt)
   ================================================================ */
.contact-hero2 {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: clamp(120px, 14vw, 150px) 0 clamp(28px, 4vw, 44px);
  text-align: center;
}
.contact-hero2 .eyebrow { color: var(--red-700, #c41230); }
.contact-hero2 h1 {
  font-size: clamp(2.1rem, 5vw, 3.4rem);
  line-height: 1.08;
  margin: 12px auto 16px;
  max-width: 18ch;
  color: var(--navy-950, #071326);
}
.contact-hero2 > p {
  font-size: 1.08rem;
  line-height: 1.6;
  color: #4a5160;
  max-width: 60ch;
  margin: 0 auto;
}
.contact-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 26px;
}
.contact-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: #fff;
  border: 1px solid #e3e7ee;
  border-radius: 100px;
  padding: 10px 18px;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--navy-950, #071326);
  text-decoration: none;
  box-shadow: 0 2px 10px rgba(10,20,40,0.05);
  transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}
.contact-chip:hover { transform: translateY(-2px); border-color: var(--gold-500, #d6a938); box-shadow: 0 6px 18px rgba(10,20,40,0.1); }
.contact-chip svg { width: 17px; height: 17px; color: var(--red-700, #c41230); }

.contact-main {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 32px;
  align-items: start;
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: clamp(20px, 4vw, 40px) 0;
}
.contact-form-card {
  background: #fff;
  border: 1px solid #e9ecf2;
  border-radius: 18px;
  padding: clamp(24px, 3vw, 38px);
  box-shadow: 0 10px 40px rgba(10,20,40,0.06);
}
.contact-form-card h2 {
  font-size: 1.5rem;
  color: var(--navy-950, #071326);
  margin: 0 0 6px;
}
.contact-form-card > p.form-sub {
  color: #6a7280;
  font-size: 0.95rem;
  margin: 0 0 24px;
}
.contact-form .field-row { display: flex; gap: 16px; flex-wrap: wrap; }
.contact-form .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; flex: 1; min-width: 0; }
.contact-form label > span { font-size: 0.82rem; font-weight: 700; color: #3a4150; }
.contact-form input,
.contact-form select,
.contact-form textarea {
  width: 100%;
  max-width: 100%;
  border: 1px solid #cfd5df;
  border-radius: 9px;
  padding: 12px 13px;
  font-size: 0.95rem;
  font-family: inherit;
  color: #0a0f1e;
  background: #fff;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.contact-form input:focus,
.contact-form select:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--navy-700, #0a1f4e);
  box-shadow: 0 0 0 3px rgba(10,31,78,0.12);
}
.contact-form .send-btn {
  width: 100%;
  margin-top: 6px;
  background: var(--red-700, #c41230);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 15px;
  font-size: 1rem;
  font-weight: 800;
  cursor: pointer;
  transition: background 160ms ease;
}
.contact-form .send-btn:hover { background: #a50f28; }
.contact-form .form-note { font-size: 0.78rem; color: var(--ink-muted); text-align: center; margin: 12px 0 0; }
.contact-msg {
  margin: 16px 0 0;
  padding: 14px 16px;
  background: #e8f3ec;
  border: 1px solid #b9dcc6;
  border-radius: 10px;
  color: #1f6b3a;
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.5;
}
.contact-aside { display: flex; flex-direction: column; gap: 16px; }
.info-card {
  background: #fff;
  border: 1px solid #e9ecf2;
  border-radius: 16px;
  padding: 22px;
  box-shadow: 0 6px 24px rgba(10,20,40,0.05);
}
.info-card .info-head { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }
.info-card .info-ico {
  width: 38px; height: 38px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 10px;
  background: rgba(196,18,48,0.08);
  color: var(--red-700, #c41230);
}
.info-card .info-ico svg { width: 19px; height: 19px; }
.info-card h3 { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.08em; color: #6a7280; margin: 0; font-weight: 800; }
.info-card strong { display: block; font-size: 1rem; color: var(--navy-950, #071326); line-height: 1.4; margin-bottom: 8px; }
/* A standalone card CTA at 17px tall, not a link inline in a sentence, so
   2.5.8's inline exception does not cover it. Same fix as .where-card a. */
.info-card a.info-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--navy-700, #0a1f4e);
  font-weight: 700;
  font-size: 0.9rem;
  text-decoration: none;
}
.info-card a.info-link:hover { text-decoration: underline; }
.info-card p { margin: 0; color: #4a5160; font-size: 0.92rem; line-height: 1.55; }
.info-card p + .info-aside { margin-top: var(--space-sm); }
.info-social { display: flex; gap: 10px; flex-wrap: wrap; }
.info-social a {
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  border: 1px solid #e3e7ee;
  color: var(--navy-700, #0a1f4e);
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.info-social a:hover { background: var(--navy-950, #071326); color: #fff; border-color: var(--navy-950, #071326); }
.info-social svg { width: 18px; height: 18px; }

.contact-map { width: min(var(--max), calc(100% - 36px)); margin: 8px auto 0; }
.contact-map iframe {
  width: 100%;
  height: 360px;
  border: 0;
  border-radius: 16px;
  display: block;
  box-shadow: 0 8px 30px rgba(10,20,40,0.08);
}

.contact-reasons2 {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: clamp(44px, 6vw, 72px) 0 clamp(20px, 3vw, 32px);
}
.contact-reasons2 .section-heading { text-align: center; margin: 0 auto 30px; }
.contact-reasons2 .section-heading .eyebrow { color: var(--red-700, #c41230); }
.contact-reasons2 .section-heading h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); color: var(--navy-950, #071326); margin: 8px 0 0; }
.reasons-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.reason-card {
  background: #fff;
  border: 1px solid #e9ecf2;
  border-radius: 14px;
  padding: 24px 22px;
  transition: transform 160ms ease, box-shadow 160ms ease;
}
.reason-card:hover { transform: translateY(-3px); box-shadow: 0 10px 28px rgba(10,20,40,0.08); }
.reason-card span { display: block; font-size: 0.8rem; font-weight: 900; color: var(--honor-on-light); margin-bottom: 8px; letter-spacing: 0.04em; }
.reason-card h3 { font-size: 1.08rem; color: var(--navy-950, #071326); margin: 0 0 8px; }
.reason-card p { font-size: 0.9rem; color: #5a616e; line-height: 1.55; margin: 0; }

.contact-faq {
  width: min(820px, calc(100% - 36px));
  margin: 0 auto;
  padding: clamp(36px, 5vw, 60px) 0 clamp(48px, 6vw, 80px);
}
.contact-faq .section-heading { text-align: center; margin-bottom: 26px; }
.contact-faq .section-heading .eyebrow { color: var(--red-700, #c41230); }
.contact-faq .section-heading h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); color: var(--navy-950, #071326); margin: 8px 0 0; }
.faq-item {
  background: #fff;
  border: 1px solid #e9ecf2;
  border-radius: 12px;
  margin-bottom: 12px;
  overflow: hidden;
}
.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 18px 22px;
  font-weight: 700;
  font-size: 1rem;
  color: var(--navy-950, #071326);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '+';
  font-size: 1.5rem;
  font-weight: 400;
  color: var(--red-700, #c41230);
  transition: transform 200ms ease;
  line-height: 1;
}
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item .faq-body { padding: 0 22px 20px; color: #4a5160; font-size: 0.95rem; line-height: 1.65; }

@media (max-width: 900px) {
  .contact-main { grid-template-columns: 1fr; }
  .reasons-grid { grid-template-columns: repeat(2, 1fr); }}
@media (max-width: 540px) {
  .reasons-grid { grid-template-columns: 1fr; }
  .contact-form .field-row { flex-direction: column; gap: 0; }}

/* ================================================================
   Store — category color dots, all-blue buttons{ display: flex !important; align-items: center; }

/* Category dot on each product card (color set inline by store.js) */
.cat-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-right: 8px;
  vertical-align: middle;
  position: relative;
  top: -1px;
}

/* All "Add to Cart" buttons blue — grid + modal{ background: #0a1f4e !important; color: #fff !important; }

/* Hover hint text — white{ color: #fff !important; }

/* Cart preview sub-line */
#hero-cart-sub {
  color: rgba(255,255,255,0.6);
  font-size: 0.9rem;
  margin: 4px 0 0;
}

.sponsors-page .page-hero .hero-actions {
  margin-top: 28px;
}

@media (max-width: 820px) {
  .sponsor-grid,
  .tier-grid {
    grid-template-columns: 1fr;
  }}
/* Turnstile mount. The widget sizes itself; this only reserves room so it does
   not shove the submit button down when it renders. */
.turnstile-mount {
  min-height: 65px;
  margin-block: var(--space-sm);
}

/* FAQ fills a desktop: heading on the left, questions on the right (2026-09-27). */
@media (min-width: 1024px) {
  .contact-faq { width: min(var(--max), calc(100% - 36px)); display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); column-gap: var(--space-2xl); align-items: start; }
  .contact-faq .section-heading { grid-column: 1; grid-row: 1 / span 20; text-align: left; margin: 0; position: sticky; top: calc(var(--header-height) + var(--space-md)); }
  .contact-faq .faq-item { grid-column: 2; }
}


/* @source website/src/css/60-header.css */
/* ============================================================================
   HEADER STACK - announcement bar, masthead, primary navigation, sticky CTA.
   Rebuilt from tokens. Supersedes the legacy rules for these components; the
   originals were deleted rather than left to drift.
   ========================================================================= */

/* --- Announcement bar + masthead: one fixed stack ---------------------------
   Final UI round (2026-11-06), replaces BUG-001's approach. main.js used to
   move the header per animation frame (--announcement-offset = bar height
   minus scrollY) so it chased the bar as the bar scrolled away. On iOS the
   frame lands after the compositor has already moved the page, so during
   momentum scroll and rubber-band the header visibly separated from the bar.
   Now both are fixed and the header's top is a constant from CSS: the two
   boxes sit in the viewport together and nothing is computed on scroll. The
   bar stays pinned (his ruling: one stack); it is one thin 36px line on a
   phone and dismissible, which removes it and puts the header back at 0. */
.announce-bar {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: var(--z-announce);
  display: flex;
  align-items: stretch;
  height: var(--announce-h);
  background: var(--red-800);
  color: var(--white);
  font-size: var(--text-sm);
  line-height: 1.2;
}

.announce-bar[hidden] { display: none; }

/* The whole bar is the link. Padded 44px both sides so the line stays
   optically centred with the X on the right. */
.announce-link {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  padding-inline: 44px;
  color: var(--white);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
}

.announce-long,
.announce-short {
  overflow: hidden;
  text-overflow: ellipsis;
}

.announce-short { display: none; }

.announce-text {
  color: var(--white);
  font-weight: var(--weight-medium);
}

.announce-go {
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.announce-link:hover .announce-go { text-decoration-thickness: 2px; }

/* Inset so the ring stays inside the 36px bar instead of being clipped by
   the viewport edge above it. */
.announce-link:focus-visible { outline-offset: -3px; }

.announce-close {
  position: absolute;
  top: 0;
  right: 0;
  display: grid;
  place-items: center;
  width: 44px;
  height: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: var(--white);
  cursor: pointer;
  opacity: 0.85;
  transition: opacity var(--duration-fast) var(--ease-out);
}

.announce-close svg { width: 14px; height: 14px; }
.announce-close:hover { opacity: 1; }
.announce-close:focus-visible { outline-offset: -3px; }

/* Phones read the short line. */
@media (max-width: 767px) {
  .announce-long { display: none; }
  .announce-short { display: inline; }
}

/* --- Masthead -------------------------------------------------------------- */
.site-header {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-xs) var(--gutter);
  color: var(--ink-inverse);
  background: var(--navy-900);
  box-shadow: var(--shadow-header);
  transition:
    background var(--duration) var(--ease-out),
    box-shadow var(--duration) var(--ease-out);
}

/* Directly under the bar while the bar is showing. A constant, not a
   per-scroll value: that is the whole fix. */
.announce-bar:not([hidden]) + .site-header { top: var(--announce-h); }

/* The homepage header floats over the hero video until the page is scrolled. */
.site-header.home-header {
  background: transparent;
  box-shadow: none;
}

.site-header.is-scrolled,
.site-header.home-header.is-scrolled,
.site-header:has(.primary-nav.is-open) {
  background: var(--navy-900);
  box-shadow: var(--shadow-header);
}

/* --- Sticky Join pill ------------------------------------------------------
   BUG-002: previously fixed to the lower left with no gutter, so it covered the
   intro paragraph. It now sits in the bottom-right safe area and stays hidden
   until the in-page call to action has scrolled out of view, so the two never
   compete and it can never sit on top of copy the reader is mid-sentence in. */
.sticky-join {
  position: fixed;
  /* Round 2, comment 5: he wants it bottom LEFT. BUG-002 was not the corner,
     it was that the old rule pinned it with no gutter at all, so it sat on the
     copy. Left corner, real gutters, and the safe-area inset so a notched phone
     in landscape cannot push it off screen. */
  left: max(var(--space-md), env(safe-area-inset-left));
  bottom: max(var(--space-md), env(safe-area-inset-bottom));
  z-index: var(--z-float);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 48px;
  padding: var(--space-xs) var(--space-md);
  background: var(--red-700);
  color: var(--white);
  border-radius: var(--radius-pill);
  font-family: var(--font-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  box-shadow: var(--shadow-lg);
  transition:
    opacity var(--duration) var(--ease-out),
    transform var(--duration) var(--ease-out),
    /* Listed so the pill still fades OUT: visibility flips at the end of the
       duration on the way to hidden, and at the start on the way back. */
    visibility var(--duration) var(--ease-out),
    background var(--duration-fast) var(--ease-out);
}

.sticky-join.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.sticky-join:hover { background: var(--accent-hover); }

/* The one control on the site whose adjacent colour is not knowable from the
   DOM. It floats over whatever happens to be scrolling beneath it, so unlike
   every other element the surface behind its ring changes as the page moves.
   Measured on the homepage at six scroll positions, 2026-09-01:

     over a dark section   blue ring 2.90:1  FAIL   gold ring 8.76:1  pass
     over a light section  blue ring 6.03:1  pass   gold ring 2.06:1  FAIL

   So no single token can pass here, and the inverted-surface list in 02-base
   cannot help: this element is inside neither surface. The fix is a two-tone
   indicator. Gold and navy contrast strongly with each other, so whichever
   surface it lands on, one of the two bands is doing the work and the ring is
   never invisible. Keeps var(--focus-ring-inverse) rather than a literal colour,
   so the gate still holds. The drop shadow is restated because box-shadow
   replaces rather than adds. */
.sticky-join:focus-visible {
  outline: 3px solid var(--focus-ring-inverse);
  outline-offset: 2px;
  box-shadow:
    0 0 0 8px var(--navy-950),
    0 32px 90px rgba(7, 19, 38, 0.24);
}

/* Hidden-until-scrolled only where scripting can reveal it again. With JS
   unavailable the pill simply stays visible rather than becoming unreachable. */
@media (scripting: enabled) {
  .sticky-join {
    opacity: 0;
    transform: translateY(0.75rem);
    pointer-events: none;
    /* Not just invisible: out of the focus order. opacity alone left a keyboard
       visitor tabbing to a pill they could not see, with no visible ring.
       Lighthouse does not test tab order against visibility. */
    visibility: hidden;
  }

  .sticky-join.is-visible {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    visibility: visible;
  }
}

/* The pill matters most on a phone: recruiting traffic arrives from a flyer QR
   code or a social post. The legacy sheet hid it below 640px to work around
   BUG-002; with the overlap fixed it belongs there more than anywhere. */
@media (max-width: 640px) {
  .sticky-join {
    left: max(var(--space-sm), env(safe-area-inset-left));
    bottom: max(var(--space-sm), env(safe-area-inset-bottom));
    padding: var(--space-xs) var(--space-sm);
  }
}

/* --- Brand mark -------------------------------------------------------------
   One rule. The legacy sheet had five, escalating 58 -> 48 -> 110 -> 60 -> 116
   -> 76px with !important as each tried to beat the last, which is why the
   masthead was 140px tall at tablet width. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  min-height: 44px;
}

.brand img {
  width: clamp(44px, 6vw, 56px);
  height: clamp(44px, 6vw, 56px);
  /* logo-patch-mark.webp is the crest cropped to its own disc (the source file is a
     384x414 frame with the crest floating inside it and stray artefacts below,
     which is why a contain fit left a white moat). Cropped to the disc it can
     sit flush: cover, no padding, and the circle IS the crest. */
  object-fit: cover;
  border-radius: 50%;
  background: transparent;
  flex: none;
}

.brand span { display: grid; line-height: 1.15; }

.brand strong {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
}

.brand small {
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink-inverse-muted);
}

/* --- Staff login (final round, 2026-09-26) ----------------------------------
   An icon to the right of Join the Division with a "Staff Login" tooltip on
   hover and keyboard focus. The tooltip is its own aria-hidden element: the
   link's name comes from .nav-staff-label, so a screen reader hears it once.
   Below 1280px this icon is hidden and the drawer carries its own labelled
   Staff login link (89-final-header.css). */
.primary-nav .nav-staff {
  position: relative;
  justify-content: center;
  width: 44px;
  padding: 0;
  border-radius: 50%;
}

.nav-staff svg { width: 20px; height: 20px; flex: none; }

.nav-staff-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.nav-staff-tip {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  padding: var(--space-3xs) var(--space-xs);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--navy-900);
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity 140ms var(--ease-out), transform 140ms var(--ease-out);
}

.nav-staff:hover .nav-staff-tip,
.nav-staff:focus-visible .nav-staff-tip {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .nav-staff-tip { transition: none; }
}


/* @source website/src/css/61-join.css */
/* ============================================================================
   JOIN PAGE
   Mode: persuade. The reader is a parent deciding whether to trust this program
   with their child, usually on a phone, arriving from a flyer QR code.
   Every section answers one question and hands off to one action.
   ========================================================================= */

.page-join main { padding-top: var(--header-height); }

/* --- Hero -------------------------------------------------------------------
   Asymmetric: the photograph carries the emotion, the type carries the promise.
   Never a centred headline over a gradient. */
.join-hero {
  display: grid;
  gap: var(--space-xl);
  align-items: center;
  max-width: var(--max-wide);
  margin: 0 auto;
  /* Review round 1 comment 45: the page opened too low. Half the old top
     pad, so the h1 sits near the fold without cropping the photo. */
  padding: var(--space-md) var(--gutter) var(--section-y-tight);
}

.join-hero-media {
  align-self: center;
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--navy-900);
}

.join-hero-media img {
  width: 100%;
  /* height:100% let the stretched grid row dictate the box and aspect-ratio was
     ignored, which is why the photo stayed 609x731 after the first attempt. */
  height: auto;
  /* Manual edit, comments 43 and 44: he pulled 609x731 down to 609x659, so the
     block is very slightly taller than it is wide rather than a tall slab. */
  aspect-ratio: 609 / 659;
  object-fit: cover;
  object-position: 50% 74%;
}

.join-hero-body h1 {
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  max-width: 15ch;
  margin-bottom: var(--space-md);
}

.join-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-lg);
}

@media (min-width: 900px) {
  .join-hero {
    grid-template-columns: 1.05fr 1fr;
    gap: var(--space-3xl);
    /* Comment 45: the page opened too low at desktop too. */
    padding-block: var(--space-md) var(--section-y);
  }
  .join-hero-media { order: 2; }
  /* Manual edit, comments 43 and 44: 609x731 down to 609x659. */
  .join-hero-media img { aspect-ratio: 609 / 659; }
}

/* --- The four answers -------------------------------------------------------
   A definition list, not a card grid. Hairlines separate the questions; the
   question is the heading and the answer is real prose a parent can act on. */
.join-answers {
  padding: var(--section-y) var(--gutter);
  background: var(--surface-raised);
  border-block: var(--border);
}

.join-answers-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.join-answers h2 {
  max-width: var(--measure-narrow);
  margin-bottom: var(--space-xl);
}

.answer-list {
  display: grid;
  gap: 0;
  margin: 0;
}

.answer {
  display: grid;
  gap: var(--space-2xs) var(--space-2xl);
  padding-block: var(--space-lg);
  border-top: var(--border);
}

.answer:last-child { border-bottom: var(--border); }

.answer dt {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--ink);
  text-wrap: balance;
}

.answer dd {
  margin: 0;
  max-width: var(--measure);
  color: var(--ink-secondary);
}

.answer dd strong {
  color: var(--ink);
  font-weight: var(--weight-bold);
}

/* Multi-paragraph answers: the cost answer states real figures, which needs more
   than one sentence. Spacing comes from the paragraph, not a wrapper. */
.answer dd > p { margin: 0; }
.answer dd > p + p { margin-block-start: var(--space-sm); }

.answer-aside {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

@media (min-width: 860px) {
  .answer { grid-template-columns: minmax(16rem, 22rem) 1fr; }
}

/* --- Full-bleed plate -------------------------------------------------------
   One photograph at scale, with a caption that says what is happening. This is
   the section that answers "what does my child actually do" without adjectives. */
.join-plate {
  display: grid;
  gap: 0;
  margin: 0;
  background: var(--surface-inverse);
  color: var(--ink-inverse);
}

.join-plate img {
  width: 100%;
  height: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.join-plate figcaption {
  display: grid;
  align-content: center;
  padding: var(--section-y-tight) var(--gutter);
}

.join-plate figcaption p {
  max-width: var(--measure-narrow);
  margin: 0;
  color: var(--ink-inverse-muted);
  font-size: var(--text-md);
  line-height: var(--leading-md);
}

.join-plate-list {
  list-style: none;
  margin: var(--space-md) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-2xs);
  max-width: var(--measure-narrow);
}

.join-plate-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-xs);
  align-items: baseline;
  padding-block: var(--space-2xs);
  border-top: 1px solid var(--line-inverse);
  color: var(--ink-inverse);
  font-size: var(--text-base);
}

.join-plate-list span {
  color: var(--honor);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

@media (min-width: 900px) {
  /* Comment 46: the photo was eating the row and the right side carried a
     single grey sentence. The columns are reversed in weight and the caption
     now does real work. */
  .join-plate { grid-template-columns: 0.9fr 1.1fr; }
  .join-plate img { aspect-ratio: auto; min-height: 21rem; }
  .join-plate figcaption { padding-inline: var(--space-2xl); }
}

/* --- Enrollment steps -------------------------------------------------------
   Numbered because the order genuinely matters: step two is where a prospect is
   lost to another division, so it is the loudest thing on the page. */
.join-steps {
  padding: var(--section-y) var(--gutter);
}

.join-steps-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.join-steps h2 {
  max-width: 24ch;
}

.step-list {
  counter-reset: step;
  list-style: none;
  margin: var(--space-2xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-lg);
}

.step {
  counter-increment: step;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-sm) var(--space-md);
  padding-top: var(--space-lg);
  border-top: var(--border);
}

.step::before {
  content: counter(step, decimal-leading-zero);
  grid-row: 1 / span 3;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
  line-height: 1.15;
}

.step h3 { margin: 0; }
.step p { margin: 0; color: var(--ink-secondary); max-width: var(--measure); }
.step p + p { margin-top: var(--space-xs); }

/* Step two decides whether the inquiry reaches this division at all. */
.step--critical { border-top-color: var(--accent); }
.step--critical::before { color: var(--accent); }

.step-callout {
  justify-self: start;
  padding: var(--space-2xs) var(--space-sm);
  background: var(--blue-050);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: var(--text-md);
  color: var(--ink) !important;
}

.step-callout strong { font-weight: var(--weight-bold); }

.step-action {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: var(--border);
  display: grid;
  gap: var(--space-sm);
  justify-items: start;
}

.step-action-note {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

.step-action-note strong { color: var(--ink); font-weight: var(--weight-semibold); }

/* --- Secondary path ---------------------------------------------------------
   For the parent who is interested but not ready. Quiet on purpose: it must not
   compete with enrollment. */
/* Comment 42: crest on the left, the "not ready yet" copy on the right. */
.join-ask-inner {
  display: grid;
  gap: var(--space-lg);
  align-items: center;
}

.join-ask-crest {
  width: clamp(96px, 14vw, 148px);
  height: auto;
  justify-self: center;
}

@media (min-width: 760px) {
  .join-ask-inner { grid-template-columns: auto minmax(0, 1fr); gap: var(--space-2xl); }
  .join-ask-crest { justify-self: start; }
}

.join-ask {
  padding: var(--section-y) var(--gutter);
  background: var(--surface-sunken);
  border-top: var(--border);
}

.join-ask-inner {
  max-width: var(--max-text);
  margin: 0 auto;
}

.join-ask h2 { font-size: var(--text-xl); line-height: var(--leading-xl); }
.join-ask p { color: var(--ink-secondary); }
.join-ask .button { margin-top: var(--space-2xs); }

/* --- Buttons used by this page ---------------------------------------------
   Sized for a 44px minimum tap target and a single-line label at every width. */
.page-join .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--space-xs) var(--space-lg);
  border-radius: var(--radius);
  font-family: var(--font-text);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  text-align: center;
  border: 1px solid transparent;
  /* Transition and depth are owned by 68-button.css. Do not restate them here
     or the page-scoped rule silently wins and this page loses the press. */
}

.page-join .button.primary {
  background-color: var(--accent);        /* 7.4:1 against white text */
  color: var(--white);
}

.page-join .button.primary:hover { background-color: var(--accent-hover); }

.page-join .button.secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}

.page-join .button.secondary:hover {
  background: var(--surface-raised);
  border-color: var(--ink);
}

.page-join .button--lg {
  min-height: 56px;
  padding-inline: var(--space-xl);
  font-size: var(--text-md);
}

/* ============================================================================
   THE ANSWER LIST AND THE TRAINING BAND  (2026-09-26)
   Camilo on the old versions: "What parents ask first ... just reads like a
   newspaper", and the training figure was "too small in the space it uses".
   Both now behave like the homepage poster run: one question per line, one
   photograph at full height, Overpass for the headings.
   Native <details name> gives an accordion with no JavaScript and no ARIA to
   get wrong: the browser already owns the expanded state and the keyboard.
   ========================================================================= */
.join-answers-inner .eyebrow {
  margin-bottom: var(--space-2xs);
}

.join-answers-inner h2 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  color: var(--ink);
  margin-bottom: var(--space-lg);
}

.qa {
  border-top: 1px solid var(--line-strong);
}

.qa:last-of-type {
  border-bottom: 1px solid var(--line-strong);
}

.qa summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-xs);
  padding: var(--space-md) 2.5rem var(--space-md) 0;
  position: relative;
  cursor: pointer;
  list-style: none;
}

.qa summary::-webkit-details-marker {
  display: none;
}

.qa-q {
  font-family: var(--font-poster);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  font-weight: var(--weight-semibold);
  color: var(--ink);
}

/* The short answer sits on the closed row, so the page answers the question
   before anyone clicks. The click is for the detail, not for the fact. */
.qa-a {
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent);
}

.qa summary::after {
  content: "";
  position: absolute;
  right: 0.35rem;
  top: 50%;
  width: 12px;
  height: 12px;
  border-right: 2px solid var(--ink-muted);
  border-bottom: 2px solid var(--ink-muted);
  transform: translateY(-70%) rotate(45deg);
  transition: transform var(--duration) var(--ease-out);
}

.qa[open] summary::after {
  transform: translateY(-20%) rotate(-135deg);
}

.qa-body {
  padding: 0 var(--space-xl) var(--space-lg) 0;
  max-width: var(--measure);
}

.qa-body p {
  margin: 0 0 var(--space-sm);
  color: var(--ink-secondary);
}

.qa-body p:last-child {
  margin-bottom: 0;
}

/* ---------------------------------------------------------------- the band */
.train-band {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  align-items: stretch;
  background: var(--surface-inverse);
}

.train-media img {
  width: 100%;
  height: 100%;
  min-height: clamp(320px, 42vw, 620px);
  object-fit: cover;
  display: block;
}

.train-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--section-y-tight) var(--gutter);
}

.train-body h2 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  color: var(--ink);
  margin: var(--space-2xs) 0 var(--space-lg);
}

.train-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 44ch;
}

.train-list li {
  display: flex;
  gap: var(--space-sm);
  padding: var(--space-sm) 0;
  border-top: 1px solid var(--line);
  color: var(--ink);
  font-size: var(--text-md);
  line-height: var(--leading-md);
}

.train-list li:last-child {
  border-bottom: 1px solid var(--line);
}

.train-list span {
  font-family: var(--font-poster);
  font-weight: var(--weight-bold);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   ORDER-BOARD ROUND  (2026-09-26)
   Camilo moved "Not ready to enroll yet?" up to sit straight under the hero and
   asked to "remove the huge white space under this section". Its full section
   padding stacked on top of the answers' own full padding, so a parent saw a
   screen of nothing between two blocks. The pair now shares one tight rhythm.
   He also asked for the words beside the training photograph to be centred:
   the column is centred on both axes, the list stays left aligned inside it so
   the numbers still line up.
   ========================================================================= */
.join-ask {
  padding-block: var(--section-y-tight);
}

.join-ask + .join-answers {
  padding-top: var(--section-y-tight);
  border-top: 0;
}

.train-body {
  align-items: center;
  text-align: center;
}

.train-list {
  margin-inline: auto;
  text-align: left;
}

/* The hero's own 112px of bottom padding now sits directly above the ask
   block, so the same "huge white space" showed up one section higher. The hero
   itself is unchanged; only the ground under it tightens. */
.join-hero {
  padding-bottom: var(--section-y-tight);
}

.step-lead-action {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm) var(--space-md);
  margin: var(--space-lg) 0 var(--space-xl);
}

.step-lead-action span {
  color: var(--ink-secondary);
  font-size: var(--text-sm);
}

/* The ask band used the middle 46rem of a wide screen; the seal now balances
   the crest on the right (2026-09-27). */
.join-ask-seal { display: none; }
@media (min-width: 1024px) {
  .join-ask { display: grid; grid-template-columns: 1fr minmax(0, var(--max-text)) 1fr; align-items: center; column-gap: var(--space-xl); }
  .join-ask-inner { grid-column: 2; grid-template-columns: minmax(0, 1fr); }
  .join-ask-inner .join-ask-crest { display: none; }
  .join-ask::before { content: ""; grid-column: 1; grid-row: 1; justify-self: center; width: clamp(150px, 12vw, 230px); aspect-ratio: 1; background: url("./assets/images/logo-patch-mark.webp") center / contain no-repeat; }
  .join-ask-seal { display: block; grid-column: 3; grid-row: 1; justify-self: center; width: clamp(150px, 12vw, 230px); height: auto; }
}


/* @source website/src/css/62-store.css */
/* ============================================================================
   STORE
   ADR-005: one page, two clearly separated sections, no shared cart. The two
   halves are visually distinct because they are genuinely different: different
   owners, different fulfilment, different checkout.
   ========================================================================= */

.page-store main { padding-top: var(--header-height); }

.store-masthead {
  padding: var(--section-y) var(--gutter) var(--section-y-tight);
  border-bottom: var(--border);
}

.store-masthead-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.store-masthead h1 {
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  max-width: 18ch;
}

/* The XO asked for obvious movement between the two counters. */
.store-jump {
  display: grid;
  gap: var(--space-xs);
  margin-top: var(--space-xl);
}

.store-jump a {
  display: grid;
  gap: var(--space-3xs);
  padding: var(--space-sm) var(--space-md);
  border: var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-raised);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    background var(--duration-fast) var(--ease-out);
}

.store-jump a:hover {
  border-color: var(--ink);
  background: var(--white);
}

.store-jump-label {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
}

.store-jump-note {
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

@media (min-width: 720px) {
  .store-jump { grid-template-columns: 1fr 1fr; gap: var(--space-sm); }
}

/* --- Sections --------------------------------------------------------------- */
.store-section { padding: var(--section-y) var(--gutter); }
.store-section--merch { background: var(--surface-raised); border-top: var(--border); }

.store-section-inner { max-width: var(--max); margin: 0 auto; }

.store-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-bottom: var(--space-sm);
  border-bottom: 2px solid var(--ink);
}

.store-section-head h2 { margin: 0; }

.store-section-meta {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

.store-section-lede {
  margin-top: var(--space-md);
  max-width: var(--measure);
  color: var(--ink-secondary);
  font-size: var(--text-md);
  line-height: var(--leading-md);
}

/* --- Unit essentials --------------------------------------------------------
   A price list, not cards. Nine priced rows read as an institution publishing its
   figures; nine decorated boxes would read as a marketing page. The price sits in
   its own column so the numbers align down the page and stay scannable. */
.essentials-list {
  list-style: none;
  margin: var(--space-xl) 0 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.essentials-list li {
  display: grid;
  gap: var(--space-3xs) var(--space-2xl);
  padding-block: var(--space-md);
  border-top: var(--border);
}

.essentials-list li:last-child { border-bottom: var(--border); }
.essentials-list h3 { margin: 0; font-size: var(--text-md); }
.essentials-list p { margin: 0; color: var(--ink-secondary); }

.essentials-price {
  color: var(--ink);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

@media (min-width: 720px) {
  .essentials-list li {
    grid-template-columns: minmax(12rem, 18rem) 1fr minmax(5rem, auto);
    align-items: baseline;
  }
  .essentials-price { text-align: right; }
}

.store-cta-row {
  margin-top: var(--space-xl);
  display: grid;
  gap: var(--space-sm);
  justify-items: start;
}

.store-note {
  margin: 0;
  max-width: var(--measure);
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

/* --- Merchandise grid -------------------------------------------------------
   The product photograph does the work. No card chrome, no shadow, no hover
   lift: a hairline and the image itself. */
.merch-grid {
  list-style: none;
  margin: var(--space-xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-lg) var(--space-md);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}

.merch-link {
  display: grid;
  gap: var(--space-xs);
  height: 100%;
  align-content: start;
}

.merch-media {
  display: block;
  overflow: hidden;
  border: var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
}

.merch-media img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  transition: transform var(--duration-slow) var(--ease-out);
}

.merch-link:hover .merch-media img { transform: scale(1.03); }
.merch-link:hover .merch-title { text-decoration: underline; text-underline-offset: 3px; }

.merch-body { display: grid; gap: var(--space-3xs); }

.merch-category {
  font-size: var(--text-2xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.merch-title {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-medium);
  color: var(--ink);
  text-wrap: pretty;
}

.merch-price {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* --- Buttons ---------------------------------------------------------------- */
.page-store .button,
.page-cadet-dashboard .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--space-xs) var(--space-lg);
  border-radius: var(--radius);
  font-family: var(--font-text);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  border: 1px solid transparent;
  /* Transition and depth are owned by 68-button.css. */
}

.page-store .button.primary,
.page-cadet-dashboard .button.primary {
  background-color: var(--accent);
  color: var(--white);
}

.page-store .button.primary:hover,
.page-cadet-dashboard .button.primary:hover { background-color: var(--accent-hover); }

/* ============================================================================
   CADET AND FAMILY ACCESS (ADR-009)
   A signpost, not a portal. There is no login here to attack and no cadet data
   behind it: the gate is a managed access check and the records live nationally.
   ========================================================================= */

.page-cadet-dashboard main { padding-top: var(--header-height); }

.access-page { padding: var(--section-y) var(--gutter); }

.access-inner {
  max-width: var(--max-text);
  margin: 0 auto;
}

.access-block {
  margin-top: var(--space-2xl);
  padding-top: var(--space-lg);
  border-top: var(--border);
}

.access-block h2 { font-size: var(--text-lg); line-height: var(--leading-lg); }
.access-block p { color: var(--ink-secondary); }
.access-block .button { margin-top: var(--space-2xs); }

.access-status {
  padding: var(--space-sm) var(--space-md);
  background: var(--blue-050);
  border-left: 3px solid var(--navy-600);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  color: var(--ink) !important;
}

.access-footnote {
  margin-top: var(--space-2xl);
  padding-top: var(--space-md);
  border-top: var(--border);
  font-size: var(--text-sm);
  color: var(--ink-muted);
}


/* @source website/src/css/63-footer.css */
/* ============================================================================
   FOOTER  (round 2, parity ruling 13, 2026-11-05)
   The Buffalo RiverWorks footer (#rw-footer) rebuilt for the division: a navy
   band with the brand block and three link columns, a centred logo row (the
   national emblem, then the sponsors), then a darker legal bar.
   New ft-* names on purpose: 50-legacy.css still carries !important rules for
   the old footer-* classes, and none of them may reach this markup.
   Every pair is an opaque token value (BUG-003): --ink-inverse-muted is 9.6:1
   on --navy-900, white is 16:1.
   ========================================================================= */

.site-footer {
  padding: 0;
  background: var(--navy-900);
  color: var(--white);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.site-footer p { margin: 0; max-width: none; color: inherit; }

.site-footer .ft-in {
  width: min(1240px, calc(100% - 2 * var(--gutter)));
  margin: 0 auto;
}

/* Round 3: the brand block, then the three link columns centred as one group
   in the space to its right. */
.site-footer .ft-top {
  display: grid;
  grid-template-columns: minmax(0, 22rem) 1fr;
  column-gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: start;
  padding-top: clamp(3rem, 6vw, 4.5rem);
}

.site-footer .ft-cols {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(2.5rem, 5vw, 4.5rem);
}

/* Brand: seal, name, one line, the social row, the one call to action, all
   centred in the block (round 3). */
.site-footer .ft-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 22rem;
}

.site-footer .ft-seal {
  display: block;
  min-height: 0;
  margin: 0 auto var(--space-sm);
}

.site-footer .ft-seal img {
  display: block;
  width: 104px;
  height: auto;
}

.site-footer .ft-name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-snug);
  line-height: 1.15;
}

.site-footer .ft-lead {
  margin-top: var(--space-2xs);
  color: var(--ink-inverse-muted);
  font-size: var(--text-base);
  line-height: var(--leading-base);
}

.site-footer .ft-soc {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: var(--space-md);
}

.site-footer .ft-soc a {
  display: grid;
  place-items: center;
  width: 44px;
  min-height: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--navy-950);
  box-shadow: inset 0 0 0 1px var(--line-inverse);
  color: var(--white);
  transition: transform var(--duration) var(--ease-out), background var(--duration) var(--ease-out);
}

.site-footer .ft-soc a:hover { background: var(--navy-700); transform: translateY(-2px); }
.site-footer .ft-soc svg { width: 18px; height: 18px; }

.site-footer .ft-join {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: var(--space-md);
  padding: 0 var(--space-md);
  border-radius: var(--radius-pill);
  background: var(--red-600);        /* white on it 5.06:1 */
  color: var(--white);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-out);
}

.site-footer .ft-join:hover { background: var(--red-700); }

/* Columns: caps heading with the short accent rule under it. Size, weight,
   tracking, case and spacing are RiverWorks' #rw-footer column h4 exactly
   (read from its CSS 2026-11-05): 26px, 800, 0.08em, uppercase, 22px below
   with 12px to the rule; 15px and 18px below on a phone. */
.site-footer .ft-h {
  position: relative;
  margin-bottom: 22px;
  padding-bottom: 12px;
  color: var(--white);
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: var(--weight-black);
  letter-spacing: 0.08em;
  line-height: 1.3;
  text-transform: uppercase;
}

.site-footer .ft-h::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 32px;
  height: 3px;
  border-radius: 2px;
  background: var(--red-600);
}

.site-footer .ft-links {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 0;
}

.site-footer .ft-links a {
  display: block;
  min-height: 0;
  padding: 6px 0;
  color: var(--ink-inverse-muted);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: 1.5;
  transition: color var(--duration-fast) var(--ease-out);
}

.site-footer .ft-links a:hover { color: var(--white); text-decoration: underline; text-underline-offset: 3px; }

/* Logo row: "Our family of companies" in RiverWorks, here the national
   program, then the division's sponsors. The emblem is a transparent cut with
   white lettering, so it sits on the navy with no white card. The sponsor
   artwork is supplied on white, so each one sits on the same white tile. */
.site-footer .ft-fam {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding: var(--space-xl) 0 var(--space-2xl);
  border-top: 1px solid var(--line-inverse);
  text-align: center;
}

.site-footer .ft-fam-h,
.site-footer .ft-fam-sub {
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.site-footer .ft-national {
  display: block;
  min-height: 0;
  margin-top: var(--space-md);
  transition: transform var(--duration) var(--ease-out);
}

.site-footer .ft-national:hover { transform: translateY(-2px); }

.site-footer .ft-national img {
  display: block;
  width: clamp(150px, 16vw, 200px);
  height: auto;
}

.site-footer .ft-fam-sub {
  margin-top: var(--space-xl);
  color: var(--ink-inverse-muted);
}

/* Sponsors (round 3): no tiles. Each logo is cut out to a transparent
   background (assets/images/sponsors/footer/) and shown as its white version
   on the navy; on hover or focus the colour cut-out fades in over it. One
   height for every mark, bottoms on a shared baseline. */
.site-footer .ft-sponsors {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-end;
  gap: var(--space-lg) clamp(1.75rem, 4vw, 3rem);
  margin: var(--space-lg) 0 0;
  padding: 0;
  list-style: none;
}

.site-footer .ft-sponsors a {
  position: relative;
  display: block;
  min-height: 0;
  border-radius: var(--radius-sm);
  transition: transform var(--duration) var(--ease-out);
}

.site-footer .ft-sponsors img {
  display: block;
  width: auto;
  height: 72px;
  max-width: 112px;
  object-fit: contain;
  object-position: bottom center;
}

.site-footer .ft-sponsors .ft-sp-color {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 220ms var(--ease-out);
}

.site-footer .ft-sponsors .ft-sp-white { transition: opacity 220ms var(--ease-out); }

.site-footer .ft-sponsors a:hover,
.site-footer .ft-sponsors a:focus-visible { transform: translateY(-2px); }
.site-footer .ft-sponsors a:hover .ft-sp-color,
.site-footer .ft-sponsors a:focus-visible .ft-sp-color { opacity: 1; }
.site-footer .ft-sponsors a:hover .ft-sp-white,
.site-footer .ft-sponsors a:focus-visible .ft-sp-white { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .site-footer .ft-sponsors a:hover,
  .site-footer .ft-sponsors a:focus-visible { transform: none; }
}

/* Legal bar: one row on a desktop, centred lines on a phone. */
.site-footer .ft-bar {
  padding: var(--space-md) 0;
  background: var(--navy-950);
}

.site-footer .ft-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-md);
  color: var(--ink-inverse-muted);
  font-size: var(--text-sm);
}

.site-footer .ft-left {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3xs) var(--space-md);
}

.site-footer .ft-legal { display: inline-flex; gap: var(--space-md); }

.site-footer .ft-bar a {
  display: inline;
  min-height: 0;
  color: var(--white);
  font-weight: var(--weight-regular);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.site-footer .ft-credit a { text-decoration: none; }
.site-footer .ft-credit b { font-style: italic; font-weight: var(--weight-black); }
.site-footer .ft-credit a:hover { text-decoration: underline; }

/* Tablet: the brand, centred, runs across the top; the three columns share
   the row under it, centred as a group. */
@media (max-width: 1100px) {
  .site-footer .ft-top {
    grid-template-columns: 1fr;
    row-gap: var(--space-xl);
  }
  .site-footer .ft-brand { max-width: 30rem; margin-inline: auto; }
}

/* Phone: everything centred, as RiverWorks does under 768px; its column
   headings drop to 15px with 18px below. */
@media (max-width: 767px) {
  .site-footer .ft-cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: var(--space-md);
    row-gap: var(--space-xl);
  }
  .site-footer .ft-seal img { width: 88px; }
  .site-footer .ft-visit { grid-column: 1 / -1; }
  .site-footer .ft-col { text-align: center; }
  .site-footer .ft-h { font-size: 15px; margin-bottom: 18px; }
  .site-footer .ft-h::after { left: 50%; transform: translateX(-50%); }
  .site-footer .ft-links { align-items: center; }
  .site-footer .ft-sponsors { gap: var(--space-md) var(--space-lg); }
  .site-footer .ft-sponsors img { height: 52px; max-width: 84px; }
  .site-footer .ft-bottom,
  .site-footer .ft-left { flex-direction: column; justify-content: center; text-align: center; }
  /* Room for the floating Join pill, which sits bottom-right on phones. */
  .site-footer .ft-bar { padding-bottom: calc(var(--space-md) + env(safe-area-inset-bottom, 0px)); }
}

/* ============================================================================
   FORM STATES
   The contact form previously had no error or confirmation state at all.
   ========================================================================= */

.field-error {
  display: block;
  margin-top: var(--space-3xs);
  color: var(--red-800);          /* 7.9:1 on white */
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.contact-form [aria-invalid="true"] {
  border-color: var(--red-700);
  outline-color: var(--red-700);
}

.contact-msg {
  margin: var(--space-sm) 0 0;
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

.contact-msg[data-state="ok"] {
  background: var(--blue-050);
  border-left: 3px solid var(--navy-600);
  color: var(--ink);
}

.contact-msg[data-state="error"] {
  background: #fdeef1;
  border-left: 3px solid var(--red-700);
  color: var(--red-800);
}

/* ============================================================================
   404 - kept quiet and useful. Its presence also switches Cloudflare Pages
   from SPA fallback (every bad URL soft-404s as the homepage) to real 404s.
   ========================================================================= */

.page-404 main { padding-top: var(--header-height); }
.notfound { padding: var(--section-y) var(--gutter) var(--section-y); }
.notfound-inner { max-width: var(--max-text); margin: 0 auto; }

.notfound-links {
  display: grid;
  gap: 0;
  margin-top: var(--space-lg);
}

.notfound-links a {
  padding: var(--space-sm) 0;
  border-top: var(--border);
  font-weight: var(--weight-semibold);
  color: var(--ink);
  transition: color var(--duration-fast) var(--ease-out);
}

.notfound-links a:last-child { border-bottom: var(--border); }
.notfound-links a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }


/* @source website/src/css/64-about.css */
/* =============================================================================
   ABOUT - rebuilt 2026-08-23
   Replaces the icon triad and the alternating 50/50 block, both banned in
   design-system.md. The page is now photograph, narrative, comparison, list.
   Four different layout families, so the page has a cadence rather than a loop.
   ========================================================================== */

/* The header is fixed, so pages without a full-bleed hero clear it on main.
   Same convention as .page-join, .page-store, .page-404. */
.page-about main { padding-top: var(--header-height); }

.about-masthead {
  padding: var(--section-y) var(--gutter) var(--section-y-tight);
}

.about-masthead-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.about-masthead h1 {
  margin: 0;
  max-width: 18ch;
  font-size: var(--text-4xl);
  line-height: var(--leading-4xl);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.about-masthead .lede {
  margin: var(--space-lg) 0 0;
}

.about-masthead-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-xl);
}

/* --- The plate --------------------------------------------------------------
   One photograph at full width, with the caption underneath in a reading
   column. Deliberately NOT the two-column dark plate the Join page uses; two
   pages sharing one layout family is how a site starts to loop. */
.about-plate {
  margin: 0;
  display: grid;
  gap: 0;
}

.about-plate img {
  width: 100%;
  /* height:auto is load-bearing. The img carries width/height attributes so the
     browser can reserve space and avoid a layout shift, but those attributes act
     as a definite height, which makes aspect-ratio a no-op. Without this the
     photograph rendered 900px tall regardless of the ratio below. */
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
}

/* The caption has to sit on the same left edge as every other section. Those
   sections pad by --gutter and then centre a --max inner box, so the caption
   centres a box of (--max + 2 * --gutter) and pads inside it. Centring --max
   directly, then padding, pushed it a gutter's width off the page grid. */
.about-plate figcaption {
  width: 100%;
  max-width: min(calc(var(--max) + (2 * var(--gutter))), 100%);
  margin-inline: auto;
  padding: var(--space-md) var(--gutter) 0;
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

@media (min-width: 900px) {
  .about-plate img { aspect-ratio: 21 / 9; }
}

/* --- Narrative --------------------------------------------------------------
   Prose, set at a real reading measure. This is the section that does the work
   the three icon cards were pretending to do. */
.about-narrative {
  padding: var(--section-y) var(--gutter);
}

.about-narrative-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.about-narrative h2,
.about-eligibility h2,
.about-training h2 {
  margin: 0;
  max-width: 20ch;
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}

.about-prose {
  margin-top: var(--space-xl);
  max-width: var(--measure);
}

.about-prose p {
  margin: 0;
  font-size: var(--text-md);
  line-height: var(--leading-md);
  color: var(--ink-secondary);
}

.about-prose p + p { margin-top: var(--space-md); }
.about-prose strong { color: var(--ink); font-weight: var(--weight-semibold); }

.about-section-lede {
  margin: var(--space-md) 0 0;
  max-width: var(--measure);
  color: var(--ink-secondary);
}

/* --- Eligibility comparison -------------------------------------------------
   A real table, because this is genuinely tabular: two programmes compared on
   the same four axes. Two decorated cards forced the reader to hold one column
   in their head while reading the other. On narrow screens the table becomes
   stacked blocks, with each cell labelled by its row header. */
.about-eligibility {
  padding: var(--section-y) var(--gutter);
  background: var(--surface-sunken);
}

.about-eligibility-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.compare {
  width: 100%;
  margin-top: var(--space-2xl);
  border-collapse: collapse;
  text-align: left;
}

.compare th,
.compare td {
  padding: var(--space-md) var(--space-md) var(--space-md) 0;
  vertical-align: top;
  border-top: var(--border);
}

.compare thead th { border-top: 0; padding-top: 0; }

.compare-name {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  letter-spacing: var(--tracking-snug);
  color: var(--ink);
}

.compare-sub {
  display: block;
  margin-top: var(--space-3xs);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-regular);
  color: var(--ink-muted);
}

.compare tbody th {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}

.compare tbody td { color: var(--ink-secondary); }

@media (max-width: 719px) {
  .compare thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .compare, .compare tbody, .compare tr, .compare th, .compare td { display: block; }
  .compare tr { padding-block: var(--space-md); border-top: var(--border); }
  .compare th, .compare td { border-top: 0; padding: 0; }
  .compare tbody th { margin-bottom: var(--space-2xs); }
  .compare tbody td { padding-block: var(--space-2xs); }
  /* Without the header row, each cell has to name its own programme. */
  .compare tbody td::before {
    content: attr(data-label) ": ";
    font-weight: var(--weight-semibold);
    color: var(--ink);
  }
}

@media (min-width: 720px) {
  .compare { table-layout: fixed; }
  .compare th:first-child { width: 11rem; }
}

.about-requirements {
  list-style: none;
  margin: var(--space-2xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-lg);
}

.about-requirements li { display: grid; gap: var(--space-3xs); }

.about-requirements span {
  font-size: var(--text-xs);
  line-height: var(--leading-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.about-requirements p { margin: 0; color: var(--ink-secondary); }

@media (min-width: 720px) {
  .about-requirements { grid-template-columns: repeat(3, 1fr); gap: var(--space-xl); }
}

/* --- Training ---------------------------------------------------------------
   Three grouped lists, not three cards. The grouping is the information; a card
   around each one would add a box and nothing else. */
.about-training {
  padding: var(--section-y) var(--gutter);
}

.about-training-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.training-groups {
  margin-top: var(--space-2xl);
  display: grid;
  gap: var(--space-xl);
}

.training-group h3 {
  margin: 0 0 var(--space-sm);
  padding-bottom: var(--space-2xs);
  border-bottom: var(--border-strong);
  font-size: var(--text-base);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  font-family: var(--font-text);
  font-weight: var(--weight-semibold);
}

.training-group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2xs);
  color: var(--ink-secondary);
}

@media (min-width: 720px) {
  .training-groups { grid-template-columns: repeat(3, 1fr); gap: var(--space-2xl); }
}

/* --- Close ------------------------------------------------------------------ */
.about-close {
  padding: var(--section-y) var(--gutter);
  background: var(--surface-inverse);
}

.about-close-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.about-close h2 {
  margin: 0;
  max-width: 22ch;
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;
  color: var(--ink);
}

.about-close p {
  margin: var(--space-md) 0 0;
  max-width: var(--measure);
  color: var(--ink-secondary);
}

.about-close-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-xl);
}


/* @source website/src/css/65-resources.css */
/* =============================================================================
   RESOURCES - rebuilt 2026-08-23
   Was four identical icon cards. This is an index: hairline rows grouped by
   audience, where a row is either a real link or an honest "not published yet".
   The unavailable rows are deliberately not links and are visually quieter, so
   the page never sells a destination it does not have.
   ========================================================================== */

.page-resource-hub main { padding-top: var(--header-height); }

.rh-masthead {
  padding: var(--section-y) var(--gutter) var(--section-y-tight);
}

.rh-masthead-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.rh-masthead h1 {
  margin: 0;
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  letter-spacing: var(--tracking-tight);
}

.rh-masthead .lede { margin: var(--space-md) 0 0; }

.rh-index {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter) var(--section-y);
  display: grid;
  gap: var(--space-2xl);
}

.rh-group-head h2 {
  margin: 0;
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  letter-spacing: var(--tracking-snug);
}

.rh-group-head p {
  margin: var(--space-3xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  max-width: var(--measure-narrow);
}

.rh-list {
  list-style: none;
  margin: var(--space-md) 0 0;
  padding: 0;
}

.rh-list li { border-top: var(--border); }
.rh-list li:last-child { border-bottom: var(--border); }

.rh-list a,
.rh-pending {
  display: grid;
  gap: var(--space-3xs);
  padding-block: var(--space-md);
  text-decoration: none;
  color: inherit;
}

.rh-list a { transition: background-color var(--duration) var(--ease-out); }

.rh-list a:hover { background: var(--surface-sunken); }
.rh-list a:hover .rh-item { text-decoration: underline; text-underline-offset: 0.18em; }

.rh-item {
  font-family: var(--font-display);
  font-size: var(--text-md);
  line-height: var(--leading-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--ink);
}

.rh-note {
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  max-width: var(--measure);
}

.rh-ext { font-size: 0.85em; }

/* A row with nothing behind it yet. Quieter, and never a link, so a reader can
   tell at a glance which rows go somewhere. Not conveyed by colour alone: the
   note itself says it is not published. */
.rh-pending .rh-item { color: var(--ink-muted); font-weight: var(--weight-medium); }
.rh-pending .rh-note { color: var(--ink-muted); }

@media (min-width: 900px) {
  .rh-index { gap: var(--space-3xl); }
  .rh-group {
    display: grid;
    grid-template-columns: minmax(14rem, 20rem) 1fr;
    gap: var(--space-2xl);
    align-items: start;
  }
  .rh-list { margin-top: 0; }
  .rh-list a,
  .rh-pending {
    grid-template-columns: minmax(12rem, 18rem) 1fr;
    gap: var(--space-2xs) var(--space-xl);
    align-items: baseline;
  }
  .rh-list a { margin-inline: calc(var(--space-sm) * -1); padding-inline: var(--space-sm); }
}

/* --- Close ------------------------------------------------------------------ */
.rh-close {
  padding: var(--section-y) var(--gutter);
  background: var(--surface-sunken);
  border-top: var(--border);
}

.rh-close-inner {
  max-width: var(--max);
  margin: 0 auto;
}

.rh-close h2 {
  margin: 0;
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
  letter-spacing: var(--tracking-tight);
}

.rh-close p {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  color: var(--ink-secondary);
}

.rh-close-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-lg);
}

/* --- Contact: "Reach out about" boxes are links (comment 63) ----------------
   The heading link stretches over the whole card, so the box is one target
   and a screen reader still hears a short link name, not the whole card. */
.reason-card { position: relative; cursor: pointer; }
.reason-link { color: inherit; text-decoration: none; }
.reason-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
/* The ring moves from the link text to the stretched layer, so it outlines the
   whole card. Still the token colour, so it follows the surface. */
.reason-link:focus-visible { outline-style: none; }
.reason-link:focus-visible::after {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}
.reason-card .reason-go {
  margin-top: var(--space-sm);
  color: var(--blue-700);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
}
.reason-card:hover .reason-go { text-decoration: underline; text-underline-offset: 3px; }

/* The unit patch sits centred in the empty space to the right (2026-09-27). */
.rh-close-mark { display: block; width: clamp(140px, 22vw, 260px); height: auto; margin: var(--space-xl) auto 0; }
@media (min-width: 768px) {
  .rh-close-inner { display: grid; grid-template-columns: minmax(0, var(--measure)) 1fr; column-gap: var(--space-xl); }
  .rh-close-inner > :not(.rh-close-mark) { grid-column: 1; }
  .rh-close-mark { grid-column: 2; grid-row: 1 / span 3; align-self: center; justify-self: center; margin: 0; }
}

/* --- Forms, answers and basics (2026-11-05, go-live parity rulings 3 and 4) ---
   Same column as the searchable list above, so the page reads as one index.
   The answers reuse the Join page's .qa rows (61-join.css). */
.rh-forms,
.rh-faq,
.rh-basics {
  padding-block: var(--section-y-tight);
  border-top: var(--border);
  scroll-margin-top: var(--header-height);
}

.rh-basics { background: var(--surface-sunken); padding-bottom: var(--section-y); }

/* The filter hides with [hidden]; .rh-form is flex, which would override it. */
.rh-form[hidden],
.rh-packet[hidden],
.rh-faq-group[hidden] { display: none; }

.rh-section-inner {
  max-width: 76rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.rh-section-inner > h2 {
  margin: 0;
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  color: var(--ink);
}

.rh-section-lede {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  color: var(--ink-secondary);
}

.rh-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--space-md);
  margin-top: var(--space-lg);
}

.rh-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-md);
  border: var(--border-strong);
  border-radius: var(--radius);
  background: var(--surface-raised);
}

.rh-form h3,
.rh-packet h3 {
  margin: 0;
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  color: var(--ink);
}

.rh-form p { margin: 0; color: var(--ink-secondary); }

.rh-form .rh-form-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: auto;
  padding-top: var(--space-xs);
}

.rh-form-size {
  margin-left: 0.4em;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  opacity: 0.85;
}

.rh-packet {
  margin-top: var(--space-lg);
  max-width: var(--measure);
}

.rh-packet ul { margin: var(--space-xs) 0; padding-left: 1.2em; color: var(--ink-secondary); }
.rh-packet li + li { margin-top: var(--space-3xs); }
.rh-packet p { margin: 0; color: var(--ink-secondary); font-size: var(--text-sm); line-height: var(--leading-sm); }

.rh-faq-group { margin-top: var(--space-lg); }

.rh-faq-group > h3 {
  margin: 0 0 var(--space-xs);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent);
}

/* Every group closes with its own rule (the Join page's .qa:last-of-type
   assumes a single group). */
.rh-faq-group .qa:last-of-type { border-bottom: 1px solid var(--line-strong); }

.rh-faq .qa-body ol,
.rh-faq .qa-body ul,
.rh-basics .qa-body ol,
.rh-basics .qa-body ul {
  margin: 0 0 var(--space-sm);
  padding-left: 1.3em;
  color: var(--ink-secondary);
}

.rh-faq .qa-body li + li,
.rh-basics .qa-body li + li { margin-top: var(--space-3xs); }

.rh-quote {
  margin: 0 0 var(--space-xs);
  padding-left: var(--space-sm);
  border-left: 3px solid var(--accent);
}

.qa-body .rh-quote p { color: var(--ink); font-style: italic; }

.qa-body .rh-quote-source { font-size: var(--text-xs); color: var(--ink-muted); }

@media (max-width: 560px) {
  .rh-form .rh-form-links .button { flex: 1 1 auto; justify-content: center; }
  .rh-faq .qa-body,
  .rh-basics .qa-body { padding-right: 0; }
}

/* --- Round 2 order (ruling 14, 2026-11-05) ---------------------------------
   Search box, then the answers as ONE list with only the questions showing,
   then the forms centred, the basics, the link index, and "Cannot find it?".
   The search box no longer heads a list, so it needs no section of space. */
.page-resource-hub .rh-search-section { padding-block: 0 var(--space-lg); }
.rh-search-section .rh-count { margin-bottom: 0; }
.rh-faq { padding-top: var(--space-lg); }

/* Questions only: the one-line short answer stays in the markup so the filter
   still finds it, but the closed row shows just the question. */
.rh-faq .qa-a { display: none; }
.rh-faq-list { margin-top: var(--space-lg); }

/* Enrollment forms: the words above and below the two boxes centred. */
.rh-forms-centred .rh-section-inner > .eyebrow,
.rh-forms-centred .rh-section-inner > h2 { text-align: center; }
.rh-forms-centred .rh-section-lede { margin-inline: auto; text-align: center; }
.rh-forms-centred .rh-form-grid { max-width: 56rem; margin-inline: auto; }
.rh-forms-centred .rh-packet { margin-inline: auto; text-align: center; }
.rh-forms-centred .rh-packet ul { padding: 0; list-style: none; }

/* --- Round 3 (owner review, 2026-11-05) -------------------------------------
   1. The page title and its line centred over the centred search box.
   2. One list of questions with topic chips and a "Show all" button (the
      "More from the division" link index became questions in that list).
   3. The forms eyebrow optically centred: uppercase tracking leaves a space
      after the last letter, so the start gets the same amount.
   4. "Cannot find it?" twice the size, the patch 30% larger. */
.rh-masthead-inner { text-align: center; }
.rh-masthead .lede { margin-inline: auto; }
.rh-search-section .rh-count,
.rh-search-section .rh-empty { max-width: none; text-align: center; }

.rh-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-md);
}
.rh-chips[hidden] { display: none; }

.rh-chip {
  appearance: none;
  min-height: 44px;
  padding: 0 var(--space-md);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  transition: background-color var(--duration) var(--ease-out), color var(--duration) var(--ease-out), border-color var(--duration) var(--ease-out);
}
.rh-chip:hover { border-color: var(--ink); }
.rh-chip[aria-pressed="true"] {
  background: var(--surface-inverse);
  border-color: var(--surface-inverse);
  color: var(--ink-inverse);
}
.rh-chip:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }

.rh-faq-list[hidden],
.rh-faq-list .qa[hidden],
.rh-show-all[hidden] { display: none; }

.rh-more-wrap { max-width: none; margin: var(--space-lg) 0 0; text-align: center; }

.rh-forms-centred .rh-section-inner > .eyebrow { max-width: none; margin-inline: auto; padding-left: var(--tracking-caps); }

.rh-close h2 {
  font-size: calc(var(--text-xl) * 2);
  line-height: 1.05;
}
.rh-close-mark { width: clamp(182px, 28.6vw, 338px); }

/* Round 4 (owner, 2026-11-05): the space left of "Cannot find it?" equals the
   space right of the patch. Both edges sit on the section's own padding. */
@media (min-width: 64rem) {
  .rh-close-mark { justify-self: end; }
}


/* @source website/src/css/66-policy.css */
/* ============================================================================
   PRIVACY PAGE
   One column of prose, no cards, no icons. A parent scanning for "what do you
   collect" should hit the answer in the first paragraph and be able to read the
   rest like a letter. Type and measure carry it; nothing here is decorated.
   ========================================================================= */

.policy-masthead {
  padding: var(--space-3xl) var(--gutter) var(--space-xl);
  border-bottom: 1px solid var(--line);
}

.policy-masthead-inner,
.policy-body {
  max-width: var(--measure-wide);
  margin-inline: auto;
}

.policy-masthead .lede {
  margin-top: var(--space-sm);
  max-width: var(--measure);
}

.policy-updated {
  margin-top: var(--space-md);
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

.policy-body {
  padding: var(--space-xl) var(--gutter) var(--space-3xl);
  display: grid;
  gap: var(--space-xl);
}

.policy-block h2 {
  font-size: var(--text-xl);
  margin-bottom: var(--space-xs);
}

.policy-block p {
  max-width: var(--measure);
  color: var(--ink-secondary);
}

.policy-block p + p { margin-top: var(--space-sm); }

/* ============================================================================
   MAP, LOADED ON REQUEST
   The button stands in for the frame at the same size, so nothing shifts when
   the map arrives. It reads as a quiet panel rather than a call to action: the
   real call to action on both pages is the join CTA, not the map.
   ========================================================================= */

.map-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  width: 100%;
  min-height: 320px;
  padding: var(--space-lg) var(--space-md);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-text);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease-out);
}

.map-loader:hover { border-color: var(--line-strong); background: var(--white); }

.map-loader-place {
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
}

.map-loader-action {
  color: var(--blue-700);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
}

.map-loader-note {
  margin-top: var(--space-2xs);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  max-width: 42ch;
  text-wrap: balance;
}

/* The frame main.js swaps in. Matches the box the button occupied. */
.map-frame {
  display: block;
  width: 100%;
  height: 320px;
  border: 0;
  border-radius: var(--radius);
}

.contact-map .map-loader,
.contact-map .map-frame { min-height: 360px; height: 360px; }

/* --- Staff sign in (2026-09-27) ------------------------------------------- */
.staff-signin {
  display: grid;
  place-items: center;
  min-height: 70vh;
  padding: calc(var(--header-height) + var(--space-lg)) var(--gutter) var(--space-2xl);
  background: var(--surface-sunken);
}
.staff-signin-card {
  width: min(30rem, 100%);
  padding: var(--space-xl);
  border: var(--border);
  border-radius: 18px;
  background: var(--surface-raised);
  box-shadow: 0 24px 60px rgba(5, 15, 31, 0.12);
  text-align: center;
}
.staff-signin-mark { display: block; width: 112px; height: auto; margin: 0 auto var(--space-md); }
.staff-signin h1 { margin: var(--space-2xs) 0 var(--space-sm); font-size: var(--text-xl); line-height: var(--leading-xl); }
.staff-signin p { margin: 0; color: var(--ink-secondary); }
.staff-signin-go { margin-top: var(--space-lg); }
.staff-signin .staff-signin-note { margin-top: var(--space-md); font-size: var(--text-sm); color: var(--ink-muted); }
.staff-signin-note a { color: var(--blue-700); font-weight: var(--weight-semibold); text-decoration: underline; text-underline-offset: 3px; }


/* @source website/src/css/67-roster.css */
/* =============================================================================
   LEADERSHIP ROSTER - built 2026-09-01
   The page was four placeholder cards saying leadership information was not
   available. It is now the division's own published staff list. Hairline rows,
   same idiom as the resources index, because a roster is a list of facts and a
   card grid would only pad it out. Rank is a fixed-width column on desktop so
   the eye can scan ranks and names as two clean edges.
   ========================================================================== */

.page-leadership main { padding-top: var(--header-height); }

.rost-masthead { padding: var(--section-y) var(--gutter) var(--section-y-tight); }

.rost-masthead-inner { max-width: var(--max); margin: 0 auto; }

.rost-masthead h1 {
  margin: var(--space-2xs) 0 0;
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  letter-spacing: var(--tracking-tight);
}

.rost-masthead .lede { margin: var(--space-md) 0 0; max-width: var(--measure); }

.rost-index {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter) var(--section-y);
  display: grid;
  gap: var(--space-2xl);
}

.rost-group-head h2 {
  margin: 0;
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  letter-spacing: var(--tracking-snug);
}

.rost-group-head p {
  margin: var(--space-3xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  max-width: var(--measure-narrow);
}

.rost-list { list-style: none; margin: var(--space-md) 0 0; padding: 0; }

.rost-list li {
  display: grid;
  gap: var(--space-3xs);
  padding-block: var(--space-md);
  border-top: var(--border);
}

.rost-list li:last-child { border-bottom: var(--border); }

.rost-rank {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.rost-name {
  font-family: var(--font-display);
  font-size: var(--text-md);
  line-height: var(--leading-md);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  color: var(--ink);
}

.rost-role {
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  max-width: var(--measure);
}

.rost-mail {
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  word-break: break-word;
}

/* No published address for this officer. Not a link, and it says why, so the
   absence never reads as a broken link. */
.rost-mail-none { color: var(--ink-muted); }

@media (min-width: 900px) {
  .rost-index { gap: var(--space-3xl); }
  .rost-group {
    display: grid;
    grid-template-columns: minmax(14rem, 20rem) 1fr;
    gap: var(--space-2xl);
    align-items: start;
  }
  .rost-list { margin-top: 0; }
  .rost-list li {
    grid-template-columns: 4.5rem minmax(10rem, 14rem) 1fr;
    gap: var(--space-2xs) var(--space-lg);
    align-items: baseline;
  }
  .rost-list .rost-role { grid-column: 3; grid-row: 1; }
  .rost-list .rost-mail { grid-column: 3; grid-row: 2; }
}

/* --- Close ------------------------------------------------------------------ */
.rost-close {
  padding: var(--section-y) var(--gutter);
  background: var(--surface-sunken);
  border-top: var(--border);
}

.rost-close-inner { max-width: var(--max); margin: 0 auto; }

.rost-close h2 {
  margin: 0;
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
  letter-spacing: var(--tracking-tight);
}

.rost-close p {
  margin: var(--space-sm) 0 0;
  max-width: var(--measure);
  color: var(--ink-secondary);
}

.rost-close-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-top: var(--space-lg);
}


/* @source website/src/css/68-button.css */
/* ============================================================================
   TACTILE BUTTON  (review round 1, comments 10-13, 28-37, 40, 41, 47)
   Camilo picked uiverse "fat-zebra-11" and asked for it adapted to the unit
   rather than pasted: the physics of that button (layered bevel, inner
   gradient, lift on hover, real press) carried by THIS site's tokens.
   Deliberately dropped: the cart icon, the sparkle burst and the two-state
   "Added" swap. They are e-commerce theatre on a CTA that says "Join the
   Division", and they cost markup every button would have to carry.
   No pseudo-element sits over the label, so the text stays selectable and the
   contrast audit still reads the real foreground.
   ========================================================================= */

/* Every element he tagged with that link, not just the ones already called
   .button: the nav pill (12), the three recruit-card links (28-30), the three
   chart cards (31-33), the floating join pill (35) and the footer join (36). */
.button,
.nav-cta,
.recruit-card a,
.chart-card-cta,
.sticky-join,
.join-footer {
  isolation: isolate;
  border-radius: 14px;
  padding: 0 26px;
  min-height: 56px;
  letter-spacing: var(--tracking-snug);
  text-shadow: 0 1px 1px rgba(5, 15, 31, 0.28);
  transition:
    transform 240ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 240ms cubic-bezier(0.22, 1, 0.36, 1),
    background 160ms ease,
    border-color 160ms ease;
}

/* position is deliberately NOT set on the group. The floating join pill is
   position:fixed in 60-header.css, and this layer loads after it, so a blanket
   `position: relative` here dropped the pill out of its fixed corner and into
   the footer flow at the bottom left, half off screen. Only the members that
   actually need a stacking context get one. */
.button,
.nav-cta,
.recruit-card a,
.chart-card-cta,
.join-footer {
  position: relative;
}

/* The bevel: a light top edge, a grounded bottom edge, and a wide soft cast
   shadow. Three layers, the same way the reference button gets its depth. */
.button.primary,
.nav-cta,
.recruit-card a,
.chart-card-cta,
.sticky-join,
.join-footer {
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.18), rgba(5, 15, 31, 0.12));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    inset 0 -2px 0 rgba(5, 15, 31, 0.22),
    0 10px 20px rgba(7, 19, 38, 0.22),
    0 4px 5px rgba(7, 19, 38, 0.06);
}

.button.secondary {
  background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.9), rgba(10, 29, 58, 0.05));
  text-shadow: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.8),
    0 8px 18px rgba(7, 19, 38, 0.1),
    0 2px 4px rgba(7, 19, 38, 0.05);
}

.button:hover,
.button:focus-visible,
.nav-cta:hover,
.nav-cta:focus-visible,
.recruit-card a:hover,
.recruit-card a:focus-visible,
.chart-card-cta:hover,
.chart-card-cta:focus-visible,
.sticky-join:hover,
.sticky-join:focus-visible,
.join-footer:hover,
.join-footer:focus-visible {
  transform: scale(1.02);
}

.button.primary:hover,
.button.primary:focus-visible,
.nav-cta:hover,
.nav-cta:focus-visible,
.recruit-card a:hover,
.recruit-card a:focus-visible,
.chart-card-cta:hover,
.chart-card-cta:focus-visible,
.sticky-join:hover,
.sticky-join:focus-visible,
.join-footer:hover,
.join-footer:focus-visible {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    inset 0 -2px 0 rgba(5, 15, 31, 0.24),
    0 16px 30px rgba(7, 19, 38, 0.3),
    0 10px 3px -3px rgba(7, 19, 38, 0.05);
}

.button.secondary:hover,
.button.secondary:focus-visible {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 14px 26px rgba(7, 19, 38, 0.14),
    0 6px 3px -3px rgba(7, 19, 38, 0.05);
}

/* Press. The lift collapses and the top highlight inverts, so the button
   reads as pushed in rather than merely darker. */
.button:active,
.nav-cta:active,
.recruit-card a:active,
.chart-card-cta:active,
.sticky-join:active,
.join-footer:active {
  transform: scale(0.995);
  box-shadow:
    inset 0 2px 5px rgba(5, 15, 31, 0.3),
    0 2px 4px rgba(7, 19, 38, 0.12);
}

@media (prefers-reduced-motion: reduce) {
  .button,
  .nav-cta,
  .recruit-card a,
  .chart-card-cta,
  .sticky-join,
  .join-footer { transition: box-shadow 160ms ease, background 160ms ease; }
  .button:hover, .button:focus-visible, .button:active,
  .nav-cta:hover, .nav-cta:focus-visible, .nav-cta:active,
  .recruit-card a:hover, .recruit-card a:focus-visible, .recruit-card a:active,
  .chart-card-cta:hover, .chart-card-cta:focus-visible, .chart-card-cta:active,
  .sticky-join:hover, .sticky-join:focus-visible, .sticky-join:active,
  .join-footer:hover, .join-footer:focus-visible, .join-footer:active { transform: none; }
}

/* Floating Join pill, round 2 (parity ruling 17, 2026-11-05).
   Not on the store, an item or the cart: a family there is buying, and the
   pill sat over the Add to bag and checkout controls. display:none also takes
   it out of the tab order. */
.page-store .sticky-join,
.page-product .sticky-join,
.page-cart .sticky-join { display: none; }

/* Phones: a small pill in the bottom RIGHT corner, clear of the home
   indicator and of a notch in landscape. 44px keeps the touch target. */
@media (max-width: 767px) {
  .sticky-join {
    left: auto;
    right: max(var(--space-sm), calc(env(safe-area-inset-right) + var(--space-2xs)));
    bottom: max(var(--space-sm), calc(env(safe-area-inset-bottom) + var(--space-2xs)));
    min-height: 44px;
    padding: 0 var(--space-sm);
    border-radius: var(--radius-pill);
    font-size: var(--text-sm);
  }
}


/* @source website/src/css/69-headings.css */
/* ============================================================================
   SECTION HEADING, SECOND VOICE  (review round 1, comments 20, 21, 48)
   His note on 48: "im sick of seeing the same style title every time, stacked
   large bold black words." Every section opened with the same 3.6rem Georgia
   slab, so the page had one volume and no rhythm.
   This is the quieter alternative, used where the heading introduces rather
   than announces: a short gold rule, the civic grotesque instead of the serif,
   optically smaller, balanced across two lines instead of stacked down the
   left edge.
   ========================================================================= */

.heading-rule {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.15rem);
  line-height: 1.18;
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  text-wrap: balance;
}

.section-heading--centred {
  max-width: 42ch;
  margin-inline: auto;
  text-align: center;
}

/* The rule reads as a mark of rank, not decoration: same weight and colour as
   the honours accent used elsewhere, never wider than a thumb. */
.section-heading--centred .eyebrow::before {
  content: "";
  display: block;
  width: 42px;
  height: 2px;
  margin: 0 auto var(--space-sm);
  background: var(--honor);
}

.section-heading--centred > * + * {
  margin-top: var(--space-xs);
}

/* Round 2, comment 4. The photograph carries the empty half of the recruit row.
   Centred like the heading above it and capped so it never out-weighs the three
   cards it sits beside. */
.recruit-intro-photo {
  display: block;
  width: 100%;
  max-width: 22rem;
  margin: var(--space-lg) auto 0;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius);
  box-shadow: 0 18px 44px rgba(5, 15, 31, 0.18);
}

@media (max-width: 940px) {
  .recruit-intro-photo { aspect-ratio: 16 / 10; max-width: 100%; }
}

/* Comment 59: "Your first step" on one row, "is simple." on the next, wherever
   the line appears. Two spans rather than a <br> so each half can still wrap on
   a phone narrow enough to need it. */
.first-step span { display: block; }


/* @source website/src/css/70-word-spin.css */
/* ============================================================================
   ROTATING LABEL  (review round 1, comments 17, 18, 19)
   He pointed at uiverse "fresh-lizard-20": a fixed-height window with the words
   spinning up through it behind a soft top and bottom fade. Same mechanism
   here, carried by this site's gold label style instead of the purple.
   The real caption stays in the DOM as visually hidden text, so a screen reader
   still hears which photograph it is describing; only the decoration rotates.
   The track repeats its first word at the end so the loop closes without a jump.
   ========================================================================= */

.word-spin {
  display: block;
  overflow: hidden;
  position: relative;
  height: 1.1rem;
  color: var(--gold-500);
  font-size: 0.76rem;
  font-weight: 950;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The clip: the caption plate is a translucent navy, so the fade has to be the
   same colour or the words appear to slide under a grey bar. */
.word-spin::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Edge feather only. The first version faded across nearly the whole strip,
     which stacked a second layer of navy on top of the caption plate and read
     as a dark bar sitting behind the word. */
  background: linear-gradient(
    rgba(7, 19, 38, 0.7) 0%,
    transparent 22%,
    transparent 78%,
    rgba(7, 19, 38, 0.7) 100%
  );
  pointer-events: none;
}

.word-spin-track {
  display: block;
  animation: word-spin 12s var(--spin-delay, 0s) infinite;
}

.word-spin b {
  display: block;
  height: 1.1rem;
  font-weight: inherit;
}

/* Four equal dwells, and the fourth word is a duplicate of the first sitting at
   -3.3rem. The loop therefore ends on the same frame it starts on, so the reset
   is invisible. The first version held the last position for an instant only,
   which is why the words appeared to stutter and skip rather than roll. */
@keyframes word-spin {
  0%,  22%  { transform: translateY(0); }
  25%, 47%  { transform: translateY(-1.1rem); }
  50%, 72%  { transform: translateY(-2.2rem); }
  75%, 100% { transform: translateY(-3.3rem); }
}

/* Motion that loops forever is exactly what this setting exists to stop. */
@media (prefers-reduced-motion: reduce) {
  .word-spin-track { animation: none; }
}


/* @source website/src/css/71-reveal-lightbox.css */
/* ============================================================================
   REVEAL CARD + LIGHTBOX  (review round 1, comments 14 and 39)
   Comment 14 pointed at uiverse "old-dingo-81": a compact card with a second
   panel that grows out from behind it on hover, 0.4s ease-in-out. Same
   mechanism, photographs instead of a weather widget.
   ========================================================================= */

.reveal-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  isolation: isolate;
}

.reveal-card img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 400ms ease-in-out;
}

.reveal-card-plate {
  position: absolute;
  inset: auto 0 0 0;
  display: grid;
  gap: 2px;
  padding: var(--space-sm) var(--space-md);
  background: linear-gradient(to top, rgba(5, 15, 31, 0.92), rgba(5, 15, 31, 0));
  color: var(--white);
  /* Parked below the frame, then slid up. translate, not height, so the text
     never reflows mid-animation. */
  transform: translateY(100%);
  opacity: 0;
  transition:
    transform 400ms ease-in-out,
    opacity 400ms ease-in-out;
}

.reveal-card-plate span {
  color: var(--gold-500);
  font-size: 0.76rem;
  font-weight: 950;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.reveal-card-plate strong {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

.reveal-card:hover img,
.reveal-card:focus-within img,
.reveal-card.is-open img {
  transform: scale(1.04);
}

.reveal-card:hover .reveal-card-plate,
.reveal-card:focus-within .reveal-card-plate,
.reveal-card.is-open .reveal-card-plate {
  transform: translateY(0);
  opacity: 1;
}

/* --- Lightbox ------------------------------------------------------------ */
.is-zoomable { cursor: zoom-in; }

.lightbox {
  max-width: min(94vw, 1200px);
  max-height: 92vh;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: var(--navy-950);
  overflow: visible;
}

.lightbox::backdrop {
  background: rgba(5, 15, 31, 0.86);
  backdrop-filter: blur(2px);
}

.lightbox img {
  display: block;
  max-width: min(94vw, 1200px);
  max-height: 92vh;
  width: auto;
  height: auto;
  border-radius: var(--radius);
}

.lightbox-close {
  position: absolute;
  top: -14px;
  right: -14px;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: var(--white);
  color: var(--navy-900);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 10px 24px rgba(5, 15, 31, 0.45);
}

@media (prefers-reduced-motion: reduce) {
  .reveal-card img,
  .reveal-card-plate { transition: none; }
}

/* ============================================================================
   PHOTO STACK  (round 2, comment 2)
   The uiverse card he pointed at keeps a second panel behind the front one and
   grows it out on hover. Two panels here, one leaving the top edge and one the
   bottom, on the same 0.4s ease-in-out.
   The pair are decorative duplicates of photographs that appear elsewhere on
   the site, so they are aria-hidden and carry no alt text: a screen reader
   should hear one photograph here, not three.
   ========================================================================= */

.photo-stack {
  position: relative;
  margin: 0;
  /* Room for the two panels to travel into without the section jumping. */
  padding-block: clamp(28px, 5vw, 58px);
  isolation: isolate;
}

.photo-stack-front {
  position: relative;
  z-index: var(--z-raised-2);
  display: block;
  overflow: hidden;
  border-radius: var(--radius);
  box-shadow: 0 22px 50px rgba(5, 15, 31, 0.24);
}

.photo-stack-front img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform 400ms ease-in-out;
}

.photo-stack-out {
  position: absolute;
  left: 50%;
  width: 74%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius);
  box-shadow: 0 16px 36px rgba(5, 15, 31, 0.26);
  z-index: var(--z-raised);
  /* Parked dead centre behind the front photograph, so on load the section
     looks exactly as it did before anyone touched it. */
  transform: translate(-50%, 0) scale(0.86);
  opacity: 0;
  transition:
    transform 400ms ease-in-out,
    opacity 320ms ease-in-out;
}

.photo-stack-out--top { top: 0; }
.photo-stack-out--bottom { bottom: 0; }

.photo-stack:hover .photo-stack-out--top,
.photo-stack:focus-within .photo-stack-out--top,
.photo-stack.is-open .photo-stack-out--top {
  transform: translate(-50%, -46%) scale(1) rotate(-1.5deg);
  opacity: 1;
}

.photo-stack:hover .photo-stack-out--bottom,
.photo-stack:focus-within .photo-stack-out--bottom,
.photo-stack.is-open .photo-stack-out--bottom {
  transform: translate(-50%, 46%) scale(1) rotate(1.5deg);
  opacity: 1;
}

.photo-stack:hover .photo-stack-front img,
.photo-stack:focus-within .photo-stack-front img,
.photo-stack.is-open .photo-stack-front img {
  transform: scale(1.03);
}

.photo-stack-plate {
  position: absolute;
  inset: auto 0 0 0;
  display: grid;
  gap: 2px;
  padding: var(--space-sm) var(--space-md);
  background: linear-gradient(to top, rgba(5, 15, 31, 0.92), rgba(5, 15, 31, 0));
  color: var(--white);
  transform: translateY(100%);
  opacity: 0;
  transition: transform 400ms ease-in-out, opacity 400ms ease-in-out;
}

.photo-stack-label {
  color: var(--gold-500);
  font-size: 0.76rem;
  font-weight: 950;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.photo-stack-plate strong {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
}

.photo-stack:hover .photo-stack-plate,
.photo-stack:focus-within .photo-stack-plate,
.photo-stack.is-open .photo-stack-plate {
  transform: translateY(0);
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .photo-stack-out,
  .photo-stack-plate,
  .photo-stack-front img { transition: none; }
}


/* @source website/src/css/72-search.css */
/* ============================================================================
   SITE SEARCH  (review round 1, comment 9)
   Collapsed: one quiet 44px icon in the nav, no wider than a social link.
   Open: the calm hairline field he pointed at (uiverse "purple-frog-72"),
   drawn with this site's tokens, plus the results underneath it.
   The panel is anchored to the header rather than pushed inline so opening it
   never reflows the navigation.
   ========================================================================= */

.site-search {
  position: relative;
  display: flex;
  align-items: center;
}

.site-search-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: currentColor;
  cursor: pointer;
  transition: background 160ms ease, transform 160ms ease;
}

.site-search-toggle svg { width: 19px; height: 19px; }

.site-search-toggle:hover,
.site-search.is-open .site-search-toggle {
  background: rgba(255, 255, 255, 0.14);
}

.site-search-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: var(--z-raised-2);
  width: min(23rem, calc(100vw - 2.25rem));
  padding: var(--space-sm);
  border-radius: 18px;
  background: var(--surface-raised);
  color: var(--gray-900);
  border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(5, 15, 31, 0.28);
}

.site-search-input {
  width: 100%;
  min-height: 46px;
  padding: 0 var(--space-sm);
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--white);
  color: var(--gray-900);
  font: inherit;
  font-size: var(--text-base);
  transition: border-color 200ms ease, box-shadow 200ms ease;
}

.site-search-input::placeholder { color: var(--gray-400); }

.site-search-input:focus {
  outline: none;
  border-color: var(--blue-500);
  box-shadow: 0 0 0 4px rgba(29, 92, 184, 0.18);
}

.site-search-hint {
  margin: var(--space-2xs) 0 0;
  color: var(--gray-600);
  font-size: var(--text-xs);
}

.site-search-results {
  list-style: none;
  margin: var(--space-2xs) 0 0;
  padding: 0;
  display: grid;
  gap: 2px;
  max-height: 17rem;
  overflow-y: auto;
}

.site-search-results a {
  display: grid;
  gap: 2px;
  padding: var(--space-2xs) var(--space-xs);
  border-radius: 10px;
  color: var(--gray-900);
  text-decoration: none;
}

.site-search-results a:hover,
.site-search-results a:focus-visible {
  background: var(--blue-050);
}

.site-search-results strong {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
}

.site-search-results span {
  color: var(--gray-600);
  font-size: var(--text-xs);
  line-height: 1.45;
}

/* Below 1280px the search icon sits in the header row itself (final UI round,
   2026-11-06). The wrapper drops its own positioning so the panel hangs from
   the full header width, under the row, instead of off the icon's edge. */
@media (max-width: 1279px) {
  .site-search { position: static; }
  .site-search-panel {
    top: calc(100% + 8px);
    right: 12px;
    left: 12px;
    width: auto;
    max-height: calc(100svh - var(--header-height) - 24px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}


/* @source website/src/css/73-merch-strip.css */
/* ============================================================================
   MERCH STRIP  (round 2, comment 6)
   The Navy Online band: one product, shown whole, a line of type, a small buy
   link. Restraint is the point. It is an advert on a recruiting page, so it
   gets a quiet ground and no colour of its own.
   ========================================================================= */

.merch-strip {
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: var(--space-lg);
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: var(--space-xl) 0;
  border-top: 1px solid var(--line);
}

/* Final UI round (2026-11-06): the whole item shows, never cropped. The store
   photographs are background-free transparent cutouts on a square canvas, so
   the band has no tile colour of its own and the item sits on the page. */
.merch-strip-photo {
  overflow: hidden;
  background: transparent;
}

.merch-strip-photo img {
  display: block;
  width: 100%;
  /* height:auto is load-bearing: the width and height attributes on the tag
     are presentational hints that set CSS height, and that hint beats
     aspect-ratio, which is why the band first rendered 641x1000. */
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: contain;
  object-position: 50% 50%;
  transition: opacity 260ms ease;
}

.merch-strip.is-swapping .merch-strip-photo img { opacity: 0; }

.merch-strip-title {
  margin: var(--space-2xs) 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  letter-spacing: var(--tracking-snug);
  text-wrap: balance;
}

.merch-strip-price {
  margin: var(--space-3xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
}

/* Small on purpose. On the Navy band the buy link is the quietest thing in the
   row, which is what keeps the band from feeling like a pop-up. */
.merch-strip-buy {
  display: inline-block;
  margin-top: var(--space-sm);
  padding-bottom: 2px;
  border-bottom: 1px solid currentColor;
  color: var(--ink);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  text-decoration: none;
}

.merch-strip-buy:hover { color: var(--accent); }

@media (min-width: 860px) {
  .merch-strip { grid-template-columns: 1.35fr 1fr; gap: var(--space-2xl); }
  .merch-strip-photo img { aspect-ratio: 1 / 1; max-height: 560px; }
}

/* Comment 58: manual arrows beside the buy link. 44px targets, quiet like the
   buy link, so the band still reads as a photograph first. */
.merch-strip-nav {
  display: flex;
  gap: var(--space-2xs);
  margin-top: var(--space-md);
}

.merch-strip-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease;
}

.merch-strip-arrow svg { width: 20px; height: 20px; }
.merch-strip-arrow:hover { border-color: var(--ink); background: var(--gray-100); }
.merch-strip-arrow:active { transform: scale(0.96); }


/* @source website/src/css/74-shop.css */
/* ============================================================================
   SHOP  (round 2, comments 7 and 8)
   Reference he picked: Aime Leon Dore. What that actually means, stripped of
   the brand: one flat tile colour behind every product, four to a row, the
   product photograph doing all the work, and type that gets out of the way -
   name and price on one quiet line, no badges, no ratings, no borders.
   The tile grey lives in the CSS; the photographs are transparent cutouts
   (2026-11-06, one kept on #f0f0f0, see merch.json note) so every item sits
   on exactly the same ground.
   ========================================================================= */

.shop-masthead {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: var(--space-2xl) 0 var(--space-xl);
}

.shop-masthead h1 {
  margin: var(--space-2xs) 0 0;
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3rem);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.shop-masthead-note {
  max-width: var(--measure-narrow);
  margin: var(--space-sm) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

.shop-section {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding-bottom: var(--space-3xl);
}

.shop-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-bottom: var(--space-sm);
  margin-bottom: var(--space-lg);
  border-bottom: 1px solid var(--line);
}

.shop-section-head h2 {
  margin: 0;
  font-family: var(--font-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.shop-section-head p {
  margin: 0;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}

.shop-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* Four across is the whole point of the reference. Two on a phone rather than
     one: a single column turns 27 products into an endless scroll. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-md) var(--space-sm);
}

@media (min-width: 780px) {
  .shop-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.shop-tile a {
  display: block;
  color: inherit;
  text-decoration: none;
}

.shop-tile-media {
  display: block;
  overflow: hidden;
  background: #f0f0f0;
}

.shop-tile-media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1);
}

.shop-tile a:hover .shop-tile-media img,
.shop-tile a:focus-visible .shop-tile-media img {
  transform: scale(1.03);
}

.shop-tile-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-top: var(--space-2xs);
  font-size: var(--text-xs);
  line-height: 1.4;
}

.shop-tile-name {
  /* Two lines maximum. Printify titles run to eight words and a pipe, and a
     ragged third line is what makes a grid stop looking like a grid. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.shop-tile-price {
  flex: none;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* --- Product page  (round 2, parity ruling 12, 2026-11-05) ----------------
   The Patagonia product page (ref-patagonia-1.png). Desktop: the photograph
   fills the left half edge to edge on a soft neutral ground and stays put
   while the right column scrolls; the column holds a centred measure with
   generous padding. Phone: the photograph on top, full width, then the column.
   The fixed header means the page starts below it (as .page-store). */
.page-product main {
  padding-top: var(--header-height);
  /* The product is filled in after load: hold the space so the footer does
     not jump up first. */
  min-height: 100vh;
  min-height: 100svh;
  background: var(--surface-raised);
}

.pdp-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 960px) {
  .pdp-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }
}

/* The photograph. multiply drops a product shot's own white ground into the
   neutral one, so every item sits on the same surface. */
.pdp-media {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  background: var(--surface-product);
}

.pdp-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}

@media (min-width: 960px) {
  /* Square, as the photographs are, so the shot meets all four edges; capped
     at the viewport so it never runs under the fold. */
  .pdp-media {
    position: sticky;
    top: var(--header-height);
    max-height: calc(100vh - var(--header-height));
    max-height: calc(100svh - var(--header-height));
  }
}

/* Small round arrows bottom-left, only when an item has several photographs. */
.pdp-arrows {
  position: absolute;
  left: var(--space-md);
  bottom: var(--space-md);
  z-index: var(--z-raised-2);
  display: flex;
  gap: var(--space-2xs);
}

.pdp-arrows[hidden] { display: none; }

.pdp-arrow {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--white);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform var(--duration) var(--ease-out);
}

.pdp-arrow:hover { transform: scale(1.06); }
.pdp-arrow svg { width: 20px; height: 20px; }

/* The column. */
.pdp-info {
  padding: var(--space-lg) var(--gutter) var(--space-3xl);
}

@media (min-width: 960px) {
  .pdp-info { padding: clamp(2.5rem, 5vw, 4rem) clamp(2rem, 6vw, 8.5rem) var(--space-4xl); }
}

.pdp-info-inner {
  max-width: 34rem;
  margin-inline: auto;
}

.pdp-crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3xs) 0;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  line-height: 1.4;
}

.pdp-crumbs li { display: inline-flex; align-items: center; min-width: 0; }

/* A thin chevron between the crumbs, as the reference. */
.pdp-crumbs li + li::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin: 0 var(--space-sm) 0 var(--space-xs);
  border-top: 1.5px solid var(--ink-muted);
  border-right: 1.5px solid var(--ink-muted);
  transform: rotate(45deg);
}

.pdp-crumbs a {
  color: var(--ink);
  text-decoration: none;
}

.pdp-crumbs a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* The item's own crumb: one line, cut short, since titles run long. */
.pdp-crumbs [aria-current] {
  display: block;
  max-width: 16rem;
  overflow: hidden;
  color: var(--ink-muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pdp-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  margin-top: var(--space-lg);
}

.pdp-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.625rem, 1.2rem + 1.1vw, 2.125rem);
  font-weight: var(--weight-black);
  line-height: 1.12;
  letter-spacing: var(--tracking-tight);
  color: var(--ink);
}

.pdp-price {
  flex: none;
  margin: 0;
  padding-top: 0.2em;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 1.05rem + 0.6vw, 1.5rem);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ink);
}

/* Processing fee disclosure (NY total-price rule): the total for one, before
   anything goes in the bag. */
.pdp-fee {
  margin: var(--space-2xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.pdp-options { margin-top: var(--space-lg); }

.pdp-opt + .pdp-opt { margin-top: var(--space-lg); }

.pdp-opt-label {
  margin: 0 0 var(--space-xs);
  color: var(--ink);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
}

.pdp-opt-value {
  margin-left: var(--space-2xs);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
}

.pdp-opt.is-invalid .pdp-opt-value { color: var(--accent); font-weight: var(--weight-semibold); }

/* Large rounded tiles in a grid. Sizes are short, five to a row; colours and
   dates are words, three or four to a row. */
.pdp-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5.5rem, 1fr));
  gap: var(--space-2xs);
}

.pdp-tiles.is-words { grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); }
.pdp-tiles.is-dates { grid-template-columns: repeat(auto-fill, minmax(7.25rem, 1fr)); }

.pdp-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 3.25rem;
  padding: var(--space-2xs) var(--space-xs);
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-product);
  box-shadow: inset 0 0 0 1px transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
  transition: box-shadow var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out);
}

.pdp-tile:hover { box-shadow: inset 0 0 0 1px var(--line-strong); }

.pdp-tile[aria-checked="true"] {
  background: var(--surface-raised);
  box-shadow: inset 0 0 0 2px var(--ink);
}

.pdp-tiles.is-dates .pdp-tile { min-height: 4rem; }
.pdp-tile-sub { color: var(--ink-muted); font-size: var(--text-xs); font-weight: var(--weight-regular); }

.pdp-tiles[aria-invalid="true"] .pdp-tile { box-shadow: inset 0 0 0 1px var(--accent); }

.pdp-opt-empty { margin: 0; color: var(--ink-muted); font-size: var(--text-sm); }

/* Quantity: a stepper the height of the tiles. */
.pdp-qty-row { margin-top: var(--space-lg); }

.pdp-qty {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius);
  background: var(--surface-product);
}

.pdp-qty-step {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}

.pdp-qty-step svg { width: 18px; height: 18px; }
.pdp-qty-step:hover:not(:disabled) { background: var(--gray-200); }
.pdp-qty-step:disabled { color: var(--gray-400); cursor: not-allowed; }

.pdp-qty-value {
  min-width: 2.5rem;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.pdp-add {
  width: 100%;
  min-height: 3.5rem;
  margin-top: var(--space-lg);
  border: 0;
  border-radius: var(--radius);
  background: var(--navy-950);
  color: var(--white);
  font: inherit;
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  cursor: pointer;
  transition: background var(--duration) var(--ease-out), transform var(--duration) var(--ease-out);
}

.pdp-add:hover { background: var(--navy-800); }
.pdp-add:active { transform: scale(0.99); }

.pdp-note {
  margin: var(--space-xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-xs);
  text-align: center;
}

.pdp-accordions { margin-top: var(--space-xl); border-bottom: 1px solid var(--line); }

.pdp-accordion { border-top: 1px solid var(--line); }
.pdp-accordion[hidden] { display: none; }

.pdp-accordion summary {
  position: relative;
  padding: var(--space-md) 2rem var(--space-md) 0;
  color: var(--ink);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  list-style: none;
  cursor: pointer;
}

.pdp-accordion summary::-webkit-details-marker { display: none; }

.pdp-accordion summary::after {
  content: "+";
  position: absolute;
  right: 0.25rem;
  top: 50%;
  color: var(--ink-muted);
  font-size: 1.4rem;
  font-weight: var(--weight-regular);
  line-height: 1;
  transform: translateY(-50%);
}

.pdp-accordion[open] summary::after { content: "\2212"; }

.pdp-accordion p {
  margin: 0 0 var(--space-md);
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

.pdp-missing {
  width: min(var(--max), calc(100% - 36px));
  margin: var(--space-3xl) auto;
  text-align: center;
}

/* --- Merch on show, not for sale (merch.json `available: false`, 2026-10-01) ---
   A red band crosses the photograph corner to corner like a stamped notice;
   the column says the same thing in words and points at what can be bought
   today. Tiles stay legible so a family can still plan. */
.pdp-ribbon {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  display: grid;
  place-items: center;
  pointer-events: none;
}

/* display: grid above beats the hidden attribute. Hidden means hidden. */
.pdp-ribbon[hidden] { display: none; }

.pdp-ribbon span {
  width: 150%;
  padding: var(--space-sm) 0;
  background: var(--accent);
  color: var(--white);
  font-family: var(--font-display);
  font-size: clamp(1rem, 0.8rem + 1.2vw, 1.6rem);
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-caps);
  text-align: center;
  text-transform: uppercase;
  box-shadow: 0 0 0 2px var(--white) inset, 0 12px 30px rgba(5, 15, 31, 0.28);
  transform: rotate(-12deg);
}

.pdp.is-unavailable .pdp-media img { filter: grayscale(0.85); opacity: 0.7; }

.pdp-paused {
  margin-top: var(--space-lg);
  padding: var(--space-sm) var(--space-md);
  border-left: 4px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--red-100);
  font-size: var(--text-sm);
}

.pdp-paused p { margin: 0; color: var(--ink-secondary); }

.pdp-paused .pdp-paused-title {
  margin-bottom: var(--space-3xs);
  color: var(--red-800);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.pdp-paused a {
  display: inline-block;
  margin-top: var(--space-xs);
  color: var(--ink);
  font-weight: var(--weight-semibold);
}

.pdp.is-unavailable .pdp-tile { opacity: 0.5; cursor: not-allowed; }

.pdp-add:disabled,
.pdp-add:disabled:hover {
  background: var(--surface-sunken);
  color: var(--red-800);
  box-shadow: inset 0 0 0 1px var(--accent);
  cursor: not-allowed;
  transform: none;
}

/* Sullivans Shop: the unit patch centred in the space right of the title. */
.shop-masthead-mark { display: none; }
@media (min-width: 768px) {
  .shop-masthead { display: grid; grid-template-columns: minmax(0, var(--measure-narrow)) 1fr; column-gap: var(--space-xl); align-items: center; }
  .shop-masthead-mark { display: block; justify-self: center; width: clamp(120px, 16vw, 200px); height: auto; }
}

.shop-paused-note { color: var(--accent); font-weight: var(--weight-semibold); }

.shop-grid.is-paused .shop-tile-media { position: relative; }

.shop-grid.is-paused .shop-tile-media::after {
  content: "Currently unavailable";
  position: absolute;
  top: var(--space-2xs);
  left: var(--space-2xs);
  padding: var(--space-3xs) var(--space-2xs);
  background: var(--accent);
  color: var(--white);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.cart-line-delivery.is-unavailable { color: var(--accent); font-weight: var(--weight-semibold); }


/* @source website/src/css/75-bag.css */
/* ============================================================================
   THE BAG + THE THROW  (round 2, comment 8)
   The icon lives beside the search in the nav. The flier is a clone of the
   product photograph on its own layer, so the page never reflows while it
   travels and nothing below it repaints.
   ========================================================================= */

.site-bag {
  position: relative;
  display: flex;
  align-items: center;
}

.site-bag-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: currentColor;
  cursor: pointer;
  transition: background 160ms ease, transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.site-bag-toggle svg { width: 19px; height: 19px; }

.site-bag-toggle:hover,
.site-bag.is-open .site-bag-toggle { background: rgba(255, 255, 255, 0.14); }

/* The catch: the icon takes the hit the moment the flier lands. */
.site-bag.is-bumping .site-bag-toggle { transform: scale(1.22); }

.site-bag-count {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--red-700);
  color: var(--white);
  font-size: 11px;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
}

.site-bag-panel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: var(--z-raised-2);
  width: min(24rem, calc(100vw - 2.25rem));
  padding: var(--space-sm);
  border-radius: 18px;
  border: 1px solid var(--line);
  background: var(--surface-raised);
  color: var(--gray-900);
  box-shadow: 0 24px 60px rgba(5, 15, 31, 0.28);
}

.site-bag-empty {
  margin: 0;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}

.site-bag-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-xs);
  max-height: 20rem;
  overflow-y: auto;
}

.site-bag-list li {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-xs);
}

.site-bag-list img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  background: #f0f0f0;
}

.site-bag-meta {
  display: grid;
  gap: 2px;
  min-width: 0;
}

/* Two lines, never an ellipsis: "Officers Alternate ..." told nobody which
   polo was in the bag (the note he lost, comment 66). */
.site-bag-meta strong {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: 1.35;
}

.site-bag-size,
.site-bag-price {
  color: var(--ink-muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.site-bag-remove {
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-muted);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.site-bag-remove:hover { background: var(--gray-100); color: var(--ink); }

.site-bag-foot {
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--line);
}

.site-bag-subtotal {
  display: flex;
  justify-content: space-between;
  margin: 0 0 var(--space-xs);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

/* Comment 64: the old per-item "Check out" was white on white, because the
   header's `.primary-nav a` (0,1,1) out-ranked `.site-bag-buy` (0,1,0). The
   panel is now a light island and this selector carries the panel's weight. */
.site-bag-panel a.site-bag-checkout {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 48px;
  padding: 0 var(--space-sm);
  border-radius: var(--radius);
  background: var(--navy-950);
  color: var(--white);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
}

.site-bag-panel a.site-bag-checkout:hover,
.site-bag-panel a.site-bag-checkout:focus-visible { background: var(--navy-700); color: var(--white); }

.site-bag-note {
  margin: var(--space-2xs) 0 0;
  color: var(--ink-muted);
  font-size: 11px;
  text-align: center;
}

/* The flier itself. Fixed, above everything, and deliberately inert. */
.bag-flier {
  position: fixed;
  z-index: var(--z-float);
  border-radius: var(--radius);
  object-fit: cover;
  pointer-events: none;
  box-shadow: 0 18px 40px rgba(5, 15, 31, 0.3);
}

/* Below 1280px the bag icon sits in the header row (final UI round,
   2026-11-06). A tap goes to My cart; the hover preview, where a mouse
   exists, hangs from the right edge of the header under the row. */
@media (max-width: 1279px) {
  .site-bag { position: static; }
  .site-bag-panel {
    top: calc(100% + 8px);
    right: 12px;
  }
}

/* The bag is a link to My cart now; hovering it with something inside previews
   the contents. This strip bridges the 10px gap so the pointer can reach it. */
.site-bag-panel::before {
  content: "";
  position: absolute;
  inset: -12px 0 auto 0;
  height: 12px;
}


/* @source website/src/css/76-poster.css */
/* ============================================================================
   POSTER RUN  (2026-09-26, Camilo's marines.com brief)
   He picked the structure off marines.com and rejected its palette: "it can be
   the same color theme we have been using, i just want to copy the idea and
   also the font they use."

   The font they use is Expressway, a Highway Gothic descendant, licensed.
   Overpass (Red Hat, SIL OFL) is drawn from the same FHWA source, so it is the
   honest free match rather than a lookalike. Self-hosted, 39 KB, one variable
   file, no third-party request. It is scoped to this run through
   --font-poster; the hero and every existing page keep Libre Franklin.

   Four blocks, in the order he listed them:
     .poster-cta      headline + three image cards        (marines: EARN YOUR PLACE)
     .film            one video, click to play            (marines: the film band)
     .creed           mission line + Learn more           (marines: OUR MISSION IS)
     .route-split     two panels, two buttons             (marines: MANY ROLES)
   ========================================================================= */

/* ---------------------------------------------------------------- 1. CTA + cards */
.poster-cta {
  background: var(--surface-inverse);
  padding-block: var(--section-y);
}

.poster-cta-head {
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
  text-align: center;
}

.poster-mark {
  width: 74px;
  height: 74px;
  margin-inline: auto;
  display: block;
}

.poster-cta-head h2 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  letter-spacing: var(--tracking-normal);
  text-transform: uppercase;
  color: var(--ink);
  margin: var(--space-md) 0 0;
}

.poster-cta-head p {
  margin: var(--space-sm) auto 0;
  max-width: 44ch;
  color: var(--ink-muted);
}

.poster-cards {
  max-width: var(--max);
  margin: var(--space-2xl) auto 0;
  padding-inline: var(--gutter);
  display: grid;
  gap: clamp(var(--space-lg), 4vw, var(--space-2xl));
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.poster-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}

.poster-card-eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
  margin: var(--space-md) 0 0;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink);
}

.poster-card-eyebrow::before {
  content: "";
  width: 12px;
  height: 12px;
  flex: none;
  background: var(--accent-on-dark);
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}

.poster-card h3 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
  text-transform: uppercase;
  color: var(--ink);
  margin: var(--space-2xs) 0 0;
}

.poster-card h3::after {
  content: "";
  display: block;
  width: 46px;
  height: 3px;
  margin-top: var(--space-sm);
  background: var(--accent-on-dark);
}

.poster-card p {
  margin: var(--space-sm) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
  /* Final UI round (2026-11-06): the text runs the full card width. A 34ch
     cap stopped every line mid card. */
  max-width: none;
}

.poster-card a {
  display: inline-block;
  margin-top: var(--space-sm);
  font-family: var(--font-poster);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid var(--accent-on-dark);
  padding-bottom: 2px;
}

.poster-card a:hover,
.poster-card a:focus-visible {
  color: var(--accent-on-dark);
}

/* ---------------------------------------------------------------- 2. the film */
/* Order-board round, 2026-09-26: the film now sits directly under the creed,
   and Camilo asked for seamless transitions with no big gaps. So the film
   takes the creed's ground and adds no padding of its own: the creed's text
   ends, the footage begins, and the next section starts where the footage
   stops. */
.film {
  background: var(--surface-inverse-raised);
}

.film-frame {
  position: relative;
  /* Full bleed at every width. A 16:9 box capped by max-height shrank its
     width instead and sat left-aligned with a navy block beside it, so the
     height is set directly and the footage crops to fill. */
  width: 100%;
  height: min(56.25vw, 86vh);
  background: var(--navy-950);
  overflow: hidden;
}

.film-frame video,
.film-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


/* ---------------------------------------------------------------- 3. the creed */
.creed {
  background: var(--surface-inverse-raised);
  padding-block: var(--section-y);
  text-align: center;
}

.creed-inner {
  max-width: 54rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.creed h2 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  text-transform: uppercase;
  color: var(--ink);
  margin: var(--space-sm) 0 0;
}

.creed p {
  margin: var(--space-md) auto 0;
  max-width: 52ch;
  color: var(--ink-muted);
}

.creed .button {
  margin-top: var(--space-lg);
}

/* ---------------------------------------------------------------- 4. two routes */
.route-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

.route-panel {
  position: relative;
  min-height: clamp(380px, 48vw, 560px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--space-xl) var(--gutter) var(--space-2xl);
  overflow: hidden;
  isolation: isolate;
}

.route-panel img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: var(--z-behind);
}

.route-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: var(--z-below);
  background: linear-gradient(180deg, rgba(5, 15, 31, 0.22) 0%, rgba(5, 15, 31, 0.62) 45%, rgba(5, 15, 31, 0.93) 82%);
}

.route-panel > * {
  position: relative;
  z-index: var(--z-base);
}

.route-panel .route-age {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink);
}

.route-panel h3 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
  text-transform: uppercase;
  color: var(--ink);
  margin: var(--space-2xs) 0 var(--space-sm);
}

/* A button that spans a whole panel reads as a banner, not a control. */
.route-panel .button {
  align-self: flex-start;
}

.route-panel p {
  color: var(--ink-muted);
  max-width: 38ch;
  margin: 0 0 var(--space-md);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}


/* ============================================================================
   HOMEPAGE RHYTHM  (order-board round, 2026-09-26)
   Camilo's page note: "follow the new order and make sure to have seamless
   clean transitions between the sections, and that there are no big
   unnecessary gaps". Measured at 1440 before this block: the three lower
   sections carried 100 to 116px of padding each side, so two neighbours put
   over 200px of empty ground between their content, and the join callout
   left a 24px strip of page background between itself and the next section.
   One tighter step for every section below the film, no stray margins.
   ========================================================================= */
.page-index .creed {
  padding-bottom: var(--section-y-tight);
}

.page-index .join-callout {
  margin-block: 0;
}

/* Round 3 (2026-11-05): the unit seal sits over the button in the right
   column, so the box is balanced; on a phone it stacks under the words. */
.join-callout-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
}

.join-callout-seal {
  display: block;
  width: clamp(130px, 13vw, 190px);
  height: auto;
  filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.35));
}

@media (max-width: 767px) {
  .join-callout-side { margin-top: var(--space-md); }
  .join-callout-seal { width: 120px; }
}

.page-index .recruit-section,
.page-index .chart-section,
.page-index .where-section {
  padding-block: var(--section-y-tight);
}

.page-index .merch-strip {
  padding-block: var(--section-y-tight);
}

/* --- Final round, 2026-09-26 ------------------------------------------------ */

/* Comment 60: the three boxes sit centred between the gold rule above "Start
   here" and the bottom of the photograph, rather than hanging from the top of
   the row. Two columns only exist above 940px (legacy breakpoint). */
@media (min-width: 941px) {
  .page-index .recruit-grid { align-self: center; }
}

/* Comment 62: the three location cards were mostly padding. Tighter cards, and
   the map centred on the column they make rather than pinned to its top. */
.page-index .where-grid { align-items: center; }
.page-index .where-info { gap: var(--space-xs); }
.page-index .where-card { padding: var(--space-sm) var(--space-md); }
.page-index .where-card span { margin-bottom: 2px; }
.page-index .where-card strong { margin-bottom: 0; }
.page-index .where-card a { min-height: 36px; }

/* Comment 61: the park's name on one line wherever the card is wide enough to
   hold it; on a phone it wraps like any other sentence. */
@media (min-width: 600px) and (max-width: 940px), (min-width: 1000px) {
  .page-index .where-place { white-space: nowrap; }
}

/* The mission flanked by the two unit logos on a desktop (2026-09-27): the
   sides were empty. Phones show neither, so the words keep the full width. */
.creed-mark { display: none; }
@media (min-width: 1024px) {
  .creed {
    display: grid;
    grid-template-columns: 1fr minmax(0, 54rem) 1fr;
    align-items: center;
    width: 100%;
    padding-inline: var(--gutter);
    column-gap: var(--space-lg);
  }
  .creed-inner { grid-column: 2; }
  .creed-mark {
    display: block;
    justify-self: center;
    width: clamp(160px, 14vw, 260px);
    height: auto;
  }
  .creed-mark--left { grid-column: 1; grid-row: 1; }
  .creed-mark--right { grid-column: 3; grid-row: 1; }
}

/* Same treatment for the dark closing bands on Join and Contact (2026-09-27). */
.flank-mark { display: none; }
@media (min-width: 1024px) {
  .flank { display: grid; grid-template-columns: 1fr minmax(0, 760px) 1fr; align-items: center; }
  .flank > :not(.flank-mark) { grid-column: 2; grid-row: 1; }
  .flank-mark { display: block; grid-row: 1; justify-self: center; width: clamp(150px, 12vw, 230px); height: auto; }
  .flank-mark--left { grid-column: 1; }
  .flank-mark--right { grid-column: 3; }
}


/* @source website/src/css/77-about.css */
/* ============================================================================
   ABOUT  (2026-09-26 rebuild)
   Camilo's answer when asked what About is for: "the story, photo led".
   His constraint on the look: quiet next to Join, which he defined as a light
   page with big type and big photographs.

   So: paper ground, Overpass headings at a smaller step than the homepage run,
   full-bleed photographs between the reading blocks, and a measure that never
   grows into a newspaper column. The only dark block is the closing call to
   action, which is shared with the rest of the site.
   ========================================================================= */


.ab-eligibility-inner,
.ab-training-inner {
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ------------------------------------------------------ the lead (round 2)
   The formation photograph IS the header of the page. The words start where
   the image stops, centred, in the same section, so there is no seam and no
   second band of padding between them. The photograph's upper third is tent
   canvas, so the crop sits low to keep every face. */
.ab-lead-photo {
  width: 100%;
  height: clamp(320px, 52vw, 720px);
  object-fit: cover;
  object-position: center 64%;
  display: block;
}

.ab-lead-body {
  max-width: 44rem;
  margin-inline: auto;
  padding: var(--space-xl) var(--gutter) var(--section-y);
  text-align: center;
}

.ab-crest {
  width: clamp(88px, 10vw, 120px);
  height: auto;
  display: block;
  margin: 0 auto var(--space-md);
}

.ab-lead-body h1 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  font-size: var(--text-3xl);
  line-height: var(--leading-3xl);
  color: var(--ink);
  margin: 0;
}

/* One sentence set larger than its neighbours is the whole hierarchy here. */
.ab-big {
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  color: var(--ink);
  max-width: 34ch;
  margin: var(--space-md) auto;
}

.ab-lead-body p:last-child {
  max-width: var(--measure-narrow);
  margin: 0 auto;
  color: var(--ink-secondary);
}

/* ----------------------------------------------------- the whole photograph
   Shown at no more than its own 1445px: any wider and the browser would
   upscale it, which is the softness he saw. Comment 55 (final round): the top
   two sixths, all sky, are cut off; the file is now 1445 x 786, cut from
   media-library/_raw-originals/NSCC Pictures/IMG_4222.jpg rows 393 to 1179. */
.ab-whole {
  margin: 0 auto;
  max-width: 1445px;
  padding-inline: var(--gutter);
}

.ab-whole img {
  width: 100%;
  height: auto;
  display: block;
}

/* --------------------------------------------------------- who can join */
.ab-eligibility,
.ab-training {
  padding-block: var(--section-y);
}

.ab-eligibility h2,
.ab-training h2 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
  color: var(--ink);
  margin: var(--space-2xs) 0 var(--space-sm);
}

.ab-lede {
  max-width: 52ch;
  color: var(--ink-secondary);
  margin: 0 0 var(--space-lg);
}

.ab-requirements {
  list-style: none;
  margin: var(--space-xl) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-lg);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

.ab-requirements span {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent);
  padding-bottom: var(--space-2xs);
  border-bottom: 2px solid var(--line-strong);
}

.ab-requirements p {
  margin: var(--space-sm) 0 0;
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

/* ------------------------------------------------------------- training */
.ab-training {
  background: var(--surface-sunken);
}

.ab-training-grid {
  display: grid;
  gap: clamp(var(--space-lg), 4vw, var(--space-2xl));
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.ab-course h3 {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  color: var(--ink);
  margin: 0 0 var(--space-sm);
  padding-bottom: var(--space-2xs);
  border-bottom: 3px solid var(--accent);
}

.ab-course ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.ab-course li {
  padding: var(--space-2xs) 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink-secondary);
  font-size: var(--text-sm);
}

/* ============================================================================
   RESOURCES  (2026-09-26 rebuild)
   Camilo picked "one searchable list" over three category doors, and "only what
   really exists today" over rows marked coming soon. The tag column keeps the
   who-is-this-for information the headings used to carry, without splitting a
   nine row list into three three-row lists.
   ========================================================================= */
.rh-search-section {
  padding-block: var(--section-y-tight) var(--section-y);
}

.rh-search-inner {
  max-width: 76rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.rh-search {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: 0 var(--space-md);
}

.rh-search:focus-within {
  border-color: var(--focus-ring);
}

.rh-search svg {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--ink-muted);
}

.rh-search input {
  flex: 1;
  min-height: 56px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--text-md);
  color: var(--ink);
}

.rh-search input:focus {
  outline: none;
}

.rh-count {
  margin: var(--space-sm) 0 var(--space-md);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.rh-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line-strong);
}

.rh-row {
  border-bottom: 1px solid var(--line);
}

.rh-row a {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: var(--space-xs) var(--space-md);
  padding: var(--space-md) 0;
  text-decoration: none;
  color: inherit;
}

@media (max-width: 560px) {
  .rh-row a {
    grid-template-columns: 1fr;
    gap: var(--space-3xs);
  }
}

.rh-tag {
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--accent);
  padding-top: 0.35rem;
}

.rh-name {
  font-family: var(--font-poster);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  color: var(--ink);
}

.rh-row a:hover .rh-name,
.rh-row a:focus-visible .rh-name {
  color: var(--accent);
}

.rh-list .rh-note {
  grid-column: 2;
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  line-height: var(--leading-sm);
}

@media (max-width: 560px) {
  .rh-list .rh-note {
    grid-column: 1;
  }
}

.rh-empty {
  padding: var(--space-xl) 0;
  color: var(--ink-secondary);
}

/* ============================================================================
   ABOUT, FINAL ROUND  (comments 49 to 57, 2026-09-26)
   ========================================================================= */

/* 49 and 50: the closing block centred on the page, its heading on one line
   wherever a line can hold it. Below 900px it wraps, balanced, because one line
   of 47 characters would need type too small to read on a phone. */
.about-close-inner { text-align: center; }
.about-close h2 { max-width: none; margin-inline: auto; }
.about-close p { margin-inline: auto; }
.about-close-actions { justify-content: center; }

@media (min-width: 900px) {
  .about-close h2 {
    white-space: nowrap;
    font-size: min(var(--text-2xl), 3.9vw);
  }
}

/* 51 and 56: both section headings a step larger, and never broken over two
   lines: the size follows the viewport down so the line always fits. */
.ab-eligibility h2,
.ab-training h2 {
  font-size: clamp(1.125rem, 4.9vw, 2.5rem);
  line-height: 1.1;
  white-space: nowrap;
}

/* 52 to 54: NLCC on light red, NSCC on light blue, and no grey text left in
   the section: every muted role reads as ink here. */
.ab-eligibility {
  --ink-secondary: var(--ink);
  --ink-muted: var(--ink);
}

.ab-eligibility .eyebrow,
.ab-eligibility .compare-sub,
.ab-eligibility .compare tbody th,
.ab-eligibility .compare tbody td,
.ab-eligibility .ab-lede,
.ab-eligibility .ab-requirements p { color: var(--ink); }

.compare th:nth-child(2),
.compare td:nth-child(2) { background: var(--red-100); }

.compare th:nth-child(3),
.compare td:nth-child(3) { background: var(--blue-100); }

@media (min-width: 720px) {
  .compare th:nth-child(n + 2),
  .compare td:nth-child(n + 2) { padding-inline: var(--space-md); }
  .compare thead th:nth-child(n + 2) { padding-top: var(--space-md); }
  /* A hairline of page between the two columns keeps them two things. */
  .compare td:nth-child(2),
  .compare th:nth-child(2) { border-right: 6px solid var(--surface); }
}

@media (max-width: 719px) {
  .compare tbody td { padding: var(--space-2xs) var(--space-sm); }
  .compare tbody td + td { margin-top: var(--space-2xs); }
}

/* 57: the three column titles centred, the lists in ink rather than grey. */
.ab-course h3 { text-align: center; }
.ab-course li { color: var(--ink); }


/* @source website/src/css/78-cart.css */
/* ============================================================================
   MY CART  (comments 65 and 66, ADR-035)
   Amazon's shape: what is in the cart on the left, the order summary on the
   right, suggestions underneath. The summary is the Uiverse checkout card he
   pasted (title bar, delivery and payment steps, totals, then the price and
   the button in a footer bar), rebuilt in the site's navy and white.
   ========================================================================= */

.page-cart main {
  padding-top: var(--header-height);
  /* The cart is drawn from this browser's storage after the page loads. Holding
     a full screen keeps the footer below the fold meanwhile, so nothing on
     screen moves when the lines arrive (Lighthouse measured a 0.65 shift). */
  min-height: 100vh;
  min-height: 100svh;
}

/* Each of these sets its own display, which beats the hidden attribute. */
.cart-layout[hidden],
.cart-empty[hidden],
.cart-recs[hidden],
.receipt-stage[hidden] { display: none; }

.cart-page {
  width: min(var(--max-wide), calc(100% - 36px));
  margin: 0 auto;
  padding: var(--space-lg) 0 var(--space-3xl);
}

.cart-title {
  margin: var(--space-md) 0 0;
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 3rem);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.05;
}

.cart-count {
  margin: var(--space-2xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

.cart-count:empty { display: none; }

.cart-layout {
  display: grid;
  gap: var(--space-xl);
  margin-top: var(--space-xl);
}

@media (min-width: 960px) {
  .cart-layout {
    grid-template-columns: minmax(0, 1fr) minmax(20rem, 24rem);
    align-items: start;
    gap: var(--space-2xl);
  }
}

/* --- The list ------------------------------------------------------------- */
.cart-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}

.cart-line {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) auto;
  grid-template-areas:
    "media info price"
    "media controls controls";
  gap: var(--space-2xs) var(--space-sm);
  padding: var(--space-md) 0;
  border-bottom: 1px solid var(--line);
}

@media (min-width: 640px) {
  .cart-line {
    grid-template-columns: 120px minmax(0, 1fr) auto;
    grid-template-areas:
      "media info price"
      "media controls price";
    column-gap: var(--space-md);
  }
}

.cart-line-media {
  grid-area: media;
  display: block;
  background: #f0f0f0;
}

.cart-line-media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.cart-line-info {
  grid-area: info;
  min-width: 0;
}

.cart-line-title {
  display: block;
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: 1.35;
  text-decoration: none;
}

.cart-line-title:hover { text-decoration: underline; text-underline-offset: 3px; }

.cart-line-picks,
.cart-line-delivery {
  margin: var(--space-3xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-xs);
}

.cart-line-price {
  grid-area: price;
  margin: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.cart-line-controls {
  grid-area: controls;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
}

.qty {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
}

.qty button {
  width: 44px;
  height: 40px;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 1.125rem;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-pill);
}

.qty button:hover:not(:disabled) { background: var(--gray-100); }
.qty button:disabled { color: var(--gray-400); cursor: default; }

.qty output {
  min-width: 2ch;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.cart-line-remove {
  min-height: 40px;
  padding: 0 var(--space-3xs);
  border: 0;
  background: transparent;
  color: var(--ink-muted);
  font: inherit;
  font-size: var(--text-xs);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.cart-line-remove:hover { color: var(--ink); }

/* --- The checkout card ------------------------------------------------------
   Uiverse: 19px top corners, a hairline under the title, stacked soft shadows,
   and a tinted footer bar that holds the price and the button. */
.checkout-card {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 19px 19px 0 0;
  background: var(--surface-raised);
  box-shadow:
    0 105px 63px rgba(7, 19, 38, 0.04),
    0 47px 47px rgba(7, 19, 38, 0.07),
    0 12px 26px rgba(7, 19, 38, 0.08);
}

@media (min-width: 960px) {
  .checkout-card {
    position: sticky;
    top: 7rem;
  }
}

.checkout-card-title {
  display: flex;
  align-items: center;
  min-height: 44px;
  margin: 0;
  padding: 0 var(--space-md);
  border-bottom: 1px solid var(--navy-800);
  font-family: var(--font-text);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.checkout-steps {
  display: grid;
  padding: var(--space-md);
}

.checkout-step + .checkout-step {
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--line);
}

.checkout-step p { margin: 0; font-size: var(--text-xs); color: var(--ink-secondary); }

.checkout-step .checkout-step-label {
  margin-bottom: var(--space-3xs);
  color: var(--ink);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.checkout-details {
  display: grid;
  gap: var(--space-2xs);
  margin: 0;
  padding: var(--space-sm) var(--space-md) var(--space-md);
  border-top: 1px solid var(--navy-800);
}

.checkout-details div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
}

.checkout-details dt { font-size: var(--text-xs); font-weight: var(--weight-semibold); }

.checkout-details dd {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.checkout-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-md);
  background: var(--blue-100);
}

.checkout-price {
  margin: 0;
  color: var(--navy-900);
  font-size: 1.375rem;
  font-weight: var(--weight-black);
  font-variant-numeric: tabular-nums;
}

.checkout-btn {
  min-width: 9.5rem;
  min-height: 48px;
  padding: 0 var(--space-md);
  border: 1px solid var(--navy-950);
  border-radius: 7px;
  background: var(--navy-950);
  color: var(--white);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
  transition: background 180ms cubic-bezier(0.15, 0.83, 0.66, 1), transform 160ms ease;
}

.checkout-btn:hover:not(:disabled) { background: var(--navy-700); }
.checkout-btn:active:not(:disabled) { transform: scale(0.98); }
.checkout-btn:disabled { opacity: 0.6; cursor: progress; }

.checkout-status {
  margin: 0;
  padding: 0 var(--space-md);
  color: var(--ink-secondary);
  font-size: var(--text-xs);
}

.checkout-status:not(:empty) { padding-block: var(--space-sm); }
.checkout-status.is-error { color: var(--red-800); }

/* --- PayPal (owner ruling 2026-11-07) ----------------------------------------
   The cadet's name, then PayPal's own buttons, in the tinted footer colour so
   the card keeps its look: price on top, the way to pay underneath. */
.checkout-pay {
  display: grid;
  gap: var(--space-3xs);
  padding: 0 var(--space-md) var(--space-md);
  background: var(--blue-100);
}

.checkout-pay[hidden] { display: none; }

.checkout-cadet-label {
  color: var(--navy-900);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}

.checkout-cadet {
  min-height: 44px;
  padding: 0 var(--space-sm);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xs);
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
}

.checkout-cadet:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
.checkout-cadet[aria-invalid="true"] { border-color: var(--red-800); }

.checkout-cadet-hint {
  margin: 0 0 var(--space-xs);
  color: var(--ink-secondary);
  font-size: var(--text-2xs);
}

.checkout-paypal { min-height: 48px; }

/* PayPal's SDK sizes its button frames with a <style> element it writes into
   the page. Our CSP allows styles from this site only (style-src 'self', no
   'unsafe-inline'), so those rules are copied here from the SDK (zoid
   container, 2026-11-07); its JS still sets the height on each resize. */
.checkout-paypal [id^="zoid-paypal-"] {
  display: inline-block;
  position: relative;
  width: 100%;
  min-height: 48px;
}

.checkout-paypal [id^="zoid-paypal-"] > iframe {
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transition: opacity 0.2s ease-in-out;
}

.checkout-paypal [id^="zoid-paypal-"] > iframe.zoid-invisible { opacity: 0; }
.checkout-paypal [id^="zoid-paypal-"] > iframe.zoid-visible { opacity: 1; }

/* --- Empty ------------------------------------------------------------------ */
.cart-empty {
  display: grid;
  justify-items: start;
  gap: var(--space-md);
  margin-top: var(--space-xl);
  padding: var(--space-xl) 0;
  border-top: 1px solid var(--line);
}

.cart-empty p { margin: 0; font-size: var(--text-md); }

/* --- Suggestions ------------------------------------------------------------ */
.cart-recs {
  margin-top: var(--space-3xl);
}

.cart-recs-title {
  margin: 0 0 var(--space-lg);
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.rec-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  margin-top: var(--space-2xs);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease;
}

.rec-add:hover { border-color: var(--ink); background: var(--gray-100); }

/* "Choose size" is a link inside .shop-tile, whose `.shop-tile a { display: block }`
   out-ranks .rec-add and pinned the label to the top left. */
.cart-recs .shop-tile a.rec-add { display: flex; }

/* --- The receipt (after payment) ---------------------------------------------
   A navy terminal with a slot; the paper feeds out of it in short bursts, the
   way a thermal printer advances, three seconds from first line to torn edge.
   The mask reserves the paper's full height from the first frame, so nothing
   below moves while it prints. */
.receipt-stage {
  display: grid;
  justify-items: center;
  width: min(26rem, 100%);
  margin: var(--space-xl) auto 0;
}

.receipt-terminal {
  position: relative;
  width: 100%;
  height: 72px;
  border-radius: 20px 20px 12px 12px;
  background: var(--navy-900);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    0 18px 40px rgba(7, 19, 38, 0.28);
}

.receipt-slot {
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: 14px;
  height: 12px;
  border-radius: var(--radius-pill);
  background: var(--navy-950);
  box-shadow:
    inset 0 3px 5px rgba(0, 0, 0, 0.7),
    0 1px 0 rgba(255, 255, 255, 0.14);
}

.receipt-stage.is-feeding .receipt-terminal {
  animation: receipt-hum 90ms linear infinite;
}

@keyframes receipt-hum {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(0.6px); }
}

/* The mask's top edge is the middle of the slot: the paper is clipped above
   it and drawn over the machine's face below it, so it reads as coming out of
   the slot rather than sliding down from behind the terminal. */
.receipt-mask {
  position: relative;
  z-index: var(--z-raised);
  width: 84%;
  margin-top: -20px;
  padding-bottom: 18px; /* room for the torn edge */
  overflow: hidden;
}

.receipt-paper {
  position: relative;
  padding: var(--space-xl) var(--space-md) var(--space-md);
  background: var(--white);
  color: var(--gray-900);
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.55;
  box-shadow: 0 10px 24px rgba(7, 19, 38, 0.12);
  will-change: transform;
}

/* The torn edge: two offset diagonal gradients make a zigzag of paper. */
.receipt-paper::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -12px;
  height: 12px;
  background:
    linear-gradient(135deg, var(--white) 6px, transparent 0) 0 0 / 12px 12px repeat-x,
    linear-gradient(225deg, var(--white) 6px, transparent 0) 0 0 / 12px 12px repeat-x;
}

.receipt-paper p,
.receipt-paper li,
.receipt-paper dt,
.receipt-paper dd { margin: 0; color: var(--gray-900); }

.receipt-brand {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
  text-align: center;
  text-transform: uppercase;
}

.receipt-paper .receipt-sub {
  color: var(--gray-600);
  font-size: 0.75rem;
  text-align: center;
}

.receipt-paper .receipt-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-top: var(--space-md);
  padding-top: var(--space-sm);
  border-top: 1px dashed var(--gray-400);
  font-size: 0.75rem;
  text-transform: uppercase;
}

.receipt-paper .receipt-ref {
  margin-top: 0;
  padding-top: var(--space-3xs);
  border-top: 0;
  color: var(--gray-600);
}

.receipt-lines {
  list-style: none;
  margin: var(--space-sm) 0 0;
  padding: var(--space-sm) 0 0;
  border-top: 1px dashed var(--gray-400);
}

.receipt-lines li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 var(--space-sm);
}

.receipt-lines li + li { margin-top: var(--space-2xs); }

.receipt-paper .receipt-line-picks {
  grid-column: 1 / -1;
  color: var(--gray-600);
  font-size: 0.75rem;
}

.receipt-lines .receipt-line-cost { font-variant-numeric: tabular-nums; }

.receipt-totals {
  display: grid;
  gap: var(--space-3xs);
  margin: var(--space-sm) 0 0;
  padding-top: var(--space-sm);
  border-top: 1px dashed var(--gray-400);
}

.receipt-totals div {
  display: flex;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}

.receipt-totals dd { margin: 0; }

.receipt-totals .receipt-grand {
  margin-top: var(--space-3xs);
  font-size: 0.9375rem;
  font-weight: var(--weight-bold);
  text-transform: uppercase;
}

.receipt-paper .receipt-stamp {
  justify-self: center;
  width: max-content;
  margin: var(--space-md) auto 0;
  padding: var(--space-3xs) var(--space-sm);
  border: 2px solid var(--red-700);
  border-radius: var(--radius-sm);
  color: var(--red-700);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  transform: rotate(-4deg);
}

.receipt-paper .receipt-stamp.is-landing {
  animation: receipt-stamp 360ms cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
}

@keyframes receipt-stamp {
  from { opacity: 0; transform: rotate(-4deg) scale(1.6); }
  to { opacity: 1; transform: rotate(-4deg) scale(1); }
}

.receipt-paper .receipt-note {
  margin-top: var(--space-md);
  padding-top: var(--space-sm);
  border-top: 1px dashed var(--gray-400);
  font-size: 0.75rem;
}

.receipt-paper .receipt-motto {
  margin-top: var(--space-md);
  color: var(--gray-600);
  font-size: 0.6875rem;
  letter-spacing: var(--tracking-caps);
  text-align: center;
  text-transform: uppercase;
}

.receipt-after {
  max-width: var(--measure-narrow);
  margin: var(--space-lg) 0 0;
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  text-align: center;
}

.receipt-back { margin-top: var(--space-md); }

@media (prefers-reduced-motion: reduce) {
  .receipt-stage.is-feeding .receipt-terminal,
  .receipt-paper .receipt-stamp.is-landing { animation: none; }
}

.cart-empty .cart-empty-title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--weight-semibold); }

/* Order summary head: title plus a small "ways to pay" card icon (owner 2026-11-07: no Delivery/Payment boxes) */
.checkout-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2, 0.5rem); position: relative; }
.checkout-payinfo summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; color: var(--ink-secondary); border-radius: 8px; }
.checkout-payinfo summary::-webkit-details-marker { display: none; }
.checkout-payinfo summary:hover, .checkout-payinfo[open] summary { color: var(--ink, currentColor); }
.checkout-payinfo summary:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; }
.checkout-payinfo p { position: absolute; right: 0; top: 100%; z-index: var(--z-float); margin: 0; width: min(18rem, 80vw); padding: 0.75rem 0.875rem; font-size: var(--text-xs); color: var(--ink-secondary); background: var(--surface, #fff); border: 1px solid var(--line, rgba(0,0,0,.12)); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.12); }


/* @source website/src/css/79-motion.css */
/* ============================================================================
   SCROLL MOTION  (ADR-036, 2026-09-27)
   Copied from occasionswny.com on Camilo's instruction: "copy pretty much there
   exactly". The build tags the pieces (src/motion.js); main.js starts each one
   as it comes onto the screen. Retuned 2026-09-27 after his review: only
   headings, pictures and picture cards move, 0.8s, 160px; the homepage store
   strip and picture-left blocks come in from the left. This overrides the
   "minimal motion" line for scroll entrances only. Reduced motion, print and
   no-script visitors get the page exactly as before.
   ========================================================================= */

@media screen and (prefers-reduced-motion: no-preference) {
  /* The cover: the first block's text fades in on load, as theirs does,
     quicker (his 2026-09-27 review). */
  [data-mo="hero"] {
    animation: mo-fade 1s ease-in 0.1s backwards;
  }
}

@media screen and (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  /* Waiting pieces sit low; the page must not grow a tail while they do. */
  main {
    overflow-y: clip;
  }

  :root [data-mo]:not([data-mo="hero"]):not(.mo-in) {
    opacity: 0;
  }

  :root [data-mo="up"]:not(.mo-in),
  :root [data-mo="img"]:not(.mo-in) {
    translate: 0 var(--scroll-rise);
  }

  /* Their plate of food: in from the left, picture and heading together. */
  :root [data-mo="left"]:not(.mo-in),
  :root [data-mo="img-left"]:not(.mo-in) {
    translate: -100% 0;
  }

  :root [data-mo].mo-in {
    transition:
      opacity 0.8s var(--ease-scroll) var(--mo-delay, 0s),
      translate 0.8s var(--ease-scroll) var(--mo-delay, 0s);
  }

  [data-mo-d="t"] { --mo-delay: 0.1s; }
  [data-mo-d="b"] { --mo-delay: 0.15s; }

  /* Safety net: if main.js never runs, nothing stays hidden. */
  html:not(.mo-live) [data-mo]:not([data-mo="hero"]) {
    animation: mo-show 0.6s ease-out 3s forwards;
  }
}

@keyframes mo-fade {
  from { opacity: 0; }
}

@keyframes mo-show {
  to {
    opacity: 1;
    translate: none;
  }
}


/* @source website/src/css/80-sponsors.css */
/* ============================================================================
   SPONSORS  (2026-10-01)
   The old homepage carousel, kept quiet: grayscale marks on white, colour on
   hover, two arrows. Four across on desktop, two on a phone, swipeable.
   ========================================================================= */

.sponsors {
  width: min(var(--max), calc(100% - 36px));
  margin: 0 auto;
  padding: var(--space-2xl) 0;
  border-top: 1px solid var(--line);
  text-align: center;
}

.sponsors-heading,
.sponsors-heading > * { margin-inline: auto; text-align: center; }

.sponsors-frame {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-xs);
  margin-top: var(--space-lg);
}

.sponsors-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - var(--space-md)) / 2);
  gap: var(--space-md);
  margin: 0;
  padding: var(--space-2xs) 0;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}

.sponsors-track::-webkit-scrollbar { display: none; }

.sponsors-item { scroll-snap-align: start; }

.sponsors-item a {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  padding: var(--space-sm);
  border-radius: var(--radius);
}

.sponsors-item img {
  width: 100%;
  height: auto;
  max-width: 180px;
  max-height: 100%;
  object-fit: contain;
  filter: grayscale(1);
  mix-blend-mode: multiply; /* old site JPEGs carry a white square */
  opacity: 0.85;
  transition: filter var(--duration-slow) var(--ease-out), opacity var(--duration-slow) var(--ease-out);
}

.sponsors-item a:hover img,
.sponsors-item a:focus-visible img { filter: none; opacity: 1; }

.sponsors-arrow {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  color: var(--ink);
  cursor: pointer;
  transition: background var(--duration) var(--ease-out), color var(--duration) var(--ease-out);
}

.sponsors-arrow svg { width: 20px; height: 20px; }

.sponsors-arrow:hover { background: var(--surface-inverse); color: var(--ink-inverse); }

.sponsors-note {
  margin: var(--space-md) auto 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

.sponsors-note a { color: var(--ink); font-weight: var(--weight-semibold); }

@media (min-width: 768px) {
  .sponsors-track { grid-auto-columns: calc((100% - 2 * var(--space-lg)) / 3); gap: var(--space-lg); }
}

@media (min-width: 1100px) {
  .sponsors-track { grid-auto-columns: calc((100% - 3 * var(--space-lg)) / 4); }
}

@media (prefers-reduced-motion: reduce) {
  .sponsors-track { scroll-behavior: auto; }
  .sponsors-item img { transition: none; }
}


/* @source website/src/css/81-national.css */
/* =============================================================================
   NATIONAL EMBLEM  (2026-11-05, go-live parity ruling 7)
   The U.S. Naval Sea Cadet Corps emblem beside "Chart Your Course" on Home
   (the footer's logo row is in 63-footer.css). Round 2 (ruling 13): no white
   card. usnscc-national-logo-light.webp is a transparent cut of the supplied
   artwork, eagle and shield in their own colours, lettering white for navy.
   ========================================================================== */

.chart-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-md);
  margin-bottom: 42px;
}

.chart-head h2 { margin-bottom: 0; }
.chart-section .chart-head h2 { margin-bottom: 0; }

.chart-national {
  flex: none;
  display: block;
  transition: transform var(--duration) var(--ease-out);
}

.chart-national:hover { transform: translateY(-2px); }

.chart-national img {
  display: block;
  width: clamp(120px, 14vw, 190px);
  height: auto;
}

@media (max-width: 560px) {
  .chart-head { align-items: center; }
  .chart-national img { width: 104px; }
}


/* @source website/src/css/85-gallery.css */
/* ============================================================================
   GALLERY  (parity plan 2026-11-05, rulings 5 and 6)
   gallery.html (round 3): the Image of the Month, then every album as a
   Flickr-style cover tile. Dates moved to events.html (86-events.css).
   gallery-<slug>.html: a photo grid and the full-screen viewer (main.js,
   GALLERY block). The masthead reuses .rost-masthead from 67-roster.css so the
   page header matches Leadership and Support.
   ========================================================================= */

.gal-masthead .eyebrow a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.gal-meta {
  margin: var(--space-xs) 0 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.gal-album {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter) var(--section-y-tight);
}

.gal-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2xs) var(--space-lg);
  padding-bottom: var(--space-sm);
  margin-bottom: var(--space-md);
  border-bottom: var(--border-strong);
}

.gal-section-head h2 {
  margin: 0;
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
}

.gal-section-head p {
  margin: 0;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

/* --- Image of the Month (round 3): NASA's "Image Of The Day" block --------
   Words in a narrow left column (small spaced kicker, a large title, the
   photo's own name, a short caption, a link with a round arrow), a large
   landscape photo on the right at about 60% with "View album" under it,
   right-aligned. Text then photo on a phone. */
.gal-month {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: var(--space-xl) clamp(2rem, 5vw, 4.5rem);
  align-items: start;
  max-width: var(--max);
  margin: 0 auto;
  padding: var(--space-md) var(--gutter) var(--section-y-tight);
}

.gal-month-text { padding-top: var(--space-xs); }

.gal-month-kicker {
  margin: 0;
  color: var(--ink);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.24em;
  text-transform: uppercase;
}

.gal-month-title {
  margin: var(--space-2xs) 0 0;
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2vw, 3rem);
  line-height: 1.1;
  font-weight: var(--weight-black);
  letter-spacing: var(--tracking-tight);
}

.gal-month-name {
  margin: clamp(2rem, 6vw, 4.5rem) 0 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
  font-weight: var(--weight-black);
}

.gal-month-caption {
  margin: var(--space-sm) 0 0;
  max-width: 34ch;
  color: var(--ink-secondary);
  line-height: 1.7;
}

.gal-month-browse,
.gal-month-album {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  color: var(--ink);
  font-weight: var(--weight-black);
  text-decoration: none;
}

.gal-month-browse { margin-top: var(--space-md); }

.gal-month-arrow {
  display: inline-grid;
  place-items: center;
  width: 1.25em;
  height: 1.25em;
  border-radius: 50%;
  background: var(--red-600);
  color: var(--white);
  transition: transform var(--duration) var(--ease-out);
}

.gal-month-arrow svg { width: 0.8em; height: 0.8em; }
.gal-month-album svg { width: 1.05em; height: 1.05em; transition: transform var(--duration) var(--ease-out); }

.gal-month-browse:hover,
.gal-month-album:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.gal-month-browse:hover .gal-month-arrow,
.gal-month-album:hover svg { transform: translateX(3px); }

.gal-month-figure { margin: 0; }

.gal-month-figure img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--surface-sunken);
}

.gal-month-figure figcaption {
  margin-top: var(--space-sm);
  text-align: right;
}

@media (max-width: 767px) {
  .gal-month { grid-template-columns: 1fr; gap: var(--space-lg); }
  .gal-month-name { margin-top: var(--space-lg); }
}

@media (prefers-reduced-motion: reduce) {
  .gal-month-arrow,
  .gal-month-album svg { transition: none; }
}

/* --- Albums (round 3): Flickr's album grid -------------------------------
   Square-ish cover tiles with a small gap, the title in white over a dark
   gradient at the bottom, "N photos" under it, and the thin stacked-paper
   lines above each tile. 4 per row, 3 near 1100px, 2 on a tablet, 1 on a
   phone; every album, all the way down. */
.gal-albums {
  max-width: var(--max);
  margin: 0 auto;
  padding: var(--space-md) var(--gutter) var(--section-y);
  border-top: var(--border);
}

.gal-tiles {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg) var(--space-sm);
  margin: var(--space-md) 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 560px) { .gal-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .gal-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1180px) { .gal-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.gal-tile {
  position: relative;
  display: block;
  aspect-ratio: 1;
  margin-top: 8px;
  color: var(--white);
  text-decoration: none;
  background: var(--surface-sunken);
  transition: transform var(--duration) var(--ease-out), box-shadow var(--duration) var(--ease-out);
}

/* The stacked-paper lines: two hairlines above the cover, each a little
   narrower, as Flickr draws an album. */
.gal-tile::before,
.gal-tile::after {
  content: "";
  position: absolute;
  left: 50%;
  height: 1px;
  background: var(--line-strong);
  transform: translateX(-50%);
}
.gal-tile::before { top: -4px; width: 96%; }
.gal-tile::after { top: -7px; width: 92%; }

.gal-tile img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.gal-tile-text {
  position: absolute;
  inset: auto 0 0;
  display: grid;
  gap: 2px;
  padding: 3.5rem var(--space-md) var(--space-md);
  background: linear-gradient(to top, rgba(4, 14, 30, 0.88), rgba(4, 14, 30, 0.55) 55%, rgba(4, 14, 30, 0));
}

.gal-tile-title {
  font-size: var(--text-lg);
  line-height: 1.2;
  font-weight: var(--weight-semibold);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

.gal-tile-count {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}

@media (hover: hover) {
  .gal-tile:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(4, 14, 30, 0.22); }
}

.gal-tile:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .gal-tile { transition: none; }
  .gal-tile:hover { transform: none; }
}

/* --- Album grid ------------------------------------------------------------ */
.gal-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

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

@media (min-width: 1024px) {
  .gal-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-xs); }
}

.gal-thumb {
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  cursor: zoom-in;
}

.gal-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-out), opacity var(--duration) var(--ease-out);
}

@media (hover: hover) {
  .gal-thumb:hover img { transform: scale(1.04); }
}

.gal-foot {
  margin: var(--space-lg) 0 0;
}

/* --- Full-screen viewer (a <dialog>: focus trap, inert page and Esc are native) */
.gal-viewer {
  width: 100vw;
  max-width: none;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--navy-950);
  color: var(--ink);
  overscroll-behavior: contain;
}

.gal-viewer::backdrop { background: var(--navy-950); }

.gal-viewer[open] {
  display: grid;
  grid-template-rows: auto 1fr auto;
}

.gal-viewer-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
}

.gal-viewer-count {
  margin: 0;
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.gal-viewer-stage {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 0;
  padding: 0 var(--space-sm);
  touch-action: pan-y pinch-zoom;
}

.gal-viewer-stage img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  min-height: 0;
  object-fit: contain;
  user-select: none;
  -webkit-user-drag: none;
}

.gal-viewer-btn {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: var(--ink);
  cursor: pointer;
}

.gal-viewer-btn:hover { background: rgba(255, 255, 255, 0.18); }

.gal-viewer-btn svg { width: 22px; height: 22px; }

.gal-viewer-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

.gal-viewer-prev { left: var(--space-sm); }
.gal-viewer-next { right: var(--space-sm); }

.gal-viewer-caption {
  margin: 0;
  padding: var(--space-xs) var(--space-sm) var(--space-sm);
  color: var(--ink-secondary);
  font-size: var(--text-sm);
  text-align: center;
}

@media (max-width: 639px) {
  /* On a phone the arrows sit under the photo, where a thumb reaches them,
     and swiping does the same job. */
  .gal-viewer-nav { position: static; transform: none; }
  .gal-viewer[open] { grid-template-rows: auto 1fr auto auto; }
  .gal-viewer-stage { padding: 0; }
  .gal-viewer-pager {
    display: flex;
    justify-content: center;
    gap: var(--space-lg);
    padding: var(--space-xs) 0 max(var(--space-md), env(safe-area-inset-bottom));
  }
}

@media (min-width: 640px) {
  .gal-viewer-pager { display: contents; }
  /* Room either side so the arrows never sit on the photograph. */
  .gal-viewer-stage { padding: 0 72px; }
  .gal-viewer-nav { z-index: var(--z-raised); }
}

.gal-viewer-caption,
.gal-viewer-count { max-width: none; }

@media (prefers-reduced-motion: reduce) {
  .gal-thumb img { transition: none; }
}

/* --- Header room for the seventh nav item --------------------------------------
   Gallery made the desktop nav seven links. Between 1280px (where the full nav
   starts) and 1440px that wrapped "The Sullivans" onto two lines, so the links
   and the header sides give back a few pixels there. Wider screens are untouched. */
@media (min-width: 1280px) and (max-width: 1439px) {
  .site-header .primary-nav > a { padding-inline: 9px; }
  .site-header { padding-inline: 28px; }
}

/* --- Photo band: a single wide photograph between sections ------------------ */
.photo-band {
  max-width: var(--max);
  margin: 0 auto var(--section-y-tight);
  padding: 0 var(--gutter);
}

.photo-band img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 34rem;
  object-fit: cover;
  border-radius: var(--radius);
}

/* Round 4 (owner, 2026-11-05): "Gallery" alone, centred, a little lower and larger. */
.gal-masthead .rost-masthead-inner { text-align: center; }
.gal-masthead { padding-top: calc(var(--section-y) + var(--space-xl)); padding-bottom: var(--section-y-tight); }
.gal-masthead h1 { font-size: clamp(3rem, 2rem + 4.2vw, 5.5rem); margin-inline: auto; }


/* @source website/src/css/86-events.css */
/* ============================================================================
   EVENTS  (parity plan 2026-11-05, row 15)
   events.html: the next date big (date block, chip, name, date line, city,
   "Add to calendar"), then a month-by-month list of compact rows. The masthead
   reuses .rost-masthead from 67-roster.css so the header matches the other
   inner pages. Rows are one line on a desktop (date, name, city, type) and two
   on a phone (date and type, then name and city).
   ========================================================================= */

.ev-page {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter) var(--section-y);
}

/* --- Next up --------------------------------------------------------------- */
.ev-next {
  margin: 0 0 var(--space-2xl);
  padding: var(--space-lg);
  background: var(--surface-raised);
  border: var(--border);
  border-radius: var(--radius);
}

.ev-next-kicker {
  margin: 0 0 var(--space-sm);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ev-next-body {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-lg);
}

.ev-next-date {
  display: grid;
  place-items: center;
  align-content: center;
  width: 8.5rem;
  aspect-ratio: 1;
  margin: 0;
  border-radius: var(--radius);
  background: var(--blue-050);
  color: var(--navy-700);
  font-family: var(--font-display);
  line-height: 1;
  text-align: center;
}

.ev-next-month,
.ev-next-year {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ev-next-day {
  display: block;
  margin: var(--space-3xs) 0;
  font-size: var(--text-4xl, 3.5rem);
  font-weight: var(--weight-black);
}

.ev-next-year { font-weight: var(--weight-semibold); color: var(--ink-muted); }

.ev-next-text h2 {
  margin: var(--space-2xs) 0 0;
  font-size: var(--text-2xl);
  line-height: var(--leading-2xl);
  letter-spacing: var(--tracking-tight);
}

.ev-next-meta {
  margin: var(--space-2xs) 0 var(--space-md);
  color: var(--ink-secondary);
  font-size: var(--text-md);
}

/* --- Next up photos (round 3) -----------------------------------------------
   Four album photos use the card's empty right side: one row of four squares
   on a wide screen, 2 by 2 when narrower, two in a row under the words on a
   phone. Same corner radius as the card. */
.ev-next:has(.ev-next-photos li) .ev-next-body {
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 1.25fr);
}

.ev-next-photos {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ev-next-photos:empty { display: none; }

.ev-next-photos img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

@media (max-width: 1199px) {
  .ev-next:has(.ev-next-photos li) .ev-next-body { grid-template-columns: auto minmax(0, 1fr) minmax(0, 0.8fr); }
  .ev-next-photos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 767px) {
  .ev-next:has(.ev-next-photos li) .ev-next-body { grid-template-columns: auto minmax(0, 1fr); }
  .ev-next-photos { grid-column: 1 / -1; }
  .ev-next-photos li:nth-child(n + 3) { display: none; }
}

/* --- Type chip ------------------------------------------------------------- */
.ev-chip {
  display: inline-block;
  justify-self: start;
  margin: 0;
  padding: 0.2em 0.65em;
  border-radius: 999px;
  background: var(--surface-sunken);
  color: var(--ink-secondary);
  font-size: var(--text-2xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-caps);
  line-height: 1.5;
  text-transform: uppercase;
  white-space: nowrap;
}

.ev-chip-drill { background: var(--blue-050); color: var(--navy-700); }

/* --- Month by month -------------------------------------------------------- */
.ev-months {
  display: grid;
  gap: var(--space-xl);
}

.ev-month-title {
  margin: 0;
  padding-bottom: var(--space-xs);
  border-bottom: var(--border-strong);
  font-size: var(--text-lg);
  line-height: var(--leading-lg);
}

.ev-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ev-row {
  display: grid;
  grid-template-columns: 10rem minmax(0, 1fr) 12rem 9rem;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) 0;
  border-bottom: var(--border);
}

.ev-row-date {
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}

.ev-row-name { font-weight: var(--weight-semibold); }

.ev-row-city {
  color: var(--ink-secondary);
  font-size: var(--text-sm);
}

.ev-row .ev-chip { justify-self: end; }

.ev-empty {
  margin: 0 0 var(--space-xl);
  color: var(--ink-secondary);
}

.ev-foot {
  margin: var(--space-2xl) 0 0;
  color: var(--ink-secondary);
}

@media (max-width: 767px) {
  .ev-next { padding: var(--space-md); }
  .ev-next-body { gap: var(--space-md); align-items: start; }
  .ev-next-date { width: 5.5rem; }
  .ev-next-day { font-size: var(--text-2xl); }
  .ev-next-text h2 { font-size: var(--text-xl); line-height: var(--leading-xl); }

  .ev-row {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--space-3xs) var(--space-sm);
  }
  .ev-row-date { grid-column: 1; grid-row: 1; }
  .ev-row .ev-chip { grid-column: 2; grid-row: 1; }
  .ev-row-name { grid-column: 1 / -1; grid-row: 2; }
  .ev-row-city { grid-column: 1 / -1; grid-row: 3; }
}

/* --- Header room for the eighth nav item -------------------------------------
   Events made the desktop nav eight links. Up to 1600px the links and the
   header sides give back a few more pixels than the seven-link rule in
   85-gallery.css, so the brand line "USNSCC Buffalo, NY" stays on one line. */
@media (min-width: 1440px) and (max-width: 1599px) {
  .site-header .primary-nav > a { padding-inline: 10px; }
  .site-header { padding-inline: 36px; }
}

@media (min-width: 1280px) and (max-width: 1439px) {
  .site-header .primary-nav > a { padding-inline: 7px; }
  .site-header { padding-inline: 24px; }
}


/* @source website/src/css/87-contact-motion.css */
/* ============================================================================
   CONTACT FORM SEND ANIMATION
   After Sarah Drasner's "Form with Animation That Assists in UX" (codepen
   sdras/LEorev), rebuilt without jQuery or GSAP: main.js drives it with the
   Web Animations API, this file holds the shapes and the idle loops.

   The story, about 3.5 s end to end:
     1. "Send message" flips away on its X axis and the red face behind it
        pinches into a disc, then a loader ring, while /api/contact is in flight.
     2. On delivery the ring flattens, a horizon line draws across the card,
        swells start rolling below it and USS The Sullivans (DDG-68) surfaces
        on the near water, rocking, her reflection rippling under her.
     3. She sails left to right up toward the horizon, smaller, slower and
        fainter, then the fields fold away and the "Message sent" panel takes
        their place, scrolled to the middle of the screen.
   Only transform and opacity move. The stage is aria-hidden: the status line
   and the panel heading carry every word. Reduced motion skips to the panel.
   ========================================================================= */

.contact-form-card { position: relative; }


/* --cm-y (button centre, from the card's top edge), --cm-w and --cm-h (button
   size) are measured by main.js at the moment of sending. */
.cm-stage {
  --cm-y: 0px;
  --cm-w: 320px;
  --cm-h: 52px;
  --cm-ship-w: clamp(172px, 39%, 230px); /* 15% up on the first cut, his call */
  --cm-rise: 18px; /* near water (the ship's start) to the horizon */
  position: absolute;
  top: var(--cm-y);
  left: 0;
  right: 0;
  z-index: var(--z-raised-2);
  height: 0;
  pointer-events: none;
  visibility: hidden;
}

.cm-stage.is-on { visibility: visible; }

.cm-stage > * {
  position: absolute;
  opacity: 0;
  will-change: transform, opacity;
}

/* --- 1. The button's underside: two caps and a middle that close to a disc */
.cm-pill {
  top: calc(var(--cm-h) / -2);
  left: 50%;
  width: var(--cm-w);
  height: var(--cm-h);
  margin-left: calc(var(--cm-w) / -2);
}

.cm-pill > span {
  position: absolute;
  top: 0;
  height: 100%;
  background: var(--red-800);
}

.cm-pill-mid {
  left: calc(var(--cm-h) / 2);
  right: calc(var(--cm-h) / 2);
}

.cm-pill-cap {
  width: var(--cm-h);
  border-radius: 50%;
}

.cm-pill-cap--l { left: 0; }
.cm-pill-cap--r { right: 0; }

/* --- The loader ring ------------------------------------------------------ */
.cm-ring {
  top: calc(var(--cm-h) / -2);
  left: 50%;
  width: var(--cm-h);
  height: var(--cm-h);
  margin-left: calc(var(--cm-h) / -2);
}

.cm-ring svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke-linecap: round;
}

.cm-ring-track { stroke: var(--blue-100); stroke-width: 3; }

.cm-ring-arc {
  stroke: var(--navy-700);
  stroke-width: 3;
  stroke-dasharray: 26 100;
}

.cm-stage.is-waiting .cm-ring svg {
  animation: cm-spin 900ms linear infinite;
}

.cm-stage.is-waiting .cm-ring-arc {
  animation: cm-arc 1.4s var(--ease-in-out) infinite;
}

@keyframes cm-spin {
  to { transform: rotate(360deg); }
}

/* The arc breathes so the wait reads as work, not a frozen icon. */
@keyframes cm-arc {
  0%, 100% { stroke-dasharray: 18 100; }
  50% { stroke-dasharray: 58 100; }
}

/* --- 2. The horizon, the sea and the ship --------------------------------- */
.cm-water {
  top: calc(var(--cm-rise) * -1);
  left: var(--space-md);
  right: var(--space-md);
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--navy-600) 14%, var(--navy-600) 86%, transparent);
  transform-origin: 50% 50%;
}

/* Swells between the horizon and the near water. Each is a seamless sine
   strip twice the sea's width sliding left by half of itself, so the loop has
   no seam. Perspective: the far ones are flatter, fainter and slower; the near
   ones taller and quicker. Only translateX moves. */
.cm-sea {
  top: calc(var(--cm-rise) * -1);
  left: var(--space-md);
  right: var(--space-md);
  height: calc(var(--cm-rise) + 18px);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}

.cm-swell {
  position: absolute;
  left: 0;
  width: 200%;
}

.cm-swell svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: none;
  stroke: var(--navy-600);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.cm-swell path,
.cm-swell use { vector-effect: non-scaling-stroke; }

.cm-swell--1 { top: 3px; height: 2px; opacity: 0.18; }
.cm-swell--2 { top: 9px; height: 3px; opacity: 0.28; }
.cm-swell--3 { top: calc(var(--cm-rise) + 1px); height: 4px; opacity: 0.4; }
.cm-swell--4 { top: calc(var(--cm-rise) + 9px); height: 6px; opacity: 0.26; }

.cm-stage.is-on .cm-swell--1 { animation: cm-swell 9s linear infinite; }
.cm-stage.is-on .cm-swell--2 { animation: cm-swell 6.5s linear infinite -2s; }
.cm-stage.is-on .cm-swell--3 { animation: cm-swell 4.4s linear infinite -1s; }
.cm-stage.is-on .cm-swell--4 { animation: cm-swell 3.2s linear infinite -2.4s; }

@keyframes cm-swell {
  to { transform: translateX(-50%); }
}

/* The vessel box is the ship drawing (viewBox 200 x 96). Its waterline sits at
   y 44, so the box is lifted by 44/200 of its width and scales from that line:
   however small she gets, her keel stays on the water. */
.cm-vessel {
  top: calc(var(--cm-ship-w) * -0.22);
  left: 50%;
  width: var(--cm-ship-w);
  margin-left: calc(var(--cm-ship-w) / -2);
  transform-origin: 50% 45.83%;
}

.cm-ship {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  color: var(--navy-800);
  transform-origin: 50% 45.83%;
}

/* At sea she never sits still. Two loops on two periods (3.4 s roll, 2.1 s
   pitch and bob) drift in and out of phase, so the motion never repeats like a
   metronome. Both turn about the waterline under her midships (viewBox 100,44).
   The reflection runs the same loops mirrored: opposite turn, opposite bob. */
.cm-roll,
.cm-bob {
  transform-box: view-box;
  transform-origin: 100px 44px;
}

.cm-stage.is-on .cm-roll { animation: cm-roll 3.4s var(--ease-in-out) infinite; }
.cm-stage.is-on .cm-bob { animation: cm-bob 2.1s var(--ease-in-out) infinite; }
.cm-stage.is-on .cm-roll--mirror { animation-name: cm-roll-mirror; }
.cm-stage.is-on .cm-bob--mirror { animation-name: cm-bob-mirror; }

@keyframes cm-roll {
  0%, 100% { transform: rotate(0deg); }
  22% { transform: rotate(2.2deg); }
  48% { transform: rotate(-1.5deg); }
  73% { transform: rotate(1.4deg); }
}

@keyframes cm-roll-mirror {
  0%, 100% { transform: rotate(0deg); }
  22% { transform: rotate(-2.2deg); }
  48% { transform: rotate(1.5deg); }
  73% { transform: rotate(-1.4deg); }
}

@keyframes cm-bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  35% { transform: translateY(1px) rotate(-0.7deg); }
  68% { transform: translateY(-0.6px) rotate(0.5deg); }
}

@keyframes cm-bob-mirror {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  35% { transform: translateY(-1px) rotate(0.7deg); }
  68% { transform: translateY(0.6px) rotate(-0.5deg); }
}

#cm-ddg68 { fill: currentColor; }
#cm-ddg68 .cm-rig { fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; }
#cm-ddg68 .cm-flag-white { fill: var(--white); stroke: var(--navy-800); stroke-width: 0.3; }
#cm-ddg68 .cm-flag-red { fill: var(--red-700); }
#cm-ddg68 .cm-flag-blue { fill: var(--navy-600); }
#cm-ddg68 .cm-number {
  fill: var(--white);
  font-family: var(--font-display);
  font-size: 7.5px;
  font-weight: var(--weight-black);
  text-anchor: middle;
}

.cm-reflection { opacity: 0.6; }

.cm-wake path {
  fill: none;
  stroke: var(--blue-500);
  stroke-width: 1;
  stroke-linecap: round;
  opacity: 0;
}

.cm-stage.is-sailing .cm-wake path {
  animation: cm-wake 900ms var(--ease-out) infinite;
}

.cm-stage.is-sailing .cm-wake path + path { animation-delay: 450ms; }

@keyframes cm-wake {
  0% { opacity: 0; transform: translateX(0); }
  30% { opacity: 0.55; }
  100% { opacity: 0; transform: translateX(-10px); }
}

/* --- 3. The sent panel ------------------------------------------------------ */
.contact-form-card.is-sent {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.cm-sent {
  padding: var(--space-lg) 0 var(--space-sm);
  text-align: center;
}

.cm-sent-title {
  margin: 0 0 var(--space-2xs);
  color: var(--navy-950);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  line-height: var(--leading-xl);
}

/* Focus lands here by script so screen readers start at the result; it is
   not a control and cannot be tabbed to, so it carries no ring. */
.cm-sent .cm-sent-title:focus { outline: none; }

.cm-sent p {
  margin: 0 auto;
  max-width: var(--measure-narrow);
  color: var(--ink-secondary);
}

.cm-sent .cm-sent-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-md);
  justify-content: center;
  margin-top: var(--space-md);
  font-weight: var(--weight-semibold);
}

.cm-sent a,
.cm-again {
  color: var(--navy-600);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.cm-again {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  .cm-stage { display: none; }
}


/* @source website/src/css/88-final-join.css */
/* ============================================================================
   FINAL UI, LANE A  (owner rulings, 2026-11-06)
   Join, Resources and Staff. Plan: project-work/04-deployment-qa/go-live/
   FINAL-UI-PLAN-2026-11-06.md, "Lane A". Phone = up to 767px, desktop = 1024px+.
   ========================================================================= */

/* --- 1. Enrollment ("Enrollment runs through the national site") ----------
   The whole block sits centred on the page: heading, lede, the lead button
   and the closing button centred; the three steps form one centred column.
   The title is larger and stays on one line wherever it fits. */
.join-steps-inner { text-align: center; }

/* The title may use the full content width; the steps keep a reading column. */
.join-steps .step-list,
.join-steps .step-action { max-width: 48rem; margin-inline: auto; }

.join-steps-inner > .eyebrow { margin-inline: auto; }

.join-steps h2 {
  max-width: none;
  font-size: clamp(2rem, 1.2rem + 2.6vw, 3.5rem);
  line-height: 1.08;
  text-wrap: balance;
}

.join-steps .lede { margin-inline: auto; }

.step-lead-action {
  flex-direction: column;
  justify-content: center;
  margin-inline: auto;
}

.step-action { justify-items: center; }

/* Steps read left to right inside the centred column, so the numbers line up.
   The number used to span 3 rows, and step 3 has 4 children, so its 4th child
   fell into the number column. Every child now goes to column 2 and the number
   spans every row, centred on the step. Row gap is zero so the spare rows the
   span creates on shorter steps take no space; spacing comes from margins. */
.step-list { text-align: left; }

.step {
  row-gap: 0;
  align-items: start;
}

.step > * { grid-column: 2; }
.step-list .step > * + * { margin-top: var(--space-sm); }
.step-list .step > p + p { margin-top: var(--space-xs); }

.step::before {
  content: counter(step);
  grid-column: 1;
  grid-row: 1 / span 8;
  align-self: center;
  min-width: 1.4ch;
  text-align: center;
  font-size: var(--text-2xl);
  line-height: 1;
}

@media (min-width: 1024px) {
  .join-steps h2 { white-space: nowrap; }
}

/* --- 4. Phone: Join hero text and "Not ready to enroll yet?" centred ------- */
@media (max-width: 767px) {
  .join-hero-body { text-align: center; }
  .join-hero-body h1,
  .join-hero-body .lede { margin-inline: auto; }
  .join-hero-actions { justify-content: center; }

  .join-ask-inner { text-align: center; justify-items: center; }
  .join-ask-inner p { margin-inline: auto; }
}

/* --- 2. Order swap: "Your first step is simple" now sits under the hero and
   "Not ready to enroll yet?" closes the page. The old rule that tightened the
   ask block against the answers below no longer has a pair to act on. */
.page-join .rh-closing + .join-answers { border-top: 0; }

/* --- 5. Resources ----------------------------------------------------------- */
/* Packet fine print: the paragraph is narrower than its box, so it needs auto
   margins to sit on the same centre line as the list above it. */
.rh-forms-centred .rh-packet p { margin-inline: auto; }

/* "Cannot find it?" on a desktop: text on the left, patch on the right, and the
   three gaps (content edge to text, text to patch, patch to content edge) are
   equal, so A = B. */
@media (min-width: 1024px) {
  .rh-close-inner {
    grid-template-columns: minmax(0, var(--measure)) auto;
    column-gap: 0;
    justify-content: space-evenly;
  }
  .rh-close-mark { justify-self: center; }
}

/* Phone: title, line and buttons centred. */
@media (max-width: 767px) {
  .rh-close-inner { text-align: center; }
  .rh-close p { margin-inline: auto; }
  .rh-close-actions { justify-content: center; }
}


/* @source website/src/css/89-final-header.css */
/* ============================================================================
   FINAL HEADER  (final UI round, 2026-11-06, lane B)
   His rulings from the phone recording:
   - the red bar is one thin line on a phone (60-header.css);
   - below 1280px the header row is logo + name, search, cart, burger;
   - the burger drawer: Join the Division and Staff login on top, the eight
     pages in two columns, the five socials in one centred row, as tall as its
     content and scrolling inside only on a short screen;
   - the floating Join pill is truly hidden while the drawer is open.
   Desktop (1280px and up) is unchanged: the drawer wrappers dissolve with
   display:contents and the row is the same items in the same order.
   ========================================================================= */

:root { --announce-h: 36px; }

@media (min-width: 768px) {
  :root { --announce-h: 40px; }
}

/* --- Desktop: the wrappers are invisible to layout ------------------------ */
@media (min-width: 1280px) {
  .nav-drawer,
  .nav-links { display: contents; }

  .nav-drawer-top { display: none; }
}

/* 85-gallery.css and 86-events.css tighten `.primary-nav > a` so eight links
   fit between 1280 and 1600px. The page links now sit one level down, in
   .nav-links, so the same values are restated for them here. */
@media (min-width: 1440px) and (max-width: 1599px) {
  .site-header .nav-links > a { padding-inline: 10px; }
}

@media (min-width: 1280px) and (max-width: 1439px) {
  .site-header .nav-links > a { padding-inline: 7px; }
}

/* --- Below 1280px: the header row ----------------------------------------- */
@media (max-width: 1279px) {
  .site-header {
    gap: var(--space-xs);
    padding-block: var(--space-2xs);
  }

  .brand { min-width: 0; }
  .brand span { min-width: 0; }
  .brand strong {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* The nav itself is the right-hand cluster: search and cart. The drawer
     inside it is lifted out of the row and hangs under the header. */
  .site-header .primary-nav {
    position: static;
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0;
    margin-left: auto;
    padding: 0;
    border: 0;
    background: none;
  }

  /* The desktop Join pill and staff icon live in the drawer below 1280px. */
  .site-header .primary-nav > .nav-cta,
  .site-header .primary-nav > .nav-staff { display: none; }

  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
  }

  .nav-toggle span { margin: 2.5px auto; }

  /* --- The drawer --------------------------------------------------------- */
  .nav-drawer {
    position: absolute;
    top: calc(100% + 8px);
    right: 12px;
    left: 12px;
    display: none;
    flex-direction: column;
    gap: var(--space-sm);
    /* As tall as its content. Only a short screen scrolls it, inside. */
    max-height: calc(100svh - var(--header-height) - 24px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-sm);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--radius);
    /* Solid: at 0.98 the page copy ghosted through behind the links. */
    background: rgb(7, 19, 38);
    box-shadow: 0 24px 60px rgba(5, 15, 31, 0.4);
  }

  .primary-nav.is-open .nav-drawer { display: flex; }

  /* Join the Division (gold, the site's button) beside Staff login. */
  .nav-drawer-top {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
  }

  .primary-nav .nav-drawer-top .nav-drawer-join {
    flex: 1 1 11rem;
    justify-content: center;
    min-height: 48px;
    margin: 0;
    padding: 0 var(--space-sm);
    font-size: var(--text-base);
  }

  .primary-nav .nav-drawer-staff {
    /* Grows to the full row when a narrow phone wraps it under Join. */
    flex: 1 0 auto;
    justify-content: center;
    gap: var(--space-2xs);
    min-height: 48px;
    padding: 0 var(--space-sm);
    border: 1px solid rgba(255, 255, 255, 0.28);
    white-space: nowrap;
  }

  .nav-drawer-staff svg { width: 20px; height: 20px; flex: none; }

  /* The eight pages, two columns: Home Join About Resources down the left,
     Gallery Events Store Contact down the right. */
  .nav-links {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(4, auto);
    grid-auto-flow: column;
    gap: var(--space-3xs) var(--space-xs);
    padding-top: var(--space-sm);
    border-top: 1px solid rgba(255, 255, 255, 0.14);
  }

  .primary-nav .nav-links a {
    justify-content: center;
    margin: 0;
    font-size: var(--text-base);
  }

  /* The five socials, one centred row, evenly spaced, 44px targets. */
  .nav-drawer .nav-social {
    display: flex;
    justify-content: center;
    gap: var(--space-xs);
    margin: 0;
    padding: var(--space-sm) 0 0;
    border: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
  }

  .nav-drawer .nav-social a {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    min-height: 44px;
    padding: 0;
    border-radius: 50%;
    color: rgba(255, 255, 255, 0.85);
  }

  .nav-drawer .nav-social svg { width: 20px; height: 20px; display: block; }
}

/* Very narrow phones (320px): the bar line and the name both stay whole. */
@media (max-width: 360px) {
  .announce-bar { font-size: var(--text-xs); }
  .announce-link { padding-inline: 8px 44px; }
  .site-header {
    gap: var(--space-3xs);
    padding-inline: 10px;
  }
  .brand { gap: 6px; }
  .brand img {
    width: 38px;
    height: 38px;
  }
  .brand strong { font-size: var(--text-sm); }
}

/* --- The floating Join pill steps out while the drawer is open ------------
   Not opacity alone: visibility takes it out of the tab order and the
   accessibility tree, and main.js also sets it inert (DECISIONS ~367, 379). */
.nav-open .sticky-join,
.nav-open .sticky-join.is-visible {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}


/* @source website/src/css/90-final-home.css */
/* ============================================================================
   FINAL HOME  (final UI round, 2026-11-06, Lane C)
   Camilo's last pass on the home page before go-live, from his screenshots and
   phone recording. Phone means up to 767px; every desktop layout is unchanged
   unless a rule below says "all widths".
   ========================================================================= */

/* ------------------------------------------------ where-we-meet rows (phone) */
/* The phone card of three tappable rows. Hidden on desktop, which keeps the
   three labelled cards. */
.where-rows { display: none; }

@media (max-width: 767px) {
  /* ---------------------------------------------------------------- 1. hero */
  /* The paragraph goes on a phone; the title gets the room instead. */
  .page-index .hero-copy { display: none; }

  .page-index .hero h1 {
    font-size: clamp(2.5rem, 12.6vw, 3.6rem);
    line-height: 1;
  }

  /* ----------------------------------------------------------- 2. the ages */
  .page-index .route-panel {
    align-items: center;
    text-align: center;
  }

  .page-index .route-panel p { margin-inline: auto; }

  .page-index .route-panel .button { align-self: center; }

  /* ---------------------------------- 4. three poster cards, one swipe row */
  .page-index .poster-cards {
    display: flex;
    gap: var(--space-md);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .page-index .poster-cards::-webkit-scrollbar { display: none; }

  .page-index .poster-cards:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: 4px;
  }

  /* Most of the screen per card, with the next one peeking in so the row
     reads as swipeable before the dots are even seen. */
  .page-index .poster-card {
    flex: 0 0 86%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }

  .poster-dots {
    display: flex;
    justify-content: center;
    gap: var(--space-2xs);
    margin-top: var(--space-lg);
  }

  /* A 44px target around a small dot. */
  .poster-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
  }

  .poster-dot::before {
    content: "";
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.35);
    transition: background 160ms ease, transform 160ms ease;
  }

  .poster-dot[aria-current="true"]::before {
    background: var(--accent-on-dark);
    transform: scale(1.25);
  }

  .poster-dot:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: -6px;
    border-radius: 50%;
  }

  /* ------------------------------------------- 6. your first step is simple */
  .page-index .join-callout,
  .page-index .join-callout > div {
    text-align: center;
  }

  .page-index .join-callout p { margin-inline: auto; }

  .page-index .join-callout .button { justify-self: center; }

  /* ---------------------------------------- 7. where we meet, one row card */
  .page-index .where-info { display: none; }

  .page-index .where-rows {
    display: block;
    margin: 0;
    padding: 0;
    list-style: none;
    background: var(--white);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 18px 46px rgba(7, 19, 38, 0.08);
    overflow: hidden;
  }

  .where-rows li + li { border-top: 1px solid var(--line); }

  .where-rows a {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    min-height: 60px;
    padding: var(--space-sm) var(--space-md);
    color: var(--navy-900);
    font-weight: var(--weight-semibold);
    font-size: 0.98rem;
    line-height: 1.35;
    text-decoration: none;
  }

  .where-rows a:active { background: var(--gray-100); }

  .where-rows a:focus-visible {
    outline: 2px solid var(--focus-ring);
    outline-offset: -4px;
  }

  .where-row-icon {
    flex: none;
    width: 22px;
    height: 22px;
    color: var(--red-700);
  }

  .where-row-text {
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
  }

  .where-row-chevron {
    flex: none;
    width: 18px;
    height: 18px;
    color: var(--ink-muted);
  }
}

/* Dots exist only for the phone carousel. */
@media (min-width: 768px) {
  .poster-dots { display: none; }
}


/* @source website/src/css/91-final-pages.css */
/* ============================================================================
   FINAL UI, LANE D  (2026-11-06, FINAL-UI-PLAN Lane D)
   About, Gallery, Events and the Store masthead. Loaded last (build.js sorts
   css/ by name), so these rules win over the page files without !important.
   ========================================================================= */

/* --- About 1: "Two programs under one roof" heading block centred ---------- */
@media (min-width: 720px) {
  .ab-eligibility-inner > .eyebrow,
  .ab-eligibility-inner > h2,
  .ab-eligibility-inner > .ab-lede { text-align: center; }
  .ab-eligibility-inner > .eyebrow,
  .ab-eligibility-inner > .ab-lede { margin-inline: auto; }
}

/* --- About 2: the brothers left, their ship right, in the white space -------
   Wide screens only (phone has no room, his call). Both are cut-out U.S. Navy
   photos in black and white; each sits in the space between the page edge and
   the centred words, vertically centred on the words, never over them. */
.ab-history { display: none; }

@media (min-width: 1024px) {
  .ab-lead-body { position: relative; }

  /* The words start one gutter inside the 44rem column; each photo keeps 2rem
     from the words and at least 2rem from the page edge. */
  .ab-history {
    display: block;
    position: absolute;
    top: 50%;
    width: min(360px, calc((100vw - 44rem) / 2 + var(--gutter) - 4rem));
    height: auto;
  }

  /* soften the straight edge where the photograph was cropped */
  .ab-history-brothers {
    -webkit-mask-image: linear-gradient(to bottom, #000 62%, transparent);
    mask-image: linear-gradient(to bottom, #000 62%, transparent);
  }
  .ab-history-ship {
    -webkit-mask-image: linear-gradient(to bottom, #000 86%, transparent);
    mask-image: linear-gradient(to bottom, #000 86%, transparent);
  }

  .ab-history-brothers {
    right: calc(100% - var(--gutter) + 2rem);
    transform: translateY(-50%);
  }

  .ab-history-ship {
    left: calc(100% - var(--gutter) + 2rem);
    transform: translateY(-42%);
  }
}

/* --- About 3: phone comparison as two cards -------------------------------
   The table stays the desktop view; under 720px it is not displayed and the
   two cards are. display:none takes the hidden one out of the accessibility
   tree too, so the facts are read once at any width. */
.ab-programs { display: none; }

@media (max-width: 719px) {
  .ab-eligibility .compare { display: none; }

  .ab-programs {
    display: grid;
    gap: var(--space-md);
    margin-top: var(--space-lg);
  }

  .ab-program {
    padding: var(--space-md);
    border-radius: var(--radius);
  }

  .ab-program-nlcc { background: var(--red-100); }
  .ab-program-nscc { background: var(--blue-100); }

  .ab-program h3 { margin: 0 0 var(--space-sm); }

  .ab-program dl { margin: 0; display: grid; gap: var(--space-sm); }

  .ab-program dt {
    font-size: var(--text-xs);
    line-height: var(--leading-xs);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-caps);
    text-transform: uppercase;
    color: var(--ink);
  }

  .ab-program dd { margin: var(--space-3xs) 0 0; color: var(--ink); }
}

/* --- Gallery 4: Image of the Month -----------------------------------------
   Source order is the phone order. On a wider screen the heading and the words
   take the left column and the photograph spans both rows on the right, as
   before. */
@media (min-width: 768px) {
  .gal-month {
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    grid-template-rows: auto 1fr;
    row-gap: 0;
  }
  .gal-month-head { grid-column: 1; grid-row: 1; padding-top: var(--space-xs); }
  .gal-month-text { grid-column: 1; grid-row: 2; padding-top: 0; }
  .gal-month-figure { grid-column: 2; grid-row: 1 / span 2; }
}

@media (max-width: 767px) {
  .gal-month { gap: var(--space-md); }
  .gal-month-text { padding-top: 0; }
  .gal-month-name { margin-top: var(--space-2xs); }
}

/* Albums: two per row on a phone, with labels sized to fit a half-width tile. */
@media (max-width: 559px) {
  .gal-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-md) var(--space-xs);
  }
  .gal-tile-text { padding: 2.25rem var(--space-xs) var(--space-xs); gap: 0; }
  .gal-tile-title { font-size: var(--text-sm); line-height: 1.25; }
  .gal-tile-count { font-size: var(--text-2xs); }
}

/* --- Events 5: masthead clear of the fixed header ---------------------------
   Every other inner page pads main by the header height; Events did not. */
.page-events main { padding-top: var(--header-height); }

@media (max-width: 767px) {
  .ev-masthead .rost-masthead-inner { text-align: center; }
  .ev-masthead .lede { margin-inline: auto; }

  /* Next up on a phone: the date box in the card's top-right corner beside
     "Next up" and the type chip; the name on its own full-width line; the
     date line hidden (the box already shows it; screen readers still get it,
     because the box is aria-hidden); city; then "Add to calendar" on the left.
     The card's inner wrappers stand aside (display: contents) so every piece
     places on one grid; the same classes come from the built page and from
     main.js's redraw. */
  .ev-next {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--space-sm);
    align-items: start;
  }
  .ev-next-body,
  .ev-next-text { display: contents; }

  .ev-next-kicker { grid-column: 1; grid-row: 1; margin: 0; }
  .ev-next-date {
    grid-column: 2;
    grid-row: 1 / span 2;
    width: 4.75rem;
  }
  .ev-next-day { margin: 2px 0; font-size: var(--text-xl); }
  .ev-next-month,
  .ev-next-year { font-size: var(--text-xs); }
  .ev-next-text .ev-chip { grid-column: 1; grid-row: 2; align-self: start; margin-top: var(--space-2xs); }

  .ev-next-text h2 {
    grid-column: 1 / -1;
    grid-row: 3;
    margin: var(--space-sm) 0 0;
    font-size: clamp(1.25rem, 6.4vw, 1.75rem);
    line-height: 1.2;
    text-align: left;
  }

  .ev-next-meta { grid-column: 1 / -1; grid-row: 4; margin: var(--space-3xs) 0 var(--space-sm); }
  .ev-next-when {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .ev-next .ev-ics { grid-column: 1; grid-row: 5; justify-self: start; }
  .ev-next .ev-next-photos { grid-column: 1 / -1; grid-row: 6; margin-top: var(--space-md); }
}

/* --- Store 6: the patch beside the title on a phone ------------------------ */
@media (max-width: 767px) {
  .shop-masthead {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--space-sm);
    align-items: start;
  }
  .shop-masthead-text { display: contents; }
  .shop-masthead .eyebrow { grid-column: 1; grid-row: 1; }
  .shop-masthead h1 { grid-column: 1; grid-row: 2; }
  .shop-masthead-note { grid-column: 1 / -1; grid-row: 3; }
  .shop-masthead-mark {
    display: block;
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    width: clamp(72px, 22vw, 104px);
    height: auto;
  }
}


/* @source website/src/css/92-final-polish.css */
/* =============================================================================
   FINAL POLISH (Lane E verify, 2026-11-06)
   Small fixes found while checking lanes A-D together on the merged build.
   Each rule names what it fixed. Nothing here changes a ruling, it only makes
   the pieces built separately sit together.
   ========================================================================== */

/* Support page: its masthead had no room for the fixed header, so on a phone
   the "Support" eyebrow sat 4px under the header bar. Same rule Leadership
   uses, since both pages share the roster masthead. */
.page-sponsors main { padding-top: var(--header-height); }

/* Gallery and album mastheads: the top padding was a fixed number with no
   relation to the header. It clears the header today, so the look is kept,
   but max() guarantees the title can never slide under it if the header
   grows (red bar shown, larger type). */
.gal-masthead {
  padding-top: max(
    calc(var(--section-y) + var(--space-xl)),
    calc(var(--header-height) + var(--space-lg))
  );
}

/* Album pages on desktop: the title was centred but the eyebrow, the date
   line and the description were narrow blocks pinned to the left edge, so the
   four lines started at four different places. Centre the blocks, not just
   their text. */
.gal-masthead .rost-masthead-inner > * { margin-inline: auto; }

/* Join "Enrollment runs through the national site.": the subtitle touched the
   bigger title. A little air between them. */
.join-steps h2 + .lede { margin-top: var(--space-sm); }


/* @source website/src/css/93-final-mobile.css */
/* ============================================================================
   FINAL MOBILE  (final mobile push, 2026-11-06)
   Desktop is final and approved. Everything in this file is phone only
   (max-width 767px) except the overflow section, which applies at every width
   and changes no desktop pixel (the scroll tracks already sat inside their
   column; these rules only stop their hidden content leaking into the page).
   ========================================================================= */

/* ------------------------------------------------ 1. no sideways page, ever */
/* Root cause, measured in WebKit: the sponsors logo track (home and Sponsors
   page, just above the footer) is a horizontal scroller, but it was not
   positioned. Every logo link holds a screen-reader "(opens in a new tab)"
   span, and .u-visually-hidden is position:absolute, so its containing block
   was an ancestor OUTSIDE the track and the track's overflow never clipped it.
   Those 1px spans sat at the logos' own spots, out to x=916 at 393px wide,
   and the page's scroll width became 917px: 2.3 times the screen with nothing
   visible past the edge. iOS Safari sizes pinch-zoom from that width, so he
   could zoom out to it: content on the left, blank on the right.
   position:relative makes the track their containing block, so it clips them
   like everything else in it. */
.sponsors-track {
  position: relative;
}

.sponsors-frame > *,
.page-index .poster-cards > * {
  min-width: 0;
}

.sponsors-track,
.page-index .poster-cards {
  min-width: 0;
  overscroll-behavior-x: contain;
}

/* Join: the training band's 340px column minimum was wider than a 320px
   phone. Same columns at every width that fits 340px. */
.train-band {
  grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
}

/* Contact: the swells are 200% wide by design and already clipped by the sea;
   paint containment guarantees no browser counts them toward the page. */
.cm-sea {
  contain: paint;
}

/* Belt and braces. clip, not hidden: hidden would make body a scroll
   container and break position: sticky (shop, cart, contact FAQ). On html the
   value goes to the viewport; on body it clips body without scrolling it.
   The fixed header and the Join pill are positioned by the viewport, so
   neither is clipped. */
html,
body {
  overflow-x: clip;
}

@supports not (overflow-x: clip) {
  body { overflow-x: hidden; }
}

@media (max-width: 767px) {
  /* Gallery: "Miscellaneous" at the 48px floor ran 12px past a 320px phone.
     Still 48px from 370px up; smaller only where the word would not fit. */
  .gal-masthead h1 {
    font-size: min(3rem, 13vw);
    overflow-wrap: break-word;
  }

  /* The store strip's picture and words slide in from the left on a phone
     too (his 2026-09-27 ruling). Clip that slide to the strip so a waiting
     piece can never sit outside the page. */
  .merch-strip {
    overflow-x: clip;
  }

  /* -------------------------------------------- 2. hero fills the screen */
  /* The red bar and the header float over the hero, so the hero itself is the
     whole first screen. svh: the screen with Safari's toolbars showing. */
  .page-index .hero {
    min-height: 100vh;
    min-height: 100svh;
  }

  /* The words stay exactly where they were; the two buttons drop to the
     bottom of the screen, 24px above the toolbar or the home indicator.
     Order: eyebrow, title, "We Stick Together.", a spacer (::before), the
     buttons. The spacer is as tall as the room the buttons gave up, so the
     words do not move, and it is the only thing that shrinks (to a 32px
     floor) on a short phone, so the buttons never fall below the first
     screen. --hero-lift is that room: up to 640px the old hero was 88dvh with
     70px under the buttons; above it, 100svh with 90px. A definite height,
     not min-height, is what lets the spacer shrink. Below 560px of height
     (an iPhone SE with Safari's bars showing, a phone on its side) the words,
     a 32px gap and both buttons cannot share one screen, so the old flow
     stays exactly as it was. */
  @media (min-height: 560px) {
    .page-index .hero-content {
      --hero-lift: calc(12vh + 80px);
      --hero-lift: calc(12svh + 80px);
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      height: 100vh;
      height: 100svh;
      padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 24px);
    }

    .page-index .hero-content > * { flex-shrink: 0; }

    .page-index .hero-content::before {
      content: "";
      order: 4;
      flex: 0 1 calc(var(--hero-lift) - env(safe-area-inset-bottom, 0px));
      min-height: 32px;
    }

    .page-index .hero-actions {
      order: 5;
      margin-top: 0;
    }
  }

  @media (min-width: 641px) and (min-height: 560px) {
    .page-index .hero-content { --hero-lift: 100px; }
  }

  /* --------------------------------------------- 3. hero video, centred */
  .page-index .hero-video,
  .page-index .hero-fallback {
    object-position: 50% 50%;
  }

  /* ------------------------- 4. mission: the film first, then the words */
  .page-index .mission-pair {
    display: flex;
    flex-direction: column;
  }

  .page-index .mission-pair > .film { order: -1; }

  .page-index .creed-seal {
    display: block;
    width: 108px;
    height: auto;
    margin: var(--space-sm) auto 0;
  }

  /* ------------------------------------------ 5. store strip, centred */
  .page-index .merch-strip-body {
    text-align: center;
  }

  .page-index .merch-strip-nav {
    justify-content: center;
  }
}

/* The pair is invisible to layout on desktop, so the creed and the film sit
   exactly as they did; the seal is phone only. */
@media (min-width: 768px) {
  .mission-pair { display: contents; }
  .creed-seal { display: none; }
}
