/* Stylesheet.
 *
 * LOGICAL PROPERTIES ONLY, FROM THE FIRST COMMIT. There is not one
 * margin-left, padding-right, text-align: left, border-left or bare left:/right:
 * offset in this file, and scripts/check-invariants.mjs fails the build if one
 * arrives. The platform this was lifted from carried 44 physical-direction
 * declarations against 5 logical ones; converting them was a day's work at that
 * size and a rewrite six months later. This repository never acquires the first
 * one — INCLUDING through a restyle: the 2026-08-25 visual pass rewrote nearly
 * every rule below and added not one physical property.
 *
 * The mapping, for anyone reaching for the physical form out of habit:
 *   margin-left        -> margin-inline-start
 *   padding-right      -> padding-inline-end
 *   text-align: left   -> text-align: start
 *   border-left        -> border-inline-start
 *   left: 0            -> inset-inline-start: 0
 *   width / height     -> inline-size / block-size
 *
 * Direction-implying ICONS still need mirroring in the markup (a "next"
 * chevron, a progress axis); media transport controls conventionally do not.
 *
 * THERE IS NO COLOUR, NO TYPE FAMILY AND NO MAGIC NUMBER IN THIS FILE. The
 * palette, the two type stacks, the four radii, the six spacing steps, the page
 * measure, the motion curve, the tap-target floor and the four shadows are all
 * GENERATED from the identity in src/product/nt2/product.config.js into
 * /brand/tokens.css by the build, and that file is linked immediately before
 * this one. This file consumes the names and defines only what is layout rather
 * than identity.
 *
 * The reason is dull and expensive: this stylesheet used to carry the palette
 * as its own placeholder custom properties, and the same six colours were also
 * in the web manifest, in a theme-color meta tag and in the styled 500 page.
 * Four copies, and nothing that fails when one of them moves.
 *
 * THE SYSTEM, IN ONE PARAGRAPH. A cool near-white page. White cards with a
 * blue-tinted hairline, a soft blue-tinted shadow and a generous corner. One
 * deep blue for chrome and for anything you press; one brighter blue for links;
 * one warm yellow, rationed, for the single thing you are meant to do today.
 * Everything that can be pressed is a pill at least --tap tall. Everything that
 * moves uses --motion and nothing else. Cards lift 2px under a pointer and take
 * the --accent-edge border; focus is a 3px ring in the chrome blue with a white
 * halo so it survives on both the page and the coloured panels.
 */

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--wash);
  color: var(--ink);
  font-family: var(--font);
  font-weight: 400;
  line-height: 1.6;
  text-align: start;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

#app {
  display: flex;
  flex-direction: column;
  min-block-size: 100vh;
}

a { color: var(--link); }

a:hover { text-underline-offset: 0.22em; }

/* A keyboard visitor's first stop, and it is off-screen without display:none —
 * a skip link that is display:none is a skip link no screen reader offers. */
.skip-link {
  position: absolute;
  inset-inline-start: -9999px;
  inset-block-start: 0;
  z-index: 40;
  padding-inline: 1.1rem;
  padding-block: 0.7rem;
  border-end-end-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: none;
}

.skip-link:focus-visible { inset-inline-start: 0; }

::selection { background: var(--accent); color: var(--accent-ink); }

/* ── Type ────────────────────────────────────────────────────────────────────
 *
 * Headings are set in the display family — the family the wordmark is drawn in
 * — and the body in the text family. Both stacks are generated tokens; neither
 * is named here. Sizes are clamped so a phone never gets a heading that wraps
 * to four lines and a wide screen never gets one that looks like body text.
 */

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.025em;
}

h1 {
  margin-block: 0 var(--space-3);
  font-size: clamp(2rem, 4.5vw, 2.75rem);
}

h2 {
  margin-block: 0 var(--space-2);
  font-size: clamp(1.4rem, 2.6vw, 1.85rem);
}

h3 {
  margin-block: 0 var(--space-2);
  font-size: 1.125rem;
  line-height: 1.3;
}

p { line-height: 1.58; }

strong, b { font-weight: 600; }

/* The eyebrow above a heading. A pill on a coloured panel, plain text on a
 * white one — the .hero rule below flips it. */
