/* The landing page at pageweaver.studio (`docs/LANDING-PAGE-SPEC.md`).
   Copied to `site/public/static/site.css` by `scripts/landing/site.tsx`.

   L3: the app's look — Source Serif 4, navy ink #2B3A52, a light paper
   ground, and the app's own pencil thread lines between sections. The tokens
   are the app's (`src/styles/global.css`); `landingSite.test.ts` holds the
   ones repeated here to it. THREAD COLOURS ARE FOR THREADS: they appear in
   underlines and drawn lines only, never as a button's fill.

   NOTHING MOVES AFTER IT IS DRAWN (CLS 0). The faces are preloaded by each
   page's head and are `font-display: optional`: there for the first paint on
   any ordinary connection, and on a very slow one the page keeps the fallback
   for that visit rather than reflowing when they arrive. */

@font-face {
  font-family: 'Source Serif 4';
  font-weight: 400;
  font-style: normal;
  font-display: optional;
  src: url(/static/fonts/source-serif-4-400.woff2) format('woff2');
}
@font-face {
  font-family: 'Source Serif 4';
  font-weight: 400;
  font-style: italic;
  font-display: optional;
  src: url(/static/fonts/source-serif-4-400-italic.woff2) format('woff2');
}
@font-face {
  font-family: 'Source Serif 4';
  font-weight: 600;
  font-style: normal;
  font-display: optional;
  src: url(/static/fonts/source-serif-4-600.woff2) format('woff2');
}
@font-face {
  font-family: 'Source Serif 4';
  font-weight: 600;
  font-style: italic;
  font-display: optional;
  src: url(/static/fonts/source-serif-4-600-italic.woff2) format('woff2');
}

:root {
  --surface-page: #fcfbf8;
  --surface-chrome: #efede7;
  --surface-raised: #f6f5f0;
  --border: #d9d5cb;
  --border-strong: #b9b4a6;
  --ink: #2b3a52;
  --ink-muted: #5f5a4f;
  --accent: #33507a;
  --accent-strong: #274063;
  --font: 'Source Serif 4', Georgia, serif;
  --gutter: 24px;
  --width: 1120px;
}

* {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  background: var(--surface-chrome);
  color: var(--ink);
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.55;
  overflow-wrap: break-word;
}

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

a {
  color: var(--accent);
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--accent-strong);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
}

.skip:focus {
  left: var(--gutter);
  top: 8px;
  z-index: 10;
  background: var(--surface-page);
  padding: 0.4rem 0.8rem;
}

.wrap {
  max-width: var(--width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ── the drawn lines: the app's ThreadLine, rendered to static SVG ─────── */

svg[data-thread-variant] {
  display: block;
  width: 100%;
  overflow: visible;
}

.band {
  margin: 0 auto;
  max-width: var(--width);
  padding: 0 var(--gutter);
}

/* ── header ───────────────────────────────────────────────────────────── */

.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.5rem;
  flex-wrap: wrap;
  padding-top: 1.25rem;
  padding-bottom: 0.75rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 1.6rem;
  letter-spacing: 0.005em;
}

.brand img {
  width: 40px;
  height: 40px;
  border-radius: 9px;
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 1.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nav a {
  color: var(--ink);
  text-decoration: none;
  font-size: 1rem;
}

.site-nav a:hover {
  text-decoration: underline;
}

/* ── buttons ──────────────────────────────────────────────────────────── */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.55rem 1.1rem;
  border: 1px solid var(--ink);
  border-radius: 4px;
  font: inherit;
  font-size: 1rem;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
}

.button.primary {
  background: var(--ink);
  color: #fff;
}

.button.primary:hover {
  background: var(--accent-strong);
  color: #fff;
}

.button.secondary {
  background: transparent;
  color: var(--ink);
}

.button.secondary:hover {
  background: var(--surface-raised);
  color: var(--ink);
}

.site-nav .button {
  min-height: 40px;
  padding: 0.35rem 0.9rem;
}

.site-nav .button.primary,
.site-nav .button.primary:hover {
  color: #fff;
  text-decoration: none;
}

.button.soon {
  border-style: dashed;
  border-color: var(--border-strong);
  color: var(--ink-muted);
  background: transparent;
  cursor: default;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.5rem 0 0;
}

/* ── type ─────────────────────────────────────────────────────────────── */

h1,
h2,
h3 {
  font-weight: 600;
  line-height: 1.15;
  margin: 0;
}

h1 {
  font-size: clamp(2.2rem, 4.4vw, 3rem);
  letter-spacing: -0.01em;
}

h2 {
  font-size: clamp(1.7rem, 3.4vw, 2.3rem);
  letter-spacing: -0.005em;
}

h3 {
  font-size: 1.3rem;
}

.lede {
  font-size: 1.2rem;
  margin: 1.2rem 0 0;
  max-width: 34em;
}

.smallcaps {
  font-variant-caps: all-small-caps;
  letter-spacing: 0.1em;
  font-size: 1.05rem;
}

.muted {
  color: var(--ink-muted);
}

/* ── sections ─────────────────────────────────────────────────────────── */

section {
  scroll-margin-top: 1rem;
}

.section {
  padding: 3rem 0;
}

.columns {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 3rem;
  align-items: center;
}

.hero {
  padding: 2.5rem 0 3rem;
}

.hero .columns {
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  /* Top, not centred: a slow connection draws the hero before the rest of its
     figure has arrived, and centred text would move down as the figure grew. */
  align-items: start;
}

.hero .stance {
  margin: 1.6rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--border-strong);
  max-width: 26em;
}

