/* One stylesheet for the whole site. A light reading surface with dark image wells:
   prose wants a page you can sit with, and the wallpapers — most of them dark — want a
   mat rather than a white void to float in. So the dark treatment stays local to the
   containers that hold pictures, and nothing else on the page goes with them.

   The layout is Wikipedia's: a sticky rail of contents on the left, the reading column
   beside it. So are the type metrics — sizes, line-height, spacing, measure — and so is
   the serif on the headings. The heading treatment is this site's own. */

/* Text is near-black on white, and the quiet gray is only one step off it. A reading
   surface earns nothing by being soft: --ink is 18:1 against the page and --ink-dim is
   10:1, so a caption, a credit or a footer reads as a different voice rather than as
   faded body text. */
:root {
  --ink: #14151a;
  --ink-dim: #3d424b;
  --ground: #ffffff;
  --bar: #fafaf8;
  --rule: #e3e2de;
  --link: #1a56b8;
  /* Quiet enough for a heading to stay a heading, dark enough to still say "link". */
  --underline: #b0b4bb;

  /* Two families and no webfont: whatever a reader already has, rendered by the engine
     that knows it best. The sans is the system stack GitHub uses and carries the body
     and every piece of furniture — rail, utility labels, nav. The serif is Wikipedia's
     and is spent only where a heading opens something: the page title and a subhead
     inside prose. Below those, headings stay sans with the rest of the machinery. */
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
    sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --serif: "Linux Libertine", Georgia, Times, serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* Image wells: every container that holds a render stays dark whatever the page
     around it does, so a picture is read against a mat and not against the paper. */
  --well: #16171c;
  --well-rule: #2b2e36;
  --well-ink: #eae8e5;
  --well-ink-dim: #c2bcb4;
  --well-link: #9ec5ff;
  --well-pending: #3b3f4a;

  /* The measure caps text and nothing else: about seventy characters of the body face
     at this size. Figures and grids of pictures are not prose and run to --wide, which
     is what the reading column is worth once the rail has taken its share. */
  --rail: 15.5rem;
  --rail-gap: 2.75rem;
  --measure: 40rem;
  --wide: 54rem;
  --page: calc(var(--rail) + var(--rail-gap) + var(--wide));
  --gutter: 1.5rem;

  /* A split figure's grid, and the well it sits in. The gap is what the pad between
     tiles came to once a composited sheet was scaled to the column, so a figure that was
     one raster and is now several sits the same way it always did. */
  --figure-gap: 0.5rem;
  --figure-pad: 0.75rem;
  /* How much of its full-width self a panel keeps before the grid drops a column.
     A tenth, which is slack rather than a threshold: the floor wants to sit just under
     one panel's share of the figure and comfortably over a share of the next arrangement
     down, and a floor derived to the pixel would be one border or one scrollbar from
     landing on the wrong side. */
  --figure-panel-fit: 0.9;
  /* How thick the coloured frame round a marked panel is. The maker drew four pixels
     into a sheet composed at half again the width it ships at, so this is what that came
     to on the page. */
  --figure-mark: 3px;
  /* The air between one band of a staged figure and the next, against --figure-gap
     inside a band: a sheet drew a clear hand-off there and three grids run together
     without one. */
  --figure-band-gap: 1.25rem;
  /* The width of the store a flow figure draws between two stages, above the breakpoint:
     narrow, because a store holds rather than does, and wide enough for a count. */
  --figure-pool: 7.5rem;
  /* What marks a judge in a stage's boxes. The same ink a mark on a picture uses — the
     first of `builder/theme.py`'s four — because a reader meets it as one colour. */
  --figure-judge: #ffc43d;
}

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

body {
  margin: 0;
  padding: 0 var(--gutter) 3rem;
  background: var(--ground);
  color: var(--ink);
  font: 1rem/1.6 var(--sans);
}

/* One column until there is room for two. Below the breakpoint the rail is not shown at
   all rather than folded into a control: every page still carries the site bar back to
   the contents and its own previous/next line, so nothing is only reachable through it,
   and the article keeps working with scripting off — which it does entirely, since it
   carries none. The explorer is the one page that runs code, and it brings its own
   stylesheet as well as its own script. */