.kicker,
.eyebrow {
  margin-block: 0 var(--space-2);
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.025em;
}

/* Any input a visitor types into is 16px or larger: below that iOS zooms the
 * page in and throws them out of the layout mid-tap. */
input, select, textarea, button {
  font-family: inherit;
  font-size: max(1rem, 16px);
}

button { cursor: pointer; }
button:disabled, input:disabled { cursor: not-allowed; }

/* ── Header ──────────────────────────────────────────────────────────────────
 *
 * Sticky, translucent, blurred, with a hairline under it. The mark keeps its
 * own aspect ratio and the <img> carries its intrinsic dimensions, so the
 * header does not jump while the SVG is still arriving.
 */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  backdrop-filter: blur(16px);
  border-block-end: 1px solid var(--line);
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  max-inline-size: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--space-4);
  padding-block: 0.72rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  margin-inline-end: auto;
}

.brand-logo {
  display: block;
  block-size: 1.75rem;
  inline-size: auto;
  max-inline-size: 58vw;
}

.menu-toggle {
  display: none;
  align-items: center;
  min-block-size: var(--tap);
  padding-inline: 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.nav-links a {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.4rem;
  padding-inline: 0.72rem;
  border-radius: 999px;
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
}

.nav-links a:hover {
  background: var(--accent-soft);
  color: var(--accent);
  text-decoration: none;
}

.nav-links a.active {
  background: var(--accent-soft);
  color: var(--accent);
}

/* ── Page ────────────────────────────────────────────────────────────────── */

#page {
  flex: 1;
  inline-size: 100%;
  max-inline-size: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--space-4);
  padding-block: var(--space-5) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.section { display: grid; gap: var(--space-4); }

.section-head { max-inline-size: 48rem; }

.section-head h2 { margin-block-end: var(--space-2); }

.section-head p { margin-block: 0; color: var(--ink-mid); }

/* ── The hero panel ──────────────────────────────────────────────────────────
 *
 * The one big coloured surface on a page, and the only place white text
 * appears. Everything below it is dark type on white cards, which is what keeps
 * long reading comfortable.
 */

.hero {
  padding: clamp(1.4rem, 5vw, 3rem);
  border: 1px solid color-mix(in srgb, var(--paper) 12%, transparent);
  border-radius: var(--radius-xl);
  background: linear-gradient(135deg, var(--accent-deep) 0%, var(--accent) 52%, color-mix(in srgb, var(--accent) 78%, var(--paper)) 100%);
  box-shadow: var(--shadow-hero);
  color: var(--accent-ink);
}

.hero-grid {
  display: grid;
  gap: clamp(1.2rem, 4vw, 2.4rem);
  align-items: center;
}

.hero-copy { min-inline-size: 0; }

.hero h1 { color: inherit; max-inline-size: 22ch; }

.hero .kicker {
  display: inline-flex;
  align-items: center;
  inline-size: fit-content;
  padding-inline: 0.62rem;
  padding-block: 0.35rem;
  border: 1px solid color-mix(in srgb, var(--paper) 24%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 10%, transparent);
  color: color-mix(in srgb, var(--accent-ink) 88%, var(--accent));
}

.lede {
  margin-block: 0 var(--space-4);
  max-inline-size: 40rem;
  font-size: clamp(1rem, 2vw, 1.12rem);
  line-height: 1.55;
}

.hero .lede { color: color-mix(in srgb, var(--accent-ink) 80%, var(--accent)); }

.cta-row,
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-block: 0;
  align-items: stretch;
}

/* The card floating beside the hero copy: one number, one line saying what it
 * is. It is decoration with a fact in it, never a claim the product cannot
 * check. */
.hero-card { display: flex; justify-content: center; min-inline-size: 0; }

.sample-card {
  display: grid;
  gap: var(--space-2);
  inline-size: min(100%, 22rem);
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow-panel);
}

.sample-card .kicker { color: var(--accent); margin-block-end: 0; }

.sample-card strong {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 4vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  color: var(--accent);
}

.sample-card span { color: var(--ink-soft); }

