/*
  kingstrikers.com — the whole site's styles, in one file.

  The site has no build step, so this is the shared layer: every page links it and
  adds nothing of its own. One file means one place to change a colour and one
  request to make, and at this size (a few kB gzipped) splitting it would cost
  more in round trips than it saves in bytes.

  The vocabulary is small on purpose:

    .topbar   the menu, on every page
    .band     a full-bleed picture with a navy wash and words on top
    .slab     a solid navy section: cards, lists, tables. No picture.
    .card     white paper with an ink border, the game's own card
    .btn      the sticker button from the style guide

  A page is a stack of .band and .slab, alternating. That alternation is the
  whole design: a picture to look at, then something to read, then another
  picture. Nothing else is needed and nothing else is here.
*/

/* ─────────────────────────────────────────────────────────────────────────────
   TOKENS

   Copied from client/src/ks/tokens.css rather than imported: this page ships no
   build step and no client code, and two files that agree today are cheaper here
   than a bundler. If the palette moves, move it here too — there is no mechanism
   that will notice.

   The contrast ratios in the comments are against the surface each colour is
   used on, and site.test.mjs recomputes every one of them out of this file.

   THE BODY FACE NOW MATCHES THE GAME. On 2026-09-20 the client's body face
   became Rubik, because the owner's read was that the UI "feels very Word
   document" — and `system-ui` on Windows is Segoe UI, which is precisely the
   face that judgement was about, so this page was the worse offender of the
   two. Done the way the note above predicted: the variable woff2 is committed
   to public/font/ and declared beside Barlow Condensed's, because this folder
   has no npm and no build step. One file covers every weight the page uses —
   the axis is 300-900 and the page only ever asks for 400 and 700.
   ───────────────────────────────────────────────────────────────────────────── */
:root {
  --ks-navy: #0e2050; /* paper 15.66:1 · yellow 10.80:1 */
  --ks-navy-raised: #16306b;
  --ks-navy-deep: #0a1737; /* the footer, and the bottom of a slab */
  --ks-yellow: #ffd21e; /* ink 12.61:1 */
  --ks-yellow-press: #f5b800;
  --ks-ink: #101425; /* paper 18.28:1 */
  --ks-ink-muted: #5a6480; /* paper 5.88:1 — muted text ON A CARD */
  --ks-paper: #ffffff;
  --ks-paper-alt: #f4f6fb;
  --ks-line: #dce2f0;
  /*
    Muted text on navy is a COLOUR, not an opacity. `opacity: 0.7` on white gives
    a ratio nothing can check, because the number depends on what is behind it;
    over a picture that is unknowable. This blue is 10.03:1 on navy and 5.2:1 on
    the worst scrim the art can produce, and both are testable.
  */
  --ks-sky: #a9c6ff;

  /*
    THE SCRIM, AND WHY IT IS THIS STRONG.

    The backdrops are illustration, and illustration is not a controlled surface:
    the art behind any given word may be a navy sky or a floodlit white shirt. So
    the contrast of the text is not a property of the art, it is a property of
    this wash — and it has to hold for the worst pixel the art could ever
    contain, which is pure white.

    Over white, 0.78 navy composites to #434F76: white text 7.8:1, yellow 5.4:1,
    sky blue 4.7:1. All three clear AA at normal size, and they clear it for ANY
    art, so a picture can be swapped without re-testing the type.

    --scrim-top/mid/bottom are the hero's gradient, which only ever adds darkness
    downwards, so the top stop is the worst case and the top stop is the number
    the test judges. --scrim-band is the flat wash on every other picture: a band
    is short, its text sits in the middle, and a ramp across 40vh would be doing
    its darkening where nothing is written.
  */
  --scrim-top: 0.78;
  --scrim-mid: 0.86;
  --scrim-bottom: 0.93;
  --scrim-band: 0.82;

  --shadow-card: 0 4px 0 #0a1a42, 0 10px 22px rgb(6 14 36 / 0.35);
  --radius: 18px;
  /* the topbar's height, so an anchor can clear it — see scroll-margin-top */
  --bar: 78px;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/font/barlow-condensed-latin-700-normal.woff2') format('woff2');
}