.page { max-width: var(--page); margin: 0 auto; }
.page-body { max-width: var(--measure); margin: 0 auto; }
.contents-rail { display: none; }

@media (min-width: 62.5rem) {
  .page { display: flex; align-items: flex-start; gap: var(--rail-gap); }
  .page-body { flex: 1 1 auto; min-width: 0; max-width: var(--wide); margin: 0; }
  .contents-rail {
    display: block;
    position: sticky;
    top: 1.5rem;
    flex: 0 0 var(--rail);
    margin-top: 2.6rem;
    padding-bottom: 1.5rem;
    max-height: calc(100vh - 3rem);
    overflow-y: auto;
  }
  /* A flow figure reads left to right once the rail is shown, which is when the column
     is wide enough for three stages and two stores side by side; below it the same
     markup stacks. Each stage takes an equal share and runs its own count across. */
  /* Two classes, because the grid rules for a figure's panels come later in this file and
     one class would lose to them on source order. */
  .figure-staged.figure-flow { display: flex; align-items: stretch; gap: var(--figure-gap); }
  .figure-flow > .figure-stage {
    flex: 1 1 0;
    min-width: 0;
    align-content: start;
    grid-template-columns: repeat(var(--figure-across), minmax(0, 1fr));
  }
  .figure-flow > .figure-pool { flex: 0 0 var(--figure-pool); padding: 0.5rem 0.4rem; }
  .figure-flow > .figure-pool::before,
  .figure-flow > .figure-pool::after { content: "→" / ""; }
}

/* The site bar: one text-height line, the same on every page. It is a way back to the
   front page, out to the code, and up to the homepage this project sits under — not a
   masthead; the article is the thing here. The links wrap rather than overflow, which is
   what a narrow phone does with three of them beside the title. */
.topbar {
  margin: 0 calc(-1 * var(--gutter));
  padding: 0 var(--gutter);
  background: var(--bar);
  border-bottom: 1px solid var(--rule);
  font-size: 0.875rem;
}

.topbar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.15rem 1.5rem;
  max-width: var(--page);
  margin: 0 auto;
  padding: 0.5rem 0;
}

.topbar a { color: var(--ink-dim); text-decoration: none; }
.topbar .topbar-site { color: var(--ink); font-weight: 600; }
.topbar a:hover { color: var(--link); text-decoration: underline; }

/* The links are laid out rather than spaced by margins so that each one is a place the
   row can break: three of them beside the site title do not fit a narrow phone, and a
   bar that overflows drags the whole page sideways with it. */
.topbar-links { display: flex; flex-wrap: wrap; gap: 0 1.1rem; }

/* The contents rail. Ten sections in reading order, the current one open to its own
   headings; the builder writes it, so it cannot fall behind the article. Dark ink and
   no underlines: a column of ten blue links reads as a link list, not as contents. */
/* Above the contents, two peers under headings of their own set like theirs: the page a
   new reader is sent to first, and the wallpaper packs. Each is ruled off, the way the
   links under the contents are, because neither is one of the sections. On the start page
   its group lists its headings as plain entries; elsewhere a group is the heading alone. */
.rail-group {
  margin: 0 0 1rem;
  padding: 0 0 0.9rem;
  border-bottom: 1px solid var(--rule);
}
.rail-group > :last-child { margin-bottom: 0; }
.rail-group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1.45;
}
.rail-group li { margin-bottom: 0.55rem; }
.rail-group li:last-child { margin-bottom: 0; }

.rail-title {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
}

/* The title is the way back to the front page, so it is a link — and it stays a label
   rather than becoming the loudest thing in the rail, which is why it inherits the
   dim ink instead of taking the link colour. */
.rail-title a { color: inherit; }

.rail-sections {
  margin: 0 0 0 1.5rem;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1.45;
}
.rail-sections > li { margin-bottom: 0.55rem; }
.rail-sections > li::marker { color: var(--ink-dim); font-size: 0.85em; }

.contents-rail a { color: var(--ink); text-decoration: none; }
.contents-rail a:hover { color: var(--link); text-decoration: underline; }
.rail-current > a { font-weight: 600; }

