/* ==========================================================================
   Marketing site — site layer
   --------------------------------------------------------------------------
   TOKENS ARE NOT DEFINED HERE.

   Every colour, face, size, space and rule weight below comes from the
   design system's token set, referenced by its `--t-*` custom properties:

     source of truth : src/Sidelore.DesignSystem/wwwroot/css/sidelore-tokens.css
     checked-in copy : site/sidelore-tokens.css
     copied verbatim : 2026-09-21 (md5 96539a4e5673d8f3444df2c4c3a29b4e)

   The copy is byte-identical and is kept as its own file, unmodified, so
   that re-syncing is `cp` and detecting drift is `diff`:

     diff site/sidelore-tokens.css \
          src/Sidelore.DesignSystem/wwwroot/css/sidelore-tokens.css

   If that diff is not empty, the token set has moved and this site is stale.
   Re-copy it deliberately; do not hand-edit site/sidelore-tokens.css, and do
   not redefine a `--t-*` value here. There are currently no local overrides
   of any token: the set carries the dark focus colour, the text-input role
   and the major-rule colour itself.

   No @import: a static site with no build step gets two <link> elements, in
   order — sidelore-tokens.css first, then this file.

   Non-negotiables held here:
   - no red, no alarm hue, anywhere
   - border radius 0 everywhere (--t-radius)
   - everything flush left, including labels inside full-width buttons
   - 2px rule between major sections; 1px hairline between rows
   - no shadows, no elevation, no floating cards
   - two faces, load-bearing: Newsreader = writing, Archivo = apparatus
   ========================================================================== */

/* --------------------------------------------------------------------------
   ⚑ THE WORDMARK LIVES HERE AND NOWHERE ELSE ⚑

   The product name is codenamed only and is blocked by trademark. It will
   change. The brand mark is therefore declared exactly once, as the custom
   property below, and rendered by the .wordmark rule further down.

   To rename the mark: change this one string. Nothing else in the CSS or in
   any HTML file carries the mark.

   (Note: the word also appears inside body copy on index.html, schools.html
   and faq.html because the copy deck uses it in running prose. Those are
   sentences, not the mark. They are listed in the build notes and can be
   swept with a find-and-replace.)

   This is a site string, not a design token, which is why it is here and not
   in the copied token file.
   -------------------------------------------------------------------------- */
:root {
  --wordmark: "Sidelore";
}

/* --------------------------------------------------------------------------
   Site-local variables. These are layout decisions this marketing site makes,
   not tokens. They default to token values and never overwrite one.

   Note on the major section rule: this site previously carried a local dark
   value of rgba(255,255,255,0.34) for it. That is gone. The token set now
   declares --t-rule-major-colour, and its reading is the correct one — a
   2px major rule is SOLID INK in both themes, and the README's dark
   rgba(255,255,255,0.18 / 0.14) pair are the minor and hairline rules only.
   -------------------------------------------------------------------------- */
:root {
  --site-gutter: var(--t-page-padding);   /* 24px */
  --site-measure: 40rem;                  /* reading column -- 65-70ch, DO NOT WIDEN */

  /* THE CONTAINER, used only from 64rem up. The page looked like a strip down the middle of a
     desktop screen, and the fix is not a wider measure: 40rem is about 65-70 characters, which
     is where prose is easiest to read, and stretching it to fill a monitor makes the page
     harder to read rather than better used. So the MEASURE stays and the PAGE grows around it.
     Headings and rules take this width; paragraphs never do. */
  --site-wide: 58rem;
}

/* --------------------------------------------------------------------------
   Reset — minimal, and radius is the token's zero everywhere
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
  border-radius: var(--t-radius);
}

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

body {
  margin: 0;
  background: var(--t-paper);
  color: var(--t-ink);
  font-family: var(--t-face-writing);
  font-size: var(--t-argument-size);
  line-height: var(--t-argument-lh);
  font-synthesis-weight: none;
}

img,
svg {
  max-width: 100%;
  height: auto;
}

/* --------------------------------------------------------------------------
   Focus and interaction states — the handoff's rule, expressed in tokens
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: var(--t-focus-width) solid var(--t-focus-colour);
  outline-offset: var(--t-focus-offset);
}

::selection {
  background: var(--t-paper-tint);
  color: var(--t-ink);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  background: var(--t-ink);
  color: var(--t-paper);
  font-family: var(--t-face-apparatus);
  font-size: var(--t-action-size);
  font-weight: var(--t-action-weight);
  padding: var(--t-space-3) var(--t-space-4);
  text-decoration: none;
}

.skip-link:focus {
  left: 0;
}

/* --------------------------------------------------------------------------
   Shell
   -------------------------------------------------------------------------- */