/* One variable file for the whole body axis. The weight range is what the file
   really carries; declaring a wider one lets the browser synthesise past the
   ends. `format('woff2')`, NOT the `woff2-variations` string fontsource emits:
   that one is from a withdrawn draft, and a parser that rejects it drops the
   whole src and falls back to system-ui silently — the exact failure this
   change exists to undo. Plain `woff2` loads a variable file everywhere. */
@font-face {
  font-family: 'Rubik Variable';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/font/rubik-latin-wght-normal.woff2') format('woff2');
}

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ks-navy);
  color: var(--ks-paper);
  font-family: 'Rubik Variable', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3,
.kicker,
.btn,
.stat__n {
  font-family: 'Barlow Condensed', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1.05;
  letter-spacing: 0.01em;
}

h2 {
  margin: 0;
  font-size: clamp(2rem, 6.2vw, 3.2rem);
}

h3 {
  margin: 0 0 8px;
  font-size: clamp(1.15rem, 3.4vw, 1.4rem);
  letter-spacing: 0.03em;
}

p {
  margin: 0;
}

a {
  color: inherit;
}

img {
  max-width: 100%;
}

:focus-visible {
  /*
    Two bands, ink then yellow, always. Yellow alone disappears on a yellow
    button; ink alone disappears against the navy scrim. The pair always has one
    band that holds, whichever surface it lands on.
  */
  outline: 3px solid var(--ks-ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px var(--ks-yellow);
  border-radius: 6px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 18px;
  background: var(--ks-yellow);
  color: var(--ks-ink);
  font-weight: 700;
  text-decoration: none;
}

.skip:focus {
  left: 8px;
  top: 8px;
}

/* ─────────────────────────────────────────────────────────────────────────────
   THE TOPBAR

   Fixed, because the whole point of the menu is that it is reachable from the
   middle of a long page. It is translucent navy with a blur, so the picture
   behind it still moves — but the fallback when `backdrop-filter` is missing is
   the SAME navy at a higher alpha, never a transparent bar, because the links
   have to stay readable over art.
   ───────────────────────────────────────────────────────────────────────────── */
.topbar {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: var(--bar);
  padding: 8px max(14px, env(safe-area-inset-left)) 8px max(14px, env(safe-area-inset-right));
  background: rgb(14 32 80 / 0.94);
  border-bottom: 1px solid rgb(255 255 255 / 0.12);
}

@supports (backdrop-filter: blur(8px)) {
  .topbar {
    background: rgb(14 32 80 / 0.78);
    backdrop-filter: blur(10px) saturate(1.2);
  }
}

/*
  THE MARK IN THE BAR IS THE OWNER'S LOGO, WHOLE.

  It was the crown on its own for a while, with the words "King Strikers" set in
  type beside it, because the full logo is a stacked lockup and a stacked lockup
  does not fit a slim bar. That was the wrong trade and it was not mine to make:
  the logo is the owner's, it is used as given, and a substitute mark is a
  branding decision rather than a layout one.

  So the bar grew instead. The logo carries its own wordmark, so there is no
  text beside it to repeat.
*/
.topbar__brand {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 6px;
  text-decoration: none;
}

.topbar__brand img {
  width: auto;
  height: 58px;
  display: block;
}

.topbar__toggle {
  display: none;
  margin-left: auto;
  padding: 9px 14px;
  border: 2px solid var(--ks-paper);
  border-radius: 999px;
  background: transparent;
  color: var(--ks-paper);
  font: inherit;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}

.nav {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

.nav__list {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 12px of padding on a 24px line is 48px tall: the 44px target minimum, cleared
   on a laptop as well as a phone, because a trackpad is not a precise instrument
   either. Every navigation target on this site is measured in site-shots. */
.nav__list a {
  display: block;
  padding: 12px;
  border-radius: 999px;
  color: var(--ks-paper);
  font-size: 0.94rem;
  text-decoration: none;
  white-space: nowrap;
}

.nav__list a:hover {
  background: var(--ks-navy-raised);
}

/* the yellow active pill, the same marker the game's own chrome uses */
.nav__list a[aria-current='page'] {
  background: var(--ks-yellow);
  color: var(--ks-ink);
  font-weight: 700;
}

/* ─────────────────────────────────────────────────────────────────────────────
   THE MENU ON A PHONE

   The list is visible by default and JavaScript COLLAPSES it. The other way
   round — hidden by default, revealed by script — leaves a visitor whose script
   failed with a menu that is in the markup and cannot be opened. `js` is set by
   site.js while the head is parsed, before the body paints, so there is no flash.
   ───────────────────────────────────────────────────────────────────────────── */
@media (max-width: 880px) {
  .topbar {
    flex-wrap: wrap;
  }

  .js .topbar__toggle {
    display: block;
  }

  .nav {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    margin: 6px 0 4px;
  }

  .js .nav[hidden] {
    display: none;
  }

  .nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
  }

  .nav__list a {
    padding: 12px 14px;
    font-size: 1.02rem;
  }

  .nav .btn {
    margin-top: 6px;
    text-align: center;
  }
}

/* ─────────────────────────────────────────────────────────────────────────────
   BUTTONS — the sticker from the style guide: yellow face, ink text, a 2px ink
   line and a darker bottom edge that collapses when it is pressed. Yellow never
   carries white — that pair is 1.45:1.
   ───────────────────────────────────────────────────────────────────────────── */
.btn {
  display: inline-block;
  padding: 13px 30px;
  border: 2px solid var(--ks-ink);
  border-radius: 999px;
  background: var(--ks-yellow);
  box-shadow: 0 4px 0 0 var(--ks-ink);
  color: var(--ks-ink);
  font-size: 1.12rem;
  letter-spacing: 0.06em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 120ms ease, box-shadow 120ms ease, background-color 120ms ease;
}

.btn:hover {
  background: var(--ks-yellow-press);
}

.btn:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 0 var(--ks-ink);
}

.btn--big {
  padding: 16px 44px;
  font-size: clamp(1.3rem, 5vw, 1.55rem);
}

.btn--small {
  padding: 12px 20px;
  font-size: 0.98rem;
  box-shadow: 0 3px 0 0 var(--ks-ink);
}

/* the second button in a pair: no fill, so the yellow one stays the loud one */
.btn--ghost {
  background: transparent;
  border-color: var(--ks-paper);
  box-shadow: 0 4px 0 0 rgb(6 14 36 / 0.55);
  color: var(--ks-paper);
}

.btn--ghost:hover {
  background: rgb(255 255 255 / 0.12);
}

/* ─────────────────────────────────────────────────────────────────────────────
   BANDS — a picture, a wash, and words
   ───────────────────────────────────────────────────────────────────────────── */
/*
  THE HEIGHT OF A BAND IS A FUNCTION OF THE WIDTH, NOT THE VIEWPORT.

  A band crops its picture with `cover`, so the taller the band the more of the
  picture survives. The first version was `min(78vh, 620px)`, which on a 2560px
  ultrawide left a 620px strip across a picture that had been scaled to 1707px
  tall — about a third of it, and the wrong third.

  `clamp(560px, 42vw, 860px)` ties the height to the width instead: the wider the
  screen, the taller the band, so the crop stays roughly proportional and the art
  keeps its shape. It stops at 860px so a band never eats a whole laptop screen.
*/
.band {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
  min-height: clamp(560px, 42vw, 860px);
  padding: clamp(64px, 12vh, 130px) 16px;
  text-align: center;
  scroll-margin-top: var(--bar);
}

/*
  `display: contents` makes the <picture> box itself disappear and hands its <img>
  straight to the band's layout, so the absolutely positioned art below behaves
  exactly as it did before the two orientations existed.

  The <picture> is what makes the art adaptive: its <source> carries the upright
  frame behind `(orientation: portrait)`, and the <img> carries the wide one. The
  browser picks one and downloads one.
*/
.band > picture {
  display: contents;
}

/*
  The art is an <img> rather than a background-image for two reasons: `loading`
  works on it, so a band five screens down costs nothing until it is nearly in
  view, and `alt=""` states plainly to a screen reader that it is decoration.
*/
.band__art {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /*
    DEAD CENTRE, and it has to be. `center 60%` was right for the first set of
    art, which put its figures low in the frame; the redrawn set puts them in the
    vertical middle so that a wide monitor — which only ever keeps a strip through
    the middle — keeps their faces. Biasing the crop downwards against art drawn
    that way cuts every head off, which is exactly what it did.
  */
  object-position: center center;
}

.band::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgb(14 32 80 / var(--scrim-band));
}

