/* Aqua Velocity Car Wash - marketing site.

   One stylesheet, no framework, no external fonts. The brand art is dark and
   glowing, so the page is dark: on white the hero would be a bright rectangle
   floating on nothing.

   Colours are lifted from the app's palette in lib/theme/app_theme.dart, with
   two additions. The app is a light POS UI read at arm's length under forecourt
   lighting; this is a dark marketing page, so it needs a lighter accent blue
   than the app's --blue to stay legible on navy. */

:root {
  --navy-900: #060f21;
  --navy: #0a1730;          /* must match NAVY in tools/extract_brand_assets.py */
  --navy-700: #0e2044;
  --navy-600: #13294f;

  --blue: #0b63ce;          /* WashColors.blue */
  --blue-lift: #1a7ae8;
  --accent: #46b4ff;        /* the comp's "BETTER." - too light for the app UI */
  --cyan: #00a9c7;          /* WashColors.cyan */

  --ink: #f2f7ff;
  --muted: #a8bcd8;
  --line: rgb(255 255 255 / 0.12);

  --wrap: 1160px;
  --radius: 16px;
}

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

html { scroll-behavior: smooth; scroll-padding-top: 84px; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

body {
  margin: 0;
  background: var(--navy);
  color: var(--ink);
  font: 400 17px/1.65 system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }

.wrap { width: min(100% - 40px, var(--wrap)); margin-inline: auto; }

/* Visible only once focused - keyboard users get past the nav in one press. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--accent); color: #04101f; padding: 12px 18px;
  font-weight: 700; border-radius: 0 0 10px 0;
}
.skip:focus { left: 0; }

:where(a, button, summary):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---------------------------------------------------------------- buttons */

.btn {
  --btn-bg: var(--blue);
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 13px 22px;
  background: var(--btn-bg);
  color: #fff;
  border-radius: 12px;
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .02em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background-color .18s ease, transform .18s ease, border-color .18s ease;
}
.btn:hover { --btn-bg: var(--blue-lift); transform: translateY(-1px); }
.btn--lg { padding: 16px 28px; font-size: 16px; }
.btn--pill { border-radius: 999px; padding: 11px 24px; }
.btn--ghost {
  --btn-bg: transparent;
  border-color: var(--line);
  color: var(--ink);
}
.btn--ghost:hover { --btn-bg: rgb(255 255 255 / 0.07); border-color: var(--accent); }
.btn__icon { width: 18px; height: 18px; fill: currentColor; }

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

.nav {
  position: sticky; top: 0; z-index: 50;
  background: rgb(6 15 33 / 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.nav__inner {
  display: flex; align-items: center; gap: 28px;
  min-height: 72px;
}
.nav__brand { flex: none; line-height: 0; }
.nav__brand img { width: 150px; height: auto; }

.nav__actions { display: flex; align-items: center; gap: 12px; flex: none; }

.nav__links {
  display: flex; gap: 26px; margin-inline: auto;
  font-size: 14px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.nav__links a { text-decoration: none; color: var(--muted); transition: color .16s ease; }
.nav__links a:hover { color: #fff; }

/* .nav__menu wraps .nav__links + .nav__actions purely so the mobile burger
   below has one element to show/hide. display:contents on desktop makes it
   transparent to layout - .nav__links and .nav__actions stay direct flex
   children of .nav__inner, same as before this wrapper existed. */
.nav__menu { display: contents; }

.nav__toggle-input { position: absolute; opacity: 0; pointer-events: none; }
.nav__toggle {
  display: none;
  flex: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px; height: 40px;
  border-radius: 8px;
  cursor: pointer;
}
.nav__toggle:hover { background: rgb(255 255 255 / 0.07); }
/* The checkbox is what actually takes focus, but it is invisible, and a
   <label> is not matched by the :focus-visible rule further up (that one
   covers a/button/summary). Without this the burger is the one control on
   the page a keyboard user cannot see themselves land on. */
.nav__toggle-input:focus-visible ~ .nav__toggle {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}
.nav__toggle span {
  width: 22px; height: 2px; margin-inline: auto;
  background: #fff; border-radius: 2px;
  transition: transform .2s ease, opacity .2s ease;
}
/* Burger -> X: middle bar fades, outer two rotate to cross in the same spot
   the gap between them used to be (5px gap + 2px bar = 7px). */
.nav__toggle-input:checked ~ .nav__toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__toggle-input:checked ~ .nav__toggle span:nth-child(2) { opacity: 0; }
.nav__toggle-input:checked ~ .nav__toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav__inner { position: relative; flex-wrap: nowrap; justify-content: space-between; padding-block: 14px; }
  .nav__brand img { width: 124px; }
  .nav__toggle { display: flex; }

  /* Collapsed dropdown, anchored under .nav__inner (position:relative above)
     so it stays pinned under the sticky header rather than pushing page
     content down. max-height/opacity (not display) so the open/close has a
     transition - display can't be animated. */
  .nav__menu {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%; left: 0; right: 0;
    margin: 0 -20px;
    padding: 4px 20px 18px;
    width: auto;
    background: rgb(6 15 33 / 0.98);
    backdrop-filter: blur(10px);
    border-bottom: 1px solid var(--line);
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height .25s ease, opacity .2s ease;
  }
  .nav__toggle-input:checked ~ .nav__menu {
    max-height: 420px;
    opacity: 1;
  }

  .nav__links {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin: 0;
    font-size: 14px;
  }
  .nav__links a {
    padding: 12px 4px;
    border-bottom: 1px solid rgb(255 255 255 / 0.08);
  }

  .nav__actions {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding-top: 14px;
  }
  .nav__actions .btn { width: 100%; }
}

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

.hero {
  position: relative;
  /* The art carries its own glow, so the backdrop stays dark behind it and
     only lifts at the edges - a bright wash here would flatten the artwork. */
  background:
    radial-gradient(120% 90% at 78% 42%, rgb(19 62 130 / .55), transparent 62%),
    radial-gradient(90% 70% at 8% 0%, rgb(11 99 206 / .28), transparent 60%),
    linear-gradient(180deg, var(--navy-900), var(--navy) 55%, var(--navy-700));
  padding-block: clamp(32px, 6vw, 76px) 74px;
  overflow: hidden;
  /* Fills most of the first screen, so the features strip is pulled well down
     from the buttons - independent of how tall the content itself is - but
     stops short of exactly one screen on purpose. "Exactly 100vh" sounds
     right but means the next section starts at the very last pixel of the
     viewport: 0% of it visible without scrolling, which is what "hidden"
     looked like from a size check that only compared numbers and never asked
     whether anything below the fold was actually showing. --peek is how much
     of the features strip shows unscrolled - comfortably past its icon row.
     72px is .nav__inner's own min-height, subtracted so nav + hero together
     total one screen rather than overshooting it before --peek is applied.
     Content shorter than the floor is centered rather than pinned to the
     top. */
  --peek: 160px;
  min-height: calc(100vh - 72px - var(--peek));
  display: grid;
  align-content: center;
}
.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: center;
  gap: clamp(24px, 4vw, 56px);
}

.hero__title {
  margin: 0 0 18px;
  font-size: clamp(42px, 7.2vw, 76px);
  line-height: 0.98;
  font-weight: 900;
  letter-spacing: -0.025em;
  font-stretch: condensed;
  text-transform: uppercase;
  text-shadow: 0 3px 30px rgb(4 12 28 / .8);
}
.hero__title span { display: block; }
.hero__title .accent {
  color: var(--accent);
  text-shadow: 0 0 34px rgb(70 180 255 / .45);
}

.hero__sub {
  margin: 0 0 26px;
  max-width: 34ch;
  color: var(--muted);
  font-size: clamp(16px, 1.5vw, 18px);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin: 0; }

.store-badges {
  /* A plain block under the img, so it is exactly as wide as the image and
     centering within it lands the pair under the logo. margin-top matches
     .hero__sub's margin-bottom - the same gap already used between the
     subhead and the buttons in the text column - rather than some new value
     invented for this one spot. */
  display: flex; flex-wrap: wrap; justify-content: center; gap: 12px;
  margin: 26px 0 0;
}
.store-badge {
  display: inline-flex; align-items: center; gap: 11px;
  padding: 9px 16px;
  border: 1px dashed var(--line);
  border-radius: 10px;
  background: rgb(255 255 255 / 0.025);
  cursor: not-allowed;
  user-select: none;
}
.store-badge__icon { width: 25px; height: 25px; fill: var(--muted); flex: none; }
.store-badge__copy { display: flex; flex-direction: column; line-height: 1.2; }
.store-badge__store {
  font-size: 12px; font-weight: 700; color: var(--muted);
}
.store-badge__status {
  font-size: 13.5px; font-weight: 800; color: var(--ink); opacity: .55;
  letter-spacing: .01em;
}

.rotator {
  /* width:100% of .hero__art rather than flex/justify-content on the
     parent: the store badges also live in .hero__art, right after the
     rotator, and need to stay stacked below it - a flex row on the parent
     would have put them beside it instead, since both are direct children
     of the same container. */
  position: relative;
  width: 100%;
  /* Matches the panels' own size (749x514, after trimming a stray white
     sliver each carried on one or more of its own edges), so the box never
     has to wait on an image to load to know its own height - no layout jump
     as each frame of the animation swaps in. */
  aspect-ratio: 749 / 514;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgb(3 10 26 / .75), 0 0 0 1px rgb(255 255 255 / .06);
}
.rotator img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Base state while animation-delay hasn't elapsed yet - see the keyframes
     below. Without this every card would default to fully visible and all
     four would show stacked on top of each other until their own delay
     kicks in and the animation takes over. */
  opacity: 0;
  /* 24s for four cards - six seconds each. It was 16s, which read as restless
     next to copy somebody is still finishing. The percentages in the keyframes
     below are proportional, so this one number is the whole speed control for
     the no-JS path; the script has its own, in index.html's data-interval,
     and the two are meant to agree. */
  animation: rotator-fade 24s infinite;
}
/* Negative delay on the first card only: at page load its animation clock is
   already past the fade-in, so it shows at full opacity immediately instead
   of the whole rotator flashing blank for that instant while every card is
   still waiting on its own (positive) delay. */
.rotator img:nth-child(1) { animation-delay: -0.96s; }
.rotator img:nth-child(2) { animation-delay: 6s; }
.rotator img:nth-child(3) { animation-delay: 12s; }
.rotator img:nth-child(4) { animation-delay: 18s; }

@keyframes rotator-fade {
  0%   { opacity: 0; }
  4%   { opacity: 1; }
  21%  { opacity: 1; }
  25%  { opacity: 0; }
  100% { opacity: 0; }
}

/* ---- the JavaScript path ------------------------------------------------
   The script adds .rotator--js once it has taken over. Turning the animation
   off here rather than in the script keeps all the timing in one file, and
   means a card cannot be left mid-fade by a keyframe that is still running
   underneath the class. */
.rotator--js img { animation: none; transition: opacity .8s ease; }
.rotator--js img.is-active { opacity: 1; }

/* The hero's dots are the shared .dots/.dot pair - see "slider dots" further
   down. Only the spacing differs: the hero sits tighter under its image than
   the locations track does under a row of cards. */
.rotator__dots { margin-top: 14px; }

@media (prefers-reduced-motion: reduce) {
  /* The page-wide reduced-motion rule already stops the animation; without
     this, every card falls back to the opacity:0 above and the rotator
     shows nothing at all rather than one static card. */
  .rotator img:first-child { opacity: 1; }
  /* Under JS the active card carries its own opacity, so first-child is the
     wrong one to force - it would show card one on top of whichever card the
     reader chose. The script does not auto-advance in this mode; the dots
     still work, which is the point of leaving them enabled. */
  .rotator--js img:first-child:not(.is-active) { opacity: 0; }
  .rotator--js img { transition: none; }
}

.wave {
  position: absolute; left: 0; right: 0; bottom: -1px;
  width: 100%; height: clamp(60px, 8vw, 110px);
  fill: var(--navy-600);
}

@media (max-width: 900px) {
  .hero { padding-bottom: 60px; }
  .hero__inner { grid-template-columns: 1fr; text-align: center; }
  .hero__sub { max-width: none; margin-inline: auto; }
  .hero__actions { justify-content: center; }
  .hero__art { order: -1; }
}

@media (max-width: 860px) {
  /* Matches .nav__inner's own breakpoint: below this the nav wraps to a
     taller block (~106px), so the amount subtracted from 100vh has to grow
     with it or the hero overshoots the fold by the difference. Kept as its
     own query, after the base .hero rule, rather than folded into the nav's
     860px block above it - a rule placed before the base one it means to
     override loses the cascade tie regardless of the media condition. */
  .hero { min-height: calc(100vh - 106px - var(--peek)); }
}

/* --------------------------------------------------------------- features */

.features { background: var(--navy-600); padding-block: 8px 46px; }
.features__grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 26px;
  text-align: center;
}
.features__grid li { display: grid; justify-items: center; gap: 12px; }
.feat__icon {
  width: 46px; height: 46px;
  fill: none; stroke: var(--accent); stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 12px rgb(70 180 255 / .35));
}
.features h2 {
  margin: 0;
  font-size: 13.5px; font-weight: 800; line-height: 1.4;
  letter-spacing: .1em; text-transform: uppercase;
}
@media (max-width: 760px) {
  .features__grid { grid-template-columns: repeat(2, 1fr); gap: 28px 16px; }
}