.rail-headings {
  list-style: none;
  margin: 0.4rem 0 0.2rem;
  padding: 0;
  border-left: 2px solid var(--rule);
}
.rail-headings li { margin: 0 0 0.3rem; padding-left: 0.7rem; }
.rail-headings a { color: var(--ink-dim); }

/* Under the ten sections: the page that runs the engine, and the code behind all of it.
   Ruled off, because these leave the article rather than moving inside it. */
.rail-links {
  list-style: none;
  margin: 1.1rem 0 0;
  padding: 0.9rem 0 0;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  line-height: 1.45;
}
.rail-links li { margin: 0 0 0.45rem; }

.masthead { padding: 1.8rem 0 1.2rem; border-bottom: 1px solid var(--rule); }

/* Wikipedia's metrics, heading by heading: the scale, the line-height, and the tight
   space above and below that keeps a long page from drifting apart. */
h1, h2, h3 { line-height: 1.3; }

h1 {
  margin: 0 0 0.25em;
  font-family: var(--serif);
  font-size: 1.75rem;
  letter-spacing: -0.01em;
}

/* This h2 labels a utility block — Contents, Galleries, Figures — rather than opening a
   section of the article, so it takes the size below the section heading's and keeps the
   small-caps treatment that says "label". */
h2 {
  margin: 1.4em 0 0.4em;
  font-size: 1.25rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
}

h3 { margin: 0.3em 0 0; font-size: 1.25rem; }

/* Inside prose a subhead is part of the reading: it keeps its own case, the body's ink,
   and the size Wikipedia gives a section heading. It is also what the rail links to, so
   it leaves room above itself for the jump to land in. */
.prose h2 {
  margin: 1em 0 0.25em;
  padding-top: 0.5em;
  scroll-margin-top: 1rem;
  font-family: var(--serif);
  font-size: 1.5rem;
  text-transform: none;
  letter-spacing: -0.005em;
  color: var(--ink);
}

code, kbd, samp, pre { font-family: var(--mono); }

p { margin: 0.4em 0 0.5em; }
ul, ol { margin: 0.3em 0 0 1.6em; padding: 0; }
li { margin-bottom: 0.1em; }

/* The measure holds the text and lets the pictures out. Everything a reader reads in
   lines stops at --measure; a figure or a grid of renders takes the column. */
.masthead > *,
.intro > *,
.prose > *,
.contents > *,
.galleries-teaser > *,
.figures > h2,
.section-nav > *,
footer > * {
  max-width: var(--measure);
}

.figure, .images .grid { max-width: none; }

/* A table in prose is a small scoreboard, not a layout: Wikipedia's rules and quiet
   header row, sized to the numbers rather than to the column. It stays inside the
   measure with the paragraphs, and scrolls inside itself on a narrow screen. */
.prose table {
  display: block;
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
  margin: 1em 0;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.prose th, .prose td {
  padding: 0.3em 1.4em 0.3em 0;
  border-bottom: 1px solid var(--rule);
  text-align: left;
  vertical-align: baseline;
}

.prose th { color: var(--ink-dim); font-weight: 600; }

.prose td:not(:first-child) { font-variant-numeric: tabular-nums; }

/* A line under a table saying how its numbers were taken. It is a fact about the
   measurement rather than something the prose argues, so it is set small and dim and
   pulled up against the table — a paragraph's worth of leading under it would read as
   the prose starting again. */
.prose .table-note {
  margin: -0.6em 0 1.4em;
  font-size: 0.875rem;
  color: var(--ink-dim);
}

/* A display formula, set the way a paper sets one: its own line, centred, typeset from
   TeX by `python -m builder formulas` into an inline SVG whose glyphs are paths filled
   with currentColor. MathJax sizes it in ex, so it scales with the text around it; its
   font's x-height is lower than the body face's, and the font size puts that back. On a
   column narrower than the formula it scales down rather than pushing the page sideways. */
.formula {
  margin: 1.2em 0;
  font-size: 1.15em;
  text-align: center;
}

.formula svg {
  max-width: 100%;
  height: auto;
  vertical-align: middle;
}

sub, sup {
  font-size: 0.72em;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}

sup { top: -0.5em; }
sub { bottom: -0.25em; }

.kicker {
  margin: 0 0 0.6rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-dim);
}