.page {
  max-width: calc(var(--site-measure) + (2 * var(--site-gutter)));
  margin-inline: auto;
  padding-inline: var(--site-gutter);
}

/* 2px between major sections. Not a hairline, not whitespace. */
.band {
  border-top: var(--t-rule-major) solid var(--t-rule-major-colour);
  padding-block: var(--t-space-6);
}

.band:first-of-type {
  border-top: 0;
}

/* Flow spacing. The class is doubled so these beat the `margin: 0` resets on
   the component classes below, which would otherwise win on source order. */
.band.band > * + * {
  margin-top: var(--t-space-5);
}

.band.band > .kicker + * {
  margin-top: var(--t-space-3);
}

/* --------------------------------------------------------------------------
   Masthead — wordmark, strapline, navigation
   -------------------------------------------------------------------------- */
.masthead {
  padding-block: var(--t-space-5);
}

.lockup {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--t-space-3);
}

/* The mark itself. The string comes from --wordmark and from nowhere else. */
.wordmark {
  font-family: var(--t-face-writing);
  font-size: var(--t-masthead-size);
  font-weight: var(--t-masthead-weight);
  letter-spacing: var(--t-masthead-tracking);
  line-height: 1;
  color: var(--t-ink);
  text-decoration: none;
}

.wordmark::after {
  content: var(--wordmark);
}

.wordmark:hover::after {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.strapline {
  margin: 0;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-kicker-size);
  font-weight: var(--t-kicker-weight);
  letter-spacing: var(--t-kicker-tracking);
  text-transform: uppercase;
  color: var(--t-ink-muted);
}

.nav {
  margin-top: var(--t-space-4);
  border-top: var(--t-rule-minor) solid var(--t-rule-hairline);
}

.nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--t-space-5);
}

.nav a {
  display: inline-block;
  padding-block: var(--t-space-3);
  font-family: var(--t-face-apparatus);
  font-size: var(--t-apparatus-size);
  font-weight: 500;
  line-height: var(--t-apparatus-lh);
  color: var(--t-ink-secondary);
  text-decoration: none;
}

.nav a:hover {
  color: var(--t-accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.nav a[aria-current="page"] {
  color: var(--t-ink);
  border-bottom: var(--t-rule-major) solid var(--t-accent);
}

/* --------------------------------------------------------------------------
   Writing — Newsreader
   -------------------------------------------------------------------------- */
h1,
h2,
h3 {
  font-family: var(--t-face-writing);
  margin: 0;
  text-wrap: pretty;
}

/* The hero headline is the hook role. In dark that role is specified as
   38px / 300 / 1.14 / −0.025em; the tokens carry the theme change, so this
   rule does not have to know about it. */
h1 {
  font-size: var(--t-hook-size);
  font-weight: var(--t-hook-weight);
  line-height: var(--t-hook-lh);
  letter-spacing: var(--t-hook-tracking);
}

h2 {
  font-size: var(--t-screen-title-size);
  font-weight: var(--t-screen-title-weight);
  line-height: var(--t-screen-title-lh-tight);
  letter-spacing: var(--t-screen-title-tracking);
}

h3 {
  font-size: var(--t-prompt-size);
  font-weight: var(--t-prompt-weight);
  line-height: var(--t-prompt-lh-tight);
  letter-spacing: var(--t-prompt-tracking);
}

p {
  margin: 0;
  font-family: var(--t-face-writing);
  font-size: var(--t-argument-size);
  font-weight: var(--t-argument-weight);
  line-height: var(--t-argument-lh);
  color: var(--t-ink-secondary);
}

p strong,
li strong {
  font-weight: 600;
  color: var(--t-ink);
}

p em,
li em {
  font-style: italic;
}

/* The lead paragraph directly under a hero headline */
.lede {
  color: var(--t-ink);
}

/* Quoted hooks and the dinner-table question examples: writing, so serif. */
.quote {
  margin: 0;
  border-left: var(--t-rule-major) solid var(--t-accent);
  padding-left: var(--t-space-4);
}

.quote p {
  font-family: var(--t-face-writing);
  font-size: var(--t-list-title-size);
  font-style: italic;
  line-height: var(--t-reflection-lh);
  color: var(--t-ink);
}

/* --------------------------------------------------------------------------
   Apparatus — Archivo
   -------------------------------------------------------------------------- */
.kicker {
  margin: 0;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-kicker-size);
  font-weight: var(--t-kicker-weight-strong);
  letter-spacing: var(--t-kicker-tracking);
  text-transform: uppercase;
  color: var(--t-ink-muted);
}

.meta {
  margin: 0;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-metadata-size);
  font-weight: var(--t-metadata-weight);
  line-height: var(--t-metadata-lh);
  color: var(--t-ink-muted);
}