/* The row of checkable facts along the bottom of the hero. */
.proof-row {
  display: grid;
  gap: var(--space-3);
  margin-block: var(--space-4) 0;
  padding-block-start: var(--space-4);
  border-block-start: 1px solid color-mix(in srgb, var(--paper) 16%, transparent);
  padding-inline-start: 0;
  list-style: none;
}

.proof-row li { display: grid; gap: 0.15rem; }

.proof-row strong { color: var(--accent-ink); font-size: 1rem; }

.proof-row span { color: color-mix(in srgb, var(--accent-ink) 76%, var(--accent)); font-size: 0.9rem; }

/* ── Buttons ─────────────────────────────────────────────────────────────────
 *
 * One shape: a pill, at least --tap tall, weight 600. Four intents. Nothing
 * else in the product is pressable-looking.
 */

.action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--tap);
  padding-inline: 1.1rem;
  padding-block: 0.72rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font: inherit;
  font-weight: 600;
  text-decoration: none;
  text-align: center;
}

.action.primary {
  background: var(--accent);
  color: var(--accent-ink);
}

.action.primary:hover { background: var(--accent-deep); color: var(--accent-ink); text-decoration: none; }

/* The one yellow control. It marks today's session and nothing else. */
.action.today {
  background: var(--highlight);
  color: var(--ink);
}

.action.today:hover { background: color-mix(in srgb, var(--highlight) 84%, var(--ink)); color: var(--ink); }

.action.secondary {
  background: var(--accent-soft);
  border-color: var(--accent-edge);
  color: var(--accent);
}

.action.secondary:hover { background: var(--link-soft); color: var(--accent-deep); text-decoration: none; }

.action.quiet {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--ink);
}

.action.quiet:hover { border-color: var(--accent-edge); color: var(--accent); text-decoration: none; }

/* On the hero the primary reverses: white on the panel, and the secondary is a
 * hairline outline rather than a second filled shape. */
.hero .action.primary { background: var(--paper); color: var(--accent); }
.hero .action.primary:hover { background: var(--accent-soft); }
.hero .action.secondary {
  background: color-mix(in srgb, var(--paper) 8%, transparent);
  border-color: color-mix(in srgb, var(--paper) 34%, transparent);
  color: var(--accent-ink);
}
.hero .action.secondary:hover { background: color-mix(in srgb, var(--paper) 16%, transparent); }

.action[disabled],
.action.inactive {
  background: var(--wash-sunken);
  border-color: var(--line-strong);
  color: var(--ink-soft);
  cursor: not-allowed;
}

/* ── Surfaces ────────────────────────────────────────────────────────────────
 *
 * ONE card treatment, listed once. Every panel in the product is this: white,
 * one hairline, one soft shadow, one radius, one padding step. The failure it
 * replaces is six near-identical card rules that drift apart one commit at a
 * time.
 */

.panel,
.card,
.fact,
.prose-block,
.test-card,
.result-card,
.price-block,
.level-test-intro,
.intro-panel,
.faq-list details,
.today-card,
.session-card,
.stat,
.subskill-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--paper);
  box-shadow: var(--shadow-card);
}

.panel,
.card,
.fact,
.prose-block,
.test-card,
.result-card,
.price-block,
.level-test-intro,
.intro-panel,
.today-card,
.session-card,
.subskill-panel {
  padding: var(--space-4);
}

.panel > :first-child,
.card > :first-child,
.prose-block > :first-child { margin-block-start: 0; }

.panel > :last-child,
.card > :last-child,
.prose-block > :last-child { margin-block-end: 0; }

.card-grid {
  display: grid;
  gap: var(--space-3);
}

.card {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  align-content: start;
}

.card h3 { margin-block: 0; }

.card p { margin-block: 0; color: var(--ink-soft); line-height: 1.5; }

.card .action { margin-block-start: auto; align-self: start; }