/* -------------------------------------------------------------- sections */

.section { padding-block: clamp(56px, 8vw, 96px); }
.section--alt { background: var(--navy-900); }

.eyebrow {
  margin: 0 0 8px;
  color: var(--accent);
  font-size: 13px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase;
}
.section__title {
  margin: 0 0 14px;
  font-size: clamp(30px, 4.2vw, 44px);
  font-weight: 900; letter-spacing: -0.02em; line-height: 1.08;
}
.section__lead { margin: 0 0 26px; max-width: 62ch; color: var(--muted); font-size: 18px; }

.included {
  list-style: none; display: flex; flex-wrap: wrap; gap: 10px;
  margin: 0 0 34px; padding: 0;
}
.included li {
  padding: 7px 15px;
  border: 1px solid var(--line); border-radius: 999px;
  background: rgb(255 255 255 / 0.04);
  font-size: 14px; color: var(--muted);
}
.included li::before { content: "✓"; color: var(--accent); font-weight: 800; margin-right: 8px; }

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

.cards {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px;
  align-items: start;
}
.card {
  position: relative;
  background: linear-gradient(180deg, var(--navy-700), var(--navy));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px 22px;
  height: 100%;
}
.card--featured {
  border-color: rgb(70 180 255 / .55);
  box-shadow: 0 0 0 1px rgb(70 180 255 / .18), 0 18px 44px rgb(3 10 26 / .55);
}
.card__badge {
  position: absolute; top: -12px; left: 22px;
  margin: 0; padding: 4px 12px;
  background: var(--accent); color: #04101f;
  border-radius: 999px;
  font-size: 11.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
}
.card__type {
  margin: 0 0 6px;
  font-size: 12px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--cyan);
}
.card__name { margin: 0 0 10px; font-size: 22px; font-weight: 800; }
.card__price { margin: 0 0 10px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
/* .price marks a money figure for tools/check_marketing_prices.py, so it is on
   every price including the ones inside the surcharge table. Keep the headline
   typography scoped to the places that want it - unscoped, it set the table
   cells to 30px, which both looked wrong and made the table's min-content wide
   enough to push the whole document past the viewport. */
.card__price .price, .panel__price .price { font-size: 30px; font-weight: 900; letter-spacing: -0.02em; }
.was { color: var(--muted); font-size: 15px; }
.card__note { margin: 0 0 14px; color: var(--muted); font-size: 14.5px; }
.card__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; font-size: 14.5px; }
.card__list li { padding-left: 22px; position: relative; color: var(--ink); }
.card__list li::before {
  content: ""; position: absolute; left: 4px; top: .62em;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
}

