/* MaeVae home page: Stage.

   Show, do not tell. The page opens with the house lights down: a dark
   band in which the drawn window stands, three panes at work, in the
   app's own shape wherever the screen leaves it the room. Where motion
   is allowed, the window plays one short scene the first time it is
   seen: the panes open, the HUD fills, a push is refused, an approval is
   given, and then the third pane asks again and lights up because its
   agent is waiting for you. The scene ends on the drawing itself. Small
   numbered marks on the window tie it to the sections below: each pairs
   one sentence with a detail of the window drawn larger, running off the
   edge of the page the way a close-up crops a scene, and the detail's
   label repeats the number.

   Amber is the attention color, and it means one thing: an agent is
   waiting for you. The lit pane, the notification, the tray badge and the
   mark's one facet use it, and nothing else does. Links, buttons, focus
   rings, numerals and the closing band are ink or night, so the page's one
   color keeps its one meaning. Monospace is used for HUD figures and the
   drawn terminal lines. Every color the page draws is a token here but the
   mark's one facet, a literal in the markup by design: the same mark is
   drawn in icons and pictures, which cannot read a token. The black in the
   field's masks is not drawn; it only sets how much of the field shows. */

:root {
  color-scheme: light;

  /* Light grounds and their ink */
  --paper: #f2f3f1;
  --strip: #e9ebe8;
  --white: #ffffff;
  --ink: #15181b;
  --quiet: #4a5056;
  --line: #d5d9d7;
  --line-strong: #b3b9b6;
  --select: #d5d9d7;

  /* The dark grounds (the stage) and their ink. The base is near-black so
     the drawn window, one step lighter, stands clear of it; night-1 is one
     step up, for the dark bands that hold the product's moments. */
  --night: #0c0e11;
  --night-1: #13161a;
  --night-raised: #1b1e22;
  --night-ink: #e6e8ea;
  --night-body: #c3c9cf;
  --night-quiet: #a9b0b7;
  --night-faint: #8b949c;
  --night-line: #2c3238;
  --night-line-strong: #48515a;
  --night-hover: #1d2227;
  --night-select: #3a4148;

  /* The drawn window: chrome, panels, the panes' terminal ground,
     splitters. Its top edge is one step lighter than its sides, so on a
     dark ground it reads as lit from above without a shadow. The hero's
     window and every drawing of the app share the one terminal ground, so
     every drawn window on the site is the same color. */
  --w-chrome: #23292f;
  --w-pane: #1b2025;
  --w-term: #15191d;
  --w-split: #343c44;
  --night-edge-top: #5a636d;

  /* The field: a quiet grid of round dots behind the first section of
     every page and the showcase. The lit colour is the same dots near the
     pointer, where a fine pointer can hover. */
  --field-dot: #30363d;
  --field-lit: #5a636d;
  --field-pitch: 24px;
  --field-dot-r: 1.1px;

  /* Attention: the amber of the app's own attention state. Used only by
     the lit pane, the notification and the tray badge; text on it is
     night. */
  --amber: #d8a051;
  --on-amber: var(--night);

  /* Set per ground below, so focus rings, outline buttons and the
     numbered marks always fit the ground they sit on */
  --focus: var(--ink);
  --line-ink: var(--ink);
  --line-edge: var(--quiet);
  --line-hover: var(--strip);
  --key-bg: var(--ink);
  --key-ink: var(--paper);

  --sans: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: Consolas, "Cascadia Mono", ui-monospace, monospace;

  /* Type roles: nothing below 15px except the footer's legal line. The
     loud steps (the h1, the sentence set very large, the statement over
     the taskbar, the step numerals) stand against a calm reading size. */
  --fs-legal: 0.875rem;                                     /* 14px */
  --fs-small: 0.9375rem;                                    /* 15px: the drawing, marks */
  --fs-tag: 0.9375rem;                                      /* 15px mono: a label that names a thing */
  --fs-ui: 1rem;                                            /* 16px: nav, buttons */
  --fs-meta: 1.0625rem;                                     /* 17px: limits, dense panes */
  --fs-body: clamp(1.0625rem, 1rem + 0.25vw, 1.1875rem);    /* 17 to 19px */
  --fs-lead: clamp(1.1875rem, 1.1rem + 0.3vw, 1.3125rem);   /* 19 to 21px */
  --fs-label: 1.25rem;                                      /* 20px */
  --fs-h3: clamp(1.25rem, 1.15rem + 0.35vw, 1.4375rem);     /* 20 to 23px */
  --fs-cast: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);        /* 24 to 36px */
  --fs-fact: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);        /* 24 to 36px mono: a fact set as a figure */
  --fs-h2: clamp(1.75rem, 1.3rem + 1.6vw, 2.5rem);          /* 28 to 40px */
  --fs-chapter: clamp(2.25rem, 1.4rem + 3vw, 3.5rem);       /* 36 to 56px: a one-idea chapter */
  --fs-statement: clamp(2rem, 1.2rem + 2.6vw, 3.25rem);     /* 32 to 52px */
  --fs-closing: clamp(2rem, 1.3rem + 2.8vw, 3.5rem);        /* 32 to 56px */
  --fs-huge: clamp(2.25rem, 1.3rem + 3.6vw, 4rem);          /* 36 to 64px */
  --fs-h1: clamp(2.75rem, 1.5rem + 4.4vw, 4.5rem);          /* 44 to 72px */
  --fs-num: clamp(2.5rem, 1.5rem + 3.4vw, 4.25rem);         /* 40 to 68px: always under the h1 at the same width */

  /* Spacing on a 4px base, with section gaps that change pace */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 64px;

  /* The section tiers. A section carries its tier as its top padding and
     only the short end below its last line, so two sections stacked never
     add two tiers. At 1440px: tight 72, normal 96, wide 136, end 23; a
     wide or normal tier opens a section on a new ground (at most 159px of
     space between two lines), a tight tier continues the same ground (95). */
  --section-tight: clamp(40px, 5vw, 72px);
  --section: clamp(56px, 7vw, 96px);
  --section-wide: clamp(80px, 10vw, 136px);
  --section-end: clamp(16px, 1.6vw, 24px);

  --radius: 4px;
  --radius-small: 3px;
  --radius-key: 2px;
  --gutter: 16px;

  /* The content track holds the text and most drawings; the wide track
     holds the hero window and the showcase, which may run to 1680px with a
     small inset from the screen's edge. The content track is 1360px up to
     a 1600px screen, then grows with the screen to 1520px at 1760px, so a
     large screen gives the text and its cells more of its width instead of
     only wider margins. */
  --content: clamp(1360px, 100vw - 240px, 1520px);
  --content-wide: 1680px;
  --wide-inset: clamp(var(--gutter), 2.5vw, 48px);
  --text-col: 29rem;
  --split-gap: 64px;

  /* Text beside its drawing, in the layouts below: never more than 48px
     apart, so the two read as one pair */
  --pair-gap: 48px;

  /* Measures: running prose, a lead, a section heading, a heading over
     the documentation pages' wider reading column, and the longer h3 of a
     task or a question */
  --measure: 70ch;
  --measure-lead: 54ch;
  --measure-heading: 24ch;
  --measure-heading-docs: 32ch;
  --measure-h3: 48ch;

  /* The documentation layout: the side navigation, the right column of a
     very wide screen, and how far below the sticky header both stick */
  --docs-nav: 16rem;
  --docs-aside: 14rem;
  --docs-top: 88px;

  /* The hero scene's one tempo: every part arrives, the notification
     included, in one beat on the same deceleration; what fades out of the
     way takes half a beat; the notification leaves on an ease-in */
  --beat: 480ms;
  --half-beat: 240ms;
  --arrive: cubic-bezier(0.22, 1, 0.36, 1);
  --leave: cubic-bezier(0.5, 0, 0.75, 0);
}

@media (min-width: 640px) {
  :root { --gutter: 24px; }
}

@media (min-width: 1024px) {
  :root { --gutter: 32px; }
}

/* Base */

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

html {
  background: var(--paper);
  scrollbar-color: var(--line-strong) var(--paper);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-wrap: break-word;
}

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

h1,
h2,
h3 {
  color: var(--ink);
  font-weight: 600;
  text-wrap: balance;
}

h2 {
  font-size: var(--fs-h2);
  line-height: 1.15;
  letter-spacing: -0.015em;
}

h3 {
  font-size: var(--fs-h3);
  line-height: 1.3;
}

p {
  max-width: 62ch;
  text-wrap: pretty;
}

strong {
  font-weight: 600;
}

/* Links are ink and underlined: the underline marks them, not a color,
   so no link can be read as an agent that needs you. */
a {
  color: var(--ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

a:hover {
  color: var(--ink);
  text-decoration-thickness: 2px;
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

main:focus {
  outline: none;
}

/* Some drawings and dark grounds run to the screen's edge on purpose.
   clip, unlike hidden, makes no scroll container, so the sticky header and
   the sticky side navigation still stick, and the page never scrolls
   sideways. */
main {
  overflow-x: clip;
}

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

kbd {
  display: inline-block;
  padding: 0 0.4em;
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: var(--radius-small);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.9em;
  line-height: 1.45;
  white-space: nowrap;
}

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

/* Grounds. Light text on the dark ground gets a little more leading. */

.night {
  --focus: var(--night-ink);
  --line-ink: var(--night-ink);
  --line-edge: var(--night-faint);
  --line-hover: var(--night-hover);
  --key-bg: var(--night-ink);
  --key-ink: var(--night);
  background: var(--night);
  color: var(--night-body);
  line-height: 1.65;
}

.night h1,
.night h2,
.night h3,
.night strong {
  color: var(--night-ink);
}

.night a,
.night a:hover {
  color: var(--night-ink);
}

.night ::selection,
.site-header ::selection,
.site-footer ::selection {
  background: var(--night-select);
  color: var(--night-ink);
}

/* The dark band one step up from the base. It is always written together
   with night (class="night night-1"), which sets the light inks. */
.night.night-1 {
  background: var(--night-1);
}

/* The light grounds: paper for the long reading, strip one step darker */
.day,
.paper {
  background: var(--paper);
}

.strip {
  background: var(--strip);
}

/* The lead and the note were made for the night hero; on a light ground
   they take the light inks */
:is(.day, .paper, .strip) .lead {
  color: var(--ink);
}

:is(.day, .paper, .strip) .note {
  color: var(--quiet);
}

/* A full-width hairline on a section's top edge, where two sections share
   a ground and still need a seam */
.hairline-top {
  border-top: 1px solid var(--line);
}

.night.hairline-top,
.night .hairline-top {
  border-top-color: var(--night-line);
}

.skip {
  position: absolute;
  top: -100px;
  left: var(--gutter);
  z-index: 20;
  padding: var(--s2) var(--s4);
  border-radius: var(--radius);
  background: var(--night-ink);
  color: var(--night);
  font-size: var(--fs-ui);
  font-weight: 600;
  text-decoration: none;
}

/* The skip link opens over the dark header, so its ring is the light ink */
.skip:focus {
  top: var(--s3);
  color: var(--night);
  outline: 2px solid var(--night-ink);
}

/* The numbered marks. Small flat squares, the inverse of the ground they
   sit on: light on the dark window and dark bands, dark on paper, dark on
   the lit amber header. A mark on the window and the label under its
   detail carry the same number. No shadow, no glow. */
.key {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  height: 1.5rem;
  padding-inline: 0.3em;
  border-radius: var(--radius-key);
  background: var(--key-bg);
  color: var(--key-ink);
  font-family: var(--sans);
  font-size: var(--fs-small);
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 700;
  line-height: 1;
}

/* Header: dark, so the page opens with the house lights down. The wordmark,
   six short links (Features, Guide, FAQ, Pricing, Download, Early access)
   and the Store action, the same on every page. Below 60em the links and
   the action fold under a Menu toggle when script runs; without it they
   wrap as an inline row, by the rule after the fold. The fold is in em so
   a larger default text size folds earlier. Between 60em and 75em the
   gaps in the row close up a step, so the six links and the Store action
   keep about a tenth of the row to spare at 60em, as five links did with
   the wider gaps. */

.site-header {
  --focus: var(--night-ink);
  --line-ink: var(--night-ink);
  --line-edge: var(--night-faint);
  border-bottom: 1px solid var(--night-line);
  background: var(--night);
  color: var(--night-ink);
}

.header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--s4);
  min-height: 64px;
}

.wordmark,
.wordmark:hover {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding-block: var(--s2);
  color: var(--night-ink);
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
  text-decoration: none;
}

/* The name beside the mark, in the header and in the footer, is a
   picture of the wordmark's own drawing, so the joined ae is the same on
   every computer. The picture is 216 by 51 at three times its size; set
   at 17px tall its M is 14px, the cap of this row's 20px text at 700,
   and its baseline is 15.33px from its top. The row centres a 24px line,
   and a flex item takes no vertical-align, so the margins keep the
   picture's box that 24px tall (4.67 + 17 + 2.33) and put its baseline
   20px down it, where the text's baseline was, with the cap's top level
   with the mark's ink. The footer's link is the same .wordmark, 20px on
   a 24px line on the same night ground, so these rules serve both. The
   name as text beside it is shown only where the picture cannot be
   (below). */
.wordmark-img {
  display: block;
  flex: none;
  width: auto;
  height: 17px;
  margin-top: 4.67px;
  margin-bottom: 2.33px;
}

.wordmark-text {
  display: none;
}

/* The mark: an M folded from one strip, its facets the panes side by side,
   the amber facet the pane where an agent waits. An inline SVG whose ink is
   currentColor, so it takes the text color of wherever it sits. The box is
   the size the drawn panes had, so the header, the notification, the tray
   and the drawn window keep their spacing. */
.mark {
  display: inline-block;
  flex: none;
  width: 20px;
  height: 16px;
  vertical-align: baseline;
}

/* On the notification's amber ground the amber facet would disappear, so
   there the whole mark takes the text color */
.scene-toast .mark path,
.mock-toast .mark path {
  fill: currentColor;
}

/* A contrast theme recolors text but not an SVG's literal fill, so the
   amber facet would keep its color on the theme's ground; there the
   whole mark takes the theme's text color, as it does on the toast */
@media (forced-colors: active) {
  .mark path,
  .hero-mark path {
    fill: currentColor;
  }
}

/* A contrast theme does not recolor a picture either, and the name's
   light ink, in the header and the footer, would all but vanish on a
   light theme's ground; there the picture gives way to the same name as
   text, in the theme's text color */
@media (forced-colors: active) {
  .wordmark-img {
    display: none;
  }

  .wordmark-text {
    display: inline;
  }
}

.nav-toggle {
  display: none;
  align-items: center;
  min-height: 44px;
  margin-left: auto;
  padding: var(--s2) var(--s4);
  border: 1px solid var(--night-faint);
  border-radius: var(--radius);
  background: transparent;
  color: var(--night-ink);
  font: inherit;
  font-size: var(--fs-ui);
  font-weight: 600;
  cursor: pointer;
}

.nav-toggle:hover,
.nav-toggle[aria-expanded="true"] {
  border-color: var(--night-quiet);
  background: var(--night-hover);
}

.site-nav ul {
  padding: 0;
  list-style: none;
}

.site-nav a {
  color: var(--night-ink);
  font-size: var(--fs-ui);
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--white);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
}

