/* ===========================================================================
   Ostraca figure styles. Everything a drawing needs and nothing a page does.

   Theming: every colour and step is a --ostraca-* custom property. The
   defaults are light-dark() pairs, so they follow the page's color-scheme
   (set `color-scheme: light dark` on your root, or `light` / `dark`).
   Override any of them on :root or on a wrapper to retheme:

     .my-card { --ostraca-thing: #0a5; --ostraca-paper: white; }

   Motion: transitions and the crew's beat are off under
   prefers-reduced-motion: reduce; the drawing still lands on its state.
   =========================================================================== */

:where(:root) {
  /* Things are drawn in blueprint blue, people in the text ink. */
  --ostraca-thing: light-dark(oklch(57% 0.09 243), oklch(80% 0.075 243));
  --ostraca-crew: light-dark(oklch(28% 0.02 72), oklch(93% 0.004 307));
  --ostraca-ground: light-dark(oklch(74% 0.016 80), oklch(100% 0 0 / 0.34));
  --ostraca-label: light-dark(oklch(44% 0.021 72), oklch(83% 0.02 250));
  /* The only fill: the paper the drawing sits on (cream pad / blueprint). */
  --ostraca-paper: light-dark(#eee6d6, #1f3b5c);
  /* Secondary detail is lower opacity, never a second weight. */
  --ostraca-temp: 0.6;
  --ostraca-faint: 0.35;
  --ostraca-sans: "Cubit Sans", ui-sans-serif, system-ui, sans-serif;
  --ostraca-mono: "Cubit Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Springs sampled into linear() (src/engine/svg.js SPRINGS). */
  --ostraca-spring-lean: linear(0, 0.012, 0.043, 0.093, 0.154, 0.23, 0.308, 0.397, 0.484, 0.576, 0.661, 0.744, 0.826, 0.898, 0.968, 1.026, 1.08, 1.123, 1.161, 1.188, 1.21, 1.224, 1.231, 1.233, 1.229, 1.221, 1.21, 1.194, 1.177, 1.158, 1.138, 1.116, 1.096, 1.076, 1.056, 1.038, 1.021, 1.006, 0.992, 0.98, 0.97, 0.962, 0.955, 0.951, 0.948, 0.946, 0.946, 0.947, 0.949, 0.952, 0.955, 0.96, 0.964, 0.969, 0.973, 1);
  --ostraca-spring-bob: linear(0, 0.032, 0.119, 0.25, 0.412, 0.593, 0.779, 0.959, 1.122, 1.261, 1.369, 1.444, 1.484, 1.491, 1.467, 1.418, 1.349, 1.266, 1.175, 1.084, 0.997, 0.92, 0.856, 0.807, 0.775, 0.759, 0.76, 0.776, 0.803, 0.839, 0.881, 0.926, 0.971, 1.012, 1.049, 1.078, 1.1, 1.114, 1.119, 1.116, 1.107, 1.092, 1.074, 1.052, 1.03, 1.009, 0.989, 0.972, 0.958, 0.948, 0.943, 0.941, 0.944, 0.949, 0.957, 1);
  --ostraca-spring-sag: linear(0, 0.015, 0.052, 0.113, 0.188, 0.276, 0.379, 0.483, 0.59, 0.704, 0.808, 0.908, 1.006, 1.09, 1.168, 1.23, 1.281, 1.322, 1.35, 1.366, 1.372, 1.367, 1.354, 1.332, 1.305, 1.271, 1.235, 1.197, 1.155, 1.115, 1.076, 1.036, 1.002, 0.97, 0.941, 0.917, 0.896, 0.882, 0.871, 0.864, 0.862, 0.863, 0.868, 0.875, 0.885, 0.898, 0.911, 0.926, 0.941, 0.956, 0.971, 0.985, 0.998, 1.011, 1.021, 1);
}

@property --ostraca-built { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --ostraca-travel { syntax: "<number>"; inherits: true; initial-value: 1; }

.ostraca { display: block; width: 100%; height: auto; overflow: visible; color: var(--ostraca-crew); }
.ostraca :is(path, rect, circle, line) { vector-effect: non-scaling-stroke; }
.ostraca .ink { fill: none; stroke: var(--ostraca-thing); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; }
.ostraca .paper { fill: var(--ostraca-paper); }
.ostraca .gnd { fill: none; stroke: var(--ostraca-ground); stroke-width: 1; stroke-linecap: round; }
.ostraca .temp { opacity: var(--ostraca-temp); }
.ostraca .faint { opacity: var(--ostraca-faint); }
/* Dimension figures: the one place the mono face is drawn. */
.ostraca .fig {
  font-family: var(--ostraca-mono); font-size: 10px; fill: var(--ostraca-thing); stroke: none;
  font-feature-settings: "tnum" 1; letter-spacing: 0.04em;
}
.ostraca .lbl { font-family: var(--ostraca-sans); font-size: 12px; fill: var(--ostraca-label); stroke: none; }
/* Lettering is the one line that scales with the drawing, as a font would:
   a marker's weight, about an eighth of the cap height, at any size. (The
   pen group carries .ink, whose 1px would otherwise win by inheritance.)
   The <text> twin is there for assistive tech and search, never shown. */
.ostraca .lt .lt-pen { stroke-width: 1.3; }
.ostraca .lt .lt-pen path { vector-effect: none; }
.ostraca .lt-font { display: none; }

/* The crew: two weights of line, in the ink of the text. */
.ostraca .crew-g { fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; }
.ostraca .crew-key { stroke-width: 1.6; opacity: 0.82; }
.ostraca .crew-hair { stroke-width: 1; opacity: 0.45; }
.ostraca .crew-g [data-pose="b"] { opacity: 0; }

/* ONE NUMBER: every course is drawn twice, set out and built, and the built
   copy shows when --ostraca-built has passed its place in the order. */
.ostraca-sub {
  --ostraca-built: 1;
  transition:
    --ostraca-built var(--ostraca-t, 900ms) var(--ostraca-ease, cubic-bezier(0.2, 0.7, 0.3, 1)),
    --ostraca-travel 240ms cubic-bezier(0.16, 0.84, 0.44, 1);
}
.ostraca .c { opacity: clamp(0, calc((var(--ostraca-built) * var(--n) - var(--i)) * 4), 1); }

/* What each state shows. Delays on entry only. */
.ostraca .L-setout { transition: opacity 260ms ease; }
.ostraca-sub:is([data-state="idle"], [data-state="success"], [data-state="changed"]) .L-setout { opacity: 0; }
.ostraca .st, .ostraca .mk { opacity: 0; transition: opacity 160ms ease; }
.ostraca .L-scaffold { opacity: 0; transition: opacity 200ms ease; }
.ostraca-sub[data-state="loading"] .L-scaffold { opacity: 1; transition: opacity 240ms ease; }
.ostraca .L-gin { display: none; }
.ostraca-sub[data-state="loading"][data-unknown] .L-gin { display: inline; }
.ostraca-sub[data-crew="off"] .L-crew,
.ostraca-sub[data-crew="off"] .rest-on,
.ostraca-sub[data-crew="on"] .rest-off { display: none; }

/* Stations and marks show in the states they list. */
.ostraca-sub[data-state="empty"] :is(.st, .mk)[data-st~="empty"],
.ostraca-sub[data-state="loading"] :is(.st, .mk)[data-st~="loading"],
.ostraca-sub[data-state="idle"] :is(.st, .mk)[data-st~="idle"],
.ostraca-sub[data-state="success"] :is(.st, .mk)[data-st~="success"],
.ostraca-sub[data-state="changed"] :is(.st, .mk)[data-st~="changed"],
.ostraca-sub[data-state="error"] :is(.st, .mk)[data-st~="error"] {
  opacity: 1; transition: opacity 280ms ease 180ms;
}
.ostraca-sub[data-unknown] .st[data-known],
.ostraca-sub:not([data-unknown]) .st[data-unknown-only] { opacity: 0 !important; }

/* Standards grow up from the ground; lifts come one ahead of the work. */
.ostraca .std { transform-box: fill-box; transform-origin: 50% 100%; transform: scaleY(0); transition: transform 300ms ease-out; }
.ostraca-sub[data-state="loading"] .std { transform: scaleY(1); }
.ostraca .lift { transition: opacity 200ms ease, translate 200ms ease; }
.ostraca-sub:not([data-state="loading"]) .lift { opacity: 0; translate: 0 2px; transition-delay: calc((12 - var(--j, 0)) * 90ms); }
.ostraca .board { transition: transform 240ms cubic-bezier(0.16, 0.84, 0.44, 1); }

/* The tick: two strokes, the short one then the long one, each drawn from
   its start by a scale rather than a dash offset. */
.ostraca .tick path { stroke-width: 1.4; transform-box: fill-box; transform: scale(0); transition: transform 0ms; }
.ostraca .tick .t1 { transform-origin: 0% 0%; }
.ostraca .tick .t2 { transform-origin: 0% 100%; }
.ostraca-sub[data-state="success"] .tick path { transform: scale(1); transition: transform 160ms ease-out 260ms; }
.ostraca-sub[data-state="success"] .tick .t2 { transition-delay: 420ms; }

/* The cloud: its scallops in clockwise order, then the tag. */
.ostraca .cloud path { opacity: 0; transition: opacity 120ms ease; }
.ostraca-sub[data-state="changed"] .cloud path { opacity: 1; transition-delay: calc(var(--k) * 30ms + 120ms); }
.ostraca .tag { opacity: 0; translate: 0 -4px; transition: opacity 160ms ease, translate 160ms ease; }
.ostraca-sub[data-state="changed"] .tag { opacity: 1; translate: 0 0; transition-delay: var(--tag-at, 700ms); }

/* The true line: the work leans, the plumb line drops from its bracket and
   the bob swings in and settles on a spring. */
.ostraca .lean { transition: transform 1.6s var(--ostraca-spring-lean, ease-out); }
.ostraca-sub[data-state="error"] .lean { transform: skewX(var(--lean)); }
.ostraca .cord { transform-box: fill-box; transform-origin: 50% 0%; transform: scaleY(0); transition: transform 0ms; }
.ostraca-sub[data-state="error"] .cord { transform: scaleY(1); transition: transform 380ms cubic-bezier(0.2, 0.8, 0.3, 1) 260ms; }
.ostraca .bob { opacity: 0; }
.ostraca-sub[data-state="error"] .bob { opacity: 1; transition: opacity 120ms ease 560ms; }
.ostraca-sub[data-state="error"] .swing { animation: ostraca-swing 2.2s var(--ostraca-spring-bob, ease-out) 560ms both; }
@keyframes ostraca-swing { from { transform: rotate(9deg); } to { transform: rotate(0deg); } }
.ostraca .sag { transition: d 1.5s var(--ostraca-spring-sag, ease-out); }
.ostraca-sub[data-state="error"] .sag { d: var(--d1); }
/* Sag drawings whose shapes cannot tween cross-fade instead. */
.ostraca .sag-a, .ostraca .sag-b { transition: opacity 220ms ease; }
.ostraca .sag-b, .ostraca-sub[data-state="error"] .sag-a { opacity: 0; }
.ostraca-sub[data-state="error"] .sag-b { opacity: 1; }

/* The default set-out: the courses again, dashed and unfilled. */
.ostraca .dash :is(path, rect, circle, line) { stroke-dasharray: 4 3; }
.ostraca .dash .paper { fill: none; }

/* Travel: work that moves instead of rising (a load up a ramp). */
.ostraca-sub[data-travel] .tr {
  transform: translate(calc(var(--ostraca-travel) * var(--tx, 0px)), calc(var(--ostraca-travel) * var(--ty, 0px)));
}

/* Right to left: the drawing is mirrored, its figures read the right way. */
.ostraca[data-dir="rtl"] text.fig { transform-box: fill-box; transform-origin: 50% 50%; transform: scaleX(-1); }

.ostraca .heave { transition: transform 240ms cubic-bezier(0.16, 0.84, 0.44, 1), d 240ms cubic-bezier(0.16, 0.84, 0.44, 1); }
.ostraca .chainline { transition: d 280ms cubic-bezier(0.2, 0.8, 0.3, 1); }
.ostraca .xfade { transition: opacity 220ms ease; }

/* The gin wheel's load: the only loop, because there, work is going on. */
.ostraca .gin-load { animation: ostraca-gin 1.6s ease-in-out infinite alternate; }
.ostraca .gin-fall { transform-box: fill-box; transform-origin: 50% 0%; animation: ostraca-gin-fall 1.6s ease-in-out infinite alternate; }
@keyframes ostraca-gin { from { transform: translateY(0); } to { transform: translateY(var(--gin-span)); } }
@keyframes ostraca-gin-fall { from { transform: scaleY(1); } to { transform: scaleY(var(--gin-scale)); } }

/* The worker's beat: two drawings, 3.4s, 64/36, a 2% smear. Busy halves it. */
@media (prefers-reduced-motion: no-preference) {
  .ostraca .crew-g [data-pose="a"] { animation: ostraca-pose-a 3.4s steps(1) var(--crew-delay, 0s) infinite; }
  .ostraca .crew-g [data-pose="b"] { animation: ostraca-pose-b 3.4s steps(1) var(--crew-delay, 0s) infinite; }
  .ostraca-sub[data-busy] .crew-g [data-pose="a"] { animation: ostraca-pose-a 0.62s steps(1) 0s infinite; }
  .ostraca-sub[data-busy] .crew-g [data-pose="b"] { animation: ostraca-pose-b 0.62s steps(1) 0s infinite; }
}
@keyframes ostraca-pose-a { 0% { opacity: 0.62; } 2% { opacity: 1; } 62% { opacity: 0.42; } 64% { opacity: 0; } }
@keyframes ostraca-pose-b { 0% { opacity: 0.42; } 2% { opacity: 0; } 62% { opacity: 0.62; } 64% { opacity: 1; } }

/* Arrival: the drawing opens as its plan on two faint guides and inks in
   the order it would be built. */
.ostraca .guides { opacity: 0; transition: opacity 400ms ease; }
.ostraca-sub[data-plan] .guides { opacity: 1; transition: none; }
.ostraca-sub[data-plan] .L-setout { opacity: 1 !important; transition: none; }
.ostraca-sub[data-plan] :is(.L-marks, .L-crew, .letter) { opacity: 0; transition: none; }
.ostraca .letter { transition: opacity 300ms ease var(--letter-at, 0ms); }

@media (prefers-reduced-motion: reduce) {
  .ostraca-sub, .ostraca *, .ostraca *::before { transition-duration: 0ms !important; transition-delay: 0ms !important; }
  .ostraca .swing, .ostraca .gin-load, .ostraca .gin-fall { animation: none !important; }
  .ostraca .gin-load { transform: translateY(var(--gin-span)); }
  .ostraca .gin-fall { transform: scaleY(var(--gin-scale)); }
}

/* ===========================================================================
   The catalogue site. Tokens are the prototype's: cream pad in light,
   blueprint in dark, as light-dark() pairs, so the theme is one
   `color-scheme` and the package's own --ostraca-* tokens follow it.
   =========================================================================== */
@font-face { font-family: "Cubit Sans"; src: url("fonts/CubitSans-Variable.woff2") format("woff2"); font-weight: 100 900; font-display: swap; }
@font-face { font-family: "Cubit Mono"; src: url("fonts/CubitMono-Variable.woff2") format("woff2"); font-weight: 100 900; font-display: swap; }

:root {
  color-scheme: light dark;
  --sans: "Cubit Sans", ui-sans-serif, system-ui, sans-serif;
  --mono: "Cubit Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --paper: light-dark(#eee6d6, #1f3b5c);
  --ink: light-dark(oklch(28% 0.02 72), oklch(93% 0.004 307));
  --muted: light-dark(oklch(44% 0.021 72), oklch(83% 0.02 250));
  --faint: light-dark(oklch(48% 0.021 72), oklch(78% 0.03 250));
  --notes-ink: light-dark(oklch(52% 0.09 243), oklch(80% 0.075 243));
  --rule: light-dark(oklch(57% 0.09 243 / 0.32), oklch(100% 0 0 / 0.2));
  --rule-strong: light-dark(oklch(57% 0.09 243 / 0.7), oklch(100% 0 0 / 0.42));
  --well: light-dark(oklch(57% 0.09 243 / 0.07), oklch(100% 0 0 / 0.06));
  --gutter: 32px;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--paper); }
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font: 400 16px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
  overflow-x: clip;
}
a { color: inherit; }
button, input { font: inherit; color: inherit; }
code, pre, kbd { font-family: var(--mono); }
:focus-visible { outline: 1px solid var(--notes-ink); outline-offset: 3px; border-radius: 2px; }
[hidden] { display: none !important; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.skip { position: absolute; left: 16px; top: -60px; background: var(--paper); padding: 6px 10px; border: 1px solid var(--rule-strong); z-index: 20; }
.skip:focus { top: 12px; }

.page { max-width: 1200px; margin: 0 auto; padding: 0 var(--gutter) 96px; }
@media (max-width: 640px) { :root { --gutter: 16px; } .page { padding-bottom: 64px; } }

/* ---------------------------------------------------------------------------
   Header
   --------------------------------------------------------------------------- */
.bar {
  max-width: 1200px; margin: 0 auto; padding: 20px var(--gutter) 0;
  display: flex; align-items: center; gap: 12px 28px; flex-wrap: wrap;
}
.mark { font-weight: 500; letter-spacing: -0.02em; text-decoration: none; font-size: 18px; margin-right: auto; }
.nav { display: flex; gap: 4px 18px; flex-wrap: wrap; font-size: 15px; }
.nav a { text-decoration: none; color: var(--muted); padding: 2px 0; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }
.nav a[aria-current="page"] { text-decoration: underline; text-decoration-color: var(--notes-ink); text-underline-offset: 5px; }
.seg { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 2px; font-size: 13px; }
.seg > span { color: var(--faint); margin-right: 6px; }
.seg button {
  border: 0; background: none; padding: 4px 9px; border-radius: 999px; cursor: pointer; color: var(--muted);
}
.seg button:hover { color: var(--ink); }
.seg button[aria-pressed="true"] { color: var(--ink); box-shadow: inset 0 0 0 1px var(--rule-strong); }
.theme button { width: 28px; height: 28px; padding: 0; display: inline-grid; place-items: center; }
.theme svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 640px) {
  .bar { padding-top: 14px; gap: 10px 18px; }
  .theme { order: 3; width: 100%; }
}