@media (max-width: 1000px) { .cards { grid-template-columns: repeat(2, 1fr); gap: 20px; } }
@media (max-width: 560px)  { .cards { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------- panels */

.panels {
  margin-top: 34px;
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 6fr); gap: 18px;
}
.panel {
  background: rgb(255 255 255 / 0.035);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
}
.panel h3 { margin: 0 0 10px; font-size: 19px; font-weight: 800; }
.panel__price { margin: 0 0 14px; color: var(--muted); }
.panel__price .price { font-size: 26px; color: var(--ink); margin-right: 6px; }
.sizes .price { font-weight: 700; }
.panel__lead { margin: 0 0 16px; color: var(--muted); font-size: 15px; }
.panel__list { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; font-size: 15px; }
.panel__list li { padding-left: 20px; position: relative; }
.panel__list li::before {
  content: "+"; position: absolute; left: 2px; top: -1px;
  color: var(--accent); font-weight: 800;
}

/* Five columns will not fit a phone. Scroll the table inside its own box so
   the page itself never scrolls sideways. */
.tablewrap { overflow-x: auto; }
.sizes { width: 100%; min-width: 400px; border-collapse: collapse; font-size: 14.5px; }
.sizes th, .sizes td { padding: 9px 8px; text-align: right; border-bottom: 1px solid var(--line); }
.sizes thead th { color: var(--muted); font-size: 12px; letter-spacing: .07em; text-transform: uppercase; }
.sizes tbody th { text-align: left; font-weight: 700; }
.sizes tbody tr:last-child th, .sizes tbody tr:last-child td { border-bottom: 0; }

.fineprint { margin: 22px 0 0; color: var(--muted); font-size: 13.5px; }

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

/* ---------------------------------------------------------- memberships */

.soon {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px;
  margin-bottom: 28px;
}
.soon__item {
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  padding: 22px;
  background: rgb(255 255 255 / 0.025);
}
.soon__item h3 { margin: 0 0 8px; font-size: 17px; font-weight: 800; }
.soon__item p { margin: 0; color: var(--muted); font-size: 15px; }
@media (max-width: 800px) { .soon { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------- locations */

/* A scroll-snap track rather than a scripted carousel. The browser does the
   scrolling - touch, trackpad, arrow keys, scrollbar - so the cards work
   before any script runs, and the dots below are the only part that needs
   one. */
.loc-slider { position: relative; }
.loc-slider__track {
  display: grid;
  /* Three across on a wide screen, so nothing is hidden from somebody who
     came to compare them; one at a time once there is no room, which is
     where a slider actually earns its place. */
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 18px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Space for the focus ring, which a plain overflow container clips. */
  padding: 4px;
  margin: -4px;
  scrollbar-width: thin;
}
.loc-slider__track > * { scroll-snap-align: start; }
.loc-slider__track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius); }

@media (max-width: 900px) {
  /* One card fills the track and the next peeks in, which is what tells
     somebody there is a next one at all - a slider with no visible edge reads
     as a single card. */
  .loc-slider__track { grid-auto-columns: 88%; }
}

.loc {
  background: linear-gradient(180deg, var(--navy-700), var(--navy));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px;
  /* The cards carry different amounts of copy - Rising Sun has one tag fewer
     - and a grid row would otherwise leave the buttons at different heights
     across the three. */
  display: flex;
  flex-direction: column;
}
.loc--next { border-style: dashed; background: rgb(255 255 255 / 0.025); color: var(--muted); }
.loc__name { margin: 0 0 10px; font-size: 22px; font-weight: 800; }
.loc__addr { font-style: normal; color: var(--muted); margin-bottom: 14px; }
.loc__tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 18px; }
.loc__tags span {
  padding: 5px 12px; border-radius: 999px;
  background: rgb(70 180 255 / .12); border: 1px solid rgb(70 180 255 / .3);
  font-size: 13px; color: var(--ink);
}
/* margin-top:auto rather than 0: the cards are flex columns of differing
   length - Rising Sun carries one tag fewer than the other two - and this is
   what keeps every "Get directions" on the same line across the row. */