/* The current page in the main nav. The underline marks it, as underlines
   mark links across the site, so it cannot read as a signal. The hover
   underline is 1px; the current page keeps a 2px one, so the two read
   apart. */
.site-nav a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.35em;
}

@media (max-width: 59.999em) {
  .js .nav-toggle { display: inline-flex; }

  .site-menu {
    flex-basis: 100%;
    padding-bottom: var(--s4);
  }

  .js .site-menu { display: none; }
  .js .site-menu.is-open { display: block; }

  .site-nav a {
    display: block;
    padding: var(--s3) 0;
    border-top: 1px solid var(--night-line);
  }

  .header-store {
    width: 100%;
    margin-top: var(--s4);
  }
}

/* A page without the toggle script has no Menu toggle, so below 60em the
   rules above would show the links as a tall stacked list over the page.
   There they wrap as an inline row instead, under one hairline, with the
   Store action at its own width under them. Where the script has run, the
   "js" class keeps these rules off and the toggle as it is. From 60em the
   links are inline either way. */
@media (max-width: 59.999em) {
  :root:not(.js) .site-nav ul {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--s5);
    border-top: 1px solid var(--night-line);
  }

  :root:not(.js) .site-nav a {
    display: inline-block;
    padding: var(--s2) 0;
    border-top: 0;
  }

  :root:not(.js) .header-store {
    width: auto;
    margin-top: var(--s2);
  }
}

@media (min-width: 60em) {
  html { scroll-padding-top: 88px; }

  .site-header {
    position: sticky;
    top: 0;
    z-index: 10;
  }

  .header-row {
    flex-wrap: nowrap;
    gap: var(--s6);
  }

  .site-menu {
    display: flex;
    flex: 1;
    align-items: center;
    gap: var(--s5);
  }

  .site-nav ul {
    display: flex;
    gap: var(--s5);
  }

  .site-nav a {
    display: inline-block;
    padding-block: var(--s2);
  }

  .header-store {
    margin-left: auto;
    white-space: nowrap;
  }
}

@media (min-width: 60em) and (max-width: 74.999em) {
  .header-row {
    gap: var(--s5);
  }

  .site-menu,
  .site-nav ul {
    gap: var(--s4);
  }
}

/* The theme switch: one icon button at the row's right end, made by
   theme.js, that cycles System, Light and Dark. The script draws it, so a
   page whose script has not run shows no button that does nothing. Where
   script runs, an empty box of the button's size holds its place until
   it comes, so the row does not move when it does. The icon is drawn in
   currentColor, so it takes the header's ink, the focus ring is the
   site's, and the hover is the Menu toggle's. Below 60em it stands close
   beside the Menu toggle, the two read as a pair, and the menu, which
   opens as a row of its own, is placed after them. */
.theme-toggle,
.js .header-row:not(.has-theme)::after {
  flex: none;
  width: 40px;
  height: 40px;
  margin-left: calc(var(--s2) - var(--s4));
}

.js .header-row:not(.has-theme)::after {
  content: "";
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--night-ink);
  cursor: pointer;
}

.theme-toggle:hover {
  border-color: var(--night-quiet);
  background: var(--night-hover);
}

.theme-toggle svg {
  display: block;
  width: 20px;
  height: 20px;
}

@media (max-width: 59.999em) {
  .site-menu {
    order: 1;
  }
}

/* From 60em the links and the Store action share one row, and at its
   narrowest the row has only a little room to spare, so the switch
   takes as little of it as it can: it stands 8px after the Store
   action, and its box reaches 12px into the gutter, 24px or more there
   at the default text size, so the icon's ink ends where the content
   does */
@media (min-width: 60em) {
  .theme-toggle,
  .js .header-row:not(.has-theme)::after {
    margin-right: -12px;
    margin-left: calc(var(--s2) - var(--s6));
  }
}

@media (min-width: 60em) and (max-width: 74.999em) {
  .theme-toggle,
  .js .header-row:not(.has-theme)::after {
    margin-left: calc(var(--s2) - var(--s5));
  }
}

/* A contrast theme gives the button the system's button text color. The
   icon has no color of its own, only currentColor, so it takes that color
   there, as the mark does */
@media (forced-colors: active) {
  .theme-toggle {
    color: ButtonText;
  }
}

/* On paper a switch is no use */
@media print {
  .theme-toggle,
  .header-row::after {
    display: none;
  }
}

/* Buttons: flat fields, a 4px radius, no shadow. Every button stands on a
   dark ground, so the primary is a light field and the second an outline.
   Amber is never a button. */

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 11px 22px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-size: var(--fs-ui);
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
}

@media (prefers-reduced-motion: no-preference) {
  .btn {
    transition: background-color 150ms cubic-bezier(0.22, 1, 0.36, 1),
                border-color 150ms cubic-bezier(0.22, 1, 0.36, 1);
  }
}

.btn-light,
.btn-light:hover,
.night .btn-light,
.night .btn-light:hover {
  color: var(--night);
  text-decoration: none;
}

.btn-light {
  border-color: var(--night-ink);
  background: var(--night-ink);
}

.btn-light:hover {
  border-color: var(--white);
  background: var(--white);
}

.btn-line,
.btn-line:hover,
.night .btn-line,
.night .btn-line:hover {
  color: var(--line-ink);
  text-decoration: none;
}

.btn-line {
  border-color: var(--line-edge);
  background: transparent;
}

.btn-line:hover {
  border-color: var(--line-ink);
  background: var(--line-hover);
}

.btn-small {
  min-height: 40px;
  padding: var(--s2) var(--s4);
  font-size: var(--fs-small);
}

@media (max-width: 479.98px) {
  .actions .btn { width: 100%; }
}

/* Hero: the headline on two set lines with the lead beside it, the
   actions under the headline, then the stage itself. The headline names
   the scene the window plays a few seconds later: several agents at work,
   and the one that needs you lights up. The text is kept short in height
   so that on a laptop screen the pane headers and HUD strips are in view
   when the page opens, and the scene is seen. */

.hero {
  padding-top: clamp(32px, 3vw, 64px);
  padding-bottom: var(--section-end);
}

.hero-top {
  display: grid;
  gap: var(--s5);
}

.hero h1 {
  font-size: var(--fs-h1);
  font-weight: 650;
  line-height: 1.02;
  letter-spacing: -0.03em;
}

.hero h1 > span {
  display: block;
}

.lead {
  max-width: 54ch;
  color: var(--night-body);
  font-size: var(--fs-lead);
  line-height: 1.55;
}

.note {
  color: var(--night-quiet);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

/* The date line under a policy page's name, on the night ground. The date
   goes in when the text is approved for publication. */
.updated {
  color: var(--night-quiet);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

@media (min-width: 1024px) {
  .hero-top {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: var(--s6) var(--split-gap);
  }

  .hero h1,
  .hero-top .lead {
    grid-row: 1;
    align-self: end;
  }

  .hero h1 { grid-column: 1; }
  .hero-top .lead { grid-column: 2; }

  .hero-top .actions {
    grid-column: 1;
    grid-row: 2;
    align-self: start;
  }

  .hero-top .note {
    grid-column: 2;
    grid-row: 2;
    align-self: center;
    max-width: 40ch;
  }
}

/* The stage: the drawn window at nearly the full width of the screen. It
   is not held to the content width; only a small inset keeps it off the
   screen's edge, and it stops growing at a size a desktop can still read.
   On the home page, from 1024px, home.css gives it the app's own shape. */

.stage {
  margin-top: clamp(32px, 3vw, 48px);
}

.window {
  position: relative;
  max-width: var(--content-wide);
  margin-inline: var(--wide-inset);
  /* The scene's notification rises from below the window's lower edge and
     leaves past its right edge, so the window clips it like a screen.
     clip, where supported, because it does not make the window a scroll
     container that a keyboard or a wheel could move. */
  overflow: hidden;
  overflow: clip;
  border: 1px solid var(--night-line-strong);
  border-top-color: var(--night-edge-top);
  border-radius: var(--radius);
  background: var(--w-term);
  color: var(--night-ink);
  font-size: var(--fs-small);
  line-height: 1.45;
}

@media (min-width: 1776px) {
  .window { margin-inline: auto; }
}

/* The caption keeps the content column's left edge, and its right padding
   holds the text to a 62ch measure (a percentage padding is taken from the
   figure, so the expression repeats the .wrap width). */
.stage figcaption {
  margin-top: var(--s5);
  padding-right: max(0px, min(100% - 2 * var(--gutter), var(--content)) - 62ch);
  color: var(--night-quiet);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

/* Panes stack as rows on narrow screens (one of the app's own layouts) and
   stand as columns from 960px. The 1px gap over the splitter color draws
   the splitters. */
.panes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  background: var(--w-split);
}

@media (min-width: 960px) {
  .panes { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* The three panes share their rows, so the headers, bodies and HUD
     strips line up even though the waiting pane's header holds a second
     row for Approve and Deny. */
  @supports (grid-template-rows: subgrid) {
    .panes { grid-template-rows: auto 1fr auto; }

    .win-pane {
      display: grid;
      grid-row: span 3;
      grid-template-rows: subgrid;
      row-gap: 0;
    }
  }
}

.win-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--w-term);
}

.win-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25em 0.7em;
  padding: 0.65em 0.8em;
  border-bottom: 1px solid var(--w-split);
  background: var(--w-chrome);
  color: var(--night-quiet);
}

.win-name {
  color: var(--night-ink);
  font-weight: 600;
}

.badge {
  margin-left: auto;
  padding: 0 0.45em;
  border: 1px solid currentColor;
  border-radius: var(--radius-small);
}

.win-ask {
  display: flex;
  flex-basis: 100%;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4em 0.5em;
  margin-top: 0.25em;
}

.ask-label {
  margin-right: auto;
  font-weight: 600;
}

.mini-btn {
  padding: 0.05em 0.7em;
  border: 1px solid currentColor;
  border-radius: var(--radius-small);
}

/* The drawn Approve is a night field with light ink: the amber around it
   is the attention, the button itself is not. */
.mini-approve {
  border-color: var(--night);
  background: var(--night);
  color: var(--night-ink);
  font-weight: 600;
}

/* The lit state, the first use of amber: the attention queue turns the
   waiting pane's header into a flat amber field and draws an amber edge
   around the pane. Night text sits on the amber. */
.p3 {
  outline: 2px solid var(--amber);
  outline-offset: -2px;
}