.apparatus {
  font-family: var(--t-face-apparatus);
  font-size: var(--t-apparatus-size);
  line-height: var(--t-apparatus-lh);
  color: var(--t-ink-secondary);
}

/* --------------------------------------------------------------------------
   Links in prose
   -------------------------------------------------------------------------- */
main a:not(.btn):not(.wordmark) {
  color: var(--t-accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

main a:not(.btn):not(.wordmark):hover {
  background: var(--t-paper-tint);
}

/* --------------------------------------------------------------------------
   Rows — 1px hairline between list items
   -------------------------------------------------------------------------- */
.rows {
  list-style: none;
  margin: 0;
  padding: 0;
}

.rows > li {
  border-top: var(--t-rule-minor) solid var(--t-rule-hairline);
  padding-block: var(--t-space-4);
}

.rows > li:first-child {
  border-top: 0;
  padding-top: 0;
}

.rows.rows > li > * + * {
  margin-top: var(--t-space-2);
}

.rows p {
  font-size: var(--t-argument-size);
}

/* A compact row list, used for the example week's subordinate lines */
.rows--tight > li {
  padding-block: var(--t-space-3);
}

.rows--tight p {
  font-size: var(--t-coverage-size);
  line-height: var(--t-coverage-lh);
}

/* Numbered steps */
.steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* THE NUMBER SITS BESIDE THE QUESTION, not above it. .step-number was display:block, which
   put each numeral on its own line and left the questions looking unnumbered -- the numbers
   read as tiny headings rather than as an index. A two-column row is what a numbered list is,
   and the column is fixed so every question starts on the same left edge however many digits
   the number has. */
.steps > li {
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr);
  column-gap: var(--t-space-3);
  align-items: baseline;
  border-top: var(--t-rule-minor) solid var(--t-rule-hairline);
  padding-block: var(--t-space-5);
}

.steps > li:first-child {
  border-top: 0;
  padding-top: 0;
}

/* No flow spacing inside a row: the number and the question are side by side now, so the
   margin that used to separate them vertically would only knock the text off the baseline. */
.steps.steps > li > * + * {
  margin-top: 0;
}

.step-number {
  display: block;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-kicker-size);
  font-weight: var(--t-kicker-weight-strong);
  letter-spacing: var(--t-kicker-tracking-wide);
  text-transform: uppercase;
  color: var(--t-accent-text);
}

/* --------------------------------------------------------------------------
   Inset block — the example week. Tinted paper, no shadow, no radius.
   In dark --t-paper-tint is dark ink at 6%, which composites over the ground
   rather than being a second opaque hex; nothing here needs to know that.
   -------------------------------------------------------------------------- */
.inset {
  background: var(--t-paper-tint);
  padding: var(--t-space-5);
}

.inset.inset > * + * {
  margin-top: var(--t-space-4);
}

.inset p {
  color: var(--t-ink-secondary);
}