/* ---------------------------------------------------------------------------
   Shared bits
   --------------------------------------------------------------------------- */
.kicker { font-size: 13px; color: var(--faint); margin: 0; }
h1 { margin: 0; font-weight: 500; letter-spacing: -0.035em; line-height: 1.02; font-size: clamp(2.5rem, 6vw, 4.25rem); }
.lede { margin: 18px 0 0; font-size: 1.25rem; line-height: 1.5; max-width: 44ch; text-wrap: balance; }
.sub { margin: 12px 0 0; color: var(--muted); max-width: 60ch; }
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--rule-strong); background: transparent; border-radius: 999px;
  padding: 5px 14px; cursor: pointer; color: var(--ink); font-size: 14px; text-decoration: none; line-height: 1.4;
}
.btn:hover { border-color: var(--notes-ink); }
.btn[data-done] { border-color: var(--notes-ink); color: var(--notes-ink); }
.check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; color: var(--muted); }
.check input {
  appearance: none; -webkit-appearance: none; flex: none; width: 15px; height: 15px; margin: 0;
  border: 1px solid var(--rule-strong); border-radius: 3px; background: transparent;
  display: inline-grid; place-content: center; cursor: pointer;
}
.check input:checked { background: var(--notes-ink); border-color: var(--notes-ink); }
.check input:checked::after {
  content: ""; width: 7px; height: 3.5px; border: solid var(--paper); border-width: 0 0 1.6px 1.6px;
  transform: translateY(-1px) rotate(-45deg);
}
.check input:focus-visible { outline: 1px solid var(--notes-ink); outline-offset: 2px; }