.p3 .win-head,
.win-head.lit {
  --key-bg: var(--night);
  --key-ink: var(--night-ink);
  border-bottom-color: var(--amber);
  background: var(--amber);
  color: var(--on-amber);
}

.p3 .win-name,
.win-head.lit .win-name {
  color: var(--on-amber);
}

.win-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.3em;
  padding: 0.9em 0.8em 1em;
}

/* A line of example output in a drawn terminal pane: real, readable text,
   cut with an ellipsis where a narrow pane cannot hold it. */
.out {
  display: block;
  overflow: hidden;
  color: var(--night-quiet);
  font-family: var(--mono);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.out-now {
  color: var(--night-ink);
}

/* The prompt: a drawn chevron and the caret that waits for you */
.prompt-line {
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin-top: auto;
  padding-top: 0.5em;
}

.chev {
  flex: none;
  width: 0.5em;
  height: 0.5em;
  margin-right: 0.15em;
  border-top: 2px solid var(--night-quiet);
  border-right: 2px solid var(--night-quiet);
  transform: rotate(45deg);
}

.caret {
  display: block;
  width: 0.6em;
  height: 1.15em;
  background: var(--night-ink);
}

/* The approval request in the waiting pane, framed in the lit color: part
   of the lit pane, so part of the same one use of amber */
.ask-box {
  position: relative;
  display: block;
  margin-top: auto;
  padding: 0.55em 0.75em;
  border: 1px solid var(--amber);
  border-radius: var(--radius-small);
}

/* The scene's earlier ask stands in the same box, over the line it gives
   way to, so the box keeps its size from the first frame to the last. It
   is not part of the drawing at rest. */
.ask-early {
  position: absolute;
  top: 0.55em;
  right: 0.75em;
  left: 0.75em;
  visibility: hidden;
}

.win-hud {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15em 1.3em;
  padding: 0.5em 0.8em;
  border-top: 1px solid var(--w-split);
  background: var(--w-chrome);
  color: var(--night-ink);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  line-height: 1.5;
}

.win-hud > span {
  white-space: nowrap;
}

.win-hud .k {
  margin-right: 1ch;
  color: var(--night-faint);
}

/* The session time that counts: each digit is a short column of digits,
   one per line, shown through a window one line tall. The digits are
   generated content, so find-in-page, copy and reader views do not pick up
   a strip of numbers. At rest, and at the end of the scene's count from
   18:06, it reads 18:10. */
.tick {
  display: inline-block;
  height: 1.5em;
  overflow: hidden;
  vertical-align: top;
}

.tick-col {
  display: block;
  width: 1ch;
  line-height: 1.5em;
}

.tick-col::before {
  white-space: pre;
}

.tick-tens::before { content: "0\A 1"; }
.tick-units::before { content: "6\A 7\A 8\A 9\A 0"; }

.tick-tens { transform: translateY(-1.5em); }
.tick-units { transform: translateY(-6em); }

/* The status strip names the waiting pane in words; its mark, 4, ties it
   to the notification further down, which says the same thing outside the
   window. */
.statusbar {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.5em 0.8em;
  border-top: 1px solid var(--w-split);
  background: var(--w-chrome);
}

.status-wait {
  color: var(--night-ink);
}

/* The scene's notification: a Windows notification drawn inside the
   window, at its lower right, in the attention amber (it says an agent is
   waiting for you, the one thing amber means here). Flat, no shadow. It
   is not part of the drawing at rest: it shows only while the scene plays. */
.scene-toast {
  position: absolute;
  right: 0.8em;
  bottom: 0.8em;
  z-index: 1;
  display: grid;
  gap: 2px;
  width: min(21rem, 100% - 1.6em);
  padding: 0.85em 1em 0.95em;
  border-radius: var(--radius);
  background: var(--amber);
  color: var(--on-amber);
  line-height: 1.4;
  visibility: hidden;
  opacity: 0;
}

.scene-toast .toast-title {
  margin-top: 2px;
  font-size: var(--fs-meta);
  line-height: 1.3;
}

.scene-toast .toast-body {
  font-size: var(--fs-small);
}

/* The scene's button: a small outline button under the window's right
   edge that skips the scene while it runs and replays it once it has
   ended. It is shown only once the scene's script has armed the window,
   so it never offers motion that a reader has asked not to see, and never
   sits dead where the script did not run. */
.scene-ctl {
  display: none;
}

/* The scene, on screens where motion is allowed. The scene's own script
   arms the window with "is-armed", adds named states to it in time order
   and ends with "is-done"; every rule here needs an armed window without
   "is-done", so the last frame is the drawing above, unchanged. The
   empty state hangs on the scene's script rather than on script in
   general, so if that one script is blocked or fails, the window is never
   emptied. A page without script, a reader who asks for reduced motion
   and a print never meet these rules and see the drawing at once.

   The rules follow the timeline. Nothing changes size: every part keeps
   its box from the first frame, hidden by opacity, and only opacity and
   transform move. Colors switch in one step, never fade, the way the
   app's own states switch. */

@media screen and (prefers-reduced-motion: no-preference) {
  /* The control keeps the window's own width and side margins, so it
     sits under the window's right edge at every size. Where script runs,
     its row is laid out from the first frame and only shown once the
     window is armed, so arming the window moves nothing below it. */
  .js .window + .scene-ctl,
  .window.is-armed + .scene-ctl {
    display: flex;
    justify-content: flex-end;
    max-width: var(--content-wide);
    margin: var(--s3) var(--wide-inset) 0;
  }

  .js .window:not(.is-armed) + .scene-ctl {
    visibility: hidden;
  }

  @media (min-width: 1776px) {
    .js .window + .scene-ctl,
    .window.is-armed + .scene-ctl { margin-inline: auto; }
  }

  /* Armed: the window stands empty but for the pane columns, their
     splitters and the bare status strip. The empty state has no
     transition, so arming and a replay clear the window at once. */
  .window.is-armed:not(.is-done) .win-head,
  .window.is-armed:not(.is-done) .win-hud,
  .window.is-armed:not(.is-done) .p1 .win-hud > :nth-child(n+3),
  .window.is-armed:not(.is-done) .win-body > :not(.cmd),
  .window.is-armed:not(.is-done) .cmd > *,
  .window.is-armed:not(.is-done) .win-ask,
  .window.is-armed:not(.is-done) .statusbar > * {
    opacity: 0;
    transform: translateY(4px);
    transition: none;
  }

  /* The third pane is lit only while its agent waits, as the app lights
     it: from the earlier ask until Approve clears it, and again from the
     second ask on. Before, and between the two, it wears the unlit
     window's colors, the same as the other two, and its ask box a quiet
     frame. */
  .window.is-armed:not(.is-done):not(.s-lit):not(.s-ask1) .p3,
  .window.is-armed:not(.is-done):not(.s-lit).s-clear .p3 {
    outline-color: transparent;
  }

  .window.is-armed:not(.is-done):not(.s-lit):not(.s-ask1) .p3 .win-head,
  .window.is-armed:not(.is-done):not(.s-lit).s-clear .p3 .win-head {
    --key-bg: var(--night-ink);
    --key-ink: var(--night);
    border-bottom-color: var(--w-split);
    background: var(--w-chrome);
    color: var(--night-quiet);
  }

  .window.is-armed:not(.is-done):not(.s-lit):not(.s-ask1) .p3 .win-name,
  .window.is-armed:not(.is-done):not(.s-lit).s-clear .p3 .win-name {
    color: var(--night-ink);
  }

  .window.is-armed:not(.is-done):not(.s-lit):not(.s-ask1) .p3 .ask-box,
  .window.is-armed:not(.is-done):not(.s-lit).s-clear .p3 .ask-box {
    border-color: var(--night-faint);
  }

  /* The second ask's line waits behind the earlier one */
  .window.is-armed:not(.is-done) .ask-early + .out {
    visibility: hidden;
  }

  /* The session time stands at 18:06 until pane 2's HUD arrives */
  .window.is-armed:not(.is-done) .tick-col {
    transform: translateY(0);
    transition: none;
  }

  /* The figures that count up. While the scene runs, each is covered by a
     column of its earlier values, one per line, seen through its own
     one-line box (the same device as the ticking time); the column moves
     by transform in steps and ends on the drawn figure, exactly over it,
     and goes when the scene ends. The values are generated content, so
     the markup keeps only the drawn figure. */
  .window.is-armed:not(.is-done) .p1 .win-hud > :nth-child(n+3),
  .window.is-armed:not(.is-done) .p2 .win-hud > :nth-child(3) {
    position: relative;
    clip-path: inset(0);
  }

  .window.is-armed:not(.is-done) .p1 .win-hud > :nth-child(n+3)::after,
  .window.is-armed:not(.is-done) .p2 .win-hud > :nth-child(3)::after {
    position: absolute;
    top: 0;
    right: 0;
    background: var(--w-chrome);
    color: var(--night-ink);
    text-align: right;
    white-space: pre;
    transform: translateY(0);
    transition: none;
  }

  .window.is-armed:not(.is-done) .p1 .win-hud > :nth-child(3)::after {
    content: "$0.00\A $0.19\A $0.37\A $0.56\A $0.74\A $0.93\A $1.12\A $1.30\A $1.49\A $1.67\A $1.86";
  }

  .window.is-armed:not(.is-done) .p1 .win-hud > :nth-child(4)::after {
    content: "0%\A 4%\A 8%\A 12%\A 16%\A 21%\A 25%\A 29%\A 33%\A 37%\A 41%";
  }

  .window.is-armed:not(.is-done) .p2 .win-hud > :nth-child(3)::after {
    content: "0%\A 3%\A 6%\A 9%\A 12%";
  }

  /* Arrivals, in time order: each part rises 4px into place as it fades
     in, on the scene's one tempo. A pane opens with its header, then its
     lines one by one, then its HUD. */
  .window.is-armed:not(.is-done).s-p1 .p1 .win-head,
  .window.is-armed:not(.is-done).s-p1-out1 .p1 .win-body > :nth-child(1),
  .window.is-armed:not(.is-done).s-p1-out2 .p1 .win-body > :nth-child(2),
  .window.is-armed:not(.is-done).s-p1-wait .p1 .prompt-line,
  .window.is-armed:not(.is-done).s-p1-hud .p1 .win-hud,
  .window.is-armed:not(.is-done).s-p1-count .p1 .win-hud > :nth-child(n+3),
  .window.is-armed:not(.is-done).s-p2 .p2 .win-head,
  .window.is-armed:not(.is-done).s-p2-out1 .p2 .win-body > :nth-child(1),
  .window.is-armed:not(.is-done).s-p2-hud .p2 .win-hud,
  .window.is-armed:not(.is-done).s-p2-push .p2 .cmd > :not(.tag),
  .window.is-armed:not(.is-done).s-p2-block .p2 .tag,
  .window.is-armed:not(.is-done).s-p2-next .p2 .out-now,
  .window.is-armed:not(.is-done).s-p3 .p3 .win-head,
  .window.is-armed:not(.is-done).s-p3-hud .p3 .win-hud,
  .window.is-armed:not(.is-done).s-ask1 .p3 .win-ask,
  .window.is-armed:not(.is-done).s-ask1 .p3 .ask-box,
  .window.is-armed:not(.is-done).s-p3-out .p3 .win-body > .out,
  .window.is-armed:not(.is-done).s-lit .statusbar > * {
    opacity: 1;
    transform: none;
    transition: opacity var(--beat) var(--arrive),
                transform var(--beat) var(--arrive);
  }

  /* The chevron in pane 2's command line is a border corner turned 45
     degrees, so its rise keeps the turn: the plain empty and arrival
     transforms above would draw it unturned during the scene and snap it
     round on the last frame. Both lists match function for function, so
     the rise interpolates the shift alone. */
  .window.is-armed:not(.is-done) .cmd > .chev {
    transform: translateY(4px) rotate(45deg);
  }

  .window.is-armed:not(.is-done).s-p2-push .p2 .cmd > .chev {
    transform: translateY(0) rotate(45deg);
  }

  /* Pane 1 waits at its prompt: the caret blinks four times and rests,
     visible, long before the scene ends */
  .window.is-armed:not(.is-done).s-p1-wait .p1 .caret {
    animation: caret-blink 1.1s steps(1, end) 4;
  }

  /* Cost and context count once they have faded in; pane 2's context
     counts as its HUD arrives */
  .window.is-armed:not(.is-done).s-p1-count .p1 .win-hud > :nth-child(n+3)::after {
    transform: translateY(-15em);
    transition: transform 1100ms steps(10, end) 200ms;
  }

  .window.is-armed:not(.is-done).s-p2-hud .p2 .win-hud > :nth-child(3)::after {
    transform: translateY(-6em);
    transition: transform 600ms steps(4, end) 200ms;
  }

  /* Pane 2's session time ticks once a second through the next four
     seconds, from 18:06 to 18:10, while the push is refused and pane 3
     asks */
  .window.is-armed:not(.is-done).s-p2-hud .tick-units {
    transform: translateY(-6em);
    transition: transform 4s steps(4, end);
  }

  .window.is-armed:not(.is-done).s-p2-hud .tick-tens {
    transform: translateY(-1.5em);
    transition: transform 4s steps(1, end);
  }

  /* The earlier ask: its line shows in the box, and Approve is pressed */
  .window.is-armed:not(.is-done).s-ask1 .ask-early {
    visibility: visible;
  }

  .window.is-armed:not(.is-done):not(.s-lit).s-press .p3 .mini-approve {
    border-color: var(--night-select);
    background: var(--night-select);
    transform: translateY(1px);
  }

  /* The ask clears: the box and the header's buttons fade where they
     stand, then drop back to their starting place unseen */
  .window.is-armed:not(.is-done).s-clear .p3 .win-ask,
  .window.is-armed:not(.is-done).s-clear .p3 .ask-box {
    opacity: 0;
    transform: translateY(4px);
    transition: opacity var(--half-beat) var(--leave),
                transform 0s linear var(--half-beat);
  }

  /* The second ask: the pane lights again (the colors switch, as the
     app's do), and the box and the buttons rise again with the new line */
  .window.is-armed:not(.is-done).s-lit .p3 .win-ask,
  .window.is-armed:not(.is-done).s-lit .p3 .ask-box {
    opacity: 1;
    transform: none;
    transition: opacity var(--beat) var(--arrive),
                transform var(--beat) var(--arrive);
  }

  .window.is-armed:not(.is-done).s-lit .ask-early {
    visibility: hidden;
  }

  .window.is-armed:not(.is-done).s-lit .ask-early + .out {
    visibility: visible;
  }

  /* The notification: the one part that travels. It waits below the
     window's lower edge, where the window clips it, rises into place,
     stays about three seconds and leaves past the right edge, the way
     Windows dismisses one. */
  .window.is-armed:not(.is-done) .scene-toast {
    visibility: visible;
    transform: translateY(calc(100% + 1em));
    transition: none;
  }

  .window.is-armed:not(.is-done).s-toast .scene-toast {
    opacity: 1;
    transform: none;
    transition: transform var(--beat) var(--arrive),
                opacity var(--half-beat) linear;
  }

  .window.is-armed:not(.is-done).s-toast-out .scene-toast {
    opacity: 0;
    transform: translateX(calc(100% + 1em));
    transition: transform var(--beat) var(--leave),
                opacity var(--beat) var(--leave);
  }
}

@keyframes caret-blink {
  50% { opacity: 0; }
}

/* The cast: the agents it drives, set as large type on hairlines, in
   place of a logo band. The heading is small; the names are the content.
   A second row says what the agents can talk to: a model server on the
   visitor's own PC or an API provider, through the Endpoint field. */

.cast {
  padding-block: var(--section) var(--section-end);
  background: var(--strip);
}

.cast h2,
.cast-sub {
  max-width: 18ch;
  font-size: var(--fs-h3);
  line-height: 1.3;
  letter-spacing: 0;
}

.cast-grid {
  display: grid;
  gap: var(--s5);
}

.cast-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--s5);
  padding: 0;
  list-style: none;
}