.band__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 2.4vh, 22px);
  max-width: 62ch;
}

/* the hero is taller, and its wash is a gradient rather than a flat wash */
.band--hero {
  min-height: 100svh;
  padding-top: calc(var(--bar) + 28px);
}

.band--hero::after {
  background: linear-gradient(
    180deg,
    rgb(14 32 80 / var(--scrim-top)) 0%,
    rgb(14 32 80 / var(--scrim-mid)) 55%,
    rgb(14 32 80 / var(--scrim-bottom)) 100%
  );
}

/* A second heading further down the same slab needs the air a new section would
   have given it. Privacy is the only page that runs two topics under one slab. */
.slab__next {
  margin-top: clamp(48px, 8vh, 84px);
}

/*
  THE PORTRAIT CROP USED TO BE A BODGE, AND IS NOT ANY MORE.

  On a phone held upright, `cover` on a 3:2 frame fits it by HEIGHT and throws
  away more than half the width — and the interest in this art is deliberately at
  the left and right edges, which is exactly the part that goes. The old fix was
  to zoom past 100% and anchor to the bottom, which salvaged the hero and nothing
  else.

  Every band now carries a second, upright drawing of the same scene behind
  `(orientation: portrait)`, so there is nothing left to salvage: the phone gets a
  picture composed for a phone. The rule below only still covers the case where
  the upright file is missing and the wide one is standing in for it.
*/
@media (max-aspect-ratio: 4 / 5) {
  .band--hero .band__art {
    object-position: center bottom;
  }
}

