/* ─────────────────────────────────────────────────────────────
   99cols.cc — the site's own layer, on top of the design system.
   Loaded AFTER /ds/styles.css, and it defines no colour, radius or
   type size of its own: every value here is a token (CLAUDE.md —
   the DS token CSS is the source of truth). Where a token needs an
   alpha the site uses color-mix on the token rather than a new hex,
   so a brand change still reaches this page.
   ───────────────────────────────────────────────────────────── */

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  /* No `fixed` attachment: a fixed body background forces the compositor's
     full-repaint path, and this pane's renderer visibly drops the hero when
     scrolled. The wash reads the same scrolling with the page. */
  background: var(--grad-hero) var(--bg-page);
  color: var(--text-body);
  font-family: var(--font-ui);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-weight: var(--w-regular);
  -webkit-font-smoothing: antialiased;
}

/* The signature motif: contour lines, always below the noise threshold. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: repeating-radial-gradient(
    circle at 82% -6%,
    transparent 0 38px,
    color-mix(in srgb, var(--ink) 4%, transparent) 38px 39px
  );
}

h1,
h2,
h3 {
  margin: 0;
  color: var(--text-strong);
  font-family: var(--font-display);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-title);
  text-wrap: balance;
}

h1 {
  font-size: clamp(var(--t-h1), 7vw, var(--t-display));
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
}

h2 {
  font-size: var(--t-h2);
  line-height: var(--lh-tight);
}

h3 {
  font-size: var(--t-h3);
  line-height: var(--lh-snug);
}

p {
  margin: 0;
  max-width: var(--measure);
}

a {
  color: var(--fn-tint);
  text-underline-offset: 3px;
}

a:hover {
  color: var(--structure-700);
}

/* ── Layout ─────────────────────────────────────────────────── */

/* `padding-inline`, never the `padding` shorthand: a section IS a shell, and a
   shorthand here would reset the block padding that gives the page its rhythm
   — silently, because `.shell` outranks `main > section`. */
.shell {
  max-width: var(--content-max);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.masthead,
main > section,
.colophon {
  padding-block: var(--sp12);
}

.masthead {
  padding-block: var(--sp8) 0;
}

.masthead-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-row);
}

.quiet-link {
  color: var(--text-muted);
  font-size: var(--t-caption);
  text-decoration: none;
}

.quiet-link:hover {
  color: var(--text-body);
  text-decoration: underline;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-stack);
  align-items: flex-start;
}

.stack--loose {
  gap: var(--sp6);
}

.overline {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--t-overline);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-overline);
  text-transform: uppercase;
}

.wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: var(--sp2);
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: var(--t-title);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-title);
  text-decoration: none;
}

.wordmark span {
  color: var(--text-muted);
  font-family: var(--font-ui);
  font-size: var(--t-overline);
  font-weight: var(--w-medium);
  letter-spacing: var(--tr-overline);
  text-transform: uppercase;
}

.lede {
  font-size: var(--t-h3);
  line-height: var(--lh-snug);
  color: var(--text-body);
}

.muted {
  color: var(--text-muted);
  font-size: var(--t-body-sm);
}

/* A section headline that reads as a claim, not a label. Sized between h1
   and the display cut so the hero keeps the top of the scale to itself. */
.statement {
  font-size: clamp(var(--t-h2), 4.5vw, var(--t-h1));
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-title);
}

/* ── Hero: the words and the object, side by side ───────────── */

.hero {
  display: grid;
  gap: var(--sp8);
  align-items: center;
}

@media (min-width: 880px) {
  .hero {
    /* A fixed track, not `auto`: the album's only intrinsic width is its
       cells', and letting the track ask them collapses the card. */
    grid-template-columns: minmax(0, 1fr) 440px;
    gap: var(--sp12);
  }
}

/* ── The night band: the one dark moment on the page ────────── */

.band {
  background: var(--grad-night);
  color: var(--night-ink-2);
}

.band .shell {
  padding-block: var(--sp16);
}

.band .overline {
  color: var(--night-ink-3);
}

.band .statement {
  color: var(--night-ink);
}

/* ── The album ──────────────────────────────────────────────── */

/* The album is the only object on the page, so it is the only thing that
   sits on a raised surface — the card recipe from the DS, nothing else. */
.album {
  width: 100%;
  max-width: 440px;
  padding: var(--space-inset-card);
  background: var(--surface-card);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-peek);
}

.album-cells {
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: var(--sp1);
}

.cell {
  aspect-ratio: 1;
  border-radius: var(--r-dot);
  /* An unearned well: the accent at 10%, the same recipe as HomeScreen —
     NOT --accent-soft, which is 22 units lighter and washes the grid out. */
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}

.cell--void {
  background: transparent;
}