/* A kicker inside the inset is still a kicker. Without this it loses to
   `.inset p` on specificity (0,1,1 beats 0,1,0) and silently renders at
   --t-ink-secondary, one step too dark. Caught by probing computed styles,
   not by reading the file — `.why` already had to be written this way for
   the same reason. */
.inset .kicker {
  color: var(--t-ink-muted);
}

.inset .hook {
  font-size: var(--t-screen-title-size);
  line-height: var(--t-hook-lh);
  letter-spacing: var(--t-hook-tracking);
  color: var(--t-ink);
}

.inset .divider {
  border: 0;
  border-top: var(--t-rule-minor) solid var(--t-rule-hairline);
  margin-block: var(--t-space-5);
}

.inset .why {
  font-family: var(--t-face-writing);
  font-style: italic;
  font-size: var(--t-coverage-size);
  color: var(--t-ink-muted);
}

/* --------------------------------------------------------------------------
   Buttons and the prominent cross-link.
   Labels are flush left. Never centred, not even at full width.
   -------------------------------------------------------------------------- */
.btn {
  display: block;
  width: 100%;
  text-align: left;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-action-size);
  font-weight: var(--t-action-weight);
  line-height: 1.4;
  letter-spacing: 0;
  padding: var(--t-space-4);
  border: var(--t-rule-major) solid var(--t-accent);
  background: var(--t-accent);
  color: var(--t-on-accent);
  text-decoration: none;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.btn:hover {
  background: var(--t-accent-pressed);
  border-color: var(--t-accent-pressed);
}

.btn--secondary {
  background: transparent;
  border: var(--t-rule-major) solid var(--t-ink);
  color: var(--t-ink);
}

.btn--secondary:hover {
  background: var(--t-paper-tint);
}

/* The "see what your child sees" link. Deliberately prominent (copy deck §0,
   open question 7.2 — the trust argument wins over the funnel argument). */
.crosslink {
  display: block;
  /* The closing rule is the next band's border-top — one rule, not two. */
  border-top: var(--t-rule-major) solid var(--t-rule-major-colour);
  padding-block: var(--t-space-5);
  text-align: left;
  text-decoration: none;
}

.crosslink:hover {
  background: var(--t-paper-tint);
}

.crosslink .crosslink-label {
  display: block;
  font-family: var(--t-face-writing);
  font-size: var(--t-prompt-size);
  line-height: var(--t-prompt-lh-tight);
  letter-spacing: var(--t-prompt-tracking);
  color: var(--t-accent-text);
}

/* --------------------------------------------------------------------------
   Signup — email address only.
   Text inputs per the design system: 2px ink bottom rule, no box, no radius,
   Archivo. Focus moves the rule to clay; the token focus outline still draws,
   because the handoff forbids leaving any focusable thing without one.
   -------------------------------------------------------------------------- */
.signup {
  display: block;
}

.signup.signup > * + * {
  margin-top: var(--t-space-3);
}

.signup label {
  display: block;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-kicker-size);
  font-weight: var(--t-kicker-weight-strong);
  letter-spacing: var(--t-kicker-tracking);
  text-transform: uppercase;
  color: var(--t-ink-muted);
}

.signup input[type="email"] {
  display: block;
  width: 100%;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-input-size);
  line-height: var(--t-input-lh);
  color: var(--t-ink);
  background: transparent;
  border: 0;
  border-bottom: var(--t-rule-major) solid var(--t-ink);
  padding: var(--t-space-3) 0;
  -webkit-appearance: none;
  appearance: none;
}

.signup input[type="email"]:focus {
  border-bottom-color: var(--t-accent);
}

.signup input[type="email"]::placeholder {
  color: var(--t-ink-muted);
}

.signup-note {
  margin: 0;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-metadata-size);
  line-height: var(--t-metadata-lh);
  color: var(--t-ink-muted);
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.footer {
  border-top: var(--t-rule-major) solid var(--t-rule-major-colour);
  padding-block: var(--t-space-5) var(--t-space-6);
}

.footer ul {
  list-style: none;
  margin: 0 0 var(--t-space-4);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--t-space-2) var(--t-space-5);
}