.loc__actions { display: flex; flex-wrap: wrap; gap: 10px; margin: auto 0 0; }

/* ---- slider dots, shared with the hero rotator ----
   Same control, same look, one definition. Both tracks are "several things,
   one at a time", and a second style for the second of them is how two
   sliders on one page end up subtly different. */
.dots { display: flex; justify-content: center; gap: 10px; margin-top: 18px; }
/* An author `display` beats the UA stylesheet's `[hidden] { display: none }`,
   so without this the hidden attribute does nothing here and the dots stay on
   a screen wide enough to show every card at once - visible, inert, and
   pointing at nothing to scroll. */
.dots[hidden] { display: none; }
.dot {
  /* Bigger than it looks: the visible pill is the ::before, while the button
     keeps a 44px touch target, which is the smallest thing a thumb reliably
     hits. Shrinking the button to the dot makes these accurate only with a
     mouse. */
  width: 44px; height: 44px; padding: 0; border: 0;
  background: none; cursor: pointer; display: grid; place-items: center;
}
.dot::before {
  content: "";
  width: 9px; height: 9px; border-radius: 999px;
  background: rgb(255 255 255 / .32);
  transition: background .25s ease, width .25s ease;
}
.dot:hover::before { background: rgb(255 255 255 / .55); }
.dot[aria-current="true"]::before {
  /* Widened as well as recoloured, so which one is current survives being
     looked at by somebody who cannot separate the two greys. */
  width: 26px;
  background: var(--accent);
}
.dot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }

/* ----------------------------------------------------------------- about */

.about { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: clamp(24px, 4vw, 52px); align-items: start; }
.about p { color: var(--muted); }
.about .section__lead { color: var(--ink); }

.stats { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.stats li {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px; text-align: center;
  background: rgb(255 255 255 / 0.035);
}
.stats strong { display: block; font-size: 34px; font-weight: 900; color: var(--accent); line-height: 1; }
.stats span { font-size: 13px; color: var(--muted); letter-spacing: .04em; }
@media (max-width: 800px) { .about { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------- cta */

.cta {
  background:
    radial-gradient(80% 140% at 50% 0%, rgb(11 99 206 / .5), transparent 65%),
    var(--navy-600);
  padding-block: clamp(52px, 7vw, 84px);
  text-align: center;
  border-top: 1px solid var(--line);
}
.cta h2 { margin: 0 0 10px; font-size: clamp(28px, 4vw, 40px); font-weight: 900; letter-spacing: -0.02em; }
.cta p { margin: 0 0 24px; color: var(--muted); }

/* ---------------------------------------------------------------- footer */

.foot { background: var(--navy-900); padding-block: 40px 26px; }
.foot__inner {
  display: flex; flex-wrap: wrap; gap: 28px;
  align-items: center; justify-content: space-between;
}
.foot__mark { width: 150px; }
.foot__tag { margin: 10px 0 0; color: var(--accent); font-size: 13px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.foot__links { display: flex; flex-wrap: wrap; gap: 18px; font-size: 14px; }
.foot__links a { color: var(--muted); text-decoration: none; }
.foot__links a:hover { color: #fff; text-decoration: underline; }
.foot__legal {
  width: min(100% - 40px, var(--wrap));
  margin: 26px auto 0; padding-top: 18px;
  border-top: 1px solid var(--line);
  color: var(--muted); font-size: 13px;
}

/* ------------------------------------------------------- the account menu */

/* An initial in the header that opens on to a way out.
   Replaced a "Sign out" button appended after </main>, which had no styling
   of its own and sat half off the bottom-left corner of every protected page.

   Built on <details>, so it opens, closes and takes focus with no JavaScript
   at all - the same instinct as the nav's checkbox toggle, using the element
   that was actually designed for it. The script on the page only adds what
   the element cannot do by itself: close when you click elsewhere or press
   Escape. */
/* Text for a screen reader and nobody else. The initial in the button is
   decorative - "D" tells you nothing if you cannot see the shape it sits in -
   so the real label is here. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

.usermenu { position: relative; }
.usermenu__btn {
  display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 999px;
  background: rgb(70 180 255 / .14);
  border: 1px solid rgb(70 180 255 / .45);
  color: var(--ink); font-weight: 800; font-size: 15px;
  cursor: pointer; user-select: none;
  transition: background .2s ease, border-color .2s ease;
}
/* The default disclosure triangle, gone in both dialects: WebKit needs the
   pseudo-element, everyone else needs list-style. */
.usermenu__btn::-webkit-details-marker { display: none; }
.usermenu__btn { list-style: none; }
.usermenu__btn:hover { background: rgb(70 180 255 / .24); border-color: var(--accent); }
.usermenu__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.usermenu[open] .usermenu__btn { background: var(--accent); color: #04101f; border-color: var(--accent); }

.usermenu__panel {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 60;
  min-width: 236px; padding: 16px;
  background: var(--navy-700);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 18px 44px rgb(3 10 26 / .6);
}
.usermenu__who { margin: 0 0 2px; font-size: 14px; }
.usermenu__note { margin: 0 0 14px; font-size: 12px; color: var(--muted); line-height: 1.45; }
.usermenu__out { width: 100%; justify-content: center; }
/* Two stacked buttons in the panel now - a way back to the admin page and a
   way out - so they need separating. The logout form carries no margin of its
   own, being a bare <form>. */
.usermenu__panel .usermenu__out + form { margin-top: 8px; }

@media (max-width: 860px) {
  /* The nav collapses behind the burger below this, and the panel would
     otherwise open off the right edge of the screen. */
  .usermenu__panel { right: auto; left: 0; }
}

/* Breadcrumbs on the pages behind the sign-in.

   The account menu already has a way back to the admin page, but it is behind
   a click on an initial in the corner - findable once somebody knows, and not
   before. This is the ordinary place to look for the way out of a page. */
.crumbs {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 0 14px; font-size: 14px; color: var(--muted);
}
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--accent); text-decoration: underline; }
.crumbs a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
/* The separator is decoration, so it is drawn by CSS rather than typed into
   the markup - a screen reader announcing "slash" between every step is noise
   in a list that already reads as a path. */
.crumbs__here::before { content: '/'; margin-right: 8px; opacity: .55; }
.crumbs__here { color: var(--ink); font-weight: 700; }