.hero .stance p {
  margin: 0;
}

.hero .stance em {
  font-size: 1.2rem;
}

/* THE HERO PICTURE (LANDING-PAGE-SPEC L4, Sam's mockup): a small stack of
   pages, turned a little, the top one carrying lines of The Final Problem,
   quoted exactly, with every underline a thread tag the sample really carries,
   in that thread's colour, carried on past the page's edges as loose strands.

   ONE PICTURE AT EVERY WIDTH. The lines are broken in the markup, and the
   stack is sized in its own em, which is a fraction of the figure's width
   (a container query), so it scales as a whole and no line ever reflows.

   ONE MEASURE FOR EVERY THREAD. The underline under a tagged run, its tail to
   the page's edge and the loose strand outside are all placed by `--ul-y`
   from the TOP OF THE LINE: a tagged run is an inline-block exactly one line
   tall, so its background sits where the tail's and the strand's do, in any
   face. `e2e/built/trailer.spec.ts` measures them against each other.

   The tilt is a variable because the hero trailer (`trailer.css`, `trailer.js`)
   reads it from the page, to lift the page off at its own angle and lay it
   back down. */
.hero-figure {
  container-type: inline-size;
}

.hero-stack {
  --page-tilt: -3deg;
  --lh: 1.62em;
  --ul-y: 1.43em;
  --ul-w: 0.21em;
  --pad-x: 2.4em;
  --pad-top: 2em;
  --pad-bottom: 2.1em;
  --paper: #f4ecdb;
  --paper-edge: #e6d9bd;
  --paper-line: #d8cbae;
  --page-border: 1px;
  position: relative;
  /* A browser without container units (Safari before 16, Chrome before 105,
     Firefox before 110) takes the first: near enough the same at any width,
     and never wider than a phone. */
  font-size: min(0.92rem, calc((100vw - 32px) / 32.5));
  font-size: calc(min(100cqw, 30rem) / 32.5);
  width: 32.5em;
  max-width: 100%;
  margin: 1.2em auto 0;
  transform: rotate(var(--page-tilt));
}

.sheet,
.page {
  background: radial-gradient(ellipse 85% 75% at 48% 42%, var(--paper) 55%, var(--paper-edge) 100%);
  border: var(--page-border) solid var(--paper-line);
  border-radius: 2px;
}

.sheet {
  position: absolute;
  inset: 0;
  box-shadow: 0 2px 10px rgba(80, 62, 30, 0.12);
}

.sheet-back {
  transform: rotate(-2.4deg) translate(-0.8em, 0.7em);
}

.sheet-middle {
  transform: rotate(2.1deg) translate(0.6em, 0.5em);
}

.page {
  position: relative;
  padding: var(--pad-top) var(--pad-x) var(--pad-bottom);
  box-shadow:
    0 1px 2px rgba(80, 62, 30, 0.1),
    0 14px 30px rgba(80, 62, 30, 0.16);
}

