

/* ================================================================== *
 * 2. How it works
 *
 * A left rail of numerals against a single column of text. The rail is what
 * makes it read as a sequence rather than as three unrelated paragraphs, and it
 * only exists once there is room for it: below the breakpoint the numeral sits
 * above its own beat, one step smaller, which is the same hierarchy in one
 * column.
 * ================================================================== */

.how__title {
  margin-bottom: clamp(var(--s-xl), 4vw, var(--s-2xl));
}

.how__beat {
  display: grid;
  gap: var(--s-2xs) var(--s-l);
  padding-block: var(--s-xl);
  border-top: 1px solid var(--paper-edge);
}

.how__num {
  font-size: var(--step-1);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--ink-faint);
  /* The numerals are a column and have to line up as one. */
  font-variant-numeric: tabular-nums;
}

.how__body {
  display: grid;
  gap: var(--s-xs);
  align-content: start;
}

.how__text {
  max-width: 54ch;
  text-wrap: pretty;
}

/* 700px is where a 54ch paragraph plus the rail plus the page gutter stop
 * fitting, measured on the longest beat. */
@media (min-width: 700px) {
  .how__beat {
    /* The rail is --s-4xl because "04" at --step-3 is about 60px wide and the
     * numeral must not sit against its own title. */
    grid-template-columns: var(--s-4xl) minmax(0, 1fr);
    /* Baseline, not start: the numeral and the title are different sizes, and
     * aligning their boxes would leave the numeral floating above the word it
     * numbers. This is the alternative to a hand-tuned top offset that would
     * have to be re-tuned at every clamp step. */
    align-items: baseline;
    padding-block: var(--s-2xl);
  }

  .how__num {
    font-size: var(--step-3);
    line-height: 1.08;
    letter-spacing: -0.025em;
  }
}

/* Beat 04 is the only one that is not something you do — it is what did not
 * happen while you did the other three. It keeps its number and its place in
 * the sequence, and it is given air above it and a heavier voice so the eye
 * reads it as the end of the argument rather than as a fourth instruction. */
.how__beat--coda {
  padding-block-start: clamp(var(--s-2xl), 5vw, var(--s-3xl));
}

.how__beat--coda .how__num {
  color: var(--ink-quiet);
}

.how__beat--coda .how__text {
  font-size: var(--step-1);
  line-height: 1.5;
  letter-spacing: -0.01em;
  max-width: 48ch;
}

/* ================================================================== *
 * 3. What's inside — shared scaffolding
 * ================================================================== */

.inside__title {
  margin-bottom: clamp(var(--s-2xl), 5vw, var(--s-3xl));
}

/* The space between two feature blocks is the largest space in the section,
 * because each block is one idea and the reader needs to be able to tell where
 * one stops. */
.inside__blocks {
  display: grid;
  gap: clamp(var(--s-3xl), 9vw, var(--s-5xl));
}

.block__head {
  display: grid;
  gap: var(--s-m);
  align-content: start;
}

.block__lede {
  max-width: 58ch;
  color: var(--ink-body);
  text-wrap: pretty;
}

/* ---- 3a. Registers by destination -------------------------------------
 *
 * A comparison, so it is set as one: the spoken sentence once, across the top,
 * and three columns under it that differ only in where the words were going.
 * Three separate cards would have implied three separate inputs, which is the
 * opposite of the claim.
 *
 * The columns carry a rule and no box. A border on four sides would have made
 * them the identical cards this block exists to argue against, and the single
 * hairline is the older and better answer for tabular material. */

.block--registers {
  display: grid;
  gap: clamp(var(--s-2xl), 4vw, var(--s-3xl));
}

/* The title and its paragraph side by side, asymmetric — the head of an article
 * rather than a centred banner. */
@media (min-width: 880px) {
  .block__head--split {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: var(--s-2xl);
    align-items: start;
  }
}

.landing {
  display: grid;
  gap: var(--s-l);
}

/* 800px is where the longest of the three landings stops falling to five lines
 * in a third of the column. */
@media (min-width: 800px) {
}

/* ---- 3b. Speak one language, write another ----------------------------
 *
 * A transformation. Two states and an arrow is the whole shape, and the arrow
 * turns to point down when the two states stack — a right-pointing arrow above
 * a block that is below it is a diagram that lies. */

.block--lang {
  display: grid;
  gap: clamp(var(--s-2xl), 5vw, var(--s-3xl));
}