.footer a {
  font-family: var(--t-face-apparatus);
  font-size: var(--t-apparatus-size);
  font-weight: 500;
  color: var(--t-ink-secondary);
  text-decoration: none;
}

.footer a:hover {
  color: var(--t-accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
   Desktop is a scaled reading view, never a denser one.
   The token set has no desktop scale — it is a 390px product — so the step
   up is a site decision, taken from the same role sizes one notch larger.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   Desktop width, from 64rem up.

   FIRST ATTEMPT, REMOVED: the kicker was pulled out into a 15rem margin
   column and everything else sat in the reading column beside it. It made
   the headings look wrong, and they were -- a section heading is display
   type and should use the width of the page, not the width of the body
   text, so holding it to 40rem left it visibly short of the right edge
   while a third of the page sat empty on the left.

   What is here now is the plain version and the more common one: one
   column, one left edge, everything aligned to the same spine. The
   CONTAINER is wide; the PROSE is held to its measure inside it; headings
   and rules use the full width. Nothing is indented and nothing floats.
   -------------------------------------------------------------------------- */
@media (min-width: 64rem) {
  .page {
    max-width: calc(var(--site-wide) + (2 * var(--site-gutter)));
  }

  /* Display type takes the page. At 46px this is still only about sixty
     characters, well inside what a heading can carry. */
  h1,
  h2 {
    max-width: none;
  }

  /* Prose does not, ever. This is the whole reason the container can be
     wide in the first place. */
  p,
  li,
  .lede,
  blockquote p {
    max-width: var(--site-measure);
  }

  /* The kicker belongs to the heading under it, so it keeps the heading's
     alignment rather than the body's. */
  .kicker {
    max-width: none;
  }
}

@media (min-width: 48rem) {
  :root {
    --site-gutter: var(--t-space-6);
  }

  body {
    font-size: var(--t-list-title-size);
  }

  .band {
    padding-block: 48px;
  }

  h1 {
    font-size: 46px;
    line-height: 1.1;
  }

  h2 {
    font-size: var(--t-hook-size);
  }

  h3 {
    font-size: 25px;
  }

  p,
  .rows p {
    font-size: var(--t-list-title-size);
    line-height: var(--t-reflection-lh);
  }

  .quote p {
    font-size: 21px;
  }

  .inset {
    padding: var(--t-space-6);
  }

  .inset .hook {
    font-size: var(--t-hook-size);
  }

  .crosslink .crosslink-label {
    font-size: 28px;
  }

  .btn {
    display: inline-block;
    width: auto;
    min-width: 18rem;
  }

  .signup input[type="email"] {
    max-width: 24rem;
  }
}

/* 360px floor — --t-screen-min */
@media (max-width: 22.5rem) {
  :root {
    --site-gutter: var(--t-space-4);
  }

  h1 {
    font-size: 30px;
  }

  .inset {
    padding: var(--t-space-4);
  }
}

/* --------------------------------------------------------------------------
   Dark — the token file carries the whole palette, including the focus
   colour and the major-rule colour, so there is nothing to override here.
   .skip-link is the one rule that has to restate its pair, because it
   inverts ink and paper deliberately.
   -------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  .skip-link {
    background: var(--t-ink);
    color: var(--t-paper);
  }
}
/* ==========================================================================
   STRUCTURE LAYER — devices that break the wall of prose
   --------------------------------------------------------------------------
   Everything below is layout and treatment. No token is redefined here and
   no colour is written as a literal.

     .band--hero   a hero treatment, not another .band
     .triad        parallel clauses set as cells, not as one sentence
     .pullquote    the strongest line, lifted, at display size
     .priceline    the price, set as a figure rather than a paragraph
     .flow         five steps and a loop — the homepage's visual anchor
     .photo        a full-bleed duotone band between text blocks
     .credits      the CC-BY attribution block. A licence obligation.

   THERE IS NO <details> ON THIS SITE, AND THAT IS DELIBERATE.

     Progressive disclosure let a word count fall without anything being
     decided: the homepage "dropped" to 596 visible words while carrying
     1,143 hidden ones. Nothing had been cut, only relocated, and a
     disclosure widget wrapping one sentence costs a reader more attention
     than the sentence would have. Every previously hidden sentence has
     been either inlined or deleted. If you are about to add a <details>
     here, you are about to defer a decision.

   THERE ARE NO CHARTS ON THIS SITE, AND THAT IS DELIBERATE.

     Five were built and all five were removed: a 500-year Colorado River
     flow reconstruction, Arctic sea ice at both ends of the year, the DofE
     share of a 14-year-old cohort, the UCAS character budget, and two
     ordinal diagrams from the activity taxonomy. Each was sourced and
     correct. All of them added detail nobody had asked for, attached to
     sample content, and a reader had to stop and decode them — which is
     the opposite of what a page with too much text needs.

     The visuals here are the five-step flow and the photographs. If a
     chart is proposed again, the question to answer first is whether the
     reader has asked the question it answers.

     One finding from that work is worth keeping, because it constrains
     anything visual that is added later. Measured with the dataviz
     validator (OKLab ΔE ×100, Machado 2009 at severity 1.0) on this
     site's own tokens:

       clay --t-accent   vs muted --t-ink-muted   ΔE  8.6 normal / 4.6 protan
       Q1 clay           vs Q2 olive              ΔE  9.5 normal / 2.7 protan
       clay --t-accent   vs ink --t-ink           ΔE 31.7 normal / 27.2 protan
       ink               vs muted                 ΔE 28.1 normal / 27.9 protan

     The first two are collapses — a protanope cannot separate clay from
     olive at all. This palette can never carry identity by colour, which
     is the design brief's own position (§2.5: the labels carry the
     meaning and the colour is a convenience), now measured rather than
     asserted. The only safe pair is ink against clay.
   ========================================================================== */

:root {
  /* Duotone endpoints for the photography. Site-local, derived from
     tokens, and — per brief §2.5a decision 13 — RE-DECLARED IN EVERY
     COLOUR SCOPE, because a custom property whose value contains var() is
     substituted where it is declared and what inherits downward is the
     resolved literal. Declared once here it would freeze to the light
     pair and every photograph would stay light-themed in dark mode. */
  --duo-shadow: var(--t-accent-text);
  --duo-high: var(--t-paper);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --duo-shadow: var(--t-paper);
    --duo-high: var(--t-accent);
  }
}

[data-theme='dark'] {
  --duo-shadow: var(--t-paper);
  --duo-high: var(--t-accent);
}

[data-surface='parent'] {
  --duo-shadow: var(--t-ink-secondary);
  --duo-high: var(--t-paper);
}

/* --------------------------------------------------------------------------
   Hero — the first eight seconds
   -------------------------------------------------------------------------- */
.band--hero {
  padding-block: var(--t-space-6) var(--t-space-5);
}

.band--hero h1 {
  max-width: 24ch;
}

/* Parallel clauses, set as cells instead of one line of prose. The words
   are the copy deck's, in its order; only the line breaks are a design
   decision. */
.triad {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--t-space-4);
}