.installs { display: flex; flex-wrap: wrap; gap: 10px; margin: 28px 0 0; }
.installs .install { margin: 0; }
.install-note { margin: 10px 0 0; font-size: 14px; color: var(--faint); }
.install {
  display: inline-flex; align-items: center; gap: 4px; margin: 28px 0 0;
  border: 1px solid var(--rule-strong); border-radius: 999px; padding: 4px 4px 4px 16px; max-width: 100%;
}
.install code { font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.install code::before { content: "$ "; color: var(--faint); }
.install .btn { border-color: transparent; padding: 3px 12px; }
.install .btn:hover { border-color: var(--rule-strong); }
/* The copy button: square, an icon in the theme switch's line, and a check
   for the moment after a copy. */
.install .copy-icon { flex: none; width: 28px; height: 28px; padding: 0; justify-content: center; }
.copy-icon svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; }
.copy-icon .i-done, .copy-icon[data-done] .i-copy { display: none; }
.copy-icon[data-done] .i-done { display: inline; }
/* Its focus ring on its own edge: two pixels out, it would meet the pill's. */
.install .copy-icon:focus-visible { outline-offset: 0; }
/* A phone fits the whole skill command: no prompt sign, a size smaller. */
@media (max-width: 480px) {
  .install { padding-left: 14px; }
  .install code { font-size: 12px; letter-spacing: -0.01em; }
  .install code::before { content: none; }
}