.block__main {
  display: grid;
  gap: clamp(var(--s-xl), 3vw, var(--s-2xl));
}

.block__aside {
  display: grid;
  gap: var(--s-s);
  align-content: start;
  max-width: 46ch;
  padding-top: var(--s-m);
  border-top: 1px solid var(--paper-edge);
  color: var(--ink-body);
}

.swap {
  display: grid;
  gap: var(--s-l);
  padding: clamp(var(--s-m), 3vw, var(--s-xl));
  border-radius: var(--radius-l);
  background-color: var(--paper-sunk);
}

/* 640px is where the two sentences stop wrapping to four lines each in half the
 * well. */
@media (min-width: 640px) {
  .swap {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: var(--s-xl);
    align-items: start;
  }
}

/* 940px is where the aside can take a column of its own without squeezing the
 * swap below its own breakpoint. */
@media (min-width: 940px) {
  .block--lang {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.55fr);
    gap: var(--s-3xl);
    align-items: start;
  }

  /* A margin note: the rule moves to the side it is now beside. */
  .block__aside {
    padding-top: 0;
    padding-inline-start: var(--s-l);
    border-top: 0;
    border-inline-start: 1px solid var(--paper-edge);
  }
}

/* ---- 3c. The dictionary and the snippets ------------------------------
 *
 * Pairs, so tables. Real `<table>` markup rather than a two-column grid,
 * because "heard / written" and "trigger / expansion" are headers a screen
 * reader should say with every cell, and a grid of divs cannot promise that.
 *
 * The two halves are given unequal widths on purpose. Equal columns would have
 * read as two cards again, and the dictionary genuinely needs more room — it is
 * two lists, not one. */

.block--words {
  display: grid;
  gap: clamp(var(--s-2xl), 6vw, var(--s-3xl));
}

.words__half {
  display: grid;
  gap: var(--s-xl);
  align-content: start;
}

.words__tables {
  display: grid;
  gap: var(--s-xl);
}

.pairs {
  width: 100%;
  border-collapse: collapse;
}

.pairs__caption {
  margin-bottom: var(--s-xs);
}

.pairs thead th {
  padding-block-end: var(--s-2xs);
  padding-inline-end: var(--s-m);
}

.pairs td,
.pairs--list li {
  padding-block: var(--s-s);
  padding-inline-end: var(--s-m);
  border-top: 1px solid var(--paper-edge);
  vertical-align: top;
  text-align: start;
}

/* The left side of a pair is what you say, and what you say is set in the
 * face the app sets it in. */
.pairs__key {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--ink);
  white-space: nowrap;
}

.pairs__val {
  color: var(--ink-body);
  /* A snippet expansion can be an address or a URL with no spaces in it, and at
   * 320px that has to break rather than push the page sideways. */
  overflow-wrap: anywhere;
}

.pairs__lines {
  display: block;
  line-height: 1.5;
}

.pairs--list ul {
  display: grid;
}

/* 900px is where the wider half still holds its longest correction row on one
 * line. */
@media (min-width: 900px) {
  .block--words {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: var(--s-3xl);
    align-items: start;
  }
}

/* ---- 3d. Notes are files ----------------------------------------------
 *
 * The only block whose media leads, and the only one whose media is on the
 * left: the file is the argument, and the sentence under it is the caption.
 * `--paper-raised` and one lift, because a file is a thing sitting on the desk
 * — the opposite material to the two wells above, which is what stops this
 * section reading as one long panel. */

.block--notes {
  display: grid;
  gap: clamp(var(--s-xl), 4vw, var(--s-2xl));
}

.file {
  /* A grid item's default `min-width: auto` is the width of its widest
   * unbreakable content, which for a 41-character UUID line is 365px — so
   * without this the file pushes the whole page sideways at 320px and the
   * `overflow-x` below never gets the chance to do its job. */
  min-width: 0;
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-m);
  background-color: var(--paper-raised);
  box-shadow: var(--lift-1);
  /* The path bar's corners follow the box's. */
  overflow: hidden;
}

.file__path {
  padding: var(--s-s) var(--s-m);
  border-bottom: 1px solid var(--paper-edge);
  background-color: var(--paper-sunk);
  color: var(--ink-quiet);
  font-size: var(--step--1);
  /* A path is one string and must not be hyphenated across lines. The
   * non-breaking space in the markup keeps "Speechfy Notes" together. */
  overflow-wrap: anywhere;
}