/* The numbered step badge and the soft icon plate: the same tint, two sizes. */
.step-number {
  display: inline-grid;
  place-items: center;
  /* A flex item stretches on the cross axis by default, which would turn this
     circle into a full-width lozenge inside a column card. */
  align-self: flex-start;
  min-inline-size: 2rem;
  inline-size: 2rem;
  block-size: 2rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.status-pill,
.tag {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  inline-size: fit-content;
  padding-inline: 0.58rem;
  padding-block: 0.28rem;
  border: 1px solid var(--accent-edge);
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.status-pill.good { border-color: color-mix(in srgb, var(--success) 30%, transparent); background: var(--success-soft); color: var(--success); }
.status-pill.warn { border-color: color-mix(in srgb, var(--highlight) 60%, transparent); background: var(--highlight-soft); color: var(--highlight-ink); }
.status-pill.bad { border-color: color-mix(in srgb, var(--danger) 30%, transparent); background: var(--danger-soft); color: var(--danger); }

/* The facts under a hero, as cards rather than a bare list. */
.fact-row {
  display: grid;
  gap: var(--space-3);
  margin-block: 0;
  padding-inline-start: 0;
  list-style: none;
}

.fact { display: grid; gap: var(--space-1); }

.fact strong { font-family: var(--font-display); font-size: 1.15rem; letter-spacing: -0.02em; }

.fact span { color: var(--ink-soft); font-size: 0.92rem; }

/* A block of explanation. It keeps the reading rule on the reading edge, which
 * flips with direction. */
.prose-block {
  display: grid;
  gap: 0.45rem;
  border-inline-start: 3px solid var(--accent-edge);
}

.prose-block p { margin-block: 0; color: var(--ink-mid); }

.small-print {
  max-inline-size: 46rem;
  margin-block: 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.faq-list { display: grid; gap: 0.7rem; }

.faq-list details {
  padding-inline: var(--space-4);
  padding-block: 0.2rem;
  border-radius: var(--radius-md);
  box-shadow: none;
}

.faq-list summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-block-size: var(--tap);
  color: var(--ink);
  font-weight: 600;
  cursor: pointer;
}

.faq-list p { margin-block: 0 0.95rem; color: var(--ink-mid); }

/* ── Forms ───────────────────────────────────────────────────────────────── */

.field {
  display: grid;
  gap: 0.3rem;
  color: var(--ink);
  font-weight: 600;
  font-size: 0.95rem;
}

.field input,
.capture-field {
  /* 16px exactly. Below it iOS zooms the page when the field takes focus. */
  font-size: max(1rem, 16px);
  min-block-size: var(--tap);
  inline-size: 100%;
  padding-inline: 0.95rem;
  padding-block: 0.72rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink);
  font-weight: 400;
}

.field input:hover,
.capture-field:hover { border-color: var(--accent-edge); }

/* ── Footer ──────────────────────────────────────────────────────────────── */

.site-footer {
  margin-block-start: var(--space-5);
  padding-inline: var(--space-4);
  padding-block: var(--space-5) var(--space-6);
  border-block-start: 1px solid var(--line);
  background: var(--paper);
}

.site-footer > * {
  max-inline-size: var(--wrap);
  margin-inline: auto;
}

.footer-disclaimer {
  margin-block: 0 var(--space-3);
  color: var(--ink-soft);
  font-size: 0.85rem;
  line-height: 1.5;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.7rem;
  font-size: 0.9rem;
}

.footer-links a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--tap);
  color: var(--ink-soft);
  font-weight: 500;
  text-decoration: none;
}

.footer-links a:hover { color: var(--accent); text-decoration: underline; }

.footer-home { margin-block: var(--space-2) 0; font-size: 0.9rem; }

.noscript-note {
  max-inline-size: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--space-4);
  color: var(--ink-soft);
}

/* ── The level test, the result card and the capture ──────────────────────────
 *
 * ONE MEASUREMENT IS LOAD-BEARING AND IT IS THE FIELD'S FONT SIZE. Below 16px
 * iOS Safari zooms the page when the field takes focus, which throws the
 * visitor out of the layout in the middle of a tap. The capture is the moment
 * the whole free asset exists for; it does not get to be the moment the page
 * jumps. Targets are at least --tap for the same reason.
 *
 * The capture sits INSIDE the result card, directly under the meter. On the
 * platform this pattern comes from it was the fourth block on the page, roughly
 * 1,600 CSS pixels below the meter on a phone and underneath the card asking for
 * money: twenty-three finished tests produced zero addresses in three days.
 */

.level-test-intro,
.intro-panel { display: grid; gap: var(--space-3); }

.level-test-intro p,
.intro-panel p { margin-block: 0; color: var(--ink-mid); }