.intro { margin-top: 1.5rem; color: var(--ink-dim); }

.toc { margin: 0.6rem 0 0 1.6em; }
.toc > li { margin-bottom: 1.2rem; }
.toc > li::marker { color: var(--ink-dim); }
.toc p { margin: 0.2em 0 0; color: var(--ink-dim); }

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

/* A heading that happens to be a link is still a heading: on a white page ten blue
   underlined lines read as a link list rather than as a table of contents. */
.toc h3 a { color: var(--ink); text-decoration-color: var(--underline); text-underline-offset: 0.15em; }
.toc h3 a:hover { color: var(--link); text-decoration-color: currentColor; }

/* The kicker is a place-marker above the title, not somewhere to click first. */
.kicker a { color: inherit; text-decoration-color: var(--underline); }
.kicker a:hover { color: var(--link); text-decoration-color: currentColor; }

/* Galleries: web-res images on the page, full size behind a release link. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 1rem;
  margin-top: 1rem;
}

.tile {
  background: var(--well);
  border: 1px solid var(--well-rule);
  margin: 0;
  color: var(--well-ink-dim);
}
.tile img { display: block; width: 100%; height: auto; }
.tile figcaption {
  padding: 0.6rem 0.8rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--well-ink-dim);
}
.tile strong { color: var(--well-ink); font-weight: 600; }
.tile a { color: var(--well-link); }
.tile a:hover { color: var(--well-ink); }

.credit { display: block; margin-top: 0.3rem; font-size: 0.8125rem; opacity: 0.8; }

/* The palette library: nine hundred gradients, grouped by the colour each is dominant in.
   A hue's grid is one dark panel — a strip is a picture and takes the well the way a
   figure does, and nine hundred separate wells on white read as confetti. The heading
   stays on the reading surface above it: the dark treatment is local to the containers
   that hold pictures, and a heading is not one. */
.palette-group > h2 { max-width: var(--measure); }
.palette-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.75rem;
  margin: 1rem 0 2rem;
  padding: 0.75rem;
  max-width: none;
  background: var(--well);
  border: 1px solid var(--well-rule);
}
.palette {
  margin: 0;
  border: 1px solid var(--well-rule);
}
.palette img { display: block; width: 100%; height: auto; }
/* A strip's name is a label and not a caption, so it is centred under its picture — the
   other half of the rule that ranges a figure's caption left *(Matt, 2026-08-22)*. */
.palette figcaption {
  display: block;
  padding: 0.35rem 0.55rem 0.2rem;
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--well-ink);
  text-align: center;
  overflow-wrap: anywhere;
}
/* The name the library actually spells it with, under the name the page reads it by, and
   only where the two differ. Dimmer and smaller: it is the key, not the label. */
.palette-id {
  margin: 0;
  padding: 0 0.55rem 0.4rem;
  font-size: 0.75rem;
  line-height: 1.3;
  color: var(--well-ink-dim);
  text-align: center;
  overflow-wrap: anywhere;
}

/* The way back into the explorer, from a gallery tile the explorer can draw again. On
   its own line under the caption and the credit, at the credit's size, because it is a
   way out of the page rather than something the caption says. A figure spells it
   differently — see .figure-open below. */
.open {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.8125rem;
  color: var(--well-link);
}
.open::before { content: "→ "; }

/* A figure runs past the measure to the width of the column: a side-by-side comparison
   squeezed into a column of prose is not a comparison. The mat is the same dark well the
   gallery tiles use — a render is a render wherever it appears. */
.figure,
.figure-placeholder {
  margin: 1.5em 0 1.75em;
  padding: var(--figure-pad);
  background: var(--well);
  border: 1px solid var(--well-rule);
}
.figure img { display: block; width: 100%; height: auto; }

