/* PogCode public surface: the product's own grammar — its faces, its grays,
   its one accent — at the size a page that is read rather than operated
   needs. Shared brand.css supplies the local Charon faces. @see ./spec.md */

:root {
  color-scheme: light dark;

  /* The grounds and the gray the product draws with; every ink is a share of one dark. */
  --canvas: light-dark(#ffffff, #0F060B);
  --gray: light-dark(#75656D, #998891);
  --pole: light-dark(#000000, #ffffff);
  --gray-2: color-mix(in oklab, var(--canvas) 94%, var(--gray));
  --gray-3: color-mix(in oklab, var(--canvas) 86%, var(--gray));
  --gray-12: color-mix(in oklab, var(--gray) 25%, var(--pole));
  --ink-strong: var(--gray-12);
  --ink: color-mix(in oklab, var(--gray-12) 92%, transparent);
  --ink-subtle: color-mix(in oklab, var(--gray-12) 76%, transparent);
  --ink-muted: color-mix(in oklab, var(--gray-12) 64%, transparent);
  --ink-faint: color-mix(in oklab, var(--gray-12) 52%, transparent);
  --ink-link: light-dark(color-mix(in oklab, var(--accent) 44%, black), var(--accent));
  --stroke-subtle: color-mix(in oklab, var(--gray-12) 8%, transparent);
  --stroke: color-mix(in oklab, var(--gray-12) 14%, transparent);
  --surface-hover: color-mix(in oklab, var(--gray-12) 5%, transparent);
  --surface-active: color-mix(in oklab, var(--gray-12) 8%, transparent);
  --surface-sunken: var(--gray-2);

  /* The one accent, spent on the one thing to do here. The hover and the
     link ink are shares of it, so a reader's own accent carries through. */
  --accent: #CBFF8C;
  --accent-hover: light-dark(color-mix(in oklab, var(--accent) 91%, black), color-mix(in oklab, var(--accent) 92%, white));
  --ink-on-accent: #0F060B;
  --selection-fill: var(--accent);
  --selection-ink: #0F060B;
  /* The one state colour the product frame needs: a step that finished. A
     reader's own syntax green, when the preference script set it, wins. */
  --good: var(--syntax-green, light-dark(oklch(47% 0.13 145), oklch(75% 0.14 145)));

  --radius: 0.25rem;
  --radius-l: 0.5rem;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;

  --gutter: clamp(1rem, 4vw, 2.5rem);
  --page: 64rem;
  --rhythm: clamp(2.5rem, 5vw, 4rem);
  --measure-prose: 74ch;

  --font-ui: "Iosevka Charon", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-code: "Iosevka Charon Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --text-display: 500 clamp(2rem, 1.2rem + 3vw, 3.25rem)/1.1 var(--font-ui);
  --text-lede: 400 clamp(1rem, 0.95rem + 0.3vw, 1.125rem)/1.5 var(--font-ui);
  --text-title: 500 1.125rem/1.35 var(--font-ui);
  --text-heading: 500 0.9375rem/1.4 var(--font-ui);
  --text-prose: 400 0.875rem/1.6 var(--font-ui);
  --text-control: 500 0.8125rem/1.25rem var(--font-ui);
  --text-caption: 400 0.75rem/1.5 var(--font-ui);
  --text-label: 400 0.6875rem/1rem var(--font-code);
  --text-code: 400 0.8125rem/1.55 var(--font-code);
  --track-caps: 0.06em;

  --motion: 90ms;
  /* A drawing decelerates into place; a dot lands with a touch of overshoot. */
  --ease-draw: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-pop: cubic-bezier(0.34, 1.45, 0.5, 1);
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
}

/* The reader's own appearance, read from the app's preference record before
   the first paint (the build inlines the script): a forced scheme, and on a
   phone the chosen scale, which redefines the rem there and nowhere else. */
html[data-color-scheme="light"] {
  color-scheme: light;
}

html[data-color-scheme="dark"] {
  color-scheme: dark;
}

html[data-phone="true"] {
  font-size: calc(100% * var(--ui-scale-choice, 1));
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

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

body {
  margin: 0;
  color: var(--ink);
  background: var(--canvas);
  font: var(--text-prose);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
p,
ul,
ol,
figure,
pre {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

img {
  display: block;
  max-inline-size: 100%;
  block-size: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

i {
  font-style: normal;
}

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

:where(:focus-visible) {
  outline: 2px solid var(--ink-link);
  outline-offset: 2px;
  border-radius: var(--radius);
}

.skip-link {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-start: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius);
  color: var(--ink-on-accent);
  background: var(--accent);
  font: var(--text-control);
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
}

.wrap {
  inline-size: min(100% - 2 * var(--gutter), var(--page));
  margin-inline: auto;
}

/* ---- masthead ------------------------------------------------------- */

.masthead {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-block-size: 3.25rem;
  padding-block: var(--space-2);
  border-block-end: 1px solid var(--stroke-subtle);
}

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

.brand-picture {
  display: block;
}

.brand-wordmark {
  inline-size: auto;
  block-size: 1.375rem;
}

.masthead-nav {
  display: flex;
  gap: var(--space-2);
}

.masthead-nav a {
  display: inline-flex;
  align-items: center;
  min-block-size: 2rem;
  padding-inline: var(--space-2);
  border-radius: var(--radius);
  color: var(--ink-muted);
  font: var(--text-control);
  transition: color var(--motion) var(--ease), background-color var(--motion) var(--ease);
}

.masthead-nav a:hover {
  color: var(--ink-strong);
  background: var(--surface-hover);
}

.masthead-nav a[aria-current] {
  color: var(--ink-strong);
}

/* A phone has room for the brand, one link and the app: the Download button
   under the headline is a thumb away. */
@media (max-width: 30rem) {
  .masthead-nav a[href="/download/"] {
    display: none;
  }
}

/* ---- controls ------------------------------------------------------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-block-size: 2rem;
  padding: 0 var(--space-3);
  border: 1px solid var(--stroke);
  border-radius: var(--radius);
  color: var(--ink);
  background: transparent;
  font: var(--text-control);
  white-space: nowrap;
  transition: color var(--motion) var(--ease), background-color var(--motion) var(--ease), border-color var(--motion) var(--ease);
}

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

.button:active {
  background: var(--surface-active);
}

.button-accent {
  border-color: transparent;
  color: var(--ink-on-accent);
  background: var(--accent);
}

.button-accent:hover,
.button-accent:active {
  color: var(--ink-on-accent);
  background: var(--accent-hover);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* A command: one block to read, select or copy. The Copy control is added by
   main.js and sits in the holder, not in the scrolling block. */
.snippet {
  position: relative;
  max-inline-size: 100%;
}

pre {
  max-inline-size: 100%;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-l);
  color: var(--ink);
  background: var(--surface-sunken);
  font: var(--text-code);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
}

pre code {
  font: inherit;
  white-space: pre;
}

/* Room at the end of the line so the text never ends under the Copy control. */
.snippet pre {
  padding-inline-end: calc(var(--space-4) + 4rem);
}

.snippet .copy {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-end: var(--space-2);
  min-block-size: 1.5rem;
  padding: 0 var(--space-2);
  border: 1px solid var(--stroke);
  border-radius: var(--radius);
  color: var(--ink-muted);
  background: var(--canvas);
  font: var(--text-caption);
  cursor: pointer;
  transition: color var(--motion) var(--ease), background-color var(--motion) var(--ease), border-color var(--motion) var(--ease);
}

.snippet .copy:hover {
  color: var(--ink-strong);
  background: var(--surface-hover);
}

.snippet .copy[data-copied] {
  border-color: var(--accent);
  color: var(--ink-strong);
}

/* ---- hero ----------------------------------------------------------- */

/* One centred block: what it is, one paragraph, one thing to do. */
.hero {
  display: grid;
  justify-items: center;
  gap: var(--space-5);
  max-inline-size: 46rem;
  padding-block: clamp(2.5rem, 6vw, 4.5rem) 0;
  text-align: center;
}

h1 {
  color: var(--ink-strong);
  font: var(--text-display);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.lede {
  max-inline-size: 56ch;
  color: var(--ink-subtle);
  font: var(--text-lede);
  text-wrap: pretty;
}

.hero .button-accent {
  min-block-size: 2.25rem;
  padding-inline: var(--space-5);
}

/* The one line of small print a download needs, tucked under the button. */
.under {
  margin-block-start: calc(var(--space-3) - var(--space-5));
  color: var(--ink-faint);
  font: var(--text-caption);
}

.under a {
  color: var(--ink-link);
}

/* ---- drawing motion -------------------------------------------------- */

/* Every drawing on this page is written in its finished state, and performs
   itself once when it is first seen. Nothing loops, nothing pulses forever,
   and nothing that moves on its own can change the size of anything. A reader
   who asks for less motion, or whose script never ran, is never marked
   `data-motion` and so only ever sees the finished drawing; main.js marks a
   drawing `data-play` the first time it comes into view. @see ./spec.md R11 */
.draw {
  transform-origin: left center;
}

.draw-y {
  transform-origin: center top;
}

[data-motion] [data-scene]:not([data-play]) .rise {
  opacity: 0;
}

[data-motion] [data-scene]:not([data-play]) .pop {
  opacity: 0;
  transform: scale(0.3);
}

[data-motion] [data-scene]:not([data-play]) .draw {
  transform: scaleX(0);
}

[data-motion] [data-scene]:not([data-play]) .draw-y {
  transform: scaleY(0);
}

[data-motion] [data-play] .rise {
  animation: rise 560ms var(--ease-draw) var(--t, 0ms) both;
}

[data-motion] [data-play] .pop {
  animation: pop 420ms var(--ease-pop) var(--t, 0ms) both;
}

[data-motion] [data-play] .draw {
  animation: draw 640ms var(--ease-draw) var(--t, 0ms) both;
}

[data-motion] [data-play] .draw-y {
  animation: draw-y 760ms var(--ease-draw) var(--t, 0ms) both;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(0.375rem);
  }
}

@keyframes pop {
  from {
    opacity: 0;
    transform: scale(0.3);
  }
}

@keyframes draw {
  from {
    transform: scaleX(0);
  }
}

@keyframes draw-y {
  from {
    transform: scaleY(0);
  }
}

/* ---- the thread ----------------------------------------------------- */

/* The picture of the product: one hairline thread, the turns hanging off it,
   the last one waiting for the reader. It draws itself top to bottom once, in
   the order the turns arrived, and then holds. Answering it is the only thing
   on the page that changes size, and the reader is the one who asks. */
.thread {
  max-inline-size: 36rem;
  margin-block-start: clamp(2rem, 5vw, 3.5rem);
  padding: clamp(1.25rem, 4vw, 2rem);
  border: 1px solid var(--stroke-subtle);
  border-radius: var(--radius-l);
  font: 400 0.9375rem/1.55 var(--font-ui);
}

/* The turns carry their own spacing rather than a grid gap, so the answer can
   open from nothing without a gap standing there waiting for it. */
.spine {
  position: relative;
  display: grid;
}

.rail {
  position: absolute;
  inset-block: 0.45rem 0.5rem;
  inset-inline-start: calc(0.5rem - 0.5px);
  inline-size: 1px;
  background: var(--stroke);
  transform-origin: center top;
}

.node {
  display: grid;
  grid-template-columns: 1rem minmax(0, 1fr);
  column-gap: var(--space-4);
}

.node + .node,
.node-slot .node {
  padding-block-start: var(--space-5);
}

/* A turn lands as its dot, then its words a beat later. */
.node .node-body {
  animation-delay: calc(var(--t, 0ms) + 90ms);
}

.mark {
  inline-size: 0.5rem;
  block-size: 0.5rem;
  margin: 0.45rem 0.25rem 0;
  border: 1px solid var(--stroke);
  border-radius: 50%;
  background: var(--canvas);
}

.mark-done {
  border-color: transparent;
  background: var(--good);
}

.mark-live {
  position: relative;
  border-color: transparent;
  background: var(--ink-link);
}

.mark-live::before,
.mark-live::after {
  content: "";
  position: absolute;
  inset: -0.25rem;
  border: 1px solid var(--ink-link);
  border-radius: 50%;
}

/* The still halo says which turn is waiting; the ring that leaves says it
   three times and then stops. */
.mark-live::before {
  border-color: color-mix(in oklab, var(--ink-link) 45%, transparent);
}

.mark-live::after {
  opacity: 0;
}

/* Three rings and then still: enough to say this turn is waiting, not a
   notification that nags for as long as the page is open. */
[data-motion] [data-play] .mark-live::after {
  animation: ping 1.5s var(--ease-draw) calc(var(--t, 0ms) + 320ms) 3;
}

@keyframes ping {
  from {
    transform: scale(0.45);
    opacity: 0.7;
  }

  to {
    transform: scale(1.9);
    opacity: 0;
  }
}

.node-body {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
}

.who {
  color: var(--ink-faint);
  font: var(--text-label);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

.who-live {
  color: var(--ink-strong);
}

.node p {
  text-wrap: pretty;
}

.node-you p {
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-l);
  color: var(--ink-strong);
  background: var(--surface-sunken);
}

/* The turn that answers the reader back. It is closed until one of the two
   replies is picked, and then it opens once and stays. */
.node-slot {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 420ms var(--ease-draw);
}

.node-slot .node {
  min-block-size: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity 220ms var(--ease);
}

.spine[data-answered] .node-slot {
  grid-template-rows: 1fr;
}

.spine[data-answered] .node-slot .node {
  opacity: 1;
  transition-delay: 220ms;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.chip {
  padding: 0.125rem var(--space-3);
  border: 1px solid var(--stroke);
  border-radius: 999px;
  color: var(--ink-subtle);
  font: var(--text-control);
  background: none;
}

/* main.js makes the two replies real buttons; without it they are the two
   answers the thread is offering, which is just as true. */
button.chip {
  cursor: pointer;
  transition: color var(--motion) var(--ease), border-color var(--motion) var(--ease), background-color var(--motion) var(--ease);
}

button.chip:hover:not(:disabled) {
  border-color: var(--ink-link);
  color: var(--ink-strong);
}

button.chip:disabled {
  cursor: default;
  opacity: 0.4;
}

button.chip[data-chosen] {
  border-color: var(--ink-link);
  color: var(--ink-strong);
  background: var(--surface-active);
  opacity: 1;
}

/* ---- claims --------------------------------------------------------- */

/* Three rows, each one sentence and one drawing of the same thing. */
.claims {
  display: grid;
  padding-block: var(--rhythm) 0;
}

.claim {
  display: grid;
  align-items: center;
  gap: var(--space-5);
  padding-block: var(--space-6);
  border-block-start: 1px solid var(--stroke-subtle);
}

.claim-text {
  display: grid;
  align-content: start;
  gap: var(--space-2);
}

.claims h2 {
  color: var(--ink-strong);
  font: var(--text-title);
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.claims p {
  max-inline-size: 46ch;
  color: var(--ink-subtle);
  text-wrap: pretty;
}

@media (min-width: 52rem) {
  .claim {
    grid-template-columns: minmax(0, 23rem) minmax(0, 1fr);
    gap: var(--space-7);
    padding-block: var(--space-7);
  }
}

/* The drawings: hairlines, one dot per moment, the product's own chips. Each
   one draws its line and then hangs what the line carries off it. */
.art {
  max-inline-size: 34rem;
  color: var(--ink-subtle);
  font: var(--text-caption);
}

.track,
.art-reach .link {
  block-size: 1px;
  background: var(--stroke);
}

.art-run .track {
  margin-inline: 0.25rem;
}

.art-run .stops {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
}

.art-run .stops li {
  position: relative;
  display: grid;
  gap: 0.125rem;
  padding-block-start: var(--space-3);
}

.art-run .stops li::before {
  content: "";
  position: absolute;
  inset-block-start: -0.3rem;
  inset-inline-start: 0;
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border: 1px solid var(--stroke);
  border-radius: 50%;
  background: var(--canvas);
}

.art-run .stops li:last-child::before {
  border-color: transparent;
  background: var(--ink-link);
}

.art-run b {
  color: var(--ink-strong);
  font-weight: 500;
}

.art-run span {
  color: var(--ink-faint);
  font: var(--text-label);
}

.art-fan {
  display: grid;
  justify-items: start;
  gap: var(--space-3);
}

.art-fan .source {
  position: relative;
  color: var(--ink-strong);
  font-weight: 500;
}

.art-fan .fan {
  position: relative;
  display: grid;
  gap: var(--space-2);
  padding-inline-start: var(--space-6);
}

/* One line down the left of the three, and a stub into each. */
.art-fan .fan::before {
  content: "";
  position: absolute;
  inset-block: var(--space-3);
  inset-inline-start: var(--space-3);
  inline-size: 1px;
  background: var(--stroke);
  transform-origin: center top;
}

.art-fan .fan li {
  position: relative;
}

.art-fan .fan li::before {
  content: "";
  position: absolute;
  inset-inline-start: var(--space-3);
  inset-block-start: calc(50% - 0.5px);
  inline-size: calc(var(--space-6) - var(--space-3));
  block-size: 1px;
  background: var(--stroke);
  transform-origin: left center;
}

/* The one thing arrives, the bracket runs down, and a stub reaches each agent
   just before its name lands: set once, delivered to all of them. */
[data-motion] [data-scene]:not([data-play]) :is(.art-fan .fan::before) {
  transform: scaleY(0);
}

[data-motion] [data-scene]:not([data-play]) :is(.art-fan .fan li::before, .art-fan .source::after) {
  transform: scaleX(0);
}

[data-motion] [data-play] .art-fan .fan::before {
  animation: draw-y 460ms var(--ease-draw) 280ms both;
}

[data-motion] [data-play] .art-fan .fan li::before {
  animation: draw 300ms var(--ease-draw) calc(var(--t, 0ms) - 170ms) both;
}

[data-motion] [data-play] .art-fan .source::after {
  animation: draw 300ms var(--ease-draw) 190ms both;
}

/* Wide enough: the one thing on the left, the agents it reaches on the right. */
@media (min-width: 34rem) {
  .art-fan {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--space-5);
  }

  .art-fan .source::after {
    content: "";
    position: absolute;
    inset-inline-start: 100%;
    inset-block-start: calc(50% - 0.5px);
    inline-size: var(--space-5);
    block-size: 1px;
    background: var(--stroke);
    transform-origin: left center;
  }

  .art-fan .fan {
    padding-inline-start: var(--space-4);
  }

  .art-fan .fan::before {
    inset-inline-start: 0;
  }

  .art-fan .fan li::before {
    inset-inline-start: 0;
    inline-size: var(--space-4);
  }
}

/* No gap: the line has to touch what it joins, or it reads as a stray mark
   rather than as the reach between them. */
.art-reach {
  display: grid;
  grid-template-columns: auto 3rem auto;
  align-items: center;
  justify-content: start;
  gap: 0;
}

/* The machine is there first and the line reaches out from it, so the drawing
   is read the way the product works: your computer, then anything you open. */
.art-reach .link.draw {
  transform-origin: right center;
}

.art-reach .side {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
}

.art-reach .devices {
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
}

.art-reach .browser,
.art-reach .handset {
  display: grid;
  align-content: start;
  gap: 0.3rem;
  padding: 0.35rem;
  border: 1px solid var(--stroke);
  border-radius: var(--radius);
}

.art-reach .browser {
  inline-size: 5.5rem;
  block-size: 3.75rem;
}

.art-reach .handset {
  position: relative;
  inline-size: 2rem;
  block-size: 3.25rem;
  border-radius: 0.375rem;
  padding-block-start: 0.6rem;
}

.art-reach .browser-bar {
  position: relative;
  block-size: 0.5rem;
  margin: -0.35rem -0.35rem 0.15rem;
  border-block-end: 1px solid var(--stroke);
}

/* The three dots every window has, drawn as one dot repeated. */
.art-reach .browser-bar::before {
  content: "";
  position: absolute;
  inset-block-start: 0.16rem;
  inset-inline-start: 0.2rem;
  inline-size: 0.1875rem;
  block-size: 0.1875rem;
  border-radius: 50%;
  background: var(--stroke);
  box-shadow: 0.3125rem 0 0 var(--stroke), 0.625rem 0 0 var(--stroke);
}

/* The handset's earpiece, so the smaller box is plainly a phone. */
.art-reach .handset::before {
  content: "";
  position: absolute;
  inset-block-start: 0.3rem;
  inset-inline-start: 50%;
  inline-size: 0.5rem;
  block-size: 1px;
  background: var(--stroke);
  transform: translateX(-50%);
}


.art-reach .browser-line {
  block-size: 1px;
  background: var(--stroke);
}

/* The window's second line is short, the way a real one runs out; the phone
   carries one line only, so its earpiece stays the mark that names it. */
.art-reach .browser .browser-line:last-child {
  inline-size: 60%;
}

.art-reach .machine {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
  min-inline-size: 0;
  padding: var(--space-3);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-l);
}

.art-reach .side b,
.art-reach .machine b {
  color: var(--ink-strong);
  font-weight: 500;
}

.art .chip {
  font: var(--text-caption);
}

/* On a narrow screen the two sides stack and the hairline stands up. */
@media (max-width: 34rem) {
  .art-reach {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
    gap: 0;
  }

  .art-reach .machine {
    order: 1;
  }

  .art-reach .link {
    order: 2;
    inline-size: 1px;
    block-size: var(--space-5);
    margin-inline-start: var(--space-5);
  }

  .art-reach .side {
    order: 3;
  }

  .art-reach .link.draw {
    transform-origin: center top;
  }

  [data-motion] [data-scene]:not([data-play]) .art-reach .link {
    transform: scaleY(0);
  }

  [data-motion] [data-play] .art-reach .link {
    animation-name: draw-y;
  }
}

/* ---- get started ---------------------------------------------------- */

.start {
  display: grid;
  justify-items: start;
  gap: var(--space-4);
  padding-block: var(--rhythm);
  border-block-start: 1px solid var(--stroke-subtle);
}

.start h2 {
  color: var(--ink-strong);
  font: var(--text-title);
  letter-spacing: -0.01em;
}

.steps {
  display: grid;
  gap: var(--space-2);
  max-inline-size: 44rem;
  counter-reset: step;
}

.steps li {
  display: grid;
  grid-template-columns: 1.25rem minmax(0, 1fr);
  gap: var(--space-2);
  color: var(--ink-subtle);
  counter-increment: step;
  text-wrap: pretty;
}

.steps li::before {
  content: counter(step);
  color: var(--ink-faint);
  font: var(--text-label);
  line-height: 1.6;
}

.fine-print {
  max-inline-size: 72ch;
  color: var(--ink-faint);
  font: var(--text-caption);
  text-wrap: pretty;
}

.fine-print a {
  color: var(--ink-link);
}

/* ---- download ------------------------------------------------------- */

/* The desktop app by operating system, then the command line. The visitor's
   own system is listed first with its first installer as the one action;
   main.js marks it, and without the script the list is still complete. */
.download {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  max-inline-size: 44rem;
  padding-block: clamp(2.5rem, 6vw, 4rem) var(--rhythm);
}

.download h1 {
  letter-spacing: -0.015em;
}

.download h2 {
  color: var(--ink-strong);
  font: var(--text-heading);
}

.download p {
  text-wrap: pretty;
}

.download a:not(.button) {
  color: var(--ink-link);
}

.download :not(pre) > code {
  padding: 0.05em 0.3em;
  border-radius: var(--radius);
  color: var(--ink-strong);
  background: var(--surface-active);
  font: var(--text-code);
  font-size: 0.9em;
  white-space: nowrap;
}

.platforms {
  display: grid;
  border-block-start: 1px solid var(--stroke);
}

.platform {
  display: grid;
  gap: var(--space-3) var(--space-5);
  padding-block: var(--space-4);
  border-block-end: 1px solid var(--stroke);
}

.platform[data-yours] {
  order: -1;
}

.platform[data-yours] h2::after {
  content: "This computer";
  margin-inline-start: var(--space-2);
  color: var(--ink-faint);
  font: var(--text-label);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}

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

.platform-head p {
  color: var(--ink-muted);
  font: var(--text-caption);
}

@media (min-width: 40rem) {
  .platform {
    grid-template-columns: minmax(0, 14rem) minmax(0, 1fr);
    align-items: start;
  }
}

.command {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  margin-block-start: var(--space-3);
}

.command p {
  color: var(--ink-subtle);
}

/* ---- footer --------------------------------------------------------- */

.site-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  padding-block: var(--space-5) var(--space-6);
  border-block-start: 1px solid var(--stroke-subtle);
}

.site-footer .brand {
  margin-inline-end: 0;
}

.site-footer .brand-wordmark {
  block-size: 1rem;
}

.footer-link {
  color: var(--ink-muted);
  font: var(--text-control);
}

.footer-link:hover {
  color: var(--ink-strong);
}

.footer-legal {
  margin-inline-start: auto;
  color: var(--ink-faint);
  font: var(--text-caption);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0s !important;
    animation: none !important;
  }

  /* A reader who asks for less motion part way through a visit still has a
     marked document; nothing it was about to draw may stay hidden. */
  [data-motion] [data-scene]:not([data-play]) :is(.rise, .pop, .draw, .draw-y) {
    opacity: 1 !important;
    transform: none !important;
  }
}