.links { display: flex; flex-wrap: wrap; gap: 8px 24px; margin: 22px 0 0; padding: 0; list-style: none; }
.links a { text-decoration: none; font-weight: 500; }
.links a::after { content: " \2192"; color: var(--notes-ink); }
.links a:hover { text-decoration: underline; text-decoration-color: var(--notes-ink); text-underline-offset: 4px; }

/* ---------------------------------------------------------------------------
   Home
   --------------------------------------------------------------------------- */
.hero { padding: 72px 0 0; }
@media (max-width: 640px) { .hero { padding-top: 44px; } }

/* The hero sheet: the README cover, live. The words and the stage stand on
   one ground line across the sheet; the figure on the stage goes through its
   states (client.js) and the title block under it reads them out. */
.hero-sheet { margin: 40px 0 0; padding: 0; border: 1px solid var(--rule-strong); }
.hs-top {
  display: grid; grid-template-columns: minmax(22.5rem, 0.78fr) minmax(0, 1.22fr); gap: 0 32px; align-items: end;
  padding: 56px 40px 0; border-bottom: 1px solid var(--ostraca-ground);
}
.hs-words { padding-bottom: 40px; }
.hero-sheet h1 { font-size: clamp(3.5rem, 8.6vw, 6.75rem); letter-spacing: -0.045em; line-height: 0.92; margin-left: -0.04em; }
.hero-sheet .lede { margin-top: 22px; font-size: clamp(1.25rem, 1.9vw, 1.5rem); line-height: 1.35; letter-spacing: -0.01em; max-width: 21em; }
/* Every figure at one scale: --fw is its width against the stage, and
   --sink drops it by its depth below the ground so its ground is the sheet's. */
.hs-stage { position: relative; }
.hs-layer { position: absolute; left: 50%; bottom: 0; width: var(--fw); translate: var(--fx) var(--sink); transition: opacity 700ms ease; }
.hs-layer[data-entering], .hs-layer[data-leaving] { opacity: 0; }
.hs-layer[data-leaving] { transition-duration: 450ms; }
.hs-stage .gnd { display: none; }