.level-test-host,
.route-host { margin-block: 0; }

.test-card { display: grid; gap: var(--space-3); }

.test-prompt {
  margin-block: 0;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--wash);
  color: var(--accent);
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 3vw, 1.5rem);
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.test-question { margin-block: 0; color: var(--ink-mid); font-weight: 600; }

.option-list {
  list-style: none;
  margin: 0;
  padding-inline-start: 0;
  display: grid;
  gap: 0.55rem;
}

.option {
  inline-size: 100%;
  min-block-size: var(--tap);
  text-align: start;
  padding-inline: 1rem;
  padding-block: 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.option:hover { border-color: var(--accent-edge); background: var(--link-soft); }

.option.correct { border-color: color-mix(in srgb, var(--success) 45%, transparent); background: var(--success-soft); color: var(--success); }

.option.wrong { border-color: color-mix(in srgb, var(--danger) 45%, transparent); background: var(--danger-soft); color: var(--danger); }

.option.chosen { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }

.result-card { display: grid; gap: var(--space-3); }

.level-meter { display: grid; gap: 0.45rem; }

.level-meter-track,
.meter-track {
  block-size: 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--wash-sunken);
  overflow: hidden;
}

.level-meter-fill,
.meter-fill {
  block-size: 100%;
  border-radius: inherit;
  background: var(--accent);
  transition: inline-size var(--motion);
}

.level-meter-band {
  margin-block: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.2rem;
}

.tier-list {
  list-style: none;
  margin-block: 0;
  padding-inline-start: 0;
  display: grid;
  gap: 0.4rem;
  font-size: 0.95rem;
}

.tier-row {
  display: flex;
  gap: 0.75rem;
  justify-content: space-between;
  border-block-end: 1px solid var(--line);
  padding-block-end: 0.4rem;
}

.tier-verdict { color: var(--ink-soft); font-weight: 600; }

.result-footnote,
.result-note {
  color: var(--ink-soft);
  font-size: 0.85rem;
  margin-block: 0;
}

.capture {
  margin-block: 0;
  padding: var(--space-4);
  border: 1px solid var(--accent-edge);
  border-radius: var(--radius-md);
  background: var(--accent-soft);
  display: grid;
  gap: 0.5rem;
}

.capture h3 { margin-block: 0; color: var(--accent); }

.capture p { margin-block: 0 0.3rem; color: var(--ink-mid); }

.capture-label { font-size: 0.9rem; font-weight: 600; }

.capture-consent {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 0.9rem;
  color: var(--ink-mid);
}

.capture-check { min-block-size: 24px; min-inline-size: 24px; accent-color: var(--accent); }

.capture-button { margin-block-start: 0.3rem; }

.capture-error { color: var(--danger); font-size: 0.9rem; }

/* Not a person's field: off-screen without display:none, which some autofill
 * implementations ignore. */
.capture-trap {
  position: absolute;
  inset-inline-start: -9999px;
  block-size: 1px;
  overflow: hidden;
}

.capture-sent { font-weight: 600; }

.checkout-state,
.unsubscribe-state { margin-block: 0; font-weight: 600; }

.test-loading,
.test-error { color: var(--ink-soft); }

/* ── The price block ─────────────────────────────────────────────────────────
 *
 * The numbers in it are the server's; this only arranges them. The
 * struck-through list price is a <s>, which carries the meaning to a screen
 * reader as well as to the eye — a line drawn with a border would say nothing
 * to either.
 */

.price-block {
  display: grid;
  gap: 0.4rem;
  max-inline-size: 30rem;
}

.price-list { color: var(--ink-soft); margin-block: 0; }

.price-now {
  margin-block: 0;
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 6vw, 3rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
  color: var(--accent);
}

.price-terms { font-weight: 600; margin-block: 0; }

.price-discount {
  margin-block: 0.3rem 0;
  padding-inline: 0.75rem;
  padding-block: 0.5rem;
  border-radius: var(--radius-sm);
  background: var(--highlight-soft);
  color: var(--highlight-ink);
  font-weight: 600;
}

.price-note { color: var(--ink-soft); font-size: 0.92rem; margin-block: 0; }