.page-content {
  font-size: 1em;
  line-height: var(--lh);
  color: var(--ink);
}

.page-content p {
  margin: 0 0 calc(var(--lh) * 0.5);
}

/* PADDING, not margin: a margin here collapses into the last paragraph's, and
   the gap before "Chapter 4" came out half a line short of the count
   `heroStrands` makes, so its strands sat half a line off their underlines
   (found by `e2e/built/trailer.spec.ts`, 2026-10-17). */
.page-chapter + .page-chapter {
  padding-top: calc(var(--lh) * 0.5);
}

.page .chapter {
  margin: 0 0 calc(var(--lh) * 0.5);
  color: var(--ink-muted);
}

.page .gap {
  margin: 0;
  text-align: center;
  color: var(--ink-muted);
  letter-spacing: 0.4em;
}

.page .line {
  display: flex;
  white-space: pre;
}

.page .words {
  flex: none;
}

/* The page's own: `--ul-w` and `--ul-y` are set on `.hero-stack` and nowhere
   else. Unscoped, this drew the story cards' quotes as solid blocks of thread
   colour (2026-10-17 to 2026-10-23): with the two undefined, the background
   fills the whole run. The cards' underline is `.story .tag`. */
.page .tag,
.page .tail-under,
.page .tail {
  background-image: linear-gradient(var(--tc), var(--tc));
  background-repeat: no-repeat;
  background-size: 100% var(--ul-w);
  background-position: 0 calc(var(--ul-y) - var(--ul-w) / 2);
}

.page .tag,
.page .tail-under {
  display: inline-block;
}

/* From the end of the line to the page's edge, where the strand outside
   takes it on. */
.tail {
  flex: 1 0 0;
  margin-right: calc(-1 * var(--pad-x));
}

/* The loose strands, between the sheets beneath and the top page: in from the
   left where a thread's underline starts, out to the right where it ends.
   Tucked under the top page's edge, so they come out from under it and lie
   over the pages below, as the mockup draws them. */
.hero-strands {
  position: absolute;
  inset: 0;
}

.hero-strand {
  position: absolute;
  /* + the page's border: the lines start inside it (review, 2026-10-17: the
     strands were a border's width high). */
  top: calc(var(--page-border) + var(--pad-top) + var(--line) * var(--lh) + var(--ul-y) - 5.5px);
  width: 8em;
  height: 11px;
  line-height: 0;
}

/* VECTOR ONLY: no filter, no bitmap, so a strand is as sharp as the text at
   any device pixel ratio (2026-10-17). Its weight is the underline's
   (`--ul-w`), so the thread runs on out of the page at the weight it has on
   it. `e2e/built/trailer.spec.ts` compares it, at ratios 2 and 3, with the
   trailer's last frame. */
.hero-strand svg {
  display: block;
  width: 100%;
  height: 11px;
  overflow: visible;
}