.home-intro { margin: 40px 0 0; max-width: 64ch; font-size: 1.125rem; line-height: 1.6; color: var(--muted); text-wrap: pretty; }

/* The title block, in the figure sheets' terms. */
.hs-block { margin-top: 30px; border-top: 3px double var(--notes-ink); display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); }
.hs-cell { padding: 12px 18px 14px; min-width: 0; }
.hs-cell + .hs-cell { border-left: 1px solid var(--rule); }
.hs-name { grid-column: span 3; padding-left: 40px; }
.hs-states { grid-column: span 9; }
.hs-code { grid-column: span 7; border-top: 1px solid var(--rule); padding-left: 40px; border-left: 0 !important; }
.hs-remark { grid-column: span 5; border-top: 1px solid var(--rule); }
.hs-k { display: block; font-size: 12px; color: var(--faint); }
.hs-name a { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 10px; margin-top: 3px; text-decoration: none; }
.hs-name b { font-weight: 500; font-size: 20px; letter-spacing: -0.015em; }
.hs-name a span { font-size: 13px; color: var(--faint); font-feature-settings: "tnum" 1; }
.hs-name a:hover b { color: var(--notes-ink); }
.hs-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: -4px; }
.hs-play { padding: 2px 11px 2px 8px; font-size: 13px; gap: 6px; color: var(--muted); }
.hs-play svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
.hs-play .i-play, .hs-play[data-paused] .i-pause { display: none; }
.hs-play[data-paused] .i-play { display: inline; }
.hs-picks { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 4px; margin-top: 6px; }
.hs-picks button {
  position: relative; display: grid; justify-items: center; gap: 4px;
  border: 0; background: none; padding: 10px 4px 8px; cursor: pointer; font-size: 13px; line-height: 1.25; color: var(--muted);
}
.hs-picks button:hover, .hs-picks button[aria-pressed="true"] { color: var(--ink); }
.hs-picks svg { width: 34px; height: 22px; overflow: visible; }
.hs-code code { display: block; margin-top: 5px; font-size: 13.5px; line-height: 1.5; color: var(--ink); }
.hs-code i { font-style: normal; color: var(--muted); }
.hs-code b { font-weight: 400; color: var(--notes-ink); }
.hs-remark p { margin: 3px 0 0; font-size: 15px; line-height: 1.45; color: var(--muted); }
@media (max-width: 960px) {
  .hs-top { grid-template-columns: minmax(0, 1fr); padding: 40px 28px 0; }
  .hs-words { padding-bottom: 8px; }
  .hs-stage { width: min(100%, 600px); justify-self: center; }
  .hs-name, .hs-code { padding-left: 28px; }
  .hs-name { grid-column: span 12; }
  .hs-states { grid-column: span 12; border-left: 0 !important; border-top: 1px solid var(--rule); padding-left: 28px; }
  .hs-code, .hs-remark { grid-column: span 12; }
  .hs-remark { border-left: 0 !important; padding-left: 28px; }
}
@media (max-width: 640px) {
  .hero-sheet { margin-top: 28px; }
  .hs-top { padding: 28px 16px 0; }
  .hs-name, .hs-states, .hs-code, .hs-remark { padding-left: 16px; padding-right: 16px; }
  .hs-picks { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.street { margin: 56px 0 0; }
.street-row { display: flex; align-items: flex-end; width: 100%; overflow-x: clip; }
.street-row > div { flex: var(--w) 1 0; min-width: 0; margin-bottom: var(--mb, 0); }
.street-row .ostraca { overflow: visible; }
.street figcaption { margin-top: 10px; font-size: 14px; color: var(--muted); }
@media (max-width: 760px) {
  /* Two streets on a phone: the same figures, four to a ground line. */
  .street-row { flex-wrap: wrap; row-gap: 28px; }
  .street-row > div { flex: 1 1 calc(var(--w) / 760 * 100%); }
}
.home-notes { margin: 64px 0 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 32px; border-top: 1px solid var(--rule); }
.home-notes > div { padding: 16px 0 0; }
.home-notes h2 { margin: 0; font-size: 16px; font-weight: 500; }
.home-notes p { margin: 6px 0 0; color: var(--muted); font-size: 15px; }
.home-notes code { font-size: 13px; color: var(--ink); }
@media (max-width: 760px) { .home-notes { grid-template-columns: minmax(0, 1fr); } .home-notes > div + div { border-top: 1px solid var(--rule); margin-top: 16px; } }

/* Arrival: the street opens as its plan, set out, then inks in build order
   (one figure after another) while the plan stays down; the plan lifts and
   the crew and marks come on once the last one is built. */
.arriving .street .ostraca-sub { --ostraca-built: 0 !important; transition: none !important; }
:is(.arriving, .inking) .street .L-setout { opacity: 1 !important; transition: none !important; }
:is(.arriving, .inking) .street :is(.L-marks, .L-crew, .letter, .L-scaffold) { opacity: 0 !important; transition: none !important; }
.street .ostraca-sub { --ostraca-t: 1400ms; --ostraca-ease: cubic-bezier(0.45, 0, 0.3, 1); }
.inking .street .ostraca-sub { transition-delay: var(--arrive-at, 0ms) !important; }
.street .L-crew { transition: opacity 420ms ease; }
.street .L-setout { transition: opacity 600ms ease; }

/* ---------------------------------------------------------------------------
   Figures index: shelves as ruled ledger sections
   --------------------------------------------------------------------------- */
.switch {
  position: sticky; top: 0; z-index: 5; background: var(--paper);
  margin: 40px 0 0; padding: 12px 0; border-bottom: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 24px;
}
.switch .seg button { font-size: 14px; }
.switch .seg { flex-wrap: wrap; }
.switch-note { flex-basis: 100%; margin: 0; font-size: 13px; color: var(--faint); }
@media (max-width: 640px) {
  .switch { gap: 6px 16px; padding: 8px 0; }
  .switch .seg { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 calc(-1 * var(--gutter)); padding: 2px var(--gutter); width: calc(100% + 2 * var(--gutter)); }
  .switch .seg::-webkit-scrollbar { display: none; }
  .switch .seg > span { display: none; }
}
.shelf { margin: 56px 0 0; }
.shelf-head {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0 24px;
  border-bottom: 1px solid var(--rule-strong); padding-bottom: 12px;
}
.shelf-head h2 { grid-column: span 4; margin: 0; font-size: 22px; font-weight: 500; letter-spacing: -0.015em; }
.shelf-head p { grid-column: span 8; margin: 0; color: var(--muted); max-width: 62ch; }
.row {
  position: relative; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0 24px;
  border-bottom: 1px solid var(--rule); text-decoration: none; padding: 0;
}
.row-words { grid-column: span 8; display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 0 24px; padding: 18px 0; align-content: start; }
.row-no { grid-column: span 1; font-size: 13px; color: var(--faint); font-feature-settings: "tnum" 1; padding-top: 2px; }
.row-name { grid-column: span 2; font-weight: 500; }
.row-use { grid-column: span 5; color: var(--muted); }
.row-cell { grid-column: span 4; border-left: 1px solid var(--rule); padding: 10px 0 10px 16px; display: flex; align-items: flex-end; }
.row-cell > div { width: 100%; }
.row:hover .row-name, .row:focus-visible .row-name { color: var(--notes-ink); }
.row:focus-visible { outline: 1px solid var(--notes-ink); outline-offset: 2px; }
.row-name::after { content: " \2192"; color: var(--notes-ink); opacity: 0; transition: opacity 160ms ease; }
.row:hover .row-name::after, .row:focus-visible .row-name::after { opacity: 1; }
@media (max-width: 860px) {
  .shelf-head h2, .shelf-head p { grid-column: 1 / -1; }
  .shelf-head p { margin-top: 4px; }
  .row-words { grid-column: 1 / -1; grid-template-columns: 56px minmax(0, 1fr); gap: 2px 12px; padding: 14px 0 6px; }
  .row-no { grid-column: 1; grid-row: span 2; }
  .row-name, .row-use { grid-column: 2; }
  .row-cell { grid-column: 1 / -1; border-left: 0; padding: 0 0 12px 68px; }
}

/* ---------------------------------------------------------------------------
   A figure's sheet, in the prototype's layout
   --------------------------------------------------------------------------- */
.crumbs { margin: 40px 0 0; font-size: 14px; color: var(--muted); display: flex; gap: 8px; flex-wrap: wrap; }
.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--ink); text-decoration: underline; text-decoration-color: var(--notes-ink); text-underline-offset: 4px; }
.sheet-title { margin: 14px 0 0; font-size: clamp(2rem, 4.5vw, 3rem); }
.sheet { margin: 28px 0 0; border: 1px solid var(--rule-strong); }
.sheet-body { display: grid; grid-template-columns: minmax(0, 1fr) 290px; }
@media (max-width: 960px) { .sheet-body { grid-template-columns: minmax(0, 1fr); } }
.drawing { padding: 28px 28px 0; min-width: 0; display: flex; flex-direction: column; }
@media (max-width: 640px) { .drawing { padding: 16px 12px 0; } }
.drawing-art { flex: 1; display: flex; align-items: flex-end; justify-content: center; min-height: 0; }
.drawing-art > div { width: 100%; max-width: 760px; }
.drawing-art .ostraca { overflow: hidden; }
.controls { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 18px; }
.controls .spacer { flex: 1; }
.controls-note { margin: 0; font-size: 13px; color: var(--faint); min-height: 1.4em; }
.side { border-left: 1px solid var(--rule); display: flex; flex-direction: column; }
@media (max-width: 960px) { .side { border-left: 0; border-top: 1px solid var(--rule); } }