.cast-list li {
  padding-block: var(--s3) var(--s4);
  border-top: 1px solid var(--line-strong);
  color: var(--ink);
  font-size: var(--fs-cast);
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.2;
}

.cast-list .shell {
  color: var(--quiet);
  font-weight: 400;
}

.cast-note {
  margin-top: var(--s5);
  color: var(--quiet);
}

.cast-sub {
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 2px solid var(--ink);
}

.local-lead {
  color: var(--ink);
  font-size: var(--fs-lead);
  line-height: 1.5;
}

.cast-local .cast-note {
  margin-top: var(--s4);
}

@media (min-width: 720px) {
  .cast-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .cast-grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    gap: var(--s7) var(--split-gap);
    align-items: start;
  }

  .cast h2 { padding-top: var(--s3); }

  /* On wide screens the local-model row has a rule across both columns:
     the heading's own rule, and one over the text beside it. */
  .cast-sub {
    margin-top: 0;
  }

  .cast-local {
    padding-top: var(--s5);
    border-top: 2px solid var(--ink);
  }
}

/* The older cut-out band: one sentence beside one detail cut from the
   window. The grid has named lines so the detail can run from its column
   to the edge of the screen (the right edge, or the left in a flipped
   band) while the text stays on the content grid. On phones everything
   stacks and the detail still runs off the right edge. A section is this
   band only while it holds a band-grid; the two-column band of the layout
   primitives, further down, uses the class band without one. */

.band:has(> .band-grid) {
  display: block;
  padding-block: var(--section) var(--section-end);
  overflow: hidden;
  overflow: clip;
}

.band-grid {
  display: grid;
  grid-template-columns:
    [full-start] minmax(var(--gutter), 1fr)
    [content-start text-start cut-start] minmax(0, var(--content))
    [content-end text-end cut-end] minmax(var(--gutter), 1fr)
    [full-end];
  row-gap: var(--s7);
}

.band-grid > * {
  grid-column: content-start / content-end;
  min-width: 0;
}

.band-grid > .cut {
  grid-column: content-start / full-end;
}

.band-flip .band-grid > .cut {
  grid-column: full-start / content-end;
}

@media (min-width: 1024px) {
  .band-grid {
    grid-template-columns:
      [full-start] minmax(var(--gutter), 1fr)
      [content-start text-start] minmax(0, var(--text-col))
      [text-end] var(--split-gap)
      [cut-start] minmax(0, calc(var(--content) - var(--text-col) - var(--split-gap)))
      [cut-end content-end] minmax(var(--gutter), 1fr)
      [full-end];
  }

  .band-flip .band-grid {
    grid-template-columns:
      [full-start] minmax(var(--gutter), 1fr)
      [content-start cut-start] minmax(0, calc(var(--content) - var(--text-col) - var(--split-gap)))
      [cut-end] var(--split-gap)
      [text-start] minmax(0, var(--text-col))
      [text-end content-end] minmax(var(--gutter), 1fr)
      [full-end];
  }

  .band-grid > .say {
    grid-column: text-start / text-end;
    grid-row: 1 / span 2;
  }

  .band-grid > .cut {
    grid-column: cut-start / full-end;
    grid-row: 1;
    align-self: start;
    margin-top: var(--s2);
  }

  .band-flip .band-grid > .cut {
    grid-column: full-start / cut-end;
  }

  .band-grid > .halves {
    grid-column: content-start / content-end;
    grid-row: 3;
  }

  /* The large band: the sentence across the content, the lit header
     running off the right edge beneath it, then two short columns. */
  .band-big .band-grid > * {
    grid-column: content-start / content-end;
    grid-row: auto;
  }

  .band-big .band-grid > .cut {
    grid-column: cut-start / full-end;
    margin-top: 0;
  }
}

/* The sentence and what follows it */

.say > * + * {
  margin-top: var(--s4);
}

.say h2 + p {
  margin-top: var(--s5);
}

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

.night .say p {
  color: var(--night-body);
}

/* A limit sits at the foot of the thing it limits, under a hairline */
.limit {
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
  color: var(--quiet);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

.say .limit {
  margin-top: var(--s5);
}

.night .limit,
.night .say .limit {
  border-top-color: var(--night-line);
  color: var(--night-quiet);
}

/* A detail cut from the window: the window's own parts, drawn larger, in
   a frame that is open on the side where it runs off the page. */

.cut {
  font-size: clamp(1.0625rem, 0.85rem + 0.7vw, 1.375rem);
  line-height: 1.45;
}

.frag {
  overflow: hidden;
  border-style: solid;
  border-color: var(--w-split);
  border-width: 1px 0 1px 1px;
  border-radius: var(--radius) 0 0 var(--radius);
  background: var(--w-pane);
  color: var(--night-ink);
}

.night .frag {
  border-color: var(--night-line-strong);
}

.band-flip .frag {
  border-width: 1px 1px 1px 0;
  border-radius: 0 var(--radius) var(--radius) 0;
}

.frag .win-head {
  padding: 0.75em 1em;
}

.frag .win-head:last-child {
  border-bottom: 0;
}

/* In a detail the header runs off the page, so its parts stay together
   at its start instead of being pushed to a far edge that is cut away. */
.frag .badge {
  margin-left: 0;
}

.frag .win-ask {
  flex-basis: auto;
  margin-top: 0;
}

.frag .ask-label {
  margin-right: 0.2em;
}

/* The visible label under each detail: its number, the same as the mark
   on the window, then what it is. The detail runs to the screen's edge, so
   the label keeps a gutter on that side. */
.cut-note {
  display: flex;
  align-items: baseline;
  gap: 0.6em;
  margin-top: var(--s3);
  padding-right: var(--gutter);
  color: var(--quiet);
  font-size: var(--fs-small);
  line-height: 1.5;
}

.night .cut-note {
  color: var(--night-quiet);
}

.band-flip .cut-note {
  justify-content: flex-end;
  max-width: none;
  padding-right: 0;
  padding-left: var(--gutter);
  text-align: right;
}

/* The HUD detail is drawn at a larger size than the others: a readout,
   not a strip, so the details do not all share one scale. */
.band-flip .cut {
  font-size: clamp(1.1875rem, 0.75rem + 1.3vw, 1.75rem);
}

.hud-big {
  gap: 0.35em 1.4em;
  padding: 0.85em 1.1em;
  border-top: 0;
}

.band-flip .hud-big {
  justify-content: flex-end;
}

/* The drawn refusal: a push command marked as blocked, and the prompt
   back, waiting for the next command (this caret does not blink) */
.frag-term {
  display: flex;
  flex-direction: column;
  gap: 0.5em;
  padding: 1.1em 1.2em 1.2em;
}

.cmd {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5em 0.8em;
  color: var(--night-ink);
  font-family: var(--mono);
}

.tag {
  padding: 0 0.5em;
  border: 1px solid var(--night-quiet);
  border-radius: var(--radius-small);
  color: var(--night-ink);
  font-family: var(--sans);
  font-weight: 600;
}

/* The large band: the one sentence on the page set very large */
.band-big:has(> .band-grid) {
  padding-block: var(--section-wide) var(--section-end);
}

.huge {
  max-width: 18ch;
  font-size: var(--fs-huge);
  font-weight: 650;
  line-height: 1.04;
  letter-spacing: -0.028em;
}

.say-cols {
  display: grid;
  gap: var(--s5);
}

.say-cols > * {
  padding-top: var(--s4);
  border-top: 1px solid var(--line-strong);
}

.say-cols > p:first-child {
  color: var(--ink);
}

@media (min-width: 900px) {
  .say-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--split-gap);
    align-items: start;
  }
}

/* The tray band: a different shape from the cutout bands. A statement set
   large across the band with its paragraph beside it, then the drawn
   desktop: the notification standing over the right end of a taskbar
   that runs the full width of the screen and closes the band at its foot.
   The second and third uses of amber are here: the notification and the
   tray badge. */

.tray-band {
  overflow: hidden;
  overflow: clip;
  padding-top: var(--section);
}

.tray-top {
  display: grid;
  gap: var(--s6);
}

.statement {
  font-size: var(--fs-statement);
  font-weight: 650;
  line-height: 1.06;
  letter-spacing: -0.025em;
}

.statement > span {
  display: block;
}

.tray-say > * + * {
  margin-top: var(--s5);
}

@media (min-width: 1024px) {
  .tray-top {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--split-gap);
    align-items: end;
  }
}

.desk {
  margin-top: var(--s8);
}

/* The label sits above the notification, so the notification stands
   directly over the tray icon it belongs to. */
.desk-note {
  padding-right: 0;
}

.desk-note > span:last-child {
  max-width: 28rem;
}

@media (min-width: 720px) {
  .desk-note { justify-content: flex-end; }
}

.desk-row {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--s3);
  padding-bottom: var(--s4);
}

.toast {
  display: grid;
  gap: var(--s2);
  width: 100%;
  max-width: 28rem;
  padding: 20px var(--s5) 22px;
  border-radius: var(--radius);
  background: var(--amber);
  color: var(--on-amber);
}

.toast-app {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.4;
}

.toast-title {
  margin-top: 6px;
  font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

.toast-body {
  font-size: var(--fs-body);
  line-height: 1.45;
}

/* The taskbar runs the full width, like the real one; the tray sits at the
   content's right edge, under the notification. The icons are drawn with
   lines, in the band's quiet ink. */
.taskbar {
  border-top: 1px solid var(--night-line);
  background: var(--night-raised);
}

.taskbar-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  height: 48px;
}

.tray {
  display: inline-flex;
  align-items: center;
  gap: 18px;
  padding-right: 6px;
  color: var(--night-quiet);
}