.triad > li {
  border-top: var(--t-rule-major) solid var(--t-ink);
  padding-top: var(--t-space-3);
}

.triad p {
  font-family: var(--t-face-writing);
  font-size: var(--t-list-title-size);
  line-height: var(--t-prompt-lh-tight);
  color: var(--t-ink);
}

/* The line that completes a triad. It declares no colour on purpose: on a
   hero it is also .lede and must stay ink, and elsewhere it takes the
   paragraph default. Declaring --t-ink-secondary here silently out-ordered
   .lede and darkened the hero's strongest line by one step — the §2.5a
   decision 13 failure mode exactly, caught by probing the resolved colour
   rather than by reading this file. */
.triad-close {
  max-width: 44ch;
}

/* --------------------------------------------------------------------------
   Pull quote — one strong line, lifted out of the prose it came from.
   Distinct from .quote, which brackets a quoted specimen with a left rule.
   -------------------------------------------------------------------------- */
.pullquote {
  margin: 0;
  border-top: var(--t-rule-major) solid var(--t-ink);
  border-bottom: var(--t-rule-major) solid var(--t-ink);
  padding-block: var(--t-space-5);
}

.pullquote p {
  font-family: var(--t-face-writing);
  font-size: var(--t-screen-title-size);
  font-weight: var(--t-screen-title-weight);
  line-height: var(--t-screen-title-lh-tight);
  letter-spacing: var(--t-screen-title-tracking);
  color: var(--t-ink);
}