.revs { border: 0; margin: 0; padding: 20px 20px 16px; min-width: 0; }
.revs legend { padding: 0; font-size: 12px; color: var(--faint); margin-bottom: 4px; float: left; width: 100%; }
.revs legend + * { clear: both; }
.rev {
  position: relative; display: grid; grid-template-columns: 34px 1fr; gap: 0 10px; align-items: center;
  padding: 8px; margin: 0 -8px; cursor: pointer;
}
.rev + .rev { border-top: 1px solid var(--rule); }
.rev input { position: absolute; opacity: 0; pointer-events: none; }
.rev svg { width: 34px; height: 22px; overflow: visible; grid-row: span 2; }
:is(.rev, .hs-picks) svg .ink { fill: none; stroke: var(--notes-ink); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; }
:is(.rev, .hs-picks) svg .paper { fill: var(--paper); }
.rev b { font-weight: 500; font-size: 14px; line-height: 1.3; }
.rev b code { font-size: 12px; color: var(--faint); font-weight: 400; margin-left: 4px; }
.rev i { font-style: normal; grid-column: 2; font-size: 13px; color: var(--muted); line-height: 1.35; }
/* The selection mark: a thin box with a handle on each corner. */
:is(.rev, .hs-picks button)::before, :is(.rev, .hs-picks button)::after { content: ""; position: absolute; pointer-events: none; opacity: 0; }
:is(.rev, .hs-picks button)::before { inset: 2px 0; border: 1px solid var(--notes-ink); }
:is(.rev, .hs-picks button)::after {
  inset: -1px -3px;
  background:
    linear-gradient(var(--paper), var(--paper)) left 1px top 1px / 5px 5px no-repeat,
    linear-gradient(var(--paper), var(--paper)) right 1px top 1px / 5px 5px no-repeat,
    linear-gradient(var(--paper), var(--paper)) left 1px bottom 1px / 5px 5px no-repeat,
    linear-gradient(var(--paper), var(--paper)) right 1px bottom 1px / 5px 5px no-repeat,
    linear-gradient(var(--notes-ink), var(--notes-ink)) left top / 7px 7px no-repeat,
    linear-gradient(var(--notes-ink), var(--notes-ink)) right top / 7px 7px no-repeat,
    linear-gradient(var(--notes-ink), var(--notes-ink)) left bottom / 7px 7px no-repeat,
    linear-gradient(var(--notes-ink), var(--notes-ink)) right bottom / 7px 7px no-repeat;
}
.rev:has(input:checked)::before, .rev:has(input:checked)::after,
.hs-picks button[aria-pressed="true"]::before, .hs-picks button[aria-pressed="true"]::after { opacity: 1; }
.rev:has(input:focus-visible) b { text-decoration: underline; text-decoration-color: var(--notes-ink); text-underline-offset: 3px; }
.rev:has(input:checked) + .rev { border-top-color: transparent; }
.rev:hover b { color: var(--notes-ink); }