.tray-chevron {
  width: 8px;
  height: 8px;
  border-top: 2px solid currentColor;
  border-left: 2px solid currentColor;
  transform: translateY(2px) rotate(45deg);
}

.tray-glyph {
  width: 14px;
  height: 12px;
  border: 2px solid currentColor;
  border-radius: 2px;
}

.tray-glyph + .tray-glyph {
  width: 13px;
  height: 13px;
  border-radius: 50%;
}

.tray-mae {
  position: relative;
  display: inline-flex;
  color: var(--night-ink);
}

/* The tray badge, the third use of amber. Its ring is the taskbar's own
   color, so the badge reads as set into the icon, not glowing on it. */
.tray-badge {
  position: absolute;
  top: -8px;
  right: -9px;
  width: 17px;
  height: 17px;
  border: 2px solid var(--night-raised);
  border-radius: 50%;
  background: var(--amber);
}

/* Restricted mode, on paper: what it does and where it stops, given
   equal weight and the same ink */
.halves {
  display: grid;
  border-top: 1px solid var(--line-strong);
}

.halves > div {
  display: grid;
  align-content: start;
  gap: var(--s3);
  padding-block: var(--s5);
}

.halves > div + div {
  border-top: 1px solid var(--line);
}

.halves h3 {
  font-size: var(--fs-label);
  line-height: 1.35;
}

@media (min-width: 720px) {
  .halves {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--split-gap);
  }

  .halves > div + div { border-top: 0; }
}

/* Steps: a real sequence, so the numerals are large and carry the order.
   They are ink, set light: structure, not a signal. */

.steps-sec {
  padding-block: var(--section) var(--section-end);
  border-block: 1px solid var(--line);
  background: var(--strip);
}

.steps-sec h2 {
  max-width: 20ch;
}

.steps {
  display: grid;
  gap: var(--s7);
  margin-top: var(--s7);
  padding: 0;
  list-style: none;
}

.steps li {
  display: grid;
  align-content: start;
  gap: var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--line-strong);
}

.step-n {
  margin-bottom: var(--s2);
  color: var(--ink);
  font-size: var(--fs-num);
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 300;
  letter-spacing: -0.04em;
  line-height: 0.9;
}

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

@media (min-width: 900px) {
  .steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--s7);
  }
}

/* Also in the app: the one dense grid of panes, sharing 1px lines */

.more {
  padding-block: var(--section) var(--section-end);
}

.more h2 {
  margin-bottom: var(--s6);
}

.tiles {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--line);
}

@media (min-width: 720px) {
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--white);
}

.pane-head {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
  background: var(--strip);
  font-size: var(--fs-label);
  line-height: 1.35;
}

.pane-body {
  padding: var(--s4) var(--s4) var(--s5);
  font-size: var(--fs-meta);
  line-height: 1.6;
}

/* Pushed to the foot, where the app puts its HUD */
.pane-limit {
  max-width: none;
  margin-top: auto;
  padding: var(--s3) var(--s4) 14px;
  border-top: 1px solid var(--line);
  background: var(--strip);
  color: var(--quiet);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

@media (min-width: 720px) {
  .pane-head,
  .pane-body,
  .pane-limit {
    padding-inline: var(--s5);
  }

  .pane-badge,
  .pane-reports {
    grid-column: span 2;
  }
}

@media (min-width: 1024px) {
  .pane-badge { grid-column: auto; }
}

/* What each agent reports: the densest pane, a two-column table on
   hairlines */
.reports {
  font-size: var(--fs-meta);
  line-height: 1.5;
}

.reports > div {
  display: grid;
  gap: 2px var(--s4);
  padding-block: 10px;
  border-bottom: 1px solid var(--line);
}

.reports > div:first-child { padding-top: 0; }
.reports > div:last-child { border-bottom: 0; padding-bottom: 0; }

@media (min-width: 480px) {
  .reports > div { grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); }
}

.reports dt {
  font-weight: 600;
}

/* What it never does: four plain statements on the strip ground, each
   set at heading size with its one-line reason under it. No boxes. */

.never-sec {
  padding-block: var(--section) var(--section-end);
  border-block: 1px solid var(--line);
  background: var(--strip);
}

.qa-split {
  display: grid;
  gap: var(--s5);
}

.never {
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line-strong);
}

.never li {
  max-width: 64ch;
  padding-block: var(--s5);
  border-bottom: 1px solid var(--line-strong);
  color: var(--quiet);
}

.never strong {
  display: block;
  margin-bottom: var(--s1);
  color: var(--ink);
  font-size: var(--fs-h3);
  line-height: 1.3;
}

/* Questions and answers, on hairlines, with no boxes */

.qa-before {
  padding-block: var(--section) var(--section-end);
}

.qa-before h2 {
  margin-bottom: var(--s6);
}

.qa-list {
  border-top: 1px solid var(--line-strong);
}

.qa {
  display: grid;
  gap: var(--s3);
  padding-block: var(--s6);
  border-bottom: 1px solid var(--line);
}

.answer > * + * {
  margin-top: var(--s4);
}

.needs {
  max-width: 64ch;
  padding-left: 1.2em;
}

.needs li + li {
  margin-top: var(--s2);
}

.needs li::marker {
  color: var(--quiet);
}

@media (min-width: 1024px) {
  .qa-split,
  .qa {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: var(--split-gap);
  }

  .qa-split { align-items: start; }
  .qa { align-items: baseline; }
}

/* Closing: the house lights go down again. One statement set large on the
   night ground, the hero's two actions once more, and the footer under a
   hairline in the same dark. */

.closing {
  padding-block: var(--section-wide) var(--section-end);
}

.closing-line {
  max-width: 22ch;
  font-size: var(--fs-closing);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.025em;
}

.closing-row {
  display: grid;
  gap: var(--s4);
  margin-top: var(--s7);
}

.closing .note {
  margin-top: 0;
}

@media (min-width: 1024px) {
  .closing-row {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: var(--s6);
  }
}

/* Footer: the brand line with the platforms, then three columns: Product
   (every page of the site but the legal two), Legal, and Contact, which
   holds the support address and the company line. */

.site-footer {
  --focus: var(--night-ink);
  padding-block: var(--s8) var(--s6);
  border-top: 1px solid var(--night-line);
  background: var(--night);
  color: var(--night-quiet);
  font-size: var(--fs-ui);
  line-height: 1.5;
}

.footer-grid {
  display: grid;
  gap: var(--s6);
}

.footer-brand p {
  max-width: 32ch;
  margin-top: var(--s2);
  color: var(--night-quiet);
}

.footer-brand .platforms {
  color: var(--night-ink);
}

.footer-nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s6) var(--s5);
}

.foot-h {
  margin-bottom: var(--s2);
  color: var(--night-ink);
  font-size: var(--fs-ui);
  line-height: 1.4;
}

.footer-nav ul {
  display: grid;
  gap: 2px;
  padding: 0;
  list-style: none;
}

/* 6px of block padding gives each link a touch target of about 36px */
.footer-nav a {
  display: inline-block;
  padding-block: 6px;
  color: var(--night-quiet);
  text-decoration: none;
}

.footer-nav a:hover {
  color: var(--night-ink);
  text-decoration: underline;
}

/* The current page in the footer, marked the same way as in the main nav */
.footer-nav a[aria-current="page"] {
  color: var(--night-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.footer-mail {
  overflow-wrap: anywhere;
}

/* The company line, under the support address in the Contact column */
.company {
  margin-top: var(--s2);
  color: var(--night-faint);
  font-size: var(--fs-legal);
}

/* The company logo under its name; the file carries its own ink tone, since an image cannot read the page's tokens */
.company-logo {
  display: block;
  width: 10rem;
  max-width: 100%;
  height: auto;
  margin-top: var(--s3);
}

@media (min-width: 600px) {
  .footer-nav { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .footer-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
    gap: var(--s7);
  }
}

/* Windows contrast themes replace backgrounds, which would erase the gap
   lines, the caret, the lit field, the marks and the notification; real
   borders and system colors keep them. */
@media (forced-colors: active) {
  .tiles,
  .panes {
    gap: 0;
  }

  .pane,
  .win-pane {
    border: 1px solid CanvasText;
  }

  .caret {
    background: CanvasText;
  }

  /* The detail keeps its open side; the mark gets a frame of its own */
  .frag {
    border-color: CanvasText;
  }

  .key {
    border: 1px solid CanvasText;
  }

  .p3 { outline-color: Highlight; }

  .p3 .win-head,
  .frag .win-head.lit {
    border-bottom: 2px solid Highlight;
  }

  .ask-box { border-color: Highlight; }
  .mini-approve { border-color: Highlight; }

  .toast,
  .scene-toast { border: 2px solid CanvasText; }
  .taskbar { border-top-color: CanvasText; }

  .tray-badge {
    forced-color-adjust: none;
    border-color: Canvas;
    background: Highlight;
  }

  .btn { border-color: ButtonText; }
}

/* ==================================================================
   The layout primitives. Every section is one of these layouts and says
   which in its class: chapter, band, cols, reading or docs, on one of the
   grounds (night, night night-1, paper, strip), with one tier. The parts
   below come in that order: the tiers, the type helpers, the field, then
   each layout, then the accordion, the question filter and the agents row.
   ================================================================== */

/* The tiers, one per section. The top padding is the tier; the bottom is
   the short section end, so the space between two sections is one tier
   and one end, never two tiers. A tight tier continues the same ground;
   normal and wide open a section on a new ground. */
.tier-tight {
  padding-block: var(--section-tight) var(--section-end);
}

.tier-normal {
  padding-block: var(--section) var(--section-end);
}

.tier-wide {
  padding-block: var(--section-wide) var(--section-end);
}

/* A section whose last part is drawn edge to edge, such as a taskbar,
   ends on that part */
.end-flush {
  padding-bottom: 0;
}

/* The type helpers. A chapter heading is the largest heading after the
   page's own; a fact is set as a figure in monospace; a label names a
   thing (a chapter of a scene, a column, a tool) in small monospace. */
.chapter-text > h2,
.fs-chapter {
  max-width: var(--measure-heading);
  font-size: var(--fs-chapter);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.025em;
}

.fact {
  display: block;
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--fs-fact);
  font-variant-numeric: tabular-nums;
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.night .fact {
  color: var(--night-ink);
}

.label-mono {
  font-family: var(--mono);
  font-size: var(--fs-tag);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.04em;
}

/* A list on hairlines: what a feature does, a few facts beside a heading */
.hair-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line-strong);
}

.hair-list > li {
  max-width: var(--measure);
  padding-block: var(--s3);
  border-bottom: 1px solid var(--line);
}

.night .hair-list {
  border-top-color: var(--night-line-strong);
}

.night .hair-list > li {
  border-bottom-color: var(--night-line);
}

/* The field: a grid of round dots drawn in CSS behind the first section
   of every page (each page opens on the night ground) and behind the
   showcase (.field). It is a pseudo-element, so no reader meets it, and it
   fills its section exactly, so it never widens the page. A veil of the
   night colour, painted over the dots, keeps them out from behind the
   text; a page tunes the veil to its own text block with --field-veil-at
   and --field-veil-size. Masks fade the dots at every edge. */
main > section.night:first-child,
.field {
  --fx: -9999px;
  --fy: -9999px;
  position: relative;
  isolation: isolate;
}

main > section.night:first-child::before,
.field::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(ellipse var(--field-veil-size, 70% 60%) at var(--field-veil-at, 42% 20%),
      color-mix(in srgb, var(--night) 96%, transparent) 0%,
      color-mix(in srgb, var(--night) 78%, transparent) 40%,
      color-mix(in srgb, var(--night) 30%, transparent) 65%,
      transparent 85%),
    radial-gradient(circle, var(--field-dot) var(--field-dot-r), transparent calc(var(--field-dot-r) + 0.5px));
  background-size: 100% 100%, var(--field-pitch) var(--field-pitch);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
}

/* Where masks can be intersected, the sides fade too. Elsewhere the one
   vertical fade above stands alone, which still reads as a field. */