.file__body {
  padding: var(--s-m);
  color: var(--ink-body);
  font-size: var(--step--1);
  line-height: 1.7;
  /* The UUID line is 41 characters and does not fit a 320px screen at any
   * legible size. It scrolls inside its own box; the page never does. */
  overflow-x: auto;
}

/* 900px is where the file and a 48ch paragraph fit side by side. */
@media (min-width: 900px) {
  .block--notes {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(var(--s-2xl), 5vw, var(--s-4xl));
    align-items: center;
  }
}

/* ---- 3e. History and the counters -------------------------------------
 *
 * The postscript. Both are records of things that already happened, so they are
 * the smallest type in the section, they share one rule, and they have no
 * specimen: a screenshot of an invented word count is not a fact anyone can
 * check, and filling the rectangle would have cost the page its only real
 * claim, which is that everything on it is true. */

.block--post {
  display: grid;
  gap: var(--s-2xl);
  padding-top: var(--s-xl);
  border-top: 1px solid var(--paper-edge);
}

.post {
  display: grid;
  gap: var(--s-s);
  align-content: start;
  max-width: 48ch;
}

.post p {
  color: var(--ink-quiet);
}

@media (min-width: 760px) {
  .block--post {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-3xl);
  }
}

/* ================================================================== *
 * 4. Privacy
 *
 * One claim, one table, two footnotes. The table is the section: a sentence
 * about storing things responsibly is a promise, and a path is an instruction
 * to go and look.
 * ================================================================== */

.privacy__lead {
  display: grid;
  gap: var(--s-m);
}

.privacy__title {
  /* Held to a short measure so the sentence breaks into two or three large
   * lines instead of running once across a 1180px page, which would set the
   * biggest type on the section at the smallest size it could be read at. */
  max-width: 18ch;
}

.privacy__body {
  font-size: var(--step-1);
  line-height: 1.5;
  letter-spacing: -0.01em;
  max-width: 58ch;
  text-wrap: pretty;
}

.privacy__kept {
  display: grid;
  gap: var(--s-m);
  margin-top: clamp(var(--s-2xl), 5vw, var(--s-3xl));
}

.kept {
  width: 100%;
  border-collapse: collapse;
}

.kept thead th {
  padding-block-end: var(--s-xs);
  padding-inline-end: var(--s-m);
  border-bottom: 1px solid var(--paper-edge);
}

.kept tbody th,
.kept td {
  padding-block: var(--s-m);
  padding-inline-end: var(--s-m);
  border-top: 1px solid var(--paper-edge);
  vertical-align: top;
  text-align: start;
}

.kept tbody th {
  /* A percentage and not a `ch`, so the column shrinks with the page rather
   * than holding a fixed width that a 320px screen cannot spare. */
  width: 30%;
  font-weight: 600;
  color: var(--ink);
}

.kept td {
  color: var(--ink-body);
}

.kept__path {
  color: var(--ink);
  /* The point of the row. It wraps mid-string rather than scrolling, because a
   * path in a scroll container at 320px is a path nobody reads. */
  overflow-wrap: anywhere;
}

.privacy__after {
  max-width: 62ch;
  color: var(--ink-quiet);
  text-wrap: pretty;
}

.privacy__pair {
  display: grid;
  gap: var(--s-2xl);
  margin-top: clamp(var(--s-2xl), 5vw, var(--s-3xl));
  padding-top: var(--s-xl);
  border-top: 1px solid var(--paper-edge);
}

.privacy__note {
  display: grid;
  gap: var(--s-s);
  align-content: start;
  max-width: 50ch;
}

.privacy__note p {
  color: var(--ink-body);
  text-wrap: pretty;
}

@media (min-width: 760px) {
  .privacy__pair {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-3xl);
  }
}

/* 900px is where the longest cell in the table — the usage row — stops running
 * to four lines once the heading has taken its rail. */
@media (min-width: 900px) {
  .privacy__kept {
    grid-template-columns: minmax(0, 0.3fr) minmax(0, 0.7fr);
    gap: var(--s-l) var(--s-2xl);
    align-items: start;
  }

  /* The heading becomes a rail beside the table rather than a line above it.
   * Scoped to this block: the same class in the pair below is a heading over a
   * paragraph and must stay one. */
  .privacy__kept > .privacy__sub {
    grid-column: 1;
    grid-row: 1;
  }

  .privacy__kept > .kept,
  .privacy__kept > .privacy__after {
    grid-column: 2;
  }
}