/*
  A page header. It has been raised twice now, and the second time is the lesson:
  a header band is a PICTURE, and a picture in a strip is a picture you have
  ruined. At 460px the sub-page banners still cropped their art down to a letterbox
  and looked cheap for it.

  It is now within a hair of a full band, which is the honest answer — the only
  reason to make it shorter at all is that a sub-page should start reading sooner
  than the home page does.
*/
.band--head {
  min-height: clamp(540px, 40vw, 820px);
  padding-top: calc(var(--bar) + 40px);
}

.hero__logo {
  width: min(340px, 72vw);
  height: auto;
  /* the art behind it is busy; the logo's own blue outline needs help holding */
  filter: drop-shadow(0 6px 18px rgb(6 14 36 / 0.65));
}

.kicker {
  font-size: clamp(0.9rem, 3.2vw, 1.05rem);
  letter-spacing: 0.18em;
  color: var(--ks-yellow);
}

/*
  `margin-inline: auto` on both of these, and it is not decoration.

  Each has a max-width, which makes it a BOX narrower than its parent. Inside a
  band the parent is a centred flex column, so the box lands in the middle by
  itself; inside a slab it is an ordinary block, so the box sits hard against the
  left while its text is centred within it — which reads as text that is somehow
  centred and off to one side at the same time. That is what the owner was
  looking at under the Play button.
*/
.lede {
  max-width: 46ch;
  margin-inline: auto;
  font-size: clamp(1.03rem, 2.6vw, 1.2rem);
  line-height: 1.55;
  text-wrap: balance;
}

.note {
  max-width: 52ch;
  margin-inline: auto;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ks-sky);
  text-align: center;
  /* two even lines rather than a full one and an orphan, which is what splitting
     "Google Play" across the break looked like */
  text-wrap: balance;
}

.band .note a,
.slab .note a {
  color: var(--ks-sky);
}

/* the arrow under the hero: something to say the page goes on */
.scroll-cue {
  position: absolute;
  bottom: 18px;
  left: 50%;
  translate: -50% 0;
  padding: 8px 12px;
  color: var(--ks-sky);
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-decoration: none;
}