.price-closed {
  margin-block: 0.3rem 0;
  padding-inline: 0.75rem;
  padding-block: 0.5rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--wash-sunken);
  color: var(--ink-soft);
  font-weight: 600;
}

/* ── The study route ─────────────────────────────────────────────────────────
 *
 * ONE ROUTE, NOT A CATALOGUE. This surface has exactly one thing to press, and
 * the three numbers that decide whether pressing it is enough — days to the
 * exam, the streak, and the predicted score — sit above it, always, on every
 * visit. A learner who cannot see whether their pace gets them there is a
 * learner guessing.
 */

.study-route { display: grid; gap: var(--space-4); }

.route-stats {
  display: grid;
  gap: var(--space-3);
  margin-block: 0;
  padding-inline-start: 0;
  list-style: none;
}

.stat {
  display: grid;
  gap: 0.15rem;
  padding: var(--space-3);
  border-radius: var(--radius-md);
}

.stat-value {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 4vw, 2rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--accent);
}

.stat-label { color: var(--ink-soft); font-size: 0.88rem; }

.stat-note { color: var(--ink-soft); font-size: 0.8rem; }

.stat.pace-behind .stat-value { color: var(--danger); }
.stat.pace-ahead .stat-value { color: var(--success); }
.stat.unknown .stat-value { color: var(--ink-soft); font-size: 1.15rem; letter-spacing: 0; }

/* TODAY'S SESSION. The one highlighted surface in the product. */
.today-card {
  display: grid;
  gap: var(--space-3);
  border-color: var(--accent-edge);
  box-shadow: var(--shadow-lift);
}

.today-card.mock { border-color: color-mix(in srgb, var(--highlight) 70%, transparent); }

.today-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  justify-content: space-between;
}

.today-card h2 { margin-block: 0; }

.today-card p { margin-block: 0; color: var(--ink-mid); }

.today-plan {
  display: grid;
  gap: 0.4rem;
  margin-block: 0;
  padding-inline-start: 0;
  list-style: none;
}

.today-plan li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  padding-inline: 0.75rem;
  padding-block: 0.55rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--wash);
  font-size: 0.92rem;
}

.today-plan .tag { font-size: 0.72rem; }

.today-plan .reason { color: var(--ink-soft); }

.session-done {
  display: grid;
  gap: 0.35rem;
  padding: var(--space-3);
  border: 1px solid color-mix(in srgb, var(--success) 28%, transparent);
  border-radius: var(--radius-md);
  background: var(--success-soft);
  color: var(--success);
  font-weight: 600;
}

/* The subskill readout. It is the reason the route bends the way it does, so it
 * is shown rather than described. */
.subskill-panel { display: grid; gap: var(--space-3); }

.subskill-list {
  display: grid;
  gap: 0.65rem;
  margin-block: 0;
  padding-inline-start: 0;
  list-style: none;
}

.subskill-row { display: grid; gap: 0.3rem; }

.subskill-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: space-between;
  font-size: 0.92rem;
}

.subskill-name { font-weight: 600; }

.subskill-score { color: var(--ink-soft); }

.subskill-row.weakest .subskill-name { color: var(--accent); }

.subskill-row.weakest .meter-fill { background: var(--highlight); }

.subskill-row.thin .subskill-score { font-style: italic; }

/* ── The session ─────────────────────────────────────────────────────────────
 *
 * SESSIONS OF ABOUT TEN MINUTES THAT END, and finishing is the reward. The
 * meter runs to a real end, the card animates in so progress is felt, and the
 * completion state is a full panel rather than a toast — the moment the work is
 * done is the moment worth designing.
 */

.session { display: grid; gap: var(--space-4); }

.session-topline {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-3);
  align-items: center;
  font-weight: 600;
  font-size: 0.92rem;
}

.session-topline .meter-track { block-size: 0.6rem; }

.session-card {
  display: grid;
  gap: var(--space-3);
  animation: card-enter 240ms cubic-bezier(.2, .8, .2, 1) both;
}

@keyframes card-enter {
  from { opacity: 0; transform: translateY(0.5rem); }
  to { opacity: 1; transform: translateY(0); }
}

.session-feedback {
  padding: var(--space-3);
  border-radius: var(--radius-md);
  font-weight: 600;
}