@supports (mask-composite: intersect) {
  main > section.night:first-child::before,
  .field::before {
    -webkit-mask-image:
      linear-gradient(to right, transparent, #000 14%, #000 86%, transparent),
      linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
    -webkit-mask-composite: source-in;
    mask-image:
      linear-gradient(to right, transparent, #000 14%, #000 86%, transparent),
      linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
    mask-composite: intersect;
  }
}

/* The pointer layer: the same dots, one step lighter, shown only in a
   circle round the pointer. It exists only where a fine pointer can hover
   and motion is welcome; the script in mock.js moves the circle when the
   pointer moves, so nothing changes while the pointer is still and nothing
   plays on its own. Its mask also leaves out the veiled area behind the
   text, so the lit dots never sit under a line of reading. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  main > section.night:first-child::after,
  .field::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image: radial-gradient(circle, var(--field-lit) var(--field-dot-r), transparent calc(var(--field-dot-r) + 0.5px));
    background-size: var(--field-pitch) var(--field-pitch);
    opacity: 0;
    transition: opacity var(--half-beat) linear;
    -webkit-mask-image: radial-gradient(180px circle at var(--fx) var(--fy), #000, transparent 70%);
    mask-image: radial-gradient(180px circle at var(--fx) var(--fy), #000, transparent 70%);
  }

  main > section.night:first-child.is-pointing::after,
  .field.is-pointing::after {
    opacity: 1;
  }

  @supports (mask-composite: intersect) {
    main > section.night:first-child::after,
    .field::after {
      -webkit-mask-image:
        radial-gradient(180px circle at var(--fx) var(--fy), #000, transparent 70%),
        radial-gradient(ellipse var(--field-veil-size, 70% 60%) at var(--field-veil-at, 42% 20%),
          rgb(0 0 0 / 0.04) 0%, rgb(0 0 0 / 0.22) 40%, rgb(0 0 0 / 0.7) 65%, #000 85%),
        linear-gradient(to right, transparent, #000 14%, #000 86%, transparent),
        linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
      -webkit-mask-composite: source-in;
      mask-image:
        radial-gradient(180px circle at var(--fx) var(--fy), #000, transparent 70%),
        radial-gradient(ellipse var(--field-veil-size, 70% 60%) at var(--field-veil-at, 42% 20%),
          rgb(0 0 0 / 0.04) 0%, rgb(0 0 0 / 0.22) 40%, rgb(0 0 0 / 0.7) 65%, #000 85%),
        linear-gradient(to right, transparent, #000 14%, #000 86%, transparent),
        linear-gradient(to bottom, transparent, #000 8%, #000 72%, transparent);
      mask-composite: intersect;
    }
  }
}

/* A contrast theme or a printed page gets the plain ground: the dots
   would be noise there */
@media (forced-colors: active), print {
  main > section.night:first-child::before,
  main > section.night:first-child::after,
  .field::before,
  .field::after {
    display: none;
  }
}

/* The track the hero window and the showcase stand on: up to 1680px, with
   the same small inset from the screen's edge as the hero window */
.wrap-wide {
  width: min(100% - 2 * var(--wide-inset), var(--content-wide));
  margin-inline: auto;
}

/* The chapter: one idea, one large drawing. The class goes on the section
   itself, not inside a wrap: the grid's outer tracks are the page margins,
   so the text keeps the content column's edge while the drawing can run on
   into the margin to the screen's edge (bleed). From 1024px the text takes
   five twelfths of the content and the drawing the rest; under the pair
   runs a full-width row, usually the limit, on its hairline. On a narrow
   screen everything stacks in the content column. At 1440px the drawing is
   765px wide, 805px when it bleeds. */
.chapter {
  --cw: min(100% - 2 * var(--gutter), var(--content));
  display: grid;
  grid-template-columns:
    [full-start] minmax(0, 1fr)
    [content-start text-start art-start] var(--cw)
    [content-end text-end art-end] minmax(0, 1fr)
    [full-end];
  row-gap: var(--pair-gap);
}

.chapter > * {
  grid-column: content;
  min-width: 0;
}

.chapter-text > * + * {
  margin-top: var(--s5);
}

.chapter-text > h2 + * {
  margin-top: var(--s5);
}

.chapter-text p {
  max-width: var(--measure);
}

.chapter-text .lead {
  max-width: var(--measure-lead);
}

/* The drawing's wrapper. The drawing inside fills it. */
.chapter-art {
  min-width: 0;
}

/* The row under the pair: the limit, a row of cells, a table */
.chapter > .limit,
.chapter > .chapter-foot {
  grid-column: content;
}

@media (min-width: 1024px) {
  .chapter {
    --tw: calc((var(--cw) - var(--pair-gap)) * 5 / 12);
    grid-template-columns:
      [full-start] minmax(0, 1fr)
      [content-start text-start] var(--tw)
      [text-end] var(--pair-gap)
      [art-start] calc(var(--cw) - var(--tw) - var(--pair-gap))
      [art-end content-end] minmax(0, 1fr)
      [full-end];
    align-items: start;
  }

  .chapter > .chapter-text {
    grid-column: text;
    grid-row: 1;
  }

  .chapter > .chapter-art {
    grid-column: art;
    grid-row: 1;
  }

  /* The drawing first, the text second, on the same lines */
  .chapter.flip {
    grid-template-columns:
      [full-start] minmax(0, 1fr)
      [content-start art-start] calc(var(--cw) - var(--tw) - var(--pair-gap))
      [art-end] var(--pair-gap)
      [text-start] var(--tw)
      [text-end content-end] minmax(0, 1fr)
      [full-end];
  }

  /* The drawing runs on to the screen's edge on its side. Its own edge on
     that side is left open, the way a close-up is cropped by the frame. */
  .chapter.bleed > .chapter-art {
    grid-column: art-start / full-end;
  }

  .chapter.flip.bleed > .chapter-art {
    grid-column: full-start / art-end;
  }

  .chapter.bleed > .chapter-art > :first-child,
  .chapter.bleed > .chapter-art > .mock-scene > :first-child {
    border-right-width: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
  }

  .chapter.flip.bleed > .chapter-art > :first-child,
  .chapter.flip.bleed > .chapter-art > .mock-scene > :first-child {
    border-right-width: 1px;
    border-top-right-radius: var(--radius);
    border-bottom-right-radius: var(--radius);
    border-left-width: 0;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }

  /* A drawing that bleeds keeps its controls and caption on the content
     grid, so they do not run off the page with it */
  .chapter.bleed > .chapter-art .mock-controls,
  .chapter.bleed > .chapter-art .mock-caption {
    padding-right: var(--gutter);
  }

  .chapter.flip.bleed > .chapter-art .mock-controls,
  .chapter.flip.bleed > .chapter-art .mock-caption {
    padding-right: 0;
    padding-left: var(--gutter);
  }

  /* A chapter that holds only words on its two sides, such as the
     showcase's heading row: the note sits level with the heading's foot */
  .chapter-art.is-note {
    align-self: end;
  }
}

/* The band: text in one column and a medium drawing in the other, from
   900px. The text takes five twelfths and the drawing seven, or they share
   the width evenly (even); flip puts the drawing first. The drawing fills
   its column. At 1440px the drawing's column is 765px (656px when even),
   and on a plate the drawing itself is 719px (610px). A row under both
   (band-foot) holds a table or a drawing as wide as the content. */
.band {
  display: grid;
  gap: var(--pair-gap);
  align-items: start;
}

.band > * {
  min-width: 0;
}

.band-text > * + * {
  margin-top: var(--s4);
}

.band-text > h2 + * {
  margin-top: var(--s5);
}

.band-text > h2 {
  max-width: var(--measure-heading);
}

.band-text p {
  max-width: var(--measure);
}

@media (min-width: 900px) {
  .band {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }

  .band.even {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .band.flip {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  }

  .band.flip.even {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .band > .band-text {
    grid-column: 1;
    grid-row: 1;
  }

  .band > .band-art {
    grid-column: 2;
    grid-row: 1;
  }

  .band.flip > .band-art {
    grid-column: 1;
  }

  .band.flip > .band-text {
    grid-column: 2;
  }

  .band > .band-foot,
  .band > .limit {
    grid-column: 1 / -1;
  }
}

/* A drawing that follows its text (follow, on a chapter or a band): beside
   a text longer than the drawing, the drawing stays in view while the
   text is read, so its column is not an empty cell on screen. Only from
   1024px on a screen at least 820px tall, where the whole drawing, its
   controls and its caption fit under the header. A sticky box is held
   inside its parent's whole box, not inside its own grid row, so a parent
   marked follow holds the text and the drawing and nothing else; with any
   third child (a limit, a foot row) the rule does not apply, and the
   drawing stands still rather than paint over that row. */
@media (min-width: 1024px) and (min-height: 820px) {
  .follow:not(:has(> :not(.chapter-text, .chapter-art, .band-text, .band-art))) > :is(.chapter-art, .band-art) {
    position: sticky;
    top: var(--docs-top);
  }
}

/* Equal columns of facts, steps or tiles: one column on a phone, two to
   1099px, three or four from 1100px. Each cell stands on a hairline. The
   last cell widens to close its row, so no cell is ever left empty. At
   1440px a cell of three is 421px wide, a cell of four 304px. */
.cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s6) var(--pair-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cols > * {
  min-width: 0;
  padding-top: var(--s4);
  border-top: 1px solid var(--line-strong);
}

.night .cols > * {
  border-top-color: var(--night-line-strong);
}

.cols > * > * + * {
  margin-top: var(--s3);
}

@media (min-width: 720px) {
  .cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .cols > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1100px) {
  .cols.cols-3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .cols.cols-4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .cols.cols-3 > :last-child,
  .cols.cols-4 > :last-child {
    grid-column: auto;
  }

  .cols.cols-3 > :last-child:nth-child(3n + 1),
  .cols.cols-4 > :last-child:nth-child(4n + 1) {
    grid-column: 1 / -1;
  }

  .cols.cols-3 > :last-child:nth-child(3n + 2),
  .cols.cols-4 > :last-child:nth-child(4n + 3) {
    grid-column: span 2;
  }

  .cols.cols-4 > :last-child:nth-child(4n + 2) {
    grid-column: span 3;
  }
}

/* Tiles: the same columns as white cells that share 1px lines, for the
   twelve small scenes. A tile's padding stays at 24px, so at 1440px the
   drawing inside a tile of three is 404px wide. */
.cols.tiled {
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--line);
}

.cols.tiled > * {
  padding: var(--s5);
  border-top: 0;
  background: var(--white);
}

/* The reading row: the heading, and under it a short note or a list of
   facts, in four twelfths; the text at a reading measure in the other
   eight; a row under both for what belongs to the two. A heading never
   stands alone above an empty cell. At 1440px the columns are 437px and
   875px. */
.reading {
  display: grid;
  gap: var(--s5) var(--pair-gap);
}

.reading > * {
  min-width: 0;
}

.reading-head > h2 {
  max-width: var(--measure-heading);
}

.reading-head > * + *,
.reading-aside > * + *,
.reading-body > * + * {
  margin-top: var(--s4);
}

.reading-head > h2 + * {
  margin-top: var(--s5);
}

.reading-body p {
  max-width: var(--measure);
}

@media (min-width: 1024px) {
  .reading {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    grid-template-rows: auto 1fr;
    align-items: start;
  }

  .reading > .reading-head {
    grid-column: 1;
    grid-row: 1;
  }

  .reading > .reading-aside {
    grid-column: 1;
    grid-row: 2;
  }

  .reading > .reading-body {
    grid-column: 2;
    grid-row: 1 / span 2;
  }

  .reading > .reading-foot {
    grid-column: 1 / -1;
    grid-row: auto;
  }
}

/* The documentation layout: a side navigation that follows the reader,
   and the reading column. From 1024px the navigation is a sticky column of
   16rem on the left; from 1600px the layout takes the wide track and a
   chapter may hold its own task list in a 14rem column on the right. Under
   1024px the navigation is a "Contents" disclosure at the top. The script
   in mock.js marks the link of the part in view and keeps it in sight;
   without it the navigation is a plain list of links, open. At 1440px the
   reading column is 1056px wide; prose in it keeps a reading measure and a
   drawing takes the whole column. */
.docs {
  display: grid;
  gap: var(--s6) var(--pair-gap);
  width: min(100% - 2 * var(--gutter), var(--content));
  margin-inline: auto;
}

.docs > * {
  min-width: 0;
}

/* The disclosure that holds the navigation */
.docs-toc {
  border-block: 1px solid var(--line-strong);
}

.docs-toc > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 48px;
  padding-block: var(--s2);
  color: var(--ink);
  font-size: var(--fs-ui);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}

.docs-toc > summary::-webkit-details-marker {
  display: none;
}

/* The disclosure's chevron, drawn with two borders */
.docs-toc > summary::after {
  content: "";
  flex: none;
  width: 0.55em;
  height: 0.55em;
  margin-right: 0.35em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-25%) rotate(45deg);
}

.docs-toc[open] > summary::after {
  transform: translateY(25%) rotate(-135deg);
}

.docs-nav {
  padding-block: var(--s2) var(--s4);
}

.docs-nav ol,
.docs-nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.docs-nav > ol > li + li {
  margin-top: var(--s1);
}

/* A link: a quiet line with a bar on its left that marks the part in
   view. The bar and the weight carry the mark, not a colour. */
.docs-nav a {
  display: block;
  padding: 5px 0 5px 12px;
  border-left: 2px solid transparent;
  color: var(--quiet);
  font-size: var(--fs-ui);
  line-height: 1.4;
  text-decoration: none;
}

.docs-nav li li a {
  padding-left: 26px;
  font-size: var(--fs-small);
}

.docs-nav a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
}

