/* ComputerWorld — the project page, the expert-work page and the three studies.

   A quiet product page. One typeface (Inter Tight) in a few sizes far apart, JetBrains
   Mono only where something is code, a warm grey studio ground with fine grain, black
   type, thin rules, and media in rounded rectangles. The only colour on the page is what
   the machines draw and the two verdict colours a check can return.

   Light is the default. Dark follows the device, or the reader's stored choice: a
   one-line script in each page's <head> writes `data-theme` on <html> before the first
   paint. The dark palette is written twice because CSS has no way to say "the device
   asked, OR the reader picked" in one rule. */
@font-face {
  font-family: "Inter Tight"; font-style: normal; font-weight: 300 700; font-display: swap;
  src: url("./fonts/inter-tight.woff2") format("woff2");
}
@font-face {
  font-family: "JetBrains Mono"; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("./fonts/jetbrains-mono.woff2") format("woff2");
}
:root {
  --radius: 10px;
  --media-radius: 14px;
  --tile-radius: 10px;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --sans: "Inter Tight", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --t-small: .875rem;
  --t-body: 1.0625rem;
  --t-title: clamp(1.125rem, 1rem + .4vw, 1.3rem);
  --t-head: clamp(2rem, 1.2rem + 2.6vw, 3.25rem);
  --t-display: clamp(3rem, 1rem + 6.4vw, 7rem);
  --page: 1200px;
  --margin: 32px;
  --ease: cubic-bezier(.22, 1, .36, 1);
}
:root, :root[data-theme="light"] {
  color-scheme: light;
  --bg: #ecebe8;
  --sweep-1: #f3f2ef; --sweep-2: #e9e8e4; --sweep-3: #dedcd7;
  --grain: .07;
  --bar: rgba(239, 238, 235, .78);
  --surface: #e4e2de;
  --surface-2: #dad8d3;
  --line: #d6d4cf;
  --ink: #111111;
  --ink-2: #3a3a3a;
  --muted: #6b6964;
  --faint: #8a8781;
  --accent: #111111;
  --accent-ink: #ffffff;
  --button-hover: #333333;
  --holds: #2b7a4b;
  --breaks: #b3261e;
  --stripe: #dcdad5;
  --code-bg: #e2e0db;
  --code-ink: #2b2b2b;
  --syn-k: #6a6863;
  --syn-s: #3f6b2f;
  --syn-t: #8a5a12;
  --syn-n: #9a4a14;
  --frame-edge: #cfcdc8;
  --tile-edge: rgba(0, 0, 0, .05);
  --tile-shadow: rgba(40, 36, 30, .30);
  --media-shadow: 0 30px 60px -32px rgba(40, 36, 30, .45), 0 0 0 1px rgba(0, 0, 0, .06);
  --series-1: #2a78d6; --series-2: #eb6834; --series-3: #1baf7a;
  --context: #cfcdc8;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #121211;
    --sweep-1: #1c1c1a; --sweep-2: #141413; --sweep-3: #0e0e0d;
    --grain: .05;
    --bar: rgba(22, 22, 21, .78);
    --surface: #1d1d1b;
    --surface-2: #272725;
    --line: #2c2c29;
    --ink: #ededea;
    --ink-2: #c9c8c3;
    --muted: #9b9992;
    --faint: #7d7b75;
    --accent: #ededea;
    --accent-ink: #121211;
    --button-hover: #ffffff;
    --holds: #8fb87a;
    --breaks: #e07a62;
    --stripe: #181817;
    --code-bg: #1a1a18;
    --code-ink: #d2d2cf;
    --syn-k: #9e9d97;
    --syn-s: #a9b88f;
    --syn-t: #e0c9a0;
    --syn-n: #f0b27a;
    --frame-edge: #2e2e2b;
    --tile-edge: rgba(255, 255, 255, .03);
    --tile-shadow: rgba(0, 0, 0, .8);
    --media-shadow: 0 30px 60px -30px rgba(0, 0, 0, .8), 0 0 0 1px rgba(255, 255, 255, .06);
    --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70;
    --context: #34343a;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #121211;
  --sweep-1: #1c1c1a; --sweep-2: #141413; --sweep-3: #0e0e0d;
  --grain: .05;
  --bar: rgba(22, 22, 21, .78);
  --surface: #1d1d1b;
  --surface-2: #272725;
  --line: #2c2c29;
  --ink: #ededea;
  --ink-2: #c9c8c3;
  --muted: #9b9992;
  --faint: #7d7b75;
  --accent: #ededea;
  --accent-ink: #121211;
  --button-hover: #ffffff;
  --holds: #8fb87a;
  --breaks: #e07a62;
  --stripe: #181817;
  --code-bg: #1a1a18;
  --code-ink: #d2d2cf;
  --syn-k: #9e9d97;
  --syn-s: #a9b88f;
  --syn-t: #e0c9a0;
  --syn-n: #f0b27a;
  --frame-edge: #2e2e2b;
  --tile-edge: rgba(255, 255, 255, .03);
  --tile-shadow: rgba(0, 0, 0, .8);
  --media-shadow: 0 30px 60px -30px rgba(0, 0, 0, .8), 0 0 0 1px rgba(255, 255, 255, .06);
  --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70;
  --context: #34343a;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 72px; -webkit-text-size-adjust: 100%; }
body {
  overflow-x: clip; margin: 0;
  background: radial-gradient(120% 80% at 50% 0%, var(--sweep-1) 0%, var(--sweep-2) 55%, var(--sweep-3) 100%) fixed var(--bg);
  color: var(--ink);
  font: 400 var(--t-body)/1.55 var(--sans);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
}
/* Fine grain over everything, as a rendered studio sweep has. */
body::after {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 50; opacity: var(--grain); mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1.2 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
:root[data-theme="dark"] body::after { mix-blend-mode: screen; }
::selection { background: var(--ink); color: var(--bg); }
a { color: inherit; text-underline-offset: 3px; text-decoration-thickness: 1px; }
img, video { max-width: 100%; display: block; }
code { font-family: var(--mono); font-size: .86em; }
button { font: inherit; color: inherit; }
h1, h2, h3 { font-weight: 500; letter-spacing: -.035em; line-height: 1.02; margin: 0; text-wrap: balance; }
p { margin: 0 0 14px; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 3px; }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 1rem; top: 1rem; background: var(--surface); padding: .6rem 1rem; z-index: 100; }
[hidden] { display: none !important; }
* { scrollbar-width: thin; scrollbar-color: var(--faint) transparent; }

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

/* THE BAR. The name on the left; the docs, the source and the one action on the right. */
.top {
  position: sticky; top: 0; z-index: 40;
  background: var(--bar); -webkit-backdrop-filter: saturate(1.6) blur(14px); backdrop-filter: saturate(1.6) blur(14px);
}
.top .wrap { display: flex; align-items: center; justify-content: space-between; gap: 1rem; height: 56px; }
.brand {
  display: inline-flex; align-items: center; gap: .5rem;
  font-weight: 600; font-size: 17px; letter-spacing: -.02em; text-decoration: none; white-space: nowrap;
}
.brand svg { flex: none; display: block; }
.top nav { display: flex; align-items: center; gap: 26px; font-size: 14px; }
.top nav a { color: var(--ink-2); text-decoration: none; white-space: nowrap; transition: color .15s ease; }
.top nav a:hover, .top nav a[aria-current] { color: var(--ink); }
.top nav a.key {
  background: var(--accent); color: var(--accent-ink); padding: 7px 15px; border-radius: 999px; font-weight: 500;
  transition: background-color .15s ease;
}
.top nav a.key:hover { background: var(--button-hover); color: var(--accent-ink); }

/* Buttons and links that go somewhere. */
.cta { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; margin-top: 28px; }
.btn {
  display: inline-block; background: var(--accent); color: var(--accent-ink); text-decoration: none;
  font-weight: 500; font-size: 16px; padding: 12px 22px; border-radius: 999px; transition: background-color .15s ease;
}
.btn:hover { background: var(--button-hover); }
.link { text-decoration: none; font-weight: 500; }
.link::after { content: "\2192"; display: inline-block; margin-left: .3em; transition: transform .2s var(--ease); }
.link:hover::after { transform: translateX(3px); }

/* THE HERO. The name at the page's one large size, one sentence, the way in; then the
   machines themselves, running. */
.hero { padding: clamp(40px, 7vh, 88px) 0 8px; }
.hero .wrap { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 24px clamp(32px, 5vw, 72px); align-items: end; }
.hero h1 { white-space: nowrap; }
.hero .wrap > div { padding-bottom: .4em; justify-self: end; }
.hero h1 { font-size: var(--t-display); letter-spacing: -.055em; line-height: .95; margin-left: -.04em; }
.hero .sub { font-size: clamp(19px, 1.8vw, 24px); line-height: 1.3; color: var(--ink-2); max-width: 26ch; letter-spacing: -.015em; margin: 0; }
.hero .cta { margin-top: 22px; }

/* A STATEMENT and the numbers under it. */
.statement { padding: clamp(80px, 11vw, 140px) 0 clamp(60px, 8vw, 100px); }
.statement h2 { font-size: clamp(30px, 4.2vw, 58px); max-width: 24ch; }
.statement h2 span { color: var(--muted); }
.nums {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 28px;
  margin-top: clamp(48px, 7vw, 90px); border-top: 1px solid var(--line); padding-top: 28px;
}
.nums b { display: block; font-weight: 500; font-size: clamp(30px, 3.4vw, 48px); letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.nums b span { display: inline; }
.nums > div > span { display: block; color: var(--muted); font-size: 14px; margin-top: 10px; max-width: 18ch; }

/* WHAT WE SELL. Three offers in a row, each a short title and one paragraph. */
.offers { padding: clamp(48px, 6.5vw, 92px) 0; border-top: 1px solid var(--line); }
.offers h2 { font-size: clamp(30px, 3.6vw, 50px); }
.offers .lede { font-size: clamp(17px, 1.45vw, 19.5px); color: var(--ink-2); max-width: 52ch; margin: 20px 0 0; line-height: 1.5; text-wrap: pretty; }
.offers .grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; margin-top: clamp(32px, 4vw, 48px); border-top: 1px solid var(--line); }
.offers article { padding: 28px 28px 28px 0; }
.offers article + article { padding-left: 28px; border-left: 1px solid var(--line); }
.offers h3 { font-weight: 500; font-size: 24px; letter-spacing: -.02em; margin: 0; }
.offers article p { color: var(--ink-2); font-size: 16px; line-height: 1.5; margin: 12px 0 0; text-wrap: pretty; }
.offers .link { display: inline-block; margin-top: 16px; font-size: 15px; }

/* THE SECTIONS. A short title and one paragraph in one column; what it says, shown, in
   the other. They alternate sides down the page. */
.sec { padding: clamp(48px, 6.5vw, 92px) 0; }
.split { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(32px, 5vw, 72px); align-items: center; }
.split.rev { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); }
.split.rev > .text { order: 2; }
.split.wide { grid-template-columns: minmax(0, .7fr) minmax(0, 1.3fr); }
.split.rev.wide { grid-template-columns: minmax(0, 1.3fr) minmax(0, .7fr); }
.text h2 { font-size: clamp(30px, 3.6vw, 50px); max-width: 14ch; }
.text p { font-size: clamp(17px, 1.45vw, 19.5px); color: var(--ink-2); max-width: 38ch; margin: 20px 0 0; line-height: 1.5; text-wrap: pretty; }
.text p b { font-weight: 500; color: var(--ink); }
.text .link { display: inline-block; margin-top: 18px; font-size: 15px; }
.eyebrow { display: block; font-size: 13px; color: var(--muted); margin-bottom: 14px; letter-spacing: 0; font-weight: 400; }
.demo { margin: 0; min-width: 0; }
.demo figcaption, .note { margin-top: 12px; font-size: 13px; color: var(--muted); max-width: 64ch; line-height: 1.5; }
.demo figcaption code, .note code { color: var(--ink-2); }

