/* ------------------------------------------------------------------ *
 * RightWrite, marketing.
 *
 * Modernist: flat, square, 2px rules, no soft edges. The one exception
 * is the suggestion card, which is Warm Paper (white, radius 12, soft
 * shadow) because it is a piece of the PRODUCT sitting on the BRAND,
 * and that is the only place the two systems are supposed to meet.
 *
 * Every value here traces to src/shared/palette.ts and
 * src/shared/tokens.ts. Never invent a hex; if a color is missing from
 * the token module, that is a conversation with the designer, not a
 * literal in this file.
 *
 * Light only, on purpose. The brand ground is a light stock and a dark
 * variant would be a second brand, not a setting.
 *
 * The ground is Graph: BRAND.ground with a 26px grid at 5.5% ink over it.
 * Chosen from six candidates by drawing all five of the product's marks on
 * each and keeping the one where every mark still read. The grid is faint
 * enough to be texture rather than pattern; if it ever competes with a
 * squiggle, the grid loses.
 * ------------------------------------------------------------------ */

:root {
  /* CATEGORY, from tokens.ts. Not tuned per ground: if a mark stops
   * reading on a ground, the ground is wrong. */
  --spelling: #ec3013;
  --grammar: #3c62a8;
  --grammar-text: #2f4e86;
  --punctuation: #6b5f55;
  --forbidden: #b8860b;
  --forbidden-text: #8a6d10;
  --forbidden-tint: #fbf1d8;

  /* BRAND, from palette.ts */
  --accent: #ec3013;
  --accent-hover: #dd2b0f;
  --accent-pressed: #ae1800;

  --chrome: "Figtree", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --prose: "Newsreader", Georgia, "Times New Roman", serif;
  --mark: "Archivo", ui-sans-serif, system-ui, sans-serif;

  /* One spring and one glide, used everywhere. Nothing pops. */
  --spring: cubic-bezier(0.34, 1.4, 0.5, 1);
  --glide: cubic-bezier(0.22, 1, 0.36, 1);

  --gap: clamp(20px, 5vw, 64px);
  --measure: 1180px;

  /* Graph. --ground is BRAND.ground from src/shared/palette.ts. */
  --ground: #f5f5f1;
  --ground-alt: #ecece7;
  --ink: #201e1d;
  --ink-soft: #625b54;
  --ink-faint: #9a938c;
  --rule: #201e1d;
  --rule-soft: #dbd9d3;
  --grid: rgba(32,30,29,0.055);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background-color: var(--ground);
  background-image:
    repeating-linear-gradient(to right, var(--grid) 0 1px, transparent 1px 26px),
    repeating-linear-gradient(to bottom, var(--grid) 0 1px, transparent 1px 26px);
  color: var(--ink);
  font-family: var(--chrome);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.wrap { width: 100%; max-width: var(--measure); margin: 0 auto; padding: 0 var(--gap); }
.center { text-align: center; display: flex; flex-direction: column; align-items: center; gap: 22px; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 60;
  background: var(--ink); color: var(--ground);
  padding: 10px 16px; font-size: 13px; font-weight: 600;
}
.skip:focus { left: 0; }

/* ---------------- Header ---------------- */
.site {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 14px var(--gap);
  background-color: var(--ground);
  border-bottom: 2px solid var(--rule);
}
.brand { display: flex; align-items: baseline; gap: 12px; text-decoration: none; }
.wordmark {
  font-family: var(--mark); font-weight: 800; font-size: 20px;
  letter-spacing: -0.024em; color: var(--ink);
}
.wordmark .w2 { color: var(--accent); }
.tagline {
  font-family: var(--prose); font-style: italic; font-size: 15px;
  color: var(--ink-faint);
}
.nav { margin-left: auto; display: flex; align-items: center; gap: 8px 22px; flex-wrap: wrap; }
.nav-link {
  font-size: 13.5px; font-weight: 500; color: var(--ink-soft);
  text-decoration: none; transition: color 160ms var(--glide);
}
.nav-link:hover { color: var(--ink); }

/* ---------------- Buttons ---------------- */
.btn {
  display: inline-block;
  font-family: var(--chrome); font-weight: 600;
  text-decoration: none; cursor: pointer;
  border: 2px solid transparent; border-radius: 0;
  transition: background 150ms var(--glide), color 150ms var(--glide),
              transform 150ms var(--spring), border-color 150ms var(--glide);
}
.btn:active { transform: scale(0.975); }
.btn-accent { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-accent:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-quiet { background: transparent; color: var(--ink); border-color: var(--rule); }
.btn-quiet:hover { background: var(--ink); color: var(--ground); }
.btn-sm { font-size: 13px; padding: 7px 14px; }
.btn-md { font-size: 14.5px; padding: 11px 18px; width: 100%; text-align: center; }
.btn-lg { font-size: 17px; padding: 15px 30px; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.ghost-btn {
  appearance: none; background: none; border: 0;
  border-bottom: 1.5px solid var(--rule-soft);
  padding: 2px 0; font-family: var(--chrome); font-size: 12.5px;
  font-weight: 600; color: var(--ink-faint); cursor: pointer;
  transition: color 160ms var(--glide), border-color 160ms var(--glide);
}
.ghost-btn:hover { color: var(--accent); border-color: var(--accent); }
.ghost-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ---------------- Hero ---------------- *
 * A full-viewport hero is usually a mistake. Here it is the brief:
 * above the fold is the demo and nothing else, so the fold is the
 * frame. svh, not vh, so a phone's collapsing toolbar does not crop it. */
.hero {
  position: relative;
  min-height: calc(100svh - 62px);
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(30px, 6vh, 70px) var(--gap) 88px;
}
.hero-inner {
  width: 100%; max-width: 940px; margin: 0 auto;
  position: relative;
}
/* The label and the replay control share a line, so the one thing that
 * restarts the demo sits next to the thing that says where the demo is,
 * rather than in the footer row with the keyboard hint. */
.stagerow {
  display: flex; align-items: center; gap: 11px;
  margin: 0 0 22px; min-height: 1.6em;
}
.stagelabel {
  font-size: 11px; letter-spacing: 0.15em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint);
  margin: 0;
  transition: color 300ms var(--glide);
}
.stagelabel.live { color: var(--accent); }

/* Hidden until the demo hands over: there is nothing to replay before then,
 * and a control that does nothing is worse than no control. */
.replay {
  appearance: none; background: none; border: 0; padding: 3px;
  display: inline-flex; color: var(--ink-faint); cursor: pointer;
  opacity: 0; pointer-events: none;
  transition: opacity 320ms var(--glide), color 160ms var(--glide),
              transform 420ms var(--spring);
}
.replay.up { opacity: 1; pointer-events: auto; }
.replay:hover { color: var(--accent); }
.replay:active { transform: rotate(-40deg); }
.replay:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.handoff {
  margin-top: 34px;
  display: flex; align-items: center; gap: 14px 26px; flex-wrap: wrap;
  opacity: 0; transform: translateY(6px);
  transition: opacity 440ms var(--glide), transform 500ms var(--glide);
}
.handoff.up { opacity: 1; transform: none; }

.tally {
  display: flex; align-items: center; gap: 16px;
  font-size: 11.5px; letter-spacing: 0.07em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint);
}
.tally .dot {
  display: inline-block; width: 7px; height: 7px; margin-right: 6px;
  vertical-align: 1px; transition: transform 320ms var(--spring);
}
.tally .n { font-variant-numeric: tabular-nums; color: var(--ink); }
.tally .bump { transform: scale(1.6); }
.d-spelling { background: var(--spelling); }
.d-grammar { background: var(--grammar); }
.d-punctuation { background: var(--punctuation); }
.d-forbidden { background: var(--forbidden); }

.shortcut { font-size: 11.5px; color: var(--ink-faint); margin-right: auto; }
.shortcut kbd {
  font-family: var(--chrome); font-size: 10.5px; font-weight: 600;
  border: 1px solid var(--rule-soft); border-radius: 3px;
  padding: 2px 5px 1px; margin-right: 3px; color: var(--ink-soft);
}

/* A chevron, not a hairline.
 *
 * This was a 1px rule pulsing on scaleY, which was meant to read as an arrow
 * and read as a faint scratch instead: at one pixel wide there is no shape to
 * recognize, and the animation made it flicker rather than point. A chevron
 * that bobs downward says the one thing this control is for. */
.scroll-cue {
  position: absolute; left: 50%; bottom: 20px;
  padding: 10px 16px;
  display: block; line-height: 0;
  color: var(--ink-faint);
  transition: color 180ms var(--glide);
  animation: cue 2.2s var(--glide) infinite;
}
.scroll-cue:hover { color: var(--accent); }
.scroll-cue:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The centering translate lives in the keyframes too, or the animation
 * overwrites it and the arrow jumps to the left edge. */
@keyframes cue {
  0%, 100% { transform: translate(-50%, 0); opacity: 0.5; }
  50%      { transform: translate(-50%, 7px); opacity: 1; }
}

/* ---------------- The editor ---------------- *
 * A transparent textarea over a backdrop that paints only the
 * underlines. Typing stays native, so the caret, selection, spell
 * menu and undo all behave, and the marks reflow because they are
 * real inline elements in the same box with the same metrics. */
.editor {
  position: relative; cursor: text;
  font-family: var(--prose);
  font-size: clamp(22px, 3.1vw, 36px);
  line-height: 1.55; font-weight: 300;
  /* Room for the rule, INSIDE the box. It used to hang 18px below on a
   * negative offset, which put the one thing that reads as "field" outside
   * the field: elementFromPoint on the rule returned .hero-inner, so
   * clicking the line a visitor was aiming at did nothing at all. */
  padding-bottom: 18px;
}
/* The min-height belongs to the textarea, not its container. On .editor it
 * left the textarea sized to its content and the rest of the box dead: a
 * 33px strip that looked like the field and was not.
 *
 * Two lines, which is what the box actually holds once the demo has run and
 * handed over: the corrected sentence, then the blank line the caret waits on.
 * At 4.6em it was a line and a half taller than that, so the rule underneath
 * floated 40px below the last word and read as a gap rather than an edge.
 * Two lines is also the height while the demo types, so nothing jumps. */
.editor textarea { min-height: 3.1em; }
.editor.small textarea { min-height: 5em; }

/* The box only looks like a field once it is the visitor's.
 *
 * A border around it from the first frame would make the hero a form, and
 * the opening shot is supposed to be a page of text that starts writing
 * itself. But the moment the performance ends, nothing on screen said the
 * text was editable: a caret sitting at the end of a finished sentence
 * reads as "done", not "your turn". So the rule draws in exactly then,
 * and pulses until the first keystroke answers it. */
.editor::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 560ms var(--glide);
}
.editor.live::after { transform: scaleX(1); }
.editor.live:not(.typed)::after {
  animation: fieldPulse 2.4s var(--glide) 760ms infinite;
}
@keyframes fieldPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.28; }
}