.hero-strand path {
  fill: none;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.hero-strand .strand-stroke {
  stroke-width: var(--ul-w);
}

/* The pencil: fine streaks of paper either side of the stroke's middle,
   broken where the lead pressed. In screen pixels (`non-scaling-stroke`), so
   they are the same at any width. */
.hero-strand .strand-grain {
  stroke: var(--paper);
  stroke-opacity: 0.32;
  stroke-width: calc(var(--ul-w) * 0.14);
  stroke-dasharray: 2 5 1 9 3 4 1 6;
}

.hero-strand .strand-grain-low {
  stroke-dasharray: 6 3 1 7 2 11 4 2;
  stroke-dashoffset: 5;
}

/* The left ones are shorter: they reach into the gap between the columns and
   stop short of the words beside the picture. */
.hero-strand-in {
  right: calc(100% - 1.5em);
  width: 4.5em;
}

.hero-strand-out {
  left: calc(100% - 1.5em);
}

/* The strands reach past the figure; nothing they reach may scroll the page
   sideways. */
.hero {
  overflow-x: hidden;
  overflow-x: clip;
}

/* The mockup has no caption under the picture; the caption is for a screen
   reader, which reads the figure by it. */
.hero-caption {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The trailer's "Watch it" button (trailer.js) arrives after the page has
   loaded. Its room is kept from the start, wherever the trailer can run (with
   scripting, without reduced motion), so its arriving moves nothing (CLS). The
   room is the button's own box: its 8px margin, 6px padding above and below,
   and one line. flow-root keeps the margin inside. */
.hero-controls {
  display: flow-root;
  font-size: 0.9rem;
  line-height: 1.5;
}
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .hero-controls { min-height: calc(1.5em + 20px); }
}


/* Three stories. */
.stories {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
  margin: 2rem 0 0;
  padding: 0;
  list-style: none;
  position: relative;
}

.story {
  position: relative;
  background: var(--surface-page);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1rem 1.1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.story h3 {
  font-size: 1.1rem;
}

.story .number {
  font-size: 0.85rem;
  color: var(--ink-muted);
  letter-spacing: 0.08em;
}

.story blockquote {
  margin: 0;
  font-size: 1rem;
  line-height: 1.75;
}

/* A quote runs over several lines: an inline run's bottom border
   underlines each one. */
.story .tag {
  border-bottom: 2px solid var(--tc);
  padding-bottom: 2px;
}

.story .absent {
  margin: 0;
  font-style: italic;
  color: var(--ink-muted);
}

.story .count {
  margin: auto 0 0;
  font-size: 0.9rem;
  color: var(--ink-muted);
}

.thread-key {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 1.5rem 0 0;
}

.thread-key .swatch {
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 50%;
  flex: none;
}

.thread-key svg[data-thread-variant] {
  flex: 1 1 auto;
  width: auto;
  min-width: 0;
}

.local h2,
.make h2 {
  font-size: clamp(1.6rem, 3vw, 2rem);
}

.local .what {
  font-weight: 600;
  margin: 0.8rem 0 0;
}

.note {
  font-style: italic;
  margin: 1.2rem 0 0;
  padding-left: 0.9rem;
  border-left: 2px solid var(--border-strong);
}

.make ul {
  padding-left: 1.2rem;
  margin: 1rem 0 0;
}

.make li {
  margin: 0 0 0.45rem;
}

.make .cover {
  display: block;
  width: 100%;
  max-width: 280px;
  height: auto;
  margin: 0 auto;
  border-radius: 2px;
  box-shadow: 0 10px 24px rgba(43, 58, 82, 0.25);
}

.make .cover-caption {
  text-align: center;
  font-size: 0.9rem;
  color: var(--ink-muted);
  margin: 0.9rem auto 0;
  max-width: 22rem;
}

/* The invitation. */
.academic .side {
  border-left: 1px solid var(--border-strong);
  padding-left: 2rem;
}

.academic .side p {
  margin: 0.6rem 0 0;
}

.academic form {
  margin: 1.4rem 0 0;
}

.academic .field {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.academic label {
  display: block;
  font-weight: 600;
  margin: 0 0 0.4rem;
}

.academic input[type='email'] {
  flex: 1 1 16rem;
  min-height: 44px;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--surface-page);
  color: var(--ink);
  font: inherit;
}

.academic .small {
  font-size: 0.95rem;
  margin: 0.8rem 0 0;
}

/* The request form (/academic-request). */
.request label {
  display: block;
  font-weight: 600;
  margin: 1rem 0 0.4rem;
}

.request input[type='email'],
.request input[type='text'] {
  display: block;
  width: 100%;
  max-width: 32rem;
  min-height: 44px;
  padding: 0.5rem 0.75rem;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--surface-page);
  color: var(--ink);
  font: inherit;
}

.request fieldset {
  margin: 1rem 0 0;
  padding: 0;
  border: 0;
}

.request legend {
  font-weight: 600;
  margin: 0 0 0.4rem;
}

.request fieldset label {
  font-weight: 400;
  margin: 0.3rem 0 0;
}

.request .small {
  font-size: 0.95rem;
}

/* Pricing. */
.pricing .prices {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.4rem;
  margin: 1rem 0 0;
  font-size: 1.15rem;
}

.pricing .price {
  font-size: clamp(2rem, 4vw, 2.6rem);
  font-weight: 600;
}

.pricing .offers {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  margin: 1.6rem 0 0;
}

.pricing .offer {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.pricing .offer form {
  margin: 0;
}

.pricing .offer .label {
  font-size: 0.95rem;
  color: var(--ink-muted);
}

/* The video, once it exists (`docs/LANDING-PAGE-SPEC.md` "Demo video"). */
.video figure {
  margin: 1.5rem 0 0;
}

.video video {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface-page);
}

/* The caption: under the video, one step at a time, every step stacked in
   one grid cell so the line keeps the height of the longest. Only with the
   script, which shows the step that is playing; without it the browser draws
   the track's captions itself and this line is not there. */
.video-caption {
  display: none;
}

@media (scripting: enabled) {
  .video-caption {
    display: grid;
    margin-top: 0.6rem;
    font-size: 1.05rem;
    line-height: 1.4;
    text-align: center;
  }

  .video-caption p {
    grid-area: 1 / 1;
    margin: 0;
    visibility: hidden;
  }

  .video-caption p.shown {
    visibility: visible;
  }
}

.video ol {
  margin: 1rem 0 0;
  padding-left: 1.3rem;
}

/* ── footer ───────────────────────────────────────────────────────────── */

.site-footer {
  padding: 2rem 0 3rem;
}

.site-footer .top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1.5rem;
}