.notes { border-top: 1px solid var(--rule); padding: 14px 0 18px; margin: 18px 0 0; }
.notes h2 { margin: 0 0 6px; font-size: 12px; font-weight: 400; color: var(--faint); }
.notes ol { margin: 0; padding: 0 0 0 18px; font-size: 13px; color: var(--muted); line-height: 1.45; }
.notes li + li { margin-top: 8px; }
.notes code { font-family: var(--mono); font-size: 11.5px; color: var(--ink); overflow-wrap: anywhere; }

.titleblock {
  margin: 0; display: grid; border-top: 3px double var(--notes-ink);
  grid-template-columns: 1.1fr 1.7fr 0.95fr 0.5fr 0.75fr 2.1fr;
}
.titleblock > div { padding: 10px 16px 12px; min-width: 0; }
.titleblock > div + div { border-left: 1px solid var(--rule); }
.titleblock dt { font-size: 12px; color: var(--faint); }
.titleblock dd { margin: 3px 0 0; font-size: 14px; line-height: 1.4; }
.titleblock .drawing-name { font-weight: 500; font-size: 16px; }
.titleblock .remark { color: var(--muted); }
@media (max-width: 960px) {
  .titleblock { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .titleblock > div:nth-child(-n + 2) { grid-column: span 3; }
  .titleblock > div:nth-child(n + 3) { grid-column: span 2; border-top: 1px solid var(--rule); }
  .titleblock > div:nth-child(3) { border-left: 0; }
  .titleblock > div.wide { grid-column: span 6; border-left: 0; }
}
@media (max-width: 480px) {
  .titleblock > div:nth-child(-n + 2) { grid-column: span 6; border-left: 0; }
  .titleblock > div:nth-child(2) { border-top: 1px solid var(--rule); }
}
.pager { display: flex; justify-content: space-between; gap: 16px; margin: 28px 0 0; font-size: 14px; }
.pager a { text-decoration: none; color: var(--muted); }
.pager a:hover { color: var(--ink); }
.pager b { font-weight: 500; color: var(--ink); }

/* ---------------------------------------------------------------------------
   Docs and prose
   --------------------------------------------------------------------------- */
.docs { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 0 56px; margin: 48px 0 0; }
.docs-nav { position: sticky; top: 24px; align-self: start; font-size: 15px; }
.docs-nav h2 { font-size: 12px; font-weight: 400; color: var(--faint); margin: 0 0 6px; }
.docs-nav ul { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.docs-nav li { border-bottom: 1px solid var(--rule); }
.docs-nav a { display: block; padding: 7px 0; text-decoration: none; color: var(--muted); }
.docs-nav a:hover { color: var(--ink); }
.docs-nav a[aria-current="page"] { color: var(--ink); font-weight: 500; }
.docs-nav a[aria-current="page"]::before { content: ""; display: inline-block; width: 6px; height: 6px; background: var(--notes-ink); margin: 0 8px 2px 0; }
@media (max-width: 860px) {
  .docs { grid-template-columns: minmax(0, 1fr); margin-top: 28px; }
  .docs-nav { position: static; margin-bottom: 28px; }
  .docs-nav ul { display: flex; flex-wrap: wrap; gap: 0 18px; border: 0; }
  .docs-nav li { border: 0; }
  .docs-nav a { padding: 3px 0; }
}
.prose { max-width: 72ch; min-width: 0; }
.prose > :first-child { margin-top: 0; }
.prose h1 { font-size: clamp(2rem, 4.5vw, 3rem); margin-bottom: 20px; }
.prose h2 { font-size: 24px; font-weight: 500; letter-spacing: -0.015em; margin: 48px 0 0; padding-top: 14px; border-top: 1px solid var(--rule); }
.prose h3 { font-size: 18px; font-weight: 500; margin: 32px 0 0; }
.prose h4 { font-size: 16px; font-weight: 500; margin: 24px 0 0; }
.prose :is(h2, h3, h4) { scroll-margin-top: 24px; }
.prose :is(h2, h3, h4) a.anchor { text-decoration: none; color: var(--faint); margin-left: 8px; opacity: 0; font-weight: 400; }
.prose :is(h2, h3, h4):hover a.anchor, .prose a.anchor:focus-visible { opacity: 1; }
.prose p, .prose ul, .prose ol { margin: 14px 0 0; }
.prose li + li { margin-top: 4px; }
.prose a { text-decoration: underline; text-decoration-color: var(--notes-ink); text-underline-offset: 3px; }
.prose a:hover { color: var(--notes-ink); }
.prose strong { font-weight: 500; }
.prose :not(pre) > code { font-size: 0.86em; background: var(--well); padding: 1px 5px; border-radius: 4px; overflow-wrap: anywhere; }
.prose blockquote { margin: 16px 0 0; padding: 0 0 0 16px; border-left: 2px solid var(--rule-strong); color: var(--muted); }
.prose img { max-width: 100%; height: auto; }
.prose hr { border: 0; border-top: 1px solid var(--rule); margin: 32px 0; }
pre.code {
  position: relative; margin: 16px 0 0; padding: 14px 16px; background: var(--well);
  border-radius: 10px; overflow-x: auto; font-size: 13px; line-height: 1.55; tab-size: 2;
}
pre.code code { font-size: inherit; }
pre.code .copy { position: absolute; top: 8px; right: 8px; font-size: 12px; padding: 2px 10px; background: var(--paper); opacity: 0; }
pre.code:hover .copy, pre.code .copy:focus-visible, pre.code .copy[data-done] { opacity: 1; }
@media (hover: none) { pre.code .copy { opacity: 1; } }
.table { margin: 16px 0 0; overflow-x: auto; }
.table table { border-collapse: collapse; width: 100%; font-size: 14px; line-height: 1.45; }
.table th { text-align: left; font-weight: 500; font-size: 13px; color: var(--muted); border-bottom: 1px solid var(--rule-strong); padding: 6px 12px 6px 0; vertical-align: bottom; }
.table td { border-bottom: 1px solid var(--rule); padding: 8px 12px 8px 0; vertical-align: top; }
.table td code { white-space: nowrap; }

/* ---------------------------------------------------------------------------
   Skill page
   --------------------------------------------------------------------------- */
.steps { list-style: none; counter-reset: step; margin: 20px 0 0; padding: 0; border-top: 1px solid var(--rule); }
.steps li { counter-increment: step; display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 0 12px; padding: 14px 0; border-bottom: 1px solid var(--rule); }
.steps li::before { content: counter(step, decimal-leading-zero); font-family: var(--mono); font-size: 13px; color: var(--faint); padding-top: 3px; }
.steps b { font-weight: 500; }
.steps p { margin: 2px 0 0; color: var(--muted); }
.example { margin: 20px 0 0; border: 1px solid var(--rule-strong); }
.example-art { padding: 24px 24px 0; }
.example-art > div { max-width: 560px; margin: 0 auto; }
.example .controls { padding: 0 24px 18px; }
.example figcaption { border-top: 1px solid var(--rule); padding: 10px 24px; font-size: 14px; color: var(--muted); }

.colophon { margin: 96px 0 0; padding-top: 14px; border-top: 1px solid var(--rule); font-size: 13px; color: var(--faint); display: flex; flex-wrap: wrap; gap: 6px 24px; }
.colophon a { color: var(--muted); }
.colophon p { margin: 0; }

/* The stage a download is drawn on: settled at once. */
.flat-stage *, .flat-stage .ostraca-sub { animation: none !important; transition: none !important; }

/* Sheet fields: the page's own lines, no grey slabs. */
.field { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--muted); }
.field input[type="text"] {
  width: 7em; padding: 3px 8px; border: 1px solid var(--rule-strong); background: transparent; color: var(--ink);
  border-radius: 6px; font-size: 14px; font-family: var(--mono);
}
.field input[type="text"]:focus-visible { outline: 1px solid var(--notes-ink); outline-offset: 1px; border-color: var(--notes-ink); }
.faint-unit { color: var(--faint); }
.how { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.how input[type="range"] { accent-color: var(--notes-ink); width: 120px; }
.how output { font-size: 13px; color: var(--ink); min-width: 4.5ch; font-feature-settings: "tnum" 1; }
.actions { display: flex; gap: 10px; flex-basis: 100%; flex-wrap: wrap; align-items: center; padding-top: 4px; }
.mono { font-family: var(--mono); }
.seg button:focus-visible, .btn:focus-visible { border-radius: 999px; outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   Theme wipe: the new theme comes down from the top over the old one, behind
   a feathered edge. client.js sets data-theme-wipe for the length of it.
   --------------------------------------------------------------------------- */
/* The stop has to be a registered property. A gradient cannot be
   animated, but a typed <percentage> can, and the gradient is redrawn
   from it on every frame. */
@property --theme-wipe {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 100%;
}

:root {
  --theme-wipe-duration: 800ms;
  --theme-wipe-ease: cubic-bezier(0.32, 0.72, 0, 1);
  /* Depth of the feather, as a share of the page's height. 0% is a hard edge. */
  --theme-wipe-bleed: 14%;
}

/* Scoped to one attribute, so nothing here touches any other view
   transition on the page. The toggle sets it before starting and clears
   it when the transition finishes. */
:root[data-theme-wipe]::view-transition-old(root),
:root[data-theme-wipe]::view-transition-new(root) {
  /* Drops the browser's cross-fade and its plus-lighter blend, which
     would wash the middle of the wipe out to white. */
  animation: none;
  mix-blend-mode: normal;
}

/* The outgoing page sits still and gets covered. */
:root[data-theme-wipe]::view-transition-old(root) {
  z-index: 0;
}

/* The incoming page shows through the mask: opaque behind the stop,
   transparent ahead of it, feathered across the bleed. */
:root[data-theme-wipe]::view-transition-new(root) {
  z-index: 1;
  mask-image: linear-gradient(
    to bottom,
    #000 var(--theme-wipe),
    transparent calc(var(--theme-wipe) + var(--theme-wipe-bleed))
  );
  animation: theme-wipe var(--theme-wipe-duration) var(--theme-wipe-ease) both;
}

/* Starts one bleed behind the leading edge, so the feather is off the
   page on the first frame and none of the new theme shows early. */
@keyframes theme-wipe {
  from {
    --theme-wipe: calc(-1 * var(--theme-wipe-bleed));
  }
  to {
    --theme-wipe: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* The toggle already skips the transition. This covers a preference that
     changes mid-wipe, where a zeroed animation would freeze the mask on its
     first frame and leave the new page invisible. */
  :root[data-theme-wipe]::view-transition-new(root) {
    mask-image: none;
  }

  :root[data-theme-wipe]::view-transition-group(*),
  :root[data-theme-wipe]::view-transition-old(*),
  :root[data-theme-wipe]::view-transition-new(*) {
    animation-duration: 0s !important;
  }
}