.cell--d4 {
  background: var(--d4);
}
.cell--d3 {
  background: var(--d3);
}
.cell--d2 {
  background: var(--d2);
}
.cell--d1 {
  background: var(--d1);
}
/* Every hors catégorie glows, on top of its own colour — not instead of it. */
.cell--dhc {
  background: var(--dhc);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--warm) 45%, transparent);
}

.album-readout {
  display: flex;
  align-items: baseline;
  gap: var(--sp2);
  margin-top: var(--sp4);
  font-family: var(--font-data);
  font-size: var(--t-data);
  color: var(--text-muted);
}

.album-readout b {
  color: var(--text-strong);
  font-size: var(--t-data-hero);
  font-weight: var(--w-medium);
  line-height: 1;
}

/* The mono is for figures only. Prose beside them goes back to the UI voice. */
.album-readout em {
  font-family: var(--font-ui);
  font-size: var(--t-caption);
  font-style: normal;
}

/* ── Cards ──────────────────────────────────────────────────── */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--sp4);
  margin: 0;
  padding: 0;
  list-style: none;
  /* .stack aligns flex-start, which would let this grid shrink to content
     and wrap early; the row of cards is the one child meant to fill it. */
  width: 100%;
}

.card {
  display: flex;
  flex-direction: column;
  gap: var(--sp2);
  padding: var(--space-inset-card);
  background: var(--surface-card);
  border-radius: var(--r-card);
  box-shadow: var(--elevation-card);
}

.card p {
  font-size: var(--t-body-sm);
}

.card .overline {
  font-family: var(--font-data);
  color: var(--fn-tint);
}

/* A note card: the wash tinted, with a 3px accent edge. */
.note {
  padding: var(--space-inset-card);
  border-radius: var(--r-card);
  border-left: 3px solid var(--human-tint);
  background: var(--human-tint-soft);
  color: var(--text-strong);
}

/* ── Actions ────────────────────────────────────────────────── */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: 0 var(--sp6);
  border: 0;
  border-radius: var(--r-control);
  background: var(--fn-tint);
  color: var(--text-on-accent);
  font-family: var(--font-ui);
  font-size: var(--t-body);
  font-weight: var(--w-medium);
  text-decoration: none;
  transition:
    transform var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease);
}

.button:hover {
  background: var(--structure-700);
  color: var(--text-on-accent);
}

.button:active {
  transform: scale(var(--press-scale));
}

.button--warm {
  background: var(--human-tint);
}

.button--warm:hover {
  background: var(--warm-ink);
}

/* ── Colophon ───────────────────────────────────────────────── */

.colophon {
  border-top: var(--border);
  color: var(--text-muted);
  font-size: var(--t-caption);
}

.colophon ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-row) var(--sp6);
  margin: 0 0 var(--sp3);
  padding: 0;
  list-style: none;
}

/* ── Prose (the privacy policy) ─────────────────────────────── */

.prose > .overline {
  margin-bottom: var(--sp2);
}

.prose h1 {
  margin-bottom: var(--sp4);
}

.prose .lede,
.prose .note {
  margin-bottom: var(--sp6);
}

.prose h2 {
  margin-top: var(--sp12);
  margin-bottom: var(--sp3);
}

.prose h3 {
  margin-top: var(--sp6);
  margin-bottom: var(--sp2);
}

.prose p,
.prose li {
  font-size: var(--t-body-sm);
  max-width: var(--measure);
}

.prose p + p {
  margin-top: var(--sp3);
}

.prose ul {
  padding-left: var(--sp4);
}

.prose li + li {
  margin-top: var(--sp2);
}

/* Deliberately loud: an unfilled blank must not survive to production. */
.todo {
  padding: 0 var(--sp1);
  border-radius: var(--r-dot);
  background: var(--human-tint-soft);
  color: var(--warm-ink);
  font-family: var(--font-data);
  font-size: var(--t-data-sm);
  text-transform: uppercase;
  letter-spacing: var(--tr-overline);
}

/* ── The Strava bounce ──────────────────────────────────────── */

.centred {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp6);
  min-height: 100svh;
  padding: var(--sp8) var(--gutter);
  text-align: center;
}

.centred p {
  max-width: 46ch;
}

.centred .stack {
  align-items: center;
}

/* Each state is revealed by the script; nothing shows before it has read the
   query string, so a code never flashes behind the wrong sentence. */
.state {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: var(--sp4);
}

body[data-status="ok"] .state--ok,
body[data-status="refused"] .state--refused,
body[data-status="idle"] .state--idle {
  display: flex;
}

body[data-status] .state--nojs {
  display: none;
}

.state--nojs {
  display: flex;
}

/* Reduced motion needs nothing here: the DS collapses --dur-* to 1ms under the
   media query, and every transition above is expressed in those tokens. */