.scroll-cue span {
  display: block;
  font-size: 1.2rem;
  animation: nudge 2.4s ease-in-out infinite;
}

@keyframes nudge {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(5px);
  }
}

/* ─────────────────────────────────────────────────────────────────────────────
   SLABS — solid navy, where the reading happens
   ───────────────────────────────────────────────────────────────────────────── */
.slab {
  position: relative;
  padding: clamp(52px, 9vh, 96px) 16px;
  scroll-margin-top: var(--bar);
  /*
    The diagonal streak from the game's own backdrops, at an alpha that reads as
    texture rather than stripes. It is decoration on a solid colour, so it can
    never change what any text contrasts against.
  */
  background: var(--ks-navy)
    repeating-linear-gradient(
      -45deg,
      rgb(255 255 255 / 0.028) 0 2px,
      transparent 2px 22px
    );
}

.slab--deep {
  background-color: var(--ks-navy-deep);
}

.wrap {
  max-width: 1080px;
  margin: 0 auto;
}

.wrap--narrow {
  max-width: 720px;
}

.slab h2 {
  text-align: center;
}

.slab__intro {
  max-width: 56ch;
  margin: 14px auto 0;
  text-align: center;
  color: var(--ks-sky);
}

/*
  GRIDS ARE COUNTED, NOT FITTED.

  `repeat(auto-fit, minmax(255px, 1fr))` packs as many columns as will go, which
  means the last row holds whatever is left over: four cards became three and a
  lonely one, six became four and two. The owner's note: "let's try to make sure
  that whatever aspect ratio we fix to continues being symmetrical".

  So each grid declares HOW MANY cards it holds, and the breakpoints only ever
  step between counts that divide it exactly:

    --two    1 → 2
    --three  1 → 3        (never 2, which would leave one on its own)
    --four   1 → 2 → 4
    --six    1 → 2 → 3

  A card with fewer words than its neighbours still fills its cell, so the row
  stays level; balancing the WORDS is the copy's job, not the grid's.
*/
.grid {
  display: grid;
  gap: 18px;
  margin-top: clamp(26px, 5vh, 44px);
  grid-template-columns: 1fr;
}