/* The invitation, on its own empty line under the corrected sentence.
 * An empty line with a blinking caret in it is the one thing everybody
 * already knows how to read. */
.ghost {
  color: var(--ink-faint);
  font-style: italic;
  animation: ghostIn 500ms var(--glide) both;
}
@keyframes ghostIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.editor.small {
  font-size: clamp(16px, 1.9vw, 21px);
  padding: 18px 18px 24px;
}
.editor .backdrop,
.editor textarea {
  margin: 0; border: 0; padding: 0;
  font-family: inherit; font-size: inherit; line-height: inherit;
  font-weight: inherit; letter-spacing: inherit;
  white-space: pre-wrap; overflow-wrap: break-word;
}
.editor.small .backdrop, .editor.small textarea { padding: 0; }
.editor .backdrop {
  position: absolute; inset: 0;
  color: transparent; pointer-events: none; user-select: none;
}
.editor.small .backdrop { inset: 18px 18px 24px; }
.editor textarea {
  position: relative; display: block; width: 100%;
  background: transparent; color: var(--ink);
  caret-color: var(--accent); resize: none; overflow: hidden;
}
.editor.live textarea { caret-color: var(--accent); }
.editor textarea:focus { outline: none; }
.editor textarea::placeholder { color: var(--ink-faint); opacity: 1; }