/* --------------------------------------------------------------------------
   Price, set as a figure rather than a sentence
   -------------------------------------------------------------------------- */
.priceline {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--t-space-3);
  border-top: var(--t-rule-major) solid var(--t-ink);
  padding-top: var(--t-space-3);
}

/* Archivo, per §2.4: a price is apparatus, not writing. Proportional
   figures — tabular-nums only aligns columns and looks loose at this size. */
.priceline .priceline-figure {
  font-family: var(--t-face-apparatus);
  font-size: var(--t-hook-size);
  font-weight: var(--t-action-weight);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--t-ink);
}

.priceline .priceline-note {
  font-family: var(--t-face-apparatus);
  font-size: var(--t-apparatus-size);
  line-height: var(--t-apparatus-lh);
  color: var(--t-ink-muted);
}

/* --------------------------------------------------------------------------
   The flow — five steps and a loop. The homepage's main visual anchor.

   THE LOOP IS THE POINT, NOT DECORATION. Product brief R8: a student who
   stops needing our suggestions is the outcome we are aiming at, not a
   lapsed user. Step 5 returns to step 1 changed, and the return arm is
   labelled. Do not drop it to save vertical space.

   Built in HTML and CSS rather than as an SVG because it has to reflow: a
   vertical spine on a phone, a five-column row on a desktop, one set of
   markup, no script. The return arm is one absolutely positioned box with
   three of its four borders drawn — a bracket on mobile, a U on desktop —
   which is the whole trick.

   Type, rules and numerals only. No icons, no illustration. The numerals
   are large so that "five steps and a loop" is legible before any label is
   read; the arrow on the return label is a pseudo-element, decorative, and
   its direction changes with the layout.
   -------------------------------------------------------------------------- */
.flow {
  position: relative;
  /* the channel the return arm runs up */
  padding-left: var(--t-space-6);
}

.flow-steps {
  list-style: none;
  margin: 0;
  padding: 0;
}

.flow-steps > li {
  border-top: var(--t-rule-major) solid var(--t-ink);
  padding-block: var(--t-space-4);
}

.flow-n {
  margin: 0;
  font-family: var(--t-face-apparatus);
  font-size: var(--t-screen-title-size);
  font-weight: var(--t-action-weight);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--t-ink-muted);
}

.flow-what {
  margin-top: var(--t-space-2);
  font-family: var(--t-face-writing);
  font-size: var(--t-prompt-size);
  font-weight: var(--t-prompt-weight);
  line-height: var(--t-prompt-lh-tight);
  letter-spacing: var(--t-prompt-tracking);
  color: var(--t-ink);
}

.flow-detail {
  margin-top: var(--t-space-2);
  font-family: var(--t-face-writing);
  font-size: var(--t-coverage-size);
  line-height: var(--t-coverage-lh);
  color: var(--t-ink-secondary);
}

/* The return arm. Three borders of an empty box: it leaves the last step
   at the bottom, runs out to the channel, and re-enters the first step at
   the top. Nothing is drawn on the side facing the steps. */
.flow-loop {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--t-space-5);
  border: var(--t-rule-major) solid var(--t-accent);
  border-right: 0;
}

.flow-return {
  margin-top: var(--t-space-3);
  font-family: var(--t-face-apparatus);
  font-size: var(--t-apparatus-size);
  font-weight: 500;
  line-height: var(--t-apparatus-lh);
  color: var(--t-accent-text);
}

/* Decorative, and it points the way the arm actually runs at this width.
   Stacked, the arm comes up the left channel and turns RIGHT into step 1.
   Five across, it runs back along the bottom and turns UP into step 1. */
.flow-return::before {
  content: "\2192\00a0";
}