/* MEDIA. Every picture and video sits in one rounded rectangle with a soft shadow. */
.media {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover;
  border-radius: var(--media-radius); background: var(--surface); box-shadow: var(--media-shadow);
}
.media.square { aspect-ratio: auto; }
.panel { border-radius: var(--media-radius); background: color-mix(in srgb, var(--surface) 70%, transparent); padding: clamp(16px, 2.4vw, 28px); }

/* THE BAND. Where to go next, as a row of three. */
.band { padding: clamp(80px, 10vw, 120px) 0; border-top: 1px solid var(--line); }
.band h2 { font-size: clamp(34px, 4.6vw, 60px); max-width: 16ch; }
.band .grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 56px; border-top: 1px solid var(--line); }
.band .grid a { display: block; text-decoration: none; padding: 28px 28px 28px 0; border-bottom: 1px solid var(--line); }
.band .grid a + a { padding-left: 28px; border-left: 1px solid var(--line); }
.band .grid b { display: block; font-weight: 500; font-size: 24px; letter-spacing: -.02em; }
.band .grid span { display: block; color: var(--muted); font-size: 15px; margin-top: 6px; }
.band .grid a b::after { content: " \2192"; opacity: 0; transition: opacity .2s ease; }
.band .grid a:hover b::after { opacity: 1; }