/* Marks.
 *
 * Only the parts that are the landing page's own concern live here. Every
 * colour, line style, thickness and offset is generated by markCss() in
 * landing/vendor-src/checker.ts from the same CATEGORY table paint.ts reads,
 * and injected at load. Writing them here by hand is what put a wavy red
 * underline on this page months after the product had moved to a solid one. */
.mk { }

/* The draw-in is a mask wipe, applied only while it runs, so nothing
 * carries a mask at rest. */
.mk.fresh {
  -webkit-mask-image: linear-gradient(to right, #000, #000);
  mask-image: linear-gradient(to right, #000, #000);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  animation: draw 280ms var(--glide) both;
}
@keyframes draw {
  from { -webkit-mask-size: 0% 100%; mask-size: 0% 100%; }
  to   { -webkit-mask-size: 100% 100%; mask-size: 100% 100%; }
}

/* The heal. Every fix in a sentence lands in one write; the wash
 * sweeps across them in reading order so the eye can follow what
 * changed. The blue is the product's new-text color. */
.healed { animation: heal 700ms var(--glide) both; }
@keyframes heal {
  0%   { background-color: rgba(60,98,168,0.26); }
  70%  { background-color: rgba(60,98,168,0.15); }
  100% { background-color: rgba(60,98,168,0); }
}

/* The suggestion card: Warm Paper, the product system, on the brand. */
.card {
  position: absolute; z-index: 8;
  min-width: 300px; max-width: 440px;
  background: #ffffff;
  border: 1px solid rgba(45,38,32,0.13);
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(60,40,30,0.1), 0 14px 38px rgba(60,40,30,0.15);
  padding: 14px 16px 13px;
  font-family: var(--chrome);
  opacity: 0; transform: translateY(7px) scale(0.975);
  transform-origin: top left;
  transition: opacity 180ms var(--glide), transform 320ms var(--spring);
  pointer-events: none;
}
.card.up { opacity: 1; transform: none; pointer-events: auto; }
.card .kinds { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 11px; }
.card .kind {
  font-size: 9.5px; letter-spacing: 0.11em; text-transform: uppercase;
  font-weight: 700; padding: 3px 7px 2px;
  border: 1px solid currentColor; border-radius: 3px;
}
.kind-spelling { color: var(--spelling); }
.kind-grammar { color: var(--grammar-text); }
.kind-punctuation { color: var(--punctuation); }
.kind-forbidden { color: var(--forbidden-text); }
.card .swap {
  font-family: var(--prose); font-size: 16px; line-height: 1.65;
  margin-bottom: 13px; color: #201e1d;
}
.card .was { color: #b09a8c; text-decoration: line-through; text-decoration-thickness: 1px; }
.card .now { color: var(--grammar); font-weight: 500; }
.card .why {
  font-size: 12.5px; line-height: 1.45; color: #635d57;
  margin: 0 0 12px;
}
.card .row { display: flex; gap: 8px; }
.card .btn {
  border-radius: 8px; font-size: 12.5px; padding: 8px 14px;
}
.card .btn-keep { background: transparent; color: #635d57; border-color: rgba(45,38,32,0.16); }
.card .btn-keep:hover { background: transparent; color: #201e1d; }
.btn.pressed { transform: scale(0.94); background: var(--accent-pressed); border-color: var(--accent-pressed); }

/* ---------------- Bands ---------------- */
.band {
  padding: clamp(56px, 9vh, 108px) 0;
  border-top: 2px solid var(--rule);
}
.band.alt { background: var(--ground-alt); }

.display {
  font-family: var(--prose);
  font-weight: 400;
  font-size: clamp(30px, 4.4vw, 54px);
  line-height: 1.1;
  letter-spacing: -0.026em;
  margin: 0 0 30px;
  max-width: 19ch;
  text-wrap: balance;
}
.display.big { max-width: none; font-size: clamp(46px, 9vw, 108px); margin-bottom: 8px; }
/* A headline that reads as one sentence and should sit on one line. The 19ch
 * measure is right for a headline the eye reads as a block; it is wrong for a
 * line naming the product, which breaks in the middle of its own name.
 * Not nowrap: a phone still has to be allowed to wrap it. */
.display.full { max-width: none; }
/* The product name inside running text, so it carries the mark's own split. */
.display .w2 { color: var(--accent); }
.center .display { max-width: none; }
.lede {
  font-size: clamp(16px, 1.5vw, 18.5px);
  line-height: 1.65; max-width: 54ch; margin: 0 0 16px;
}
.lede.muted { color: var(--ink-soft); font-size: 15.5px; }
.two-up {
  display: grid; grid-template-columns: minmax(300px, 1fr) minmax(280px, 0.85fr);
  gap: clamp(30px, 5vw, 70px); align-items: center;
}

/* ---------------- Everywhere ---------------- */
.places { display: flex; flex-wrap: wrap; border-bottom: 2px solid var(--rule); }
.place {
  appearance: none; background: none; border: 0;
  padding: 10px 16px 11px;
  font-family: var(--chrome); font-size: 13px; font-weight: 600;
  color: var(--ink-faint); cursor: pointer; position: relative;
  transition: color 200ms var(--glide);
}
.place:hover { color: var(--ink-soft); }
.place[aria-selected="true"] { color: var(--ink); }
.place::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -2px;
  height: 2px; background: var(--accent);
  transform: scaleX(0); transition: transform 340ms var(--glide);
}
.place[aria-selected="true"]::after { transform: scaleX(1); }
.place:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }
/* The box wears the app; the underline stays ours.
 *
 * Color and corner only, no logos and no wordmarks. Two trademarks in a row
 * would read as a wall of endorsements nobody gave us, and the argument this
 * section is making does not need them: it is that the composer belongs to
 * somebody else and the checker still shows up in it. */
.fauxbox {
  --app-accent: var(--accent);
  --app-radius: 0px;
  border: 2px solid var(--rule);
  border-top: 0;
  background: var(--ground);
  border-radius: 0 0 var(--app-radius) var(--app-radius);
  transition: border-radius 420ms var(--glide);
}
.fauxhead {
  display: flex; align-items: center; gap: 10px; min-height: 42px;
  padding: 11px 18px; border-bottom: 1px solid var(--rule-soft);
}
/* Stands in for whatever mark the app puts here, without being one. */
.fauxdot {
  width: 9px; height: 9px; flex: 0 0 auto;
  background: var(--app-accent);
  border-radius: var(--app-radius);
  transition: background 420ms var(--glide), border-radius 420ms var(--glide);
}
.field { font-size: 12.5px; font-weight: 500; color: var(--ink-faint); transition: opacity 200ms var(--glide); }

.fauxfoot {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 12px 18px 14px;
  border-top: 1px solid var(--rule-soft);
}
/* Not a button: nothing here sends anything, and a control that looks live
 * and does nothing is worse than a label. */
.fauxsend {
  font-size: 12.5px; font-weight: 600; color: #fff;
  background: var(--app-accent);
  padding: 7px 15px;
  border-radius: var(--app-radius);
  transition: background 420ms var(--glide), border-radius 420ms var(--glide),
              opacity 200ms var(--glide);
}
.fauxhint { font-size: 11.5px; color: var(--ink-faint); }

/* ---------------- Feature cards ---------------- *
 * A tinted panel holding a real sentence and the real card that sentence
 * produces, with the title underneath. The tint is the category's own colour
 * from CATEGORY in tokens.ts at low alpha, so the four grounds are a legend
 * rather than decoration: the wash a card sits on is the colour of the
 * underline inside it. */
.showcase-rail { position: relative; }
.showcase {
  display: grid;
  grid-auto-flow: column;
  /* Three across, with the fourth showing its edge. A row that fits exactly
   * looks finished, and nobody scrolls a thing that looks finished. */
  grid-auto-columns: calc((100% - 62px) / 3);
  gap: 0;
  border: 2px solid var(--rule);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
}
.showcase::-webkit-scrollbar { display: none; }
.shot-card { scroll-snap-align: start; }

/* The affordance, in the product's own shape: square, 2px, no radius.
 * Each side appears only when there is something that way to reach. */
.showcase-step {
  position: absolute; top: 50%;
  transform: translateY(-50%);
  width: 36px; height: 36px;
  display: grid; place-items: center;
  background: var(--ground); color: var(--ink);
  border: 2px solid var(--rule);
  cursor: pointer;
  transition: background 160ms var(--glide), color 160ms var(--glide),
              opacity 200ms var(--glide);
  z-index: 3;
}
.showcase-prev { left: -18px; }
.showcase-next { right: -18px; }
.showcase-step:hover { background: var(--ink); color: var(--ground); }
.showcase-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.showcase-step[hidden] { display: none; }
.shot-card {
  margin: 0;
  border-right: 2px solid var(--rule);
  display: flex; flex-direction: column;
  background: var(--ground);
}
.shot-card:last-child { border-right: 0; }

.shot {
  position: relative;
  padding: 22px 20px 26px;
  min-height: 232px;
  border-bottom: 1px solid var(--rule-soft);
  background: var(--tint);
  overflow: hidden;
}
.shot-card[data-kind="spelling"]    { --tint: rgba(236, 48, 19, 0.07); }
.shot-card[data-kind="grammar"]     { --tint: rgba(60, 98, 168, 0.08); }
.shot-card[data-kind="punctuation"] { --tint: rgba(107, 95, 85, 0.09); }
.shot-card[data-kind="forbidden"]   { --tint: rgba(184, 134, 11, 0.11); }

.shot-text {
  font-family: var(--prose);
  font-size: 16px; line-height: 1.5; font-weight: 300;
  color: var(--ink);
  margin: 0 0 16px;
}

/* The product's card, standing still. It is absolutely positioned and hidden
 * in the live editors; here it is simply part of the layout. */
.shot .card.shot-card-popup {
  position: static;
  opacity: 1; transform: none; pointer-events: none;
  min-width: 0; max-width: none;
  box-shadow: 0 1px 3px rgba(60,40,30,0.10), 0 10px 26px rgba(60,40,30,0.13);
}
.shot .card .swap { font-size: 14.5px; line-height: 1.5; margin-bottom: 10px; }
.shot .card .why { font-size: 11.5px; margin-bottom: 11px; }
.shot .card .btn { font-size: 11.5px; padding: 6px 11px; }

.shot-caption { padding: 18px 20px 22px; }
.shot-caption h3 {
  font-family: var(--chrome);
  font-size: 15.5px; font-weight: 700; letter-spacing: -0.005em;
  margin: 0 0 6px; color: var(--ink);
}
.shot-caption p { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }

@media (max-width: 900px) {
  .shot-card { border-right: 0; border-bottom: 2px solid var(--rule); }
  .shot-card:last-child { border-bottom: 0; }
}

/* ---------------- Privacy claims ---------------- *
 * This was a boxes-and-wires diagram, then an animated one, and both were
 * answering a question nobody asked. The claim is one sentence long and does
 * not need a mechanism drawn for it. Four flat statements, each true, each
 * checkable, is the whole section. */
.lede-link {
  font-size: clamp(16px, 1.5vw, 18.5px);
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1.5px solid var(--accent);
  padding-bottom: 1px;
  transition: color 160ms var(--glide), border-color 160ms var(--glide);
}
.lede-link::after { content: " \2192"; }
.lede-link:hover { color: var(--ink); border-color: var(--ink); }
.lede-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.claims { list-style: none; margin: 0; padding: 0; border-top: 2px solid var(--rule); }
.claims li {
  display: flex; align-items: baseline; gap: 13px;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule-soft);
  font-size: clamp(15px, 1.5vw, 17.5px);
  line-height: 1.4;
  color: var(--ink);
}
.claims li::before {
  content: "";
  flex: 0 0 auto;
  width: 9px; height: 9px;
  background: var(--accent);
  transform: translateY(-1px);
}

/* ---------------- Quiz ---------------- */
.questions { list-style: none; margin: 0 0 26px; padding: 0; display: flex; flex-direction: column; }
.q {
  display: flex; align-items: center; gap: 18px 24px; flex-wrap: wrap;
  padding: 20px 0; border-top: 1px solid var(--rule-soft);
}
.q:last-child { border-bottom: 1px solid var(--rule-soft); }
.q-text {
  font-family: var(--prose); font-size: clamp(19px, 2.3vw, 27px);
  line-height: 1.3; flex: 1 1 300px; margin: 0;
}
.q-answers { display: flex; gap: 8px; }
.q-btn {
  appearance: none; cursor: pointer;
  font-family: var(--chrome); font-size: 14px; font-weight: 600;
  padding: 9px 24px;
  background: transparent; color: var(--ink-soft);
  border: 2px solid var(--rule-soft); border-radius: 0;
  transition: background 160ms var(--glide), color 160ms var(--glide),
              border-color 160ms var(--glide), transform 160ms var(--spring);
}
.q-btn:hover { border-color: var(--rule); color: var(--ink); }
.q-btn:active { transform: scale(0.96); }
.q-btn[aria-pressed="true"] { background: var(--ink); color: var(--ground); border-color: var(--ink); }
.q-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.quiz-out { font-size: 14px; color: var(--ink-soft); margin: 0; min-height: 1.5em; }
.quiz-out strong { color: var(--ink); }

/* ---------------- Plans ---------------- */
.plans {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 0; border: 2px solid var(--rule);
}
.plan {
  padding: 26px 24px 26px;
  border-right: 2px solid var(--rule);
  background: var(--ground);
  display: flex; flex-direction: column; gap: 16px;
  position: relative;
  transition: background 300ms var(--glide), transform 420ms var(--spring);
}
.plan:last-child { border-right: 0; }
.plan.picked { background: var(--ground); z-index: 2; }
.plan.picked::before {
  content: ""; position: absolute; inset: -2px;
  border: 2px solid var(--accent);
  pointer-events: none;
}
.plan-flag {
  position: absolute; top: -2px; right: -2px;
  background: var(--accent); color: #fff;
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;
  font-weight: 700; padding: 4px 9px 3px;
  opacity: 0; transform: translateY(-4px);
  transition: opacity 260ms var(--glide), transform 320ms var(--spring);
}
.plan.picked .plan-flag { opacity: 1; transform: none; }
.plan-name {
  font-family: var(--mark); font-weight: 700; font-size: 15px;
  letter-spacing: 0.02em; margin: 0;
}
.plan-price { font-family: var(--prose); font-size: 40px; line-height: 1; margin: 0; letter-spacing: -0.03em; }
.plan-price .per { font-family: var(--chrome); font-size: 12.5px; color: var(--ink-soft); letter-spacing: 0; }
.plan-feats { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; flex: 1 1 auto; }
.plan-feats li { font-size: 13.5px; line-height: 1.45; display: flex; gap: 10px; color: var(--ink); }
.plan-feats li.off { color: var(--ink-faint); }
.plan-feats .tick { flex: 0 0 auto; width: 11px; height: 11px; margin-top: 5px; position: relative; }
.plan-feats li:not(.off) .tick { background: var(--accent); }
.plan-feats li.off .tick { border: 1px solid var(--rule-soft); }
.plan-note { font-size: 11.5px; color: var(--ink-faint); margin: 0; }
.fineprint { font-size: 12.5px; color: var(--ink-soft); max-width: 66ch; margin: 22px 0 0; }
.fineprint.center-text { text-align: center; margin-left: auto; margin-right: auto; }

/* ---------------- Install ---------------- */
.install .display.big { margin-bottom: 14px; }
.selfword {
  cursor: pointer; position: relative;
  /* Solid, because CATEGORY.spelling.line is solid. Thicker and further off
   * the baseline than the product's 2px/4px only because this word is set at
   * eight times the size; the shape is the same mark. */
  text-decoration-line: underline; text-decoration-style: solid;
  text-decoration-color: var(--spelling); text-decoration-thickness: 5px;
  text-underline-offset: 0.12em;
  -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none;
}
.selfword.accepted { text-decoration-line: none; }
.selfword:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

/* ---------------- Footer ---------------- */
.site-foot { border-top: 2px solid var(--rule); padding: 34px 0 46px; }
.foot-grid { display: flex; justify-content: space-between; gap: 24px 40px; flex-wrap: wrap; }
.foot-note { font-size: 13px; color: var(--ink-soft); margin: 8px 0 0; max-width: 40ch; }
.site-foot nav { display: flex; gap: 22px; flex-wrap: wrap; align-items: flex-start; }
.site-foot nav a { font-size: 13.5px; color: var(--ink-soft); text-decoration: none; }
.site-foot nav a:hover { color: var(--accent); }

/* ---------------- Reveal ---------------- *
 * Added by script only, so with no JS every section is simply visible.
 * The resting state is visible; this animates from a small offset, it
 * does not park content at zero. */
.reveal { opacity: 0; transform: translateY(14px); }
.reveal.shown { opacity: 1; transform: none; transition: opacity 600ms var(--glide), transform 700ms var(--glide); }


@media (max-width: 820px) {
  .two-up { grid-template-columns: 1fr; }
  .plan { border-right: 0; border-bottom: 2px solid var(--rule); }
  .plan:last-child { border-bottom: 0; }
  .tagline { display: none; }
  .shortcut { margin-right: 0; }
  .hero { min-height: auto; padding-bottom: 70px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