/* A split figure: one picture per panel instead of several composited into one raster,
   so each opens in the explorer at its own view and each label is text rather than
   pixels. The arrangement is the composite's at the article's width, and it reflows on
   its own as the column narrows — the thing a sheet could never do: six tiles of one
   image on a phone are six pictures at a sixth of the size the phone could have shown
   one at. `auto-fit` over a floor rather than a media query, because the breakpoint is
   the rail's business.

   The floor is what one panel is worth at the article's own figure width — the size the
   sheet this figure replaced showed that tile at — less the slack above.
   `--figure-across` is the only thing the markup passes in, a count and never a metric,
   and every length in the sum is this file's. It is a **fixed** length rather than a
   share of the container, and that is the whole trick: at the article's width the floor
   sits just under one panel's share, so the grid lands on exactly the arrangement the
   composite had; as the column narrows the floor stays put and a column is dropped
   rather than every panel shrinking. One floor for every figure cannot do this — a
   figure drawn four across showed its tiles at about 200px and one drawn six across at
   about 130, and a floor that suits one turns the other into a different picture, which
   is what a single 13rem floor did to the four-across roster. `min(100%, …)` is what
   stops the last column overflowing a phone. */
.figure-panels, .figure-stage {
  display: grid;
  gap: var(--figure-gap);
  --figure-panel: calc(
    var(--figure-panel-fit)
    * (var(--wide) - (var(--figure-across) - 1) * var(--figure-gap))
    / var(--figure-across)
  );
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--figure-panel)), 1fr));
}
.figure-panel { min-width: 0; }

/* A figure in **bands**: several grids down one figure, with a heading over each and a
   hand-off between them. That is the shape the staged sheets had, and it is the only way
   a stage three panels across can sit above one four across — a grid has one column count
   and a sheet had none, so each band is its own grid and the outer one is a single
   column. The gap between bands is larger than the gap inside one: the sheets drew a
   clear hand-off there, and without it three grids read as one. */
.figure-staged { grid-template-columns: 1fr; gap: var(--figure-band-gap); }
/* The store between two stages of a flow figure: a title and what it holds, set as quiet
   furniture on the pending tone so it reads as a thing the stages hand to rather than a
   stage of its own. The hand-offs either side are glyphs with empty alternative text, and
   they point down here and across above the breakpoint. */
.figure-pool {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.2rem;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--well-rule);
  background: var(--well-pending);
  text-align: center;
}
.figure-pool::before,
.figure-pool::after {
  content: "↓" / "";
  font-size: 1.25rem;
  line-height: 1;
  color: var(--well-ink-dim);
}
.figure-pool-title { margin: 0; font-size: 0.875rem; font-weight: 600; color: var(--well-ink); }
.figure-pool-note { margin: 0; font-size: 0.8125rem; line-height: 1.35; color: var(--well-ink-dim); }

/* A band's heading: what the band is, then what it does, then the boxes that say what
   it is made of. One flex row that wraps, with the boxes pushed to the far end — the
   sheets drew them down the right-hand side, and `margin-left: auto` is what keeps them
   there without pinning the two halves apart when a band has none. */
.figure-band {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.75rem;
  margin: 0.15rem 0 0.1rem;
}
.figure-band-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--panel-ink, var(--well-ink));
}
.figure-band-note {
  margin: 0;
  max-width: var(--measure);
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--well-ink-dim);
}

/* The boxes a stage sheet drew down its right-hand side: the pieces that stage is made
   of. A judge is marked in the same ink every mark on this site uses, because a judge is
   the thing the article keeps pointing at. */
.figure-blocks { margin: 0 0 0 auto; display: flex; flex-wrap: wrap; gap: 0.35rem; }
.figure-block {
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--well-rule);
  background: var(--well-pending);
  font-size: 0.8125rem;
  color: var(--well-ink-dim);
}
.figure-block-judge { border-color: var(--figure-judge); color: var(--figure-judge); }

/* The step from one band to the next. `aria-hidden`, because the band titles already
   say the order and a screen reader gains nothing from *down arrow* between them. */
.figure-arrow {
  margin: 0;
  text-align: center;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--well-ink-dim);
}

/* A panel that is not one cell of the grid but the whole row: the parameter plane over
   the four Julia sets it draws, a stage heading over the pictures it names. `1 / -1`
   rather than a span, so it stays the full row through every reflow. */
.figure-panel-wide { grid-column: 1 / -1; }

/* A cell held open with no picture in it: the arrangement asks for a panel here and no
   frame fills it yet. The dashed hole a pending figure is, at one panel's size, whose
   shape arrives on the element because it is the row's datum. */