/* THE CLOSE. */
.foot { border-top: 1px solid var(--line); padding: 36px 0 48px; color: var(--muted); font-size: 13px; }
.foot .wrap { display: flex; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap; }
.foot nav { display: flex; flex-wrap: wrap; gap: 8px 22px; }
.foot a { text-decoration: none; }
.foot a:hover { color: var(--ink); }

/* Secondary pages: a page head, then the same sections. */
.pagehead { padding: clamp(56px, 9vw, 96px) 0 0; }
.pagehead h1 { font-size: clamp(44px, 6.5vw, 88px); letter-spacing: -.05em; }
.pagehead .lead { font-size: clamp(18px, 1.6vw, 21px); color: var(--ink-2); max-width: 52ch; margin-top: 20px; line-height: 1.45; }

/* Reveal on scroll: a section rises into place the first time it is seen. media.js adds
   `.in`; without it (no script, or reduced motion) everything is simply there. */
.js-reveal .sec .split > *, .js-reveal .statement .wrap > * { opacity: 0; transform: translateY(18px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.js-reveal .sec.in .split > *, .js-reveal .statement.in .wrap > * { opacity: 1; transform: none; }
.js-reveal .sec.in .split > :nth-child(2) { transition-delay: .08s; }

/* THE LIGHT/DARK SWITCH, on the studies. */
/* THE LIGHT/DARK SWITCH. It starts on whatever the device asked for; a click stores the
   reader's own answer and the page keeps it from then on. The button carries both icons
   and shows the one for the theme it would switch TO, so the control says what it does.
   theme.js unhides it, so a page without scripts never offers a switch that cannot work. */
.theme {
  display: inline-grid; place-items: center; width: 2rem; height: 2rem; padding: 0;
  border: 0; border-radius: var(--radius); background: none;
  color: var(--muted); cursor: pointer; transition: color .15s ease, background-color .15s ease;
}
.theme:hover { color: var(--ink); background: var(--surface); }
.theme svg { display: block; width: 15px; height: 15px; }
:root[data-theme="dark"] .theme .moon, :root[data-theme="light"] .theme .sun { display: none; }


/* The slideshow: a strip of machines as wide as the window. The one in the middle is
   running and takes input; its neighbours wait, dimmed, at the edges. */
.stage {
  position: relative;
  --w-desk: min(1080px, 84vw, (100vh - 21rem) * 1.6);
  --h-desk: calc(var(--w-desk) * .625);
  --h-phone: var(--h-desk);
  /* The room a whole slide has. A team of machines is allowed to run wider than one of
     them, but not so much wider that it dwarfs its neighbours on the strip; app.js reads
     these three back in pixels and sizes every tile inside them. */
  --w-group: min(94vw, calc(var(--w-desk) * 1.34));
  --gut: clamp(.45rem, 1.1vw, 1rem);
  margin-inline: calc(50% - 50vw); overflow: hidden;
  padding: 1rem 0 0;
}
.track {
  position: relative; column-gap: clamp(.75rem, 3vw, 2.5rem);
  margin-bottom: 5.5rem;   /* room for the shadow, which `overflow` would otherwise cut */
  transition: height .55s cubic-bezier(.22, .8, .24, 1);
}
.slide {
  position: absolute; left: 50%; top: 50%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--gut);
  opacity: .28; cursor: pointer;
  transform: translate(calc(-50% + var(--x, 0px)), -50%) scale(.94);
  transition: opacity .55s ease, transform .55s cubic-bezier(.22, .8, .24, 1);
}
.slide:hover { opacity: .5; }
.slide.active { opacity: 1; cursor: default; transform: translate(calc(-50% + var(--x, 0px)), -50%); }
.slide.far { visibility: hidden; transition: none; }
.track.still, .track.still .slide { transition: none; }

/* A shallow arc. The strip lies on the face of a very wide cylinder: a slide that stands
   off centre is set back into the page (`--z`) and turned away from the viewer (`--rot`),
   both written by app.js beside `--x`, so the running machine is square on at the front of
   the curve and its neighbours lean away at the edges. The setting-back is what keeps the
   turn from swinging them out of the window: on a curve they sit a little closer together
   than they would in a straight line, exactly as much as the turn takes off their width.
   It rides the transform transition above, so a slide turns as it slides. A browser with
   no 3D transforms keeps the flat row, and so does anyone who asked for less motion. */
@supports (perspective: 1px) {
  .track { perspective: clamp(700px, 130vw, 2200px); }
  .slide {
    transform: translate(calc(-50% + var(--x, 0px)), -50%) translateZ(var(--z, 0px))
               rotateY(var(--rot, 0deg)) scale(.94);
  }
  .slide.active {
    transform: translate(calc(-50% + var(--x, 0px)), -50%) translateZ(var(--z, 0px))
               rotateY(var(--rot, 0deg));
  }
}
/* Equal share: a slide is one rectangle cut in two, and each half cut in two again, down
   to the machines — `.row` for a cut side by side, `.col` for one above the other — so the
   halves fill what they were given and the composition has no holes in it. app.js writes
   the heights, the corner radii and the shadow depth, since it is the one that knows how
   the slide was cut and how much room there is; the sizes here are what one machine on its
   own gets, and what a slide falls back to before the first measurement. */
.slide .row, .slide .col { display: flex; align-items: center; justify-content: center; gap: var(--gut); }
.slide .col { flex-direction: column; }
.tile {
  position: relative; flex: none; height: var(--h-desk); aspect-ratio: 1280 / 800;
  border-radius: var(--tile-radius); overflow: hidden; background: #000;
  box-shadow: 0 0 0 1px var(--line), 0 1px 0 1px var(--tile-edge);
  transition: box-shadow .55s ease;
}
.tile.phone { height: var(--h-phone); border-radius: clamp(16px, 2.2vw, 28px); }
/* A machine whose still has not been rendered yet: an empty screen, not a broken image. */
.tile.blank { background: repeating-linear-gradient(-45deg, var(--surface) 0 10px, var(--stripe) 10px 20px); }
.tile.blank img { display: none; }
/* One shadow rule for every tile, lifted by its own size: app.js writes `--lift` from the
   height it gave the tile, so seven machines on one slide do not each drop the shadow of a
   laptop, and one machine on its own still does. These are screens standing on the page,
   and the shadow is what says so. */
.slide.active .tile {
  box-shadow: 0 0 0 1px var(--line), 0 1px 0 1px var(--tile-edge),
              0 var(--lift, 40px) calc(var(--lift, 40px) * 2.25) calc(var(--lift, 40px) * -.5) var(--tile-shadow);
}
.tile img, .tile canvas { width: 100%; height: 100%; display: block; }
.live-canvas { outline: none; touch-action: none; cursor: default; }
.slide.active .tile:has(.live-canvas:focus-visible) {
  box-shadow: 0 0 0 1px var(--accent),
              0 var(--lift, 40px) calc(var(--lift, 40px) * 2.25) calc(var(--lift, 40px) * -.5) var(--tile-shadow);
}

/* WHILE THE SIMULATOR IS COMING DOWN. The still darkened, a spinner, and the download's
   own percentage — nothing else. `data-boot` on the document says which of the four it is,
   because there is one download for the whole page: `ask` is a Save-Data browser waiting
   to be told to go and shows the one control that tells it; `load` is the download, and
   the label is empty whenever the bytes cannot honestly be counted (see live.js), leaving
   the spinner on its own; `work` is a world being built out of what came down. A machine
   that is running has no overlay at all, and neither has a slide nobody is looking at. */
.boot {
  position: absolute; inset: 0; display: none; place-content: center; justify-items: center;
  gap: .55rem; padding: .5rem; text-align: center;
  background: rgba(8, 8, 9, .62);
}
html[data-boot] .slide.active .tile:not(.live) > .boot { display: grid; }
.spin {
  width: 26px; aspect-ratio: 1; border-radius: 50%;
  border: 2px solid rgba(237, 237, 236, .2); border-top-color: var(--accent);
  animation: spin .85s linear infinite;
}
@keyframes spin { to { transform: rotate(1turn); } }
.pct {
  margin: 0; color: #ededec; font-size: .8rem; font-weight: 500;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  text-shadow: 0 1px 12px rgba(0, 0, 0, .9);
}
.pct:empty { display: none; }
html[data-boot="ask"] .spin, html[data-boot="ask"] .pct { display: none; }
.get {
  display: none; place-items: center; width: 2.6rem; height: 2.6rem; padding: 0;
  border: 0; border-radius: 50%; background: rgba(20, 20, 22, .8);
  color: #ededec; cursor: pointer; transition: background-color .15s ease, color .15s ease;
}
html[data-boot="ask"] .get { display: grid; }
.get:hover { background: var(--accent); color: var(--accent-ink); }
/* In a team every tile is small, and one the size of a stamp has room for the spinner and
   nothing beside it. app.js marks both, since it is the one that knows how a tile came out. */
.tile.small .spin { width: 18px; border-width: 1.5px; }
.tile.small .pct { font-size: .62rem; }
.tile.small .get { width: 2rem; height: 2rem; }
.tile.tight .pct { display: none; }
.tile.tight .spin { width: 13px; border-width: 1.5px; }
.tile.tight .get { width: 1.5rem; height: 1.5rem; }

/* ONE MACHINE, THE WHOLE SCREEN. The control sits in the tile's top right and is there
   only while that machine is live — over a still there is nothing to be full screen with,
   and `display: none` keeps it out of the tab order as well as out of the picture. */
.grow {
  position: absolute; top: .4rem; right: .4rem; z-index: 3;
  display: none; place-items: center; width: 1.9rem; height: 1.9rem; padding: 0;
  border: 0; border-radius: 7px; background: rgba(8, 8, 9, .55); color: rgba(237, 237, 236, .8);
  cursor: pointer; opacity: .55; transition: opacity .15s ease, color .15s ease, background .15s ease;
}
.tile.live > .grow { display: grid; }
.tile:hover > .grow, .grow:hover, .grow:focus-visible { opacity: 1; }
.grow:hover { background: rgba(8, 8, 9, .8); color: var(--accent); }
.grow svg + svg, .tile.full > .grow svg:first-child { display: none; }
.tile.full > .grow svg + svg { display: block; }
/* A phone's corners are rounded far harder than a desktop's, so the control comes in off
   them rather than sitting in the curve. */
.tile.phone > .grow { top: .75rem; right: .75rem; }
.tile.small > .grow { width: 1.5rem; height: 1.5rem; border-radius: 5px; top: .3rem; right: .3rem; }
.tile.phone.small > .grow { top: .5rem; right: .5rem; }
.tile.tight > .grow { width: 1.2rem; height: 1.2rem; border-radius: 4px; top: .2rem; right: .2rem; }
.tile.small > .grow svg { width: 12px; height: 12px; }
.tile.tight > .grow svg { width: 10px; height: 10px; }

/* The tile that has the screen, whether the Fullscreen API put it in the top layer or
   `.fs-host` is holding it instead. Both give the tile the whole viewport; the canvas then
   takes as much of it as ITS OWN SHAPE allows, so the machine is never stretched and the
   box the pointer is measured against is the box the picture is drawn in. app.js writes
   `--ar`, the machine's width over its height. */
.fs-host { position: fixed; inset: 0; z-index: 60; background: #000; display: grid; place-items: center; }
.tile.full {
  width: 100vw !important; height: 100vh !important; aspect-ratio: auto !important;
  border-radius: 0 !important; box-shadow: none !important;
  display: grid; place-items: center; background: #000;
}
.tile.full > canvas, .tile.full > img {
  width: min(100vw, calc(100vh * var(--ar, 1.6)));
  height: min(100vh, calc(100vw / var(--ar, 1.6)));
}
.tile.full::backdrop { background: #000; }
.tile.full > .grow { width: 2.4rem; height: 2.4rem; top: .9rem; right: .9rem; }
.tile.full > .grow svg { width: 17px; height: 17px; }

/* What the machines on this slide are doing, and the two arrows. The caption is the
   indicator: it says where in the cast this is, so there is no strip of dots to read. */
.pager {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  margin-top: -2.6rem; padding: 0 1rem; position: relative;
}
.pager > button {
  flex: none; display: grid; place-items: center; width: 2.25rem; height: 2.25rem; padding: 0;
  border: 0; border-radius: 50%; background: var(--surface); cursor: pointer;
  color: var(--muted); font-size: 1rem; line-height: 1;
  transition: color .15s ease, background-color .15s ease;
}
.pager > button:hover { color: var(--ink); background: var(--surface-2); }
/* The caption is two things, and they are not the same kind of thing. The title is what
   this slide IS, set in the full ink a step above the text size. The summary is the
   detail under that name — the part, the file, the ticket, the branch — at the text size
   in the softer ink. The count is a small line above them. */
.caption {
  flex: 0 1 76rem; min-width: 0; margin: 0;
  /* The room the longest caption in the cast needs at this width, kept back whatever is
     on screen, so the page under the strip does not step up and down as one caption runs
     a word longer than the last. Wide enough and that is a title's line and a summary's;
     the ladder below is where the summary starts wrapping under it, measured over all
     the scenes rather than guessed at. */
  min-height: 7.4rem;
  /* One grid column, and the column is as wide as the paragraph wants to be. The title
     and the count take their left edge from it instead of each being centred on its own
     width, so the three lines share one leading edge; `justify-content` then centres that
     column under the strip. */
  display: grid; justify-items: start; justify-content: center;
  row-gap: .3rem; text-align: left;
  font-family: var(--sans); line-height: 1.4;
}
#caption-title {
  font-size: var(--t-title); font-weight: 600; letter-spacing: -.02em;
  color: var(--ink); text-wrap: balance;
}
#caption-summary {
  max-width: 78ch; font-size: .875rem; line-height: 1.55; color: var(--muted);
  text-wrap: pretty;
}
#caption-summary:empty { display: none; }
/* Where in the cast this is, a small line above the title it counts. */
#caption-where {
  order: -1; color: var(--faint); font-size: .8125rem;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Where the summary no longer sits beside the title, and then where it wraps again. */
@media (max-width: 919px) { .caption { min-height: 7.2rem; } }
.stage noscript img { display: block; width: var(--w-desk); height: auto; margin: 0 auto; border-radius: var(--tile-radius); }


/* THE FRAME AND THE SCENE IT CAME FROM. One picture over the other, revealed by hovering,
   by the checkbox, or by a keyboard focus on it. No script: with the stylesheet gone both
   pictures are simply there, one under the other, which reads perfectly well. */
/* The scene comes and goes on its own — about five seconds of the frame, then three of
   the boxes over it — because the point of the figure is the pair, and a reader who never
   hovers would otherwise only ever see half of it. Hovering, or the control below, holds
   it on; a reader who asked for less motion gets no cycle and keeps both. */
.compare > .over { position: absolute; inset: 0; height: 100%; opacity: 0; transition: opacity .35s ease; animation: scene-cycle 8s ease-in-out infinite; }
@keyframes scene-cycle { 0%, 60% { opacity: 0 } 65%, 95% { opacity: 1 } 100% { opacity: 0 } }
.compare:hover > .over, .compare-toggle:checked ~ .over, .compare-toggle:focus-visible ~ .over { opacity: 1; animation: none; }
/* Left in the tab order and out of the picture; the label is what is seen and focused. */
.compare-toggle { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; }
.compare label {
  position: absolute; left: .75rem; bottom: .75rem; padding: .45rem .8rem;
  border-radius: var(--radius); background: rgba(10, 10, 11, .82);
  color: #ededec; font-size: .8125rem; font-weight: 500;
  cursor: pointer; transition: background-color .15s ease;
}
.compare label:hover { background: rgba(10, 10, 11, .95); }
.compare-toggle:focus-visible ~ label { outline: 2px solid var(--accent); outline-offset: 2px; }
.compare label .off { display: none; }
.compare-toggle:checked ~ label .on { display: none; }
.compare-toggle:checked ~ label .off { display: inline; }

/* ONE CHECKPOINT, THREE TRAJECTORIES. */
/* ONE CHECKPOINT, THREE TRAJECTORIES. The checkpoint at the top, a bracket, and one
   column per branch with its actions running down it, in order, to the verdict where it
   ended. Down rather than across: a row of five frames needs five frame-widths and a
   phone has one, and a figure that has to be scrolled sideways, or swapped for a list of
   words, is a figure that does not fit. A column needs the width of ONE frame, so the
   same picture works at every size and nothing is taken away to make it. */
.branch-body { border-radius: var(--radius); background: var(--surface); }
.audience-section.field .branch-body, .audience-section.field .map-content { background: var(--bg); }
.branch-diagram { display: flex; flex-direction: column; align-items: center; padding: 20px 14px 22px; }
.branch-frame { overflow: hidden; border-radius: 4px; background: var(--surface-2); }
.branch-frame img { display: block; width: 100%; height: auto; }
.branch-frame > span { display: block; padding: 5px 7px; color: var(--ink); font-size: .7rem; line-height: 1.35; font-weight: 500; }
.branch-frame > span small { display: block; color: var(--muted); font-size: .95em; font-weight: 400; }
.branch-root { width: min(190px, 52%); }

/* The bracket under the checkpoint: a stem down, then a bar out to each column's stem.
   It is one element rather than three pseudo-elements so the corners meet exactly. */
.branch-fork {
  position: relative; width: 100%; height: 18px;
  background: linear-gradient(var(--faint), var(--faint)) center top / 1px 9px no-repeat;
}
.branch-fork::before {
  content: ''; position: absolute; left: 16.667%; right: 16.667%; top: 9px;
  border-top: 1px solid var(--faint);
}
.branch-paths {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 10px; width: 100%; margin: 0; padding: 0; list-style: none;
}
.branch-path { position: relative; display: flex; flex-direction: column; align-items: center; padding-top: 9px; }
/* Each column's own stem up to the bar. */
.branch-path::before {
  content: ''; position: absolute; top: 0; left: 50%; height: 9px;
  border-left: 1px solid var(--faint);
}
.branch-path > ol {
  display: flex; flex-direction: column; align-items: center; gap: 15px;
  width: 100%; margin: 0; padding: 0; list-style: none;
}
.branch-path > ol > li { position: relative; width: 100%; max-width: 160px; }
/* The arrow from one action to the next, drawn in the gap the column left. */
.branch-path > ol > li + li::before {
  content: ''; position: absolute; left: 50%; top: -14px; height: 9px;
  border-left: 1px solid var(--faint);
}
.branch-path > ol > li + li::after {
  content: ''; position: absolute; left: 50%; top: -6px; transform: translateX(-50%);
  border-inline: 2.5px solid transparent; border-top: 4px solid var(--faint);
}
.branch-path > ol img {
  display: block; width: 100%; height: auto;
  border-radius: 3px; background: var(--surface-2); outline: 1px solid var(--frame-edge); outline-offset: -1px;
}
.branch-path > ol span { display: block; margin-top: .3rem; color: var(--muted); font-size: .68rem; line-height: 1.3; }
.branch-path > ol span b {
  display: inline-block; min-width: 1.1em; margin-right: .2em;
  color: var(--faint); font-weight: 400; font-variant-numeric: tabular-nums;
}
/* The verdict closes the column where the branch ended, so a branch that stopped early
   is seen to have stopped. The mark and the word carry it together, so the column reads
   the same way with the colour taken away. */
.branch-verdict {
  display: flex; align-items: baseline; justify-content: center; gap: .3rem; margin: .8rem 0 0;
  font-size: .72rem; line-height: 1.35; font-weight: 500; text-align: center;
}
.branch-verdict span { font-size: .85rem; line-height: 1; }
.holds .branch-verdict { color: var(--holds); }
.breaks .branch-verdict { color: var(--breaks); }

.table-wrap { margin: 2rem 0 0; overflow-x: auto; }
.policies { width: 100%; border-collapse: collapse; text-align: left; font-size: var(--t-small); }
.policies caption {
  caption-side: bottom; padding-top: 1rem; text-align: left;
  color: var(--muted); font-size: .8125rem; line-height: 1.6;
}
.policies th, .policies td { padding: .7rem .9rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.policies thead th { color: var(--muted); font-weight: 500; font-size: .8125rem; }
.policies tbody th { padding-left: 1rem; color: var(--muted); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; }
.policies tbody td { color: var(--ink); }
.policies tr.holds th { box-shadow: inset 2px 0 0 var(--holds); }
.policies tr.breaks th { box-shadow: inset 2px 0 0 var(--breaks); }
.policies td.v { font-size: .8125rem; font-weight: 500; white-space: nowrap; }
.policies tr.holds td.v { color: var(--holds); }
.policies tr.breaks td.v { color: var(--breaks); }
.policies tr.note td, .fallback { color: var(--muted); }
.policies details { margin-top: .55rem; }
.policies summary { cursor: pointer; color: var(--muted); font-size: .8125rem; }
.policies summary:hover { color: var(--ink); }
/* The run writes each action with its own step number, so the list does not add one. */
.policies ol { list-style: none; margin: .65rem 0 .2rem; padding-left: 0; color: var(--muted); font-family: var(--mono); font-size: .75rem; line-height: 1.75; }
.fallback { margin: 1.4rem 0 0; font-size: .82rem; }

.codebox { border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.codebox .bar { display: flex; align-items: center; justify-content: space-between; padding: .5rem .5rem 0 .5rem; }
.tabs { display: flex; gap: .25rem; }
.tabs button, .copy {
  padding: .45rem .8rem; border: 0; border-radius: var(--radius); background: none; cursor: pointer;
  color: var(--muted); font-size: var(--t-small); font-weight: 500;
  transition: color .15s ease, background-color .15s ease;
}
.tabs button:hover, .copy:hover { color: var(--ink); }
.tabs button[aria-selected="true"] { color: var(--ink); background: var(--surface-2); }
.codebox pre { margin: 0; padding: 1.25rem 1.4rem 1.4rem; overflow-x: auto; }
.codebox code { color: var(--code-ink); line-height: 1.7; font-size: .8125rem; }
#install { margin: .5rem .5rem 0; padding: .8rem .9rem; border-radius: var(--radius); background: var(--surface-2); cursor: copy; }
#install code { color: var(--ink); }
#install code::before { content: "$ "; color: var(--faint); }
#install code::after { content: attr(data-said); color: var(--accent); margin-left: 1.5em; }

/* Syntax colours, written into the markup rather than fetched from a highlighter. */
.k { color: var(--syn-k); }                       /* keywords */
.s { color: var(--syn-s); }                       /* strings */
.n { color: var(--accent); }                      /* numbers */
.f { color: var(--ink); }                         /* calls and macros */
.t { color: var(--syn-t); }                       /* types */
.c { color: var(--faint); font-style: italic; }

/* CHARTS. Thin marks on the page's own ground, a recessive grid, text in the text inks
   and never in a series colour, a tooltip for every mark and a table for every chart. */
.chart { position: relative; margin: 0; min-width: 0; }
.chart svg { display: block; overflow: visible; max-width: 100%; height: auto; }
.chart svg text { fill: var(--faint); font-size: 11px; font-family: var(--sans); font-variant-numeric: tabular-nums; }
.chart .axis-title, .chart .col-head { fill: var(--muted); font-size: 11.5px; }
.chart .grid line { stroke: var(--line); stroke-width: 1; }
.chart .grid line.major { stroke: color-mix(in srgb, var(--faint) 45%, transparent); }
.chart .row { outline: none; cursor: default; }
.chart .row .band { fill: transparent; }
.chart .row:hover .band, .chart .row:focus-visible .band { fill: var(--surface); }
.chart .row .name { fill: var(--ink); font-size: 12.5px; }
.chart .row .value { fill: var(--ink); font-size: 12.5px; font-weight: 500; }
.chart .row .value.soft { fill: var(--muted); font-weight: 400; }
.chart .stem { stroke: var(--faint); stroke-width: 2; stroke-linecap: round; }
.chart .tool { fill: var(--bg); stroke: var(--muted); stroke-width: 2; }
.chart .gui { fill: var(--ink); stroke: var(--bg); stroke-width: 2; }
.chart .gui.hot { stroke: var(--accent); }
.chart .dot { stroke: var(--bg); stroke-width: 2; }
.chart .dot.hot { stroke: var(--ink); }
.chart .hit { fill: transparent; outline: none; }
.chart-key { display: flex; flex-wrap: wrap; gap: .4rem 1.25rem; margin: 0 0 .9rem; font-size: .8125rem; color: var(--muted); }
.chart-key span { display: inline-flex; align-items: center; gap: .45rem; }
.chart-key i { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.chart-key .k-tool { box-shadow: inset 0 0 0 2px var(--muted); }
.chart-key .k-gui { background: var(--ink); }
.chart-tip {
  position: fixed; z-index: 70; pointer-events: none; min-width: 12rem; max-width: 18rem;
  padding: .6rem .75rem; border-radius: var(--radius); background: var(--surface-2); color: var(--ink);
  font-size: .75rem; line-height: 1.45; box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
}
.chart-tip b { display: block; margin-bottom: .3rem; font-size: .8125rem; font-weight: 600; }
.chart-tip div { display: flex; justify-content: space-between; gap: 1rem; color: var(--muted); }
.chart-tip strong { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
.chart-fallback { color: var(--muted); font-size: var(--t-small); }
.data-table { width: 100%; border-collapse: collapse; font-size: .8125rem; font-variant-numeric: tabular-nums; }
.data-table th, .data-table td { padding: .55rem .7rem; border-bottom: 1px solid var(--line); text-align: right; white-space: nowrap; }
.data-table th:first-child { text-align: left; }
.data-table thead th { color: var(--muted); font-weight: 500; white-space: normal; vertical-align: bottom; }
.data-table tbody th, .data-table tfoot th { color: var(--ink); font-weight: 500; }
.data-table tfoot th, .data-table tfoot td { border-bottom: 0; color: var(--ink); font-weight: 600; }
.swarm-table td:nth-child(2) { text-align: left; }

.swarm-controls { display: flex; flex-wrap: wrap; align-items: end; gap: .75rem 1.25rem; margin: 0 0 1rem; }
.swarm-controls label { display: grid; gap: .3rem; color: var(--muted); font-size: .8125rem; }
.swarm-controls select {
  font: inherit; font-size: var(--t-small); color: var(--ink); background: var(--surface);
  border: 0; border-radius: var(--radius); padding: .5rem .6rem; max-width: 100%;
}
.legend { display: flex; flex-wrap: wrap; gap: .4rem 1.25rem; margin-left: auto; font-size: .8125rem; color: var(--muted); }
.legend span::before { content: ""; display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: .45rem; background: var(--c); vertical-align: -1px; }
.swarm-main { min-height: 300px; }
.swarm-multiples { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 1.25rem 1rem; margin-top: 1.25rem; }
.swarm-multiples figure { margin: 0; }
.swarm-multiples figcaption { margin: 0 0 .2rem; font-size: .75rem; color: var(--muted); }
.swarm-multiples svg { display: block; width: 100%; height: auto; }


/* THE STUDIES. One column of reading, with the page's bar and close. */
main.study { max-width: 760px; }
.study-nav { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.75rem; padding: 1.5rem 0; font-size: var(--t-small); }
.study-nav:first-child a:first-child { margin-right: auto; color: var(--ink); font-weight: 600; font-size: 1rem; letter-spacing: -.02em; }
.study-nav a { text-decoration: none; color: var(--muted); transition: color .15s ease; }
.study-nav a:hover { color: var(--ink); }
.study-nav:last-child { margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--line); }
.study article { padding: clamp(2rem, 6vw, 4rem) 0 0; }
.study h1 { font-size: var(--t-head); line-height: 1.05; letter-spacing: -.04em; font-weight: 600; margin: 0 0 1.25rem; text-wrap: balance; }
.study header p { font-size: var(--t-title); color: var(--muted); line-height: 1.5; }
.study h2 { font-size: var(--t-title); font-weight: 600; letter-spacing: -.02em; margin: 3rem 0 .75rem; }
.study p, .study li { font-size: 1rem; line-height: 1.7; color: var(--muted); }
.study strong { color: var(--ink); }
.study a { text-decoration-color: color-mix(in srgb, var(--ink) 30%, transparent); text-underline-offset: .2em; }
.study a:hover { text-decoration-color: var(--accent); }
.study-window { margin: 2rem 0; }
.study-window > img { width: 100%; height: auto; display: block; border-radius: var(--radius); background: var(--surface); }
.study figcaption { font-size: var(--t-small); }
.study pre { padding: 1.2rem; overflow-x: auto; border-radius: var(--radius); background: var(--surface); font-size: .8125rem; line-height: 1.65; }
.study p code, .study li code { color: var(--ink); }

/* The slideshow on this page: no extra room above it, the caption tighter under it. */
.stage { padding-top: 8px; --w-desk: min(1080px, 84vw, (100vh - 19rem) * 1.6); }
.stage .boot { background: rgba(20, 20, 18, .55); }
.stage .spin { border-top-color: #fff; }
.pager > button { background: color-mix(in srgb, var(--surface) 80%, transparent); }

/* The code, set on one step of tone, with the install line copying itself. */
.codebox { box-shadow: var(--media-shadow); border-radius: var(--media-radius); background: var(--code-bg); }
.n { color: var(--syn-n); }
#install code::after { color: var(--muted); }

/* Policy counts beside the check's video. */
.counts { display: flex; gap: 28px; margin-top: 24px; flex-wrap: wrap; }
.counts b { display: block; font-weight: 500; font-size: clamp(26px, 2.6vw, 36px); letter-spacing: -.04em; line-height: 1; font-variant-numeric: tabular-nums; }
.counts span { display: block; font-size: 13px; color: var(--muted); margin-top: 6px; }

/* The chart beside its paragraph. */
.chart-panel { padding: clamp(16px, 2.4vw, 28px); border-radius: var(--media-radius); background: color-mix(in srgb, var(--bg) 55%, transparent); box-shadow: var(--media-shadow); }
.chart-panel details { margin-top: 16px; font-size: 14px; }
.chart-panel summary { cursor: pointer; color: var(--muted); }
.chart-panel summary:hover { color: var(--ink); }
.chart-panel .table-wrap { margin-top: 12px; }
.compare { position: relative; overflow: hidden; box-shadow: var(--media-shadow); border-radius: var(--media-radius); }
.compare > img { display: block; width: 100%; height: auto; }
.compare label { border-radius: 999px; }
.branch-body { border-radius: var(--media-radius); background: color-mix(in srgb, var(--surface) 70%, transparent); }

@media (max-width: 900px) {
  .hero .wrap, .split, .split.wide, .split.rev, .split.rev.wide { grid-template-columns: minmax(0, 1fr); }
  .hero .wrap > div { justify-self: start; }
  .split.rev > .text { order: 0; }
  .nums { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nums div:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .band .grid { grid-template-columns: minmax(0, 1fr); }
  .band .grid a + a { padding-left: 0; border-left: 0; }
  .offers .grid { grid-template-columns: minmax(0, 1fr); }
  .offers article + article { padding-left: 0; border-left: 0; border-top: 1px solid var(--line); }
  .text h2 { max-width: 18ch; }
  .text p { max-width: 52ch; }
}
@media (max-width: 720px) {
  .stage { --w-desk: 86vw; --h-phone: min(640px, 150vw, 100vh - 12rem); }
  .track { margin-bottom: 4.5rem; }
  .pager { margin-top: -1.6rem; align-items: flex-start; padding-inline: .5rem; }
  .pager > button { width: 2rem; height: 2rem; }
  .caption { min-height: 8.1rem; }
  #caption-summary { font-size: .8125rem; }
  .codebox pre { padding-inline: 1rem; }
  .codebox code { font-size: .75rem; }
  .branch-diagram { padding: 18px 12px 22px; }
  .branch-root { width: min(240px, 70%); }
  .tabs button, .copy { padding-inline: .6rem; }
}
@media (max-width: 560px) {
  :root { --margin: 16px; }
  .top nav { gap: 14px; font-size: 13.5px; }
  .top nav .opt { display: none; }
  .top nav a.key { padding: 6px 12px; }
  .legend { margin-left: 0; }
  .swarm-multiples { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem .75rem; }
}
@media (max-width: 479px) { .caption { min-height: 12rem; } }
@media (max-width: 359px) { .caption { min-height: 13.2rem; } .brand span { display: none; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
  .spin { border-color: rgba(255, 255, 255, .38); }
  .track { perspective: none; }
  .slide { transform: translate(calc(-50% + var(--x, 0px)), -50%) scale(.94) !important; }
  .slide.active { transform: translate(calc(-50% + var(--x, 0px)), -50%) !important; }
}

/* THE STUDIES. One column of reading. */
main.study { margin: 0 auto; padding: 0 var(--margin) 48px; box-sizing: content-box; }
.figure-bar { margin: 0 0 .75rem; color: var(--ink); font-size: var(--t-small); font-weight: 500; }
figcaption { margin-top: .9rem; color: var(--muted); font-size: var(--t-small); line-height: 1.6; }

/* The expert page's method, folded away beside its paragraph. */
.method-details > summary { cursor: pointer; font-weight: 500; }
.method-details .method { margin-top: 12px; color: var(--muted); font-size: 14px; line-height: 1.6; }
.method code { color: var(--ink-2); overflow-wrap: anywhere; }
.method pre { margin: 12px 0 0; padding: 14px 16px; border-radius: var(--radius); background: var(--code-bg); overflow-x: auto; font-size: 12px; line-height: 1.7; }
.method pre code { overflow-wrap: normal; }
.pagehead.statement { padding-bottom: clamp(40px, 6vw, 72px); }
.pagehead .nums { margin-top: clamp(40px, 6vw, 72px); }
/* A tall demonstration keeps its paragraph in view beside it. */
.split.top { align-items: start; }
.split.top > .text { position: sticky; top: 96px; }
@media (max-width: 900px) { .split.top > .text { position: static; } }

/* Homepage: the market simulation research list. */
.studies-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.studies-list a { display: block; padding: 18px 0; border-bottom: 1px solid var(--line); text-decoration: none; }
.studies-list b { display: block; font-weight: 500; font-size: 20px; letter-spacing: -.02em; }
.studies-list span { display: block; color: var(--muted); font-size: 15px; margin-top: 4px; }
.studies-list a b::after { content: " \2192"; opacity: 0; transition: opacity .2s ease; }
.studies-list a:hover b::after { opacity: 1; }