/* Beside the text the navigation scrolls its own list, which clips
   whatever stands outside its box, so the focus ring is drawn inside the
   link, on all four sides */
.docs-nav a:focus-visible {
  outline-offset: -2px;
}

.docs-nav a[aria-current="location"] {
  border-left-color: var(--ink);
  color: var(--ink);
  font-weight: 600;
}

/* The chapter that holds the task in view reads as open */
.docs-nav li:has(a[aria-current="location"]) > a {
  color: var(--ink);
}

/* A chapter's number in the navigation */
.docs-n {
  display: inline-block;
  min-width: 2ch;
  margin-right: 0.6ch;
  color: var(--quiet);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* A chapter: its number in Stage's large light numerals, its title, one
   line on what the reader will be able to do, then its tasks */
.docs-sec {
  padding-block: var(--section-tight) var(--section-end);
}

.docs-main > .docs-sec:first-child {
  padding-top: 0;
}

.docs-main > .docs-sec + .docs-sec:not(.night) {
  border-top: 1px solid var(--line-strong);
}

/* A chapter that has its own task list on a very wide screen wraps the
   rest of its content in docs-sec-body; the flow below holds in both */
:is(.docs-sec, .docs-sec-body) > * + * {
  margin-top: var(--s4);
}

/* A chapter's heading stands over a reading column wider than a marketing
   section's text, so it takes a longer measure and wraps less */
:is(.docs-sec, .docs-sec-body) > h2 {
  max-width: var(--measure-heading-docs);
}

:is(.docs-sec, .docs-sec-body) > h2 + * {
  margin-top: var(--s5);
}

.docs-sec p,
.docs-sec li {
  max-width: var(--measure);
}

.docs-sec ol:not([class]),
.docs-sec ul:not([class]) {
  padding-left: 1.4em;
}

.docs-sec ol:not([class]) > li + li,
.docs-sec ul:not([class]) > li + li {
  margin-top: var(--s2);
}

.docs-num {
  color: var(--ink);
  font-size: var(--fs-num);
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 300;
  letter-spacing: -0.04em;
  line-height: 0.9;
}

.night .docs-num {
  color: var(--night-ink);
}

/* A task: its name as a heading on a hairline, then its steps, its scene
   and what the reader sees. The scene stands within 32px of its text. */
.docs-task {
  max-width: var(--measure-h3);
  margin-top: var(--s7);
  padding-top: var(--s5);
  border-top: 1px solid var(--line);
  scroll-margin-top: var(--s4);
}

.night .docs-task {
  border-top-color: var(--night-line);
}

:is(.docs-sec, .docs-sec-body) > .docs-task + * {
  margin-top: var(--s3);
}

:is(.docs-sec, .docs-sec-body) > .mock-scene,
:is(.docs-sec, .docs-sec-body) > .plate {
  margin-top: var(--s6);
}

/* Back to the contents at the end of a chapter: needed only where the
   navigation is not beside the text */
.docs-top {
  display: inline-block;
  margin-top: var(--s5);
  font-size: var(--fs-meta);
}

/* A chapter on the dark band (the guard passage) inside the reading
   column. Its ground runs from just left of the column to the screen's
   right edge (main clips what lies beyond), so the side navigation keeps
   its paper. Two dark chapters in a row share one ground. */
.docs-main > .night,
.docs-main > .night.night-1 {
  position: relative;
  isolation: isolate;
  background: transparent;
}

.docs-main > .night::before {
  content: "";
  position: absolute;
  inset: 0 -100vw;
  z-index: -1;
  background: var(--night);
}

.docs-main > .night.night-1::before {
  background: var(--night-1);
}

.docs-main > .night + .night {
  border-top: 1px solid var(--night-line);
}

.docs-aside {
  display: none;
}

@media (min-width: 1024px) {
  .docs {
    grid-template-columns: var(--docs-nav) minmax(0, 1fr);
    align-items: start;
  }

  /* Beside the text the navigation is always open: its toggle goes */
  .docs-toc {
    position: sticky;
    top: var(--docs-top);
    border: 0;
  }

  .docs-toc > summary {
    display: none;
  }

  .docs-nav {
    max-height: calc(100vh - var(--docs-top) - var(--s5));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-block: 0;
    scrollbar-width: thin;
  }

  .docs-main {
    grid-column: 2;
  }

  .docs-top {
    display: none;
  }

  .docs-main > .night::before {
    left: calc(var(--pair-gap) / -2);
  }

  .docs-main > .night {
    padding-inline: 0;
  }
}

@media (min-width: 1600px) {
  .docs {
    width: min(100% - 2 * var(--gutter), var(--content-wide));
  }

  /* A chapter with its own task list: the list stays in view beside the
     chapter while the chapter is read */
  .docs-sec:has(> .docs-aside) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--docs-aside);
    column-gap: var(--pair-gap);
    align-items: start;
  }

  .docs-sec:has(> .docs-aside) > .docs-sec-body {
    grid-column: 1;
    grid-row: 1;
  }

  .docs-aside {
    display: block;
    position: sticky;
    top: var(--docs-top);
    grid-column: 2;
    grid-row: 1;
    margin-top: 0;
    padding-left: var(--s4);
    border-left: 1px solid var(--line);
    font-size: var(--fs-small);
  }

  .night .docs-aside {
    border-left-color: var(--night-line);
  }
}

/* Inside the reading column a chapter stacks: its text, then its drawing
   across the whole column (1056px at 1440px), then its limit. The column
   is too narrow for the two side by side at a chapter's drawing size, and
   it never bleeds, since the navigation stands beside it. */
.docs-main .chapter {
  display: block;
}

.docs-main .chapter > * + * {
  margin-top: var(--pair-gap);
}

.docs-main .chapter.bleed > .chapter-art > :first-child,
.docs-main .chapter.bleed > .chapter-art > .mock-scene > :first-child {
  border-width: 1px;
  border-radius: var(--radius);
}

/* The accordion: one disclosure per question. The question is the
   summary, at the sub-heading size, with a chevron drawn in CSS at its
   end; the answer keeps a reading measure. Closed questions sit on
   hairlines. A link to a question opens it (mock.js). */
.acc-list {
  border-top: 1px solid var(--line-strong);
}

.acc {
  border-bottom: 1px solid var(--line);
}

.acc > summary {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  padding-block: var(--s4);
  color: var(--ink);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.3;
  list-style: none;
  cursor: pointer;
}

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

.acc > summary > :first-child,
.acc-q {
  flex: 1 1 auto;
  max-width: var(--measure-h3);
}

.acc > summary::after {
  content: "";
  flex: none;
  align-self: center;
  width: 0.5em;
  height: 0.5em;
  margin-left: auto;
  margin-right: 0.3em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-25%) rotate(45deg);
}

.acc[open] > summary::after {
  transform: translateY(25%) rotate(-135deg);
}

.acc > summary:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.acc-body {
  padding-bottom: var(--s6);
}

.acc-body > * + * {
  margin-top: var(--s4);
}

.acc-body p,
.acc-body li {
  max-width: var(--measure);
}

/* The answer's last line, where it points into the guide */
.acc-link {
  color: var(--quiet);
  font-size: var(--fs-meta);
}

.night .acc-list {
  border-top-color: var(--night-line-strong);
}

.night .acc {
  border-bottom-color: var(--night-line);
}

.night .acc > summary {
  color: var(--night-ink);
}

.night .acc-link {
  color: var(--night-quiet);
}

@media (prefers-reduced-motion: no-preference) {
  .acc > summary::after,
  .docs-toc > summary::after {
    transition: transform 150ms var(--arrive);
  }
}

/* A group of questions: its heading, its one line, and its Expand all and
   Collapse all pair, which the script reveals (without script every
   question still opens on its own) */
.acc-group + .acc-group {
  margin-top: var(--section-tight);
}

.acc-group-head {
  display: grid;
  gap: var(--s3);
  margin-bottom: var(--s5);
}

.acc-group-head > h2 {
  max-width: var(--measure-heading-docs);
}

.acc-tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
}

@media (min-width: 1024px) {
  .acc-group-head {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    column-gap: var(--pair-gap);
  }

  /* The heading and its line keep the first column, whether or not the
     pair beside them is shown */
  .acc-group-head > :not(.acc-tools) {
    grid-column: 1;
  }

  .acc-group-head > .acc-tools {
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: end;
  }
}

/* The question filter, above the groups: a text box and the count of the
   questions it leaves. The script reveals it; without script the page
   shows every question. */
.faq-filter {
  display: grid;
  gap: var(--s2);
  max-width: 40rem;
  margin-bottom: var(--s7);
}

.faq-filter label {
  color: var(--ink);
  font-weight: 600;
}

.faq-filter input {
  min-height: 48px;
  padding: 10px 14px;
  border: 1px solid var(--quiet);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-body);
}

.faq-filter input:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.faq-count {
  color: var(--quiet);
  font-size: var(--fs-meta);
}

/* Parts the script shows or hides by the hidden attribute: a display rule
   of their own must never bring them back */
.acc[hidden],
.acc-group[hidden],
.acc-tools[hidden],
.faq-filter[hidden] {
  display: none !important;
}

/* The agents row under the hero: the tools MaeVae drives, named in text in
   place of a row of logos, and the one line that says it bundles none */
.agents-row {
  display: grid;
  gap: var(--s3) var(--pair-gap);
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}

.agents-row > p {
  color: var(--quiet);
  font-size: var(--fs-meta);
  line-height: 1.55;
}

.agents-row > ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s6);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--fs-tag);
  letter-spacing: 0.04em;
  line-height: 1.4;
}

.night .agents-row {
  border-top-color: var(--night-line);
}

.night .agents-row > p {
  color: var(--night-quiet);
}

.night .agents-row > ul {
  color: var(--night-ink);
}

@media (min-width: 1024px) {
  .agents-row {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    align-items: baseline;
  }
}

/* A contrast theme keeps the marks the colours drew */
@media (forced-colors: active) {
  .docs-nav a[aria-current="location"] {
    border-left-color: Highlight;
  }

  .cols.tiled {
    gap: 0;
  }

  .cols.tiled > * {
    border: 1px solid CanvasText;
  }
}

/* Printed, the navigation and the controls are no use; every answer of
   the accordion prints as it stands */
@media print {
  .docs-toc,
  .docs-top,
  .acc-tools,
  .faq-filter {
    display: none !important;
  }
}

/* The jump control: two round buttons at the bottom right, "To the top"
   over "To the end", made by jump.js. They float over every ground, light
   and dark, so they keep one face: ink on paper with a hairline and a soft
   shadow that lifts them off a paper ground. Each button keeps its slot
   while the other is away, so neither moves under the pointer. The stack
   sits above the page's drawings (whose layers go to 4) and under the
   sticky header (10) and the skip link (20); the script hides it whenever
   a part that stays put on screen stands in its corner. On a phone it
   keeps clear of the rounded corners and the home bar. */
.jump {
  position: fixed;
  right: calc(var(--s4) + env(safe-area-inset-right, 0px));
  bottom: calc(var(--s4) + env(safe-area-inset-bottom, 0px));
  z-index: 9;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  pointer-events: none;
}

.jump-btn {
  --focus: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--night) 16%, transparent);
  cursor: pointer;
  opacity: 0;
  transform: translateY(var(--s2));
  pointer-events: none;
}

.jump-btn.is-shown {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* Gone once faded out: out of the tab order and the accessibility tree,
   while its slot stays */
.jump-btn.is-gone {
  visibility: hidden;
}

.jump-btn svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.jump-btn:hover {
  border-color: var(--ink);
  background: var(--strip);
}

/* The ring may fall on a dark ground or a light one, so the ink ring is
   set between two paper rings and reads on both */
.jump-btn:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 6px var(--paper);
}

@media (prefers-reduced-motion: no-preference) {
  .jump-btn {
    transition: opacity 200ms var(--arrive), transform 200ms var(--arrive);
  }
}

/* The footer takes the focus after "To the end", as the main content does
   after "To the top"; a ring around the whole footer would only distract */
.site-footer:focus {
  outline: none;
}

@media print {
  .jump {
    display: none !important;
  }
}

/* The dark scheme. A computer set to dark gets the page with the house
   lights further down. The night bands stay the page's darkest ground,
   and the paper sections become a deep charcoal one clear step lighter,
   so the rhythm of light and dark becomes a rhythm of dark and darker,
   never one flat black. Every ground, line and ink is a neutral gray: the
   blue lean the night and window tokens carry in the light scheme is
   taken out at the same lightness, so the bands, the reading sections and
   the drawn app read as one family. Amber keeps its value and its one
   meaning. No ground is pure black and no text is pure white.

   The computer's setting is the default. The header's switch (theme.js)
   can choose Light or Dark instead, kept as data-theme on the root: this
   block applies on a computer set to dark unless Light is chosen, and the
   block after it holds the same rules for Dark chosen on a computer set
   to light; a change to one is made to the other. Each rule's prefix
   sits in :where(), which adds no weight, so every rule wins or loses
   against the rules above exactly as it did without the switch. Light
   chosen needs no rule: the root's light color-scheme above stands. It
   is for the screen only: a printer drops the dark grounds and would
   leave light ink on white paper, so a printed page keeps the light
   scheme and the pages' own print rules. The rules above stand as they
   are; this block takes over the tokens and adds the few rules a token
   cannot carry. */