.figure-blank { border: 1px dashed var(--well-pending); }

/* A panel that answers to a mark drawn on another panel. The maker used to draw a frame
   of the mark's colour into the tile and letter the label in it; both are here now, and
   the colour arrives on the panel as `--panel-ink`, which is the figure's own datum. An
   outline drawn inward rather than a border, so the picture keeps the size the grid gave
   it and the mat's rhythm is unbroken. */
.figure-panel-marked img {
  outline: var(--figure-mark) solid var(--panel-ink);
  outline-offset: calc(-1 * var(--figure-mark));
}
.figure-panel-marked .figure-label { color: var(--panel-ink); }

/* The label under a panel is a label and not a caption, so it centres — the same rule
   the short name under a gradient strip keeps. `note` is the quieter half the drawn
   label spelled with a dash between the two; the separator is this rule's, which is how
   the words a reader meets carry no punctuation the article would not write. */
.figure-label {
  margin: 0.4rem 0 0.1rem;
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--well-ink);
  text-align: center;
  text-wrap: balance;
}
.figure-label .figure-note { color: var(--well-ink-dim); }
/* The separator is a space, the dot, then a no-break space: a label that wraps breaks
   *before* the dot and carries it onto the next line with the words it introduces, where
   a plain " · " leaves the dot dangling at the end of the line above. */
.figure-label .figure-note::before { content: " · "; }

/* The caption sits under the left edge of the picture, at a size a step above the site's
   other small print: it is the second thing a reader looks at, after the figure itself,
   and it used to be set at the footer's size. It is held to the reading measure however
   wide the figure runs — a caption spread across the full column is a line nobody tracks
   back. **Ranged left whatever its length** *(Matt, 2026-08-22, replacing the rule that
   centred a caption until it passed about three hundred characters)*: a caption is prose
   and reads as prose, and the centring belongs to the short labels under a picture. */
.figure figcaption,
.figure-placeholder figcaption {
  margin: 0.7rem 0 0.1rem;
  max-width: var(--measure);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--well-ink-dim);
  text-align: left;
  text-wrap: pretty;
}
.figure a { color: var(--well-link); }
.figure a:hover { color: var(--well-ink); }

/* A picture the explorer can draw again is itself the way into it. The mark in the
   corner is the affordance — a picture that is quietly a link is a link nobody finds —
   and the words ride on the anchor, where a hover and a screen reader both reach them.
   Deliberately small and quiet: the figure is the thing here, and the mark is a door. */
.figure-open { display: block; position: relative; }
.figure-open .figure-open-mark {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  width: 1.65rem;
  height: 1.65rem;
  border: 1px solid var(--well-rule);
  border-radius: 0.25rem;
  background: rgba(22, 23, 28, 0.72);
  color: var(--well-ink-dim);
  font-size: 0.9375rem;
  line-height: 1.55rem;
  text-align: center;
}
.figure-open:hover .figure-open-mark,
.figure-open:focus-visible .figure-open-mark {
  border-color: var(--well-link);
  background: rgba(22, 23, 28, 0.92);
  color: var(--well-link);
}
/* A panel is a third of the width a whole figure is, and the mark is a door rather than
   a feature: it steps down with the picture so that six of them stay quiet. */
.figure-split .figure-open-mark {
  right: 0.35rem;
  bottom: 0.35rem;
  width: 1.35rem;
  height: 1.35rem;
  font-size: 0.8125rem;
  line-height: 1.25rem;
}

/* A wallpaper pack (packs_page_ckpt153): its name, five of its pictures, and the zip.
   The download is the thing on this page a reader came for, so it is a filled button in
   the well's own link colour, and nothing else in the well looks like one. The explorer
   line under it is a small plain link in the quiet ink, so it reads as an aside. */