@media (min-width: 680px) {
  .grid--two,
  .grid--four,
  .grid--six {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1000px) {
  .grid--three,
  .grid--six {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 1200px) {
  .grid--four {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ─────────────────────────────────────────────────────────────────────────────
   CARDS — the game's own card, on the site
   ───────────────────────────────────────────────────────────────────────────── */
/*
  Cards are CENTRED, inside and out (owner, 2026-09-20: "these cards, they seem to
  be on the left. I rather if you center them"). Every card on this site carries a
  heading and two or three short sentences, which is the length centred text is
  good at; nothing here runs long enough to need a ragged-right edge to find.
  A list inside a card is the exception — see `.card .ticks` below.
*/
.card {
  padding: 22px 22px 24px;
  border: 4px solid var(--ks-navy);
  border-radius: var(--radius);
  background: var(--ks-paper);
  box-shadow: var(--shadow-card);
  color: var(--ks-ink);
  text-align: center;
}

.card h3 {
  color: var(--ks-navy);
}

.card p + p {
  margin-top: 10px;
}

.card__muted {
  color: var(--ks-ink-muted);
  font-size: 0.93rem;
}

.card__tag {
  display: inline-block;
  margin-bottom: 10px;
  padding: 3px 11px;
  border-radius: 999px;
  background: var(--ks-paper-alt);
  border: 1px solid var(--ks-line);
  color: var(--ks-ink-muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.card--flat {
  border-color: rgb(255 255 255 / 0.18);
  background: var(--ks-navy-raised);
  box-shadow: none;
  color: var(--ks-paper);
}

.card--flat h3 {
  color: var(--ks-yellow);
}

.card--flat .card__muted {
  color: var(--ks-sky);
}

/* ─────────────────────────────────────────────────────────────────────────────
   LISTS — the ticked and crossed kind, used by the roadmap and the FAQ
   ───────────────────────────────────────────────────────────────────────────── */
.ticks {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ticks li {
  position: relative;
  padding-left: 30px;
}

.ticks li + li {
  margin-top: 10px;
}

/*
  A list inside a card follows a paragraph, so it needs the gap a <p> would get.
  Its ITEMS stay left-aligned while the list as a whole is centred in the card:
  a ticked list reads down the ticks, and centring the rows puts every tick in a
  different place. `inline-block` inside a centred parent does exactly that.
*/
.card .ticks {
  display: inline-block;
  margin-top: 10px;
  text-align: left;
}

.ticks li::before {
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 700;
}

.ticks--done li::before {
  content: '✓';
  color: #2fbf71;
}

.ticks--next li::before {
  content: '▸';
  color: var(--ks-yellow);
}

.ticks--no li::before {
  content: '—';
  color: var(--ks-ink-muted);
}

.card--flat .ticks--no li::before {
  color: var(--ks-sky);
}

/* ─────────────────────────────────────────────────────────────────────────────
   STATS — three or four numbers in a row
   ───────────────────────────────────────────────────────────────────────────── */
/* Flex rather than grid, so two tiles sit as a centred pair instead of stretching
   to fill a row built for five. */
.stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin-top: clamp(26px, 5vh, 40px);
}

.stats .stat {
  flex: 0 1 190px;
}

.stat {
  padding: 18px 14px;
  border: 2px solid rgb(255 255 255 / 0.18);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.05);
  text-align: center;
}

.stat__n {
  display: block;
  font-size: clamp(2rem, 6vw, 2.6rem);
  color: var(--ks-yellow);
}

.stat__l {
  display: block;
  margin-top: 4px;
  font-size: 0.88rem;
  color: var(--ks-sky);
}

/* ─────────────────────────────────────────────────────────────────────────────
   Q&A and the changelog
   ───────────────────────────────────────────────────────────────────────────── */
.qa {
  margin-top: clamp(26px, 5vh, 40px);
  text-align: center;
}

.qa details {
  border: 2px solid rgb(255 255 255 / 0.16);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.05);
}

.qa details + details {
  margin-top: 12px;
}

.qa summary {
  padding: 16px 18px;
  font-family: 'Barlow Condensed', system-ui, sans-serif;
  font-weight: 700;
  font-size: 1.16rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  cursor: pointer;
}

.qa summary::marker {
  color: var(--ks-yellow);
}

.qa details > p,
.qa details > ul {
  margin: 0 auto;
  max-width: 60ch;
  padding: 0 18px 18px;
  color: var(--ks-sky);
}

.qa details > p + p {
  padding-top: 12px;
}

.qa details > ul {
  padding-left: 40px;
}

/*
  The one question whose answer costs somebody a month if they miss it gets the
  warning's own colours (owner: "highlight that with a yellow, like we've done
  with the other ones"). Yellow on the rule and the heading, never as a fill
  behind the body text, which is white.
*/
.qa details.qa--warn {
  border-color: var(--ks-yellow);
  border-width: 3px;
  background: rgb(10 23 55 / 0.6);
}

.qa details.qa--warn summary {
  color: var(--ks-yellow);
  font-size: 1.3rem;
}

.qa details.qa--warn strong {
  color: var(--ks-yellow);
}

/* Centred like everything else, so the rule that used to run down the left is a
   divider between entries instead. */
.log {
  margin-top: clamp(26px, 5vh, 40px);
  text-align: center;
}

.log__item + .log__item {
  margin-top: 26px;
  padding-top: 26px;
  border-top: 2px solid rgb(255 255 255 / 0.14);
}

.log__item p {
  max-width: 62ch;
  margin-left: auto;
  margin-right: auto;
}

.log__date {
  font-family: 'Barlow Condensed', system-ui, sans-serif;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ks-yellow);
}

.log__item h3 {
  margin: 4px 0 6px;
}

.log__item p {
  color: var(--ks-sky);
}

/* ─────────────────────────────────────────────────────────────────────────────
   THE WARNING

   One thing on this site has to be read before somebody spends a month on a
   career, and it is that the alpha gets wiped. So it does not look like the rest
   of the page: yellow rule, yellow heading, its own box, and it sits inside the
   band rather than after it.

   Yellow as a border and a heading, never as a fill behind body text — the body
   text here is white, and white on yellow is 1.45:1.
   ───────────────────────────────────────────────────────────────────────────── */
.warn {
  max-width: 62ch;
  margin: clamp(6px, 1.4vh, 14px) auto;
  padding: 20px 22px;
  border: 2px solid var(--ks-yellow);
  border-radius: var(--radius);
  background: rgb(10 23 55 / 0.72);
  text-align: center;
}

.warn p + p {
  margin-top: 12px;
}

/* The roadmap's copy of the warning is the page's main event rather than a note
   inside a band, so it gets the room and the weight to match. */
.warn--loud {
  max-width: none;
  margin: 0;
  padding: clamp(24px, 4vw, 34px);
  border-width: 3px;
  background: rgb(10 23 55 / 0.55);
}

.warn--loud .warn__title {
  font-size: clamp(1.4rem, 4.6vw, 2rem);
}

.warn__title {
  margin-bottom: 10px;
  font-family: 'Barlow Condensed', system-ui, sans-serif;
  font-weight: 700;
  font-size: 1.22rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ks-yellow);
}

.warn strong {
  color: var(--ks-yellow);
}

/* ─────────────────────────────────────────────────────────────────────────────
   PROSE — a column of plain text, used by the long pages
   ───────────────────────────────────────────────────────────────────────────── */
.prose {
  margin-top: clamp(22px, 4vh, 34px);
  text-align: center;
}

/*
  The exception, and the reason it is one: a page somebody reads to find a
  specific sentence — what is stored, how to delete it — is scanned rather than
  read, and a centred column gives the eye no fixed edge to come back to. Every
  other .prose on this site is three short sentences under a heading.
*/
.prose--left {
  text-align: left;
}

.prose h3 {
  margin-top: 30px;
  color: var(--ks-yellow);
}

.prose p,
.prose li {
  color: var(--ks-sky);
}

.prose p + p {
  margin-top: 12px;
}

.prose strong {
  color: var(--ks-paper);
}

.prose a {
  color: var(--ks-paper);
}

/* Same reasoning as `.card .ticks`: the list is centred as a block, its rows are
   not, because a bullet that moves on every line is not a bullet. */
.prose ul {
  display: inline-block;
  margin: 12px 0 0;
  padding-left: 22px;
  text-align: left;
}

.prose li + li {
  margin-top: 8px;
}

/* ─────────────────────────────────────────────────────────────────────────────
   THE FOOTER
   ───────────────────────────────────────────────────────────────────────────── */
.foot {
  padding: 46px 16px max(34px, env(safe-area-inset-bottom));
  background: var(--ks-navy-deep);
  border-top: 1px solid rgb(255 255 255 / 0.12);
  text-align: center;
}

.foot__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 4px;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}

.foot__links a {
  display: block;
  padding: 11px 12px;
  border-radius: 999px;
  color: var(--ks-sky);
  font-size: 0.94rem;
  text-decoration: none;
}

.foot__links a:hover {
  background: rgb(255 255 255 / 0.08);
  color: var(--ks-paper);
}

.foot__note {
  max-width: 52ch;
  margin: 0 auto;
  color: var(--ks-sky);
  font-size: 0.85rem;
}

.foot__note a {
  color: var(--ks-paper);
}

/* ─────────────────────────────────────────────────────────────────────────────
   TWO UTILITIES, AND NO MORE

   Everything else in this file is a named thing. These two exist so that no page
   has to carry a `style=` attribute, which is the one thing that would put a
   spacing or a colour outside this file where nothing can check it.
   ───────────────────────────────────────────────────────────────────────────── */
.prose--narrow {
  max-width: 68ch;
  margin-left: auto;
  margin-right: auto;
}

.cta-row {
  margin-top: clamp(26px, 5vh, 40px);
  text-align: center;
}

/* ─────────────────────────────────────────────────────────────────────────────
   MOTION
   ───────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .btn,
  .scroll-cue span {
    transition: none;
    animation: none;
  }
}