/* --------------------------------------------------------------------------
   Photography — a band between text blocks, for the eye to rest on.

   NO RECOGNISABLE FACES, ANYWHERE, EVER. A Creative Commons licence grants
   copyright permission; it does not grant likeness rights, and no
   photographer here obtained a model release. Using an identifiable person
   to advertise a product is a personality-rights problem whatever the
   licence, and using an identifiable child to advertise a product aimed at
   children is the worst version of it. Four of the six frames contain no
   people at all; one is gloved hands with the head outside the frame; one
   is figures at distance, bent over or turned away. If the only good frame
   has a face in it, discard the frame.

   No captions and no explanatory text on these. They exist to let the eye
   rest, which is exactly what a caption would undo.

   One duotone across the whole set, from tokens, so six photographers read
   as one designed set and sit inside the palette rather than fighting it:
   screen lifts the blacks to --duo-shadow, multiply pulls the whites down
   to --duo-high, and both ends change with the theme. isolation:isolate
   keeps the blend off the page behind.
   -------------------------------------------------------------------------- */
.photo {
  position: relative;
  isolation: isolate;
  display: block;
  /* out to the page edges — a clear break from the reading column */
  margin-inline: calc(-1 * var(--site-gutter));
  aspect-ratio: 16 / 7;
  overflow: hidden;
}

.photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the duotone needs a single channel to tint */
  filter: grayscale(1) contrast(1.06);
}

.photo::before,
.photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.photo::before {
  background: var(--duo-shadow);
  mix-blend-mode: screen;
}

.photo::after {
  background: var(--duo-high);
  mix-blend-mode: multiply;
}

/* Forced colours and high-contrast users get the photograph untinted
   rather than a blend that the OS palette would fight. */
@media (forced-colors: active) {
  .photo::before,
  .photo::after {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   Credits — CC BY requires attribution, and a site whose pitch is that it
   cites things should look like it.
   -------------------------------------------------------------------------- */
.credits {
  border-top: var(--t-rule-minor) solid var(--t-rule-hairline);
  padding-top: var(--t-space-3);
  margin-top: var(--t-space-4);
}

.credits p,
.credits li {
  font-family: var(--t-face-apparatus);
  font-size: var(--t-metadata-size);
  line-height: var(--t-metadata-lh);
  color: var(--t-ink-muted);
}

.credits ul {
  list-style: none;
  margin: var(--t-space-2) 0 0;
  padding: 0;
}

.credits a {
  color: var(--t-ink-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.credits a:hover {
  color: var(--t-accent-text);
}

/* --------------------------------------------------------------------------
   Structure layer — wider
   -------------------------------------------------------------------------- */
@media (min-width: 48rem) {
  .band--hero {
    padding-block: 56px var(--t-space-6);
  }

  .triad {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--t-space-5);
  }

  .triad p {
    font-size: var(--t-prompt-size);
  }

  .pullquote p {
    font-size: var(--t-hook-size);
  }

  /* Five across, and the return arm becomes a U beneath them. */
  .flow {
    padding-left: 0;
    padding-bottom: var(--t-space-6);
  }

  .flow-steps {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: var(--t-space-4);
  }

  .flow-steps > li {
    padding-block: var(--t-space-3) 0;
  }

  .flow-loop {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    height: var(--t-space-6);
    border: var(--t-rule-major) solid var(--t-accent);
    border-top: 0;
  }

  .flow-return::before {
    content: "\2191\00a0";
  }

  .photo {
    aspect-ratio: 16 / 6;
  }

}

/* Motion communicates state or space, or it does not exist. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* The subscribe call to action. It appears three times on the parent page — beside the
   price in the hero, once mid-page, and at the price section — because the only one that
   existed was at the bottom, past everything, which asked somebody who had already decided
   in the first screen to scroll through the whole argument to act on it.

   The button is full-width by design (see .btn), so these just control the space around it. */
.cta {
  margin: var(--t-space-5) 0 0;
}

/* In the hero, where it sits under the price line and above the crosslink. Tighter, so the
   three read as one block rather than as three separate offers. */
.cta--inline {
  margin-top: var(--t-space-4);
  margin-bottom: var(--t-space-4);
}