.pack-title {
  margin: 0 0 0.5rem;
  color: var(--well-ink);
  font-size: 1.0625rem;
  font-weight: 600;
}
.pack-downloads {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin: 0.85rem 0 0;
  padding: 0;
  list-style: none;
}
.pack-downloads li { margin: 0; }
.figure a.pack-download {
  display: inline-block;
  padding: 0.55rem 1.1rem;
  border-radius: 0.3rem;
  background: var(--well-link);
  color: var(--well);
  font-size: 1.0625rem;
  font-weight: 600;
  text-decoration: none;
}
.figure a.pack-download:hover,
.figure a.pack-download:focus-visible { background: var(--well-ink); color: var(--well); }
.pack-explore { margin: 0.6rem 0 0; font-size: 0.875rem; }
.figure .pack-explore a { color: var(--well-ink-dim); }
.figure .pack-explore a:hover { color: var(--well-ink); }

/* A figure registered before its picture exists. Prose gets written before pictures get
   made, so the well stays where it will be and says what will fill it — a dashed hole
   the page owns up to, rather than a broken image or a silent gap. */
.figure-pending .pending {
  margin: 0;
  padding: 2.75rem 1.5rem;
  border: 1px dashed var(--well-pending);
  text-align: center;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--well-ink-dim);
}

/* A live figure: a piece of the site running in the page rather than a picture of it
   (atlas_live_ckpt146). The atlas frame is the explorer's own and brings `atlas/frame.css`
   with it; what is this file's is the well. Until the frame is in it, the well holds a
   line and a link, the same honesty a pending well has, and that is all a page opened
   from disk or read with scripting off ever shows. While the frame is loading the well
   holds roughly the frame's own shape, so the text under it does not jump when it lands;
   once it has landed the well's height is the frame's, and nothing here sizes it. */
.figure-live-host.is-loading { aspect-ratio: 9 / 10; }
.figure-live-note {
  margin: 0;
  padding: 1.5rem;
  text-align: center;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--well-ink-dim);
}
.figure-live-note a { color: var(--well-link); }
/* `.figure img` sizes a figure's picture to its width and lets the height follow, and the
   frame's pictures are sized by the frame. The frame's stylesheet arrives after this one
   and wins on order alone; this says so rather than leaning on it. */
.figure-live .frame img { height: 100%; }

/* A video figure: a YouTube player (start_video_embed_ckpt152), the width of the well and
   16:9, so the markup carries no size of its own and the player scales with the column. */
.figure-video iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
}
/* The linked pictures under the player (start_video_links_ckpt152) are a split figure's
   grid, set off from the player by the grid's own gap. */
.figure-video iframe + .figure-panels,
.figure-video .video-pending + .figure-panels { margin-top: var(--figure-gap); }
/* A video whose pictures landed before its player (publish_prep_ckpt154): the player's
   place, 16:9 and dashed like a pending well, until the row names the video. */
.figure-video .video-pending {
  aspect-ratio: 16 / 9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0 1.5rem;
  border: 1px dashed var(--well-pending);
  text-align: center;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--well-ink-dim);
}

/* A slot held open before its figure is even registered: the slug its row will carry and
   the draft caption, on a 16:9 well. Placed prose is reviewed on the site before a figure
   round draws anything, and this is how that page shows where the figures go. It is not a
   `.figure` on purpose, since `check` holds every `.figure` to a registry row and this has
   none; a figure round replaces every `figure-placeholder` on the site. */
.figure-placeholder .placeholder-well {
  aspect-ratio: 16 / 9;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0;
  border: 1px dashed var(--well-pending);
  font-family: var(--mono);
  font-size: 0.9375rem;
  color: var(--well-ink-dim);
}

.pending-label {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--well-ink);
}

/* A figure whose picture is made and whose *numbers* are not settled: a reading of a
   measurement that is going to be taken again. Every page here is a draft and none of
   them says so; this mark is for the narrower case, where a reader who copied a number
   off the chart would be copying something with a shelf life. It opens the caption
   rather than riding on the picture — a badge over a chart competes with the chart —
   and it is the pending label's lettering at the pending label's rank, because it is
   the same kind of note about the same kind of gap. */
.figure-draft {
  display: inline-block;
  margin-right: 0.45rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--well-pending);
  border-radius: 0.2rem;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  vertical-align: 0.08em;
  color: var(--well-ink);
}

.section-nav {
  margin-top: 2.5rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
}
.section-nav p { margin: 0; color: var(--ink-dim); }

footer {
  margin-top: 3rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  font-size: 0.875rem;
  color: var(--ink-dim);
}
footer p { margin: 0; }