@media screen and (prefers-color-scheme: dark) {
  :root:where(html:not([data-theme="light"])) {
    /* Form controls, scroll bars and the browser's own parts follow */
    color-scheme: dark;

    /* The reading grounds and their ink, in the light scheme's order.
       Paper is the lightest band, a clear step above the night bands and
       above the drawn app's panes. Strip is a step below paper, as in the
       light scheme, a quieter passage between paper and night. White, the
       ground of cards, tiles, tables and keys, is a step above paper, so a
       card stands without a shadow and its strip header sits a step below
       its body. Ink is the same off white as the night ink, so a heading
       reads the same on every ground. */
    --paper: #242527;
    --strip: #1e1f21;
    --white: #2b2c2e;
    --ink: #e7e8e8;
    --quiet: #abacad;
    --line: #3a3b3e;
    --line-strong: #545558;
    --select: #45464a;

    /* The night grounds and their ink: the built values made neutral at
       about the same lightness, so no band moves by more than one step */
    --night: #0e0f10;
    --night-1: #151617;
    --night-raised: #1d1e20;
    --night-ink: #e7e8e8;
    --night-body: #c5c6c7;
    --night-quiet: #abacad;
    --night-faint: #8f9092;
    --night-line: #2e2f31;
    --night-line-strong: #4a4b4e;
    --night-hover: #1f2022;
    --night-select: #3c3d40;

    /* The drawn window's chrome, panels, terminal and splitters, neutral
       at their built lightness, so the hero's window and every drawing
       keep their place one step above the night ground */
    --w-chrome: #272829;
    --w-pane: #1e1f20;
    --w-term: #18191a;
    --w-split: #3a3b3d;

    /* The lit top edge of a drawing and the field's dots, neutral too */
    --night-edge-top: #5d5e61;
    --field-dot: #323335;
    --field-lit: #5d5e61;

    /* An outline button's hover ground lightens, as it does on the night
       ground; the light scheme's strip would sink it below the paper */
    --line-hover: var(--white);

    /* Two values only this scheme needs. In the light scheme the header's
       link hover and the light button's hover take --white, pure white;
       here --white is the dark card, so they take a bright neutral that
       is still short of pure white. The raised card is one step above the
       card ground: the floating jump button's hover, and a key on a card. */
    --night-bright: #f4f4f4;
    --card-raised: #343537;
  }

  /* mock.css declares its own root tokens and loads after this file, so
     the drawn app's rail, field and selection grounds and its field edge
     are set here with one element more in the selector, which wins in
     that order: neutral at their built lightness, as the window's are */
  html:root:where(html:not([data-theme="light"])) {
    --m-rail: #1a1b1c;
    --m-field: #151617;
    --m-field-edge: #727374;
    --m-select: #303133;
  }

  /* The two hovers the light scheme draws in --white */
  :where(html:not([data-theme="light"])) .site-nav a:hover {
    color: var(--night-bright);
  }

  :where(html:not([data-theme="light"])) .btn-light:hover {
    border-color: var(--night-bright);
    background: var(--night-bright);
  }

  /* A key in running text stands a step above the paper, as a card does;
     a page's own rule for a key on a night band keeps its ground */
  :where(html:not([data-theme="light"])) kbd {
    background: var(--white);
  }

  /* On a card, as in the home page's tiles, a key takes the raised card,
     so it still stands a step above its ground */
  :where(html:not([data-theme="light"])) .cols.tiled kbd {
    background: var(--card-raised);
  }

  /* The home page sets its inline code on the strip ground, which here is
     a step below the paper and would sink the code into the sentence. On
     the code element alone strip is the card ground, so the code stands a
     step above the text around it, as an inset does; the night band's
     own rule sets its ground directly and keeps it. */
  :where(html:not([data-theme="light"])) main :not(pre) > code {
    --strip: var(--white);
  }

  /* The floating jump buttons. A shadow does not read on a dark ground,
     so a button is a card with a lit top edge instead. The light scheme's
     hover ground is the strip, a step below paper here, so the hover
     takes the raised card; the hover's ink edge and the focus rings stand
     as they are, their rules being more specific than this one. */
  :where(html:not([data-theme="light"])) .jump-btn {
    border-top-color: var(--night-edge-top);
    background: var(--white);
    box-shadow: none;
  }

  :where(html:not([data-theme="light"])) .jump-btn:hover {
    background: var(--card-raised);
  }

  /* The three drawings of the home page's first steps stand directly on
     the paper. Here the paper is close to the drawn window's own grounds,
     so each drawing gets the plate the site's other drawings in a reading
     passage stand on: the night ground with the field's dots, faded at
     its edges, and the drawing's lit top edge. The plate is drawn by the
     figure itself: a one-column grid whose first row holds the drawing,
     inset by the plate's frame, over the plate's two layers, so the
     scene's controls and caption stay on the paper below, as a plate
     leaves them. In the light scheme the dark drawing stands clear of
     the light paper as it is. */
  :where(html:not([data-theme="light"])) .h-steps .mock-scene {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    /* The figure holds its own layers, so the plate's two layers can
       sit under the drawing without sinking under the paper */
    isolation: isolate;
  }

  /* The dots' mask makes their layer one of its own, and such a layer
     paints over a positioned drawing that comes before it. One layer
     down inside the figure, both plate layers paint under the
     drawing, as a plate's dots do. */
  :where(html:not([data-theme="light"])) .h-steps .mock-scene::before,
  :where(html:not([data-theme="light"])) .h-steps .mock-scene::after {
    content: "";
    z-index: -1;
    grid-row: 1;
    grid-column: 1;
    border-radius: var(--radius);
    pointer-events: none;
  }

  :where(html:not([data-theme="light"])) .h-steps .mock-scene::before {
    background: var(--night);
  }

  :where(html:not([data-theme="light"])) .h-steps .mock-scene::after {
    background-image: radial-gradient(circle, var(--field-dot)
      var(--field-dot-r), transparent calc(var(--field-dot-r) + 0.5px));
    background-position: center;
    background-size: var(--field-pitch) var(--field-pitch);
    -webkit-mask-image: linear-gradient(to bottom, transparent,
      #000 12px, #000 calc(100% - 12px), transparent);
    mask-image: linear-gradient(to bottom, transparent,
      #000 12px, #000 calc(100% - 12px), transparent);
  }

  @supports (mask-composite: intersect) {
    :where(html:not([data-theme="light"])) .h-steps .mock-scene::after {
      -webkit-mask-image:
        linear-gradient(to right, transparent,
          #000 12px, #000 calc(100% - 12px), transparent),
        linear-gradient(to bottom, transparent,
          #000 12px, #000 calc(100% - 12px), transparent);
      -webkit-mask-composite: source-in;
      mask-image:
        linear-gradient(to right, transparent,
          #000 12px, #000 calc(100% - 12px), transparent),
        linear-gradient(to bottom, transparent,
          #000 12px, #000 calc(100% - 12px), transparent);
      mask-composite: intersect;
    }
  }

  :where(html:not([data-theme="light"]))
    .h-steps .mock-scene > :is(.mock-window, .mock-dialog, .mock-editor,
      .mock-quick, .mock-palette, .mock-desk, .mock-report,
      .mock-pane)[role="img"] {
    grid-row: 1;
    grid-column: 1;
    margin: var(--plate-pad);
    border-top-color: var(--night-edge-top);
  }

  /* A contrast theme replaces the plate's ground, so there the plate
     keeps its edge as a frame and drops its dots, as a plate does */
  @media (forced-colors: active) {
    :where(html:not([data-theme="light"])) .h-steps .mock-scene::before {
      border: 1px solid CanvasText;
    }

    :where(html:not([data-theme="light"])) .h-steps .mock-scene::after {
      display: none;
    }
  }
}

/* Dark chosen with the header's switch on a computer set to light: the
   rules of the block above, the same in the same order, with the prefix
   for a chosen Dark. On a computer set to dark with Dark chosen both
   blocks apply and agree. Screen only, as above. */
@media screen {
  :root:where(html[data-theme="dark"]) {
    color-scheme: dark;

    --paper: #242527;
    --strip: #1e1f21;
    --white: #2b2c2e;
    --ink: #e7e8e8;
    --quiet: #abacad;
    --line: #3a3b3e;
    --line-strong: #545558;
    --select: #45464a;

    --night: #0e0f10;
    --night-1: #151617;
    --night-raised: #1d1e20;
    --night-ink: #e7e8e8;
    --night-body: #c5c6c7;
    --night-quiet: #abacad;
    --night-faint: #8f9092;
    --night-line: #2e2f31;
    --night-line-strong: #4a4b4e;
    --night-hover: #1f2022;
    --night-select: #3c3d40;

    --w-chrome: #272829;
    --w-pane: #1e1f20;
    --w-term: #18191a;
    --w-split: #3a3b3d;

    --night-edge-top: #5d5e61;
    --field-dot: #323335;
    --field-lit: #5d5e61;

    --line-hover: var(--white);

    --night-bright: #f4f4f4;
    --card-raised: #343537;
  }

  html:root:where(html[data-theme="dark"]) {
    --m-rail: #1a1b1c;
    --m-field: #151617;
    --m-field-edge: #727374;
    --m-select: #303133;
  }

  :where(html[data-theme="dark"]) .site-nav a:hover {
    color: var(--night-bright);
  }

  :where(html[data-theme="dark"]) .btn-light:hover {
    border-color: var(--night-bright);
    background: var(--night-bright);
  }

  :where(html[data-theme="dark"]) kbd {
    background: var(--white);
  }

  :where(html[data-theme="dark"]) .cols.tiled kbd {
    background: var(--card-raised);
  }

  :where(html[data-theme="dark"]) main :not(pre) > code {
    --strip: var(--white);
  }

  :where(html[data-theme="dark"]) .jump-btn {
    border-top-color: var(--night-edge-top);
    background: var(--white);
    box-shadow: none;
  }

  :where(html[data-theme="dark"]) .jump-btn:hover {
    background: var(--card-raised);
  }

  :where(html[data-theme="dark"]) .h-steps .mock-scene {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    isolation: isolate;
  }

  :where(html[data-theme="dark"]) .h-steps .mock-scene::before,
  :where(html[data-theme="dark"]) .h-steps .mock-scene::after {
    content: "";
    z-index: -1;
    grid-row: 1;
    grid-column: 1;
    border-radius: var(--radius);
    pointer-events: none;
  }

  :where(html[data-theme="dark"]) .h-steps .mock-scene::before {
    background: var(--night);
  }

  :where(html[data-theme="dark"]) .h-steps .mock-scene::after {
    background-image: radial-gradient(circle, var(--field-dot)
      var(--field-dot-r), transparent calc(var(--field-dot-r) + 0.5px));
    background-position: center;
    background-size: var(--field-pitch) var(--field-pitch);
    -webkit-mask-image: linear-gradient(to bottom, transparent,
      #000 12px, #000 calc(100% - 12px), transparent);
    mask-image: linear-gradient(to bottom, transparent,
      #000 12px, #000 calc(100% - 12px), transparent);
  }

  @supports (mask-composite: intersect) {
    :where(html[data-theme="dark"]) .h-steps .mock-scene::after {
      -webkit-mask-image:
        linear-gradient(to right, transparent,
          #000 12px, #000 calc(100% - 12px), transparent),
        linear-gradient(to bottom, transparent,
          #000 12px, #000 calc(100% - 12px), transparent);
      -webkit-mask-composite: source-in;
      mask-image:
        linear-gradient(to right, transparent,
          #000 12px, #000 calc(100% - 12px), transparent),
        linear-gradient(to bottom, transparent,
          #000 12px, #000 calc(100% - 12px), transparent);
      mask-composite: intersect;
    }
  }

  :where(html[data-theme="dark"])
    .h-steps .mock-scene > :is(.mock-window, .mock-dialog, .mock-editor,
      .mock-quick, .mock-palette, .mock-desk, .mock-report,
      .mock-pane)[role="img"] {
    grid-row: 1;
    grid-column: 1;
    margin: var(--plate-pad);
    border-top-color: var(--night-edge-top);
  }

  @media (forced-colors: active) {
    :where(html[data-theme="dark"]) .h-steps .mock-scene::before {
      border: 1px solid CanvasText;
    }

    :where(html[data-theme="dark"]) .h-steps .mock-scene::after {
      display: none;
    }
  }
}