.session-feedback.good { background: var(--success-soft); color: var(--success); }

.session-feedback.bad { background: var(--danger-soft); color: var(--danger); }

.session-feedback .why { display: block; margin-block-start: 0.3rem; font-weight: 400; color: var(--ink-mid); }

.session-final {
  display: grid;
  gap: var(--space-4);
  padding: clamp(1.4rem, 5vw, 2.6rem);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  background: radial-gradient(circle at 12% 8%, var(--accent-soft), transparent 18rem), var(--paper);
  box-shadow: var(--shadow-panel);
}

.session-final h2 {
  font-size: clamp(1.8rem, 4vw, 2.4rem);
  letter-spacing: -0.035em;
}

.final-stats {
  display: grid;
  gap: var(--space-3);
  margin-block: 0;
  padding-inline-start: 0;
  list-style: none;
}

.final-stats li {
  display: grid;
  gap: 0.15rem;
  padding: var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: var(--paper);
}

.final-stats strong {
  font-family: var(--font-display);
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  color: var(--accent);
}

.final-stats span { color: var(--ink-soft); font-size: 0.88rem; }

.streak-flame {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding-inline: 0.7rem;
  padding-block: 0.35rem;
  border-radius: 999px;
  background: var(--highlight-soft);
  color: var(--highlight-ink);
  font-weight: 600;
}

.exam-date-form {
  display: grid;
  gap: 0.7rem;
  align-items: end;
}

.exam-date-form .action { align-self: start; }

.plan-note { margin-block: 0; color: var(--ink-soft); font-size: 0.9rem; }

/* ── States: motion, hover, focus ────────────────────────────────────────────
 *
 * One curve for everything that moves. A card lifts 2px and takes the visible
 * edge colour; a button dips 1px when pressed. Focus is a 3px ring in the
 * chrome blue with a white halo, so it survives on the page AND on the hero.
 */

a,
button,
.action,
.card,
.option,
.faq-list details,
.today-card,
.stat { transition: transform var(--motion), box-shadow var(--motion), border-color var(--motion), background-color var(--motion), color var(--motion); }

.card:hover,
.option:hover {
  transform: translateY(-2px);
  border-color: var(--accent-edge);
  box-shadow: var(--shadow-lift);
}

.action:active,
button:active { transform: translateY(1px); }

:where(a, button, input, select, summary):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--paper) 90%, transparent);
}

.hero :where(a, button):focus-visible { outline-color: var(--paper); }

:where(a, button, select, summary) { min-block-size: var(--tap); }

input[type="checkbox"], input[type="radio"] { min-block-size: auto; }

.nav-links a,
.footer-links a,
.brand,
.status-pill,
.tag { min-block-size: auto; }

.nav-links a,
.footer-links a { min-block-size: var(--tap); }

/* ── Responsive ──────────────────────────────────────────────────────────────
 *
 * Phone first in behaviour: the menu collapses into a floating panel, the hero
 * card is dropped rather than squashed, every action goes full width, and the
 * spacing scale tightens through the same tokens rather than a second set of
 * numbers.
 */

@media (min-width: 48rem) {
  .hero-grid { grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.72fr); }
  .proof-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fact-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .card-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .card-grid.pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .route-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .final-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .exam-date-form { grid-template-columns: 1fr auto; }
}

@media (max-width: 47.99rem) {
  .menu-toggle { display: inline-flex; }
  .nav-links {
    display: none;
    position: absolute;
    inset-inline: var(--space-3);
    inset-block-start: 3.6rem;
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-3);
    border: 1px solid var(--line);
    border-radius: var(--radius-lg);
    background: var(--paper);
    box-shadow: var(--shadow-panel);
    z-index: 12;
  }
  .nav-links.open { display: grid; gap: var(--space-1); }
  .hero-card { display: none; }
  .cta-row,
  .hero-actions { display: grid; grid-template-columns: 1fr; }
  .session-topline { grid-template-columns: auto 1fr; }
  .session-topline .session-remaining { grid-column: 1 / -1; }
  #page { padding-inline: var(--space-3); gap: var(--space-4); }
  .topbar { padding-inline: var(--space-3); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .card:hover,
  .option:hover,
  .action:active { transform: none !important; }
}