.site-footer .tagline {
  font-style: italic;
  margin: 0.4rem 0 0;
}

.site-footer ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer .company {
  font-size: 0.9rem;
  color: var(--ink-muted);
  margin: 1.6rem 0 0;
  max-width: 48em;
}

/* ── the plain pages: privacy, terms, refunds, contact, check your inbox ─ */

.doc {
  max-width: 44rem;
  padding: 2rem 0 3rem;
}

.doc h1 {
  font-size: clamp(2rem, 4vw, 2.6rem);
}

.doc h2 {
  font-size: 1.35rem;
  margin: 2rem 0 0.4rem;
}

.doc p,
.doc li {
  max-width: 40em;
}

.doc .updated {
  color: var(--ink-muted);
  margin: 0.6rem 0 0;
}

.doc dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1.2rem;
}

.doc dt {
  font-weight: 600;
}

.doc dd {
  margin: 0;
}

/* The FAQ (2026-10-25): plain details and summary, so the browser makes each
   question a button that says whether it is open, keyboard and screen reader
   alike. The marker is drawn with borders, so there is no text in it for a
   screen reader to read out. */
.faq .wrap {
  border-top: 1px solid var(--border-strong);
  padding-top: 2.5rem;
}

.faq .faq-group {
  max-width: 46rem;
  margin: 2rem 0 0;
}

.faq .faq-group h3 {
  font-size: 1.05rem;
  font-variant-caps: all-small-caps;
  letter-spacing: 0.1em;
  color: var(--ink-muted);
  margin: 0 0 0.4rem;
}

.faq details {
  border-top: 1px solid var(--border);
}

.faq details:last-of-type {
  border-bottom: 1px solid var(--border);
}

.faq summary {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.7rem 0;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::before {
  content: '';
  flex: none;
  width: 0.45em;
  height: 0.45em;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: translateY(-0.12em) rotate(-45deg);
}

.faq details[open] > summary::before {
  transform: translateY(-0.2em) rotate(45deg);
}

.faq summary:hover {
  color: var(--accent-strong);
}

.faq details p {
  margin: 0 0 1rem;
  padding-left: calc(0.45em + 0.75rem);
}

.faq .faq-group > p {
  margin: 0;
}

/* ── one column under about 760px (L5) ────────────────────────────────── */

@media (max-width: 760px) {
  :root {
    --gutter: 16px;
  }

  .columns,
  .hero .columns,
  .stories {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }

  .hero {
    padding-top: 1.5rem;
  }

  .hero-stack {
    --page-tilt: -2deg;
  }

  .academic .side {
    border-left: 0;
    border-top: 1px solid var(--border-strong);
    padding: 1.2rem 0 0;
  }

  .doc dl {
    grid-template-columns: minmax(0, 1fr);
  }

  .brand {
    font-size: 1.4rem;
  }
}

/* The hero and the three story cards need more room than the rest: at a
   tablet's 768px the manuscript page and three cards of quotation were each a
   word or two wide. One column below 900px for these two. */
@media (max-width: 900px) {
  .hero .columns,
  .stories {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }

}

@media (prefers-reduced-motion: reduce) {
  * {
    scroll-behavior: auto !important;
  }
}
