/* Tokens first. The palette is the toolbox's — light ground, white cards, one
   loud accent — because the instrument and the register are one site and the
   register is the part that has to look like it belongs to the instrument,
   not the other way round.

   `--bg` is the ground the page sits on and `--card` is what content sits on.
   They were one colour until 2026-08-23, which is why every rule that wants a
   surface names `--card` explicitly rather than inheriting white. */
:root {
  --ink: #16202e; --dim: #5c6675; --line: #e2e6ec;
  --bg: #f6f7f9; --card: #ffffff; --panel: #f1f3f6;
  --link: #2456a6; --good: #178a4c; --bad: #a4341f; --warn: #93690a;
  --accent: #e8641b; --accent-ink: #b34a0e;
  --accent-wash: #fdf1e9; --accent-edge: #f3c9ac;
  /* `--ground` and `--los` exist for exactly one caller, the terrain profile
     SVG in profiles.py — declared here anyway rather than left as a
     `var(--x, #fallback)` that supplied its own colour forever, because a
     custom property nothing ever declares is not a fallback, it is a token
     that only ever reads as unset. There is no `--fg`: profiles.py's mast
     stroke used its own near-black/near-white pair, close enough to `--ink`
     that a second ink token would just be `--ink` with extra steps. */
  --ground: #d8d2c4; --los: #2f5d8a;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(22,32,46,.06), 0 4px 16px rgba(22,32,46,.05);
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  /* Jost first and self-hosted — see the `@font-face` rules `html.py` appends
     to this file at build time (its `src` is a hash of bytes this file does
     not have access to, so the rules cannot be written here directly). Futura
     and Century Gothic stay as the fallback chain: before this, "the display
     face" meant Futura on Jake's Mac and Century Gothic or a plain system
     sans for literally everyone else, which is what made the identity read as
     fragmented rather than as one face used consistently. */
  --display: "Jost", Futura, "Century Gothic", var(--sans);
  --mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;
  --top-h: 3.1rem;

  /* Type scale. Ratio 1.125 — a "major second", the gentlest of the common
     type-scale ratios — because this is a text-dense reference site where
     most sizes on any one page are close variations on body copy (a table
     header, a caption, a footnote), not a poster with three or four sizes
     doing all the work. A coarser ratio snapped those into visibly different
     sizes; this one mostly lands within a few hundredths of a rem of what was
     already hand-picked, which is the point — it replaces two dozen
     near-identical magic numbers with seven names, without making anything
     on the page visibly bigger or smaller. `--t-3xl` (h1) is the one visible
     move, 1.9rem → 1.8rem: the next step down from where a pure 1.9 would
     round to, chosen over adding an eighth step for one heading. */
  --t-xs: .79rem; --t-sm: .89rem; --t-md: 1rem; --t-lg: 1.13rem;
  --t-xl: 1.27rem; --t-2xl: 1.42rem; --t-3xl: 1.8rem;

  /* Space scale. Ratio 1.5, rounded to the nearest .05rem so the numbers stay
     readable in the rules below. Used for generic content rhythm — the gap
     between a heading and what follows it, a card's own padding, the space
     inside a note — not for the handful of values tuned against something
     specific next to them (a table cell's padding against its border, the
     few pixels that centre the wordmark in a fixed-height header bar). Those
     stay literal, same as `--radius` above stays a flat 10px rather than a
     step of anything: not every number on the page is spacing rhythm. */
  --s-1: .25rem; --s-2: .4rem; --s-3: .55rem;
  --s-4: .85rem; --s-5: 1.25rem; --s-6: 1.9rem;
}
@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e6e9ec; --dim: #9aa4b0; --line: #2c333c;
    --bg: #10141a; --card: #171c23; --panel: #1c2229;
    --link: #79b8ff; --good: #4cc38a; --bad: #f0806c; --warn: #d9a441;
    --accent: #ff8340; --accent-ink: #ffa06b;
    --accent-wash: #2a1c14; --accent-edge: #5a3a24;
    --ground: #3a3730; --los: #7fb0dd;
    --shadow: 0 1px 2px rgba(0,0,0,.4), 0 4px 16px rgba(0,0,0,.3);
  }
}
* { box-sizing: border-box; }
/* The other half of the ships-hidden convention. `[hidden]` is a user-agent
   rule at the lowest specificity there is, so ANY rule of ours that sets
   `display` on the same element beats it — `.field { display: flex }` and
   `.cols > span { display: block }` both did — and the control then ships
   visible to exactly the visitor the convention exists to protect: the one
   with no JavaScript, for whom it does nothing at all. It fails silently,
   because with scripting on the script clears the attribute immediately and
   the page looks perfect. One `!important` at the top of the sheet is
   cheaper than remembering this at every call site. */
[hidden] { display: none !important; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font: 16px/1.55 var(--sans);
}
.wrap { max-width: 62rem; margin: 0 auto; padding: 0 1.1rem 4rem; }
a { color: var(--link); }
header.top { border-bottom: 1px solid var(--line); background: var(--card); }
body.document header.top { margin-bottom: 1.6rem; }
header.top .wrap { display: flex; gap: var(--s-5); align-items: center;
  min-height: var(--top-h); padding-top: .45rem; padding-bottom: .45rem;
  flex-wrap: wrap; max-width: none; }
body.document header.top .wrap { max-width: 62rem; }
header.top .name { font-family: var(--display); font-weight: 700;
  font-size: var(--t-lg); letter-spacing: .01em; text-decoration: none;
  display: flex; align-items: center; gap: .48rem;
  color: var(--ink); letter-spacing: .02em; }
header.top .name .accent { color: var(--accent); }
header.top .name .mark { width: 1.25rem; height: 1.25rem;
  flex: none; display: block; }
/* `flex-wrap: wrap` is not decoration. Without it seven links in a flex row
   cannot break as a row, so each link's own text wraps instead — "Find my
   signal" became three lines — while the nav kept its min-content sum width
   of 446px and pushed every one of the 2,199 pages 74px wider than a 390px
   phone. Every page on the site scrolled sideways, which is most of what
   "it looks broken" meant. Found 2026-08-26 by measuring, not by looking:
   the cut-off link is off the right edge, so a screenshot shows a tidy
   header and hides the fault. */
header.top nav { margin-left: auto; display: flex; flex-wrap: wrap; gap: 1rem;
  font-size: var(--t-sm); }
/* The display face reaches h1 and h2 and stops there. h3 and below sit
   inside running prose, where a second family starts to read as noise
   rather than as structure. */
h1, h2 { font-family: var(--display); letter-spacing: .005em; }
h1 { font-size: var(--t-3xl); line-height: 1.2; margin: .2rem 0 .3rem; }
h2 { font-size: var(--t-xl); margin: 2.2rem 0 .6rem; }
h3 { font-size: var(--t-md); margin: 1.5rem 0 .4rem; }
.sub { color: var(--dim); margin: 0 0 1.4rem; }

/* The path back up. Sits above the `h1` and reads as chrome, not as content —
   dim, small, and the separator drawn by the stylesheet rather than shipped as
   text, so a screen reader reads "Transmitters, England, Crystal Palace" and
   not three slashes. */
.crumbs { display: flex; flex-wrap: wrap; align-items: baseline;
  font-size: var(--t-sm); color: var(--dim); margin: 0 0 .4rem; }
.crumbs > * + *::before { content: "/"; padding: 0 .45em; color: var(--line);
  /* The one place the line colour is used as ink. It is deliberately the
     faintest thing in the row: the separator is punctuation, not a step. */ }
.crumbs a { color: var(--dim); }
.crumbs a:hover { color: var(--ink); }
.crumbs [aria-current] { color: var(--ink); }
.scroller { overflow-x: auto; margin: var(--s-4) 0 var(--s-5); background: var(--card);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: .1rem .9rem .3rem; }
table { border-collapse: collapse; width: 100%; font-size: var(--t-sm); }
caption { text-align: left; color: var(--dim); font-size: var(--t-sm);
  padding-bottom: .4rem; }
th, td { text-align: left; padding: .42rem .7rem .42rem 0; white-space: nowrap;
  border-bottom: 1px solid var(--line); vertical-align: top; }
th { font-weight: 600; color: var(--dim); font-size: var(--t-sm);
  text-transform: uppercase; letter-spacing: .03em; }
td.num, th.num { text-align: right; padding-right: 1.1rem; }
/* A cell holding a sentence rather than a value. Left nowrap it pushes every
   other column off the side of the scroller, where nobody finds it.
   Not named `.wrap`: that is the page container, and a `td class="wrap"`
   silently inherits its 4rem bottom padding. */
td.prose, th.prose { white-space: normal; min-width: 11rem; }
.cite { display: block; color: var(--dim); font-size: .85em; }
dl { display: grid; grid-template-columns: max-content 1fr; gap: .3rem 1.2rem;
  margin: var(--s-4) 0 1.4rem; font-size: var(--t-md); }
dt { color: var(--dim); }
dd { margin: 0; }
/* A definition is prose, so it arrives wrapped in <p> — and the paragraph's own
   top margin then drops it half a line below the term it belongs to, on a grid
   whose whole job is putting the two on one line. Nothing looks broken; the
   list just reads as slightly out of register. */
dd > :first-child { margin-top: 0; }
dd > :last-child { margin-bottom: 0; }
.note { background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: .7rem .9rem; margin: 1rem 0; font-size: var(--t-sm); }
.note-warn { border-left-color: var(--warn); }
/* The read-more fold under a short explainer. Quiet by design: the two
   sentences above it are the answer, this is the working. */
.more { margin: .6rem 0 1rem; font-size: var(--t-sm); }
.more summary { cursor: pointer; color: var(--dim); }
.more[open] summary { margin-bottom: .5rem; }
.more p { margin: .5rem 0; }
.ev { text-decoration: none; font-size: .78em; font-weight: 700;
  vertical-align: .25em; color: var(--dim); cursor: help; }
.ev-v { color: var(--good); } .ev-a { color: var(--warn); }
.verdict { font-weight: 600; }
.v-good { color: var(--good); } .v-usable { color: var(--good); }
.v-marginal { color: var(--warn); } .v-unlikely { color: var(--bad); }
.cards { display: grid; gap: var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); margin: 1rem 0; }
.card { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow); padding: var(--s-4) var(--s-4); }
.card h3 { margin: 0 0 .3rem; }
.headline { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--card); box-shadow: var(--shadow);
  padding: 1rem 1.1rem; margin: 1rem 0 1.4rem; }
.headline .band { font-size: var(--t-2xl); font-weight: 700; }
.cols { columns: 3 12rem; column-gap: 1.6rem; font-size: var(--t-md); }
.cols > span { display: block; break-inside: avoid; }
.cols .data { color: var(--dim); }
.dim { color: var(--dim); font-size: .85em; padding-left: .35em; }
footer { border-top: 1px solid var(--line); margin-top: 3rem; padding-top: 1rem;
  color: var(--dim); font-size: var(--t-sm); }
footer .ends { margin: .5rem 0 0; }
input[type=search], input[type=text] {
  font: inherit; padding: .55rem .7rem; border: 1px solid var(--line);
  border-radius: 7px; background: var(--card); color: var(--ink); width: 15rem;
}
/* Every button sets `color` as well as `background`. A rule that sets only
   one of them is how a band button came out white on white; the trap is
   pinned by a test and this comment is the other half of it. */
button { font: inherit; padding: .55rem 1rem; border-radius: 7px;
  border: 1px solid var(--accent); background: var(--accent); color: #fff; }
/* Present for a screen reader, absent for everyone else. Labels matter most on
   the two inputs whose placeholder is their only visible name, and a
   placeholder is gone the moment anyone types. */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }

/* The location field. Global for the same reason the palette is: it is the
   control that goes on every map, and a second copy of these four rules in
   tools.css is how the toolbox's version and the map's version drift into
   two different-looking controls doing one job. The toolbox keeps only what
   is genuinely its own — the labelled number rows — in tools.css. */
.field { display: flex; gap: .5rem; margin-top: .625rem; }
.field input, .field select { font: inherit; color: inherit;
  border: 1px solid var(--line); border-radius: 7px; padding: .4375rem .625rem;
  background: var(--bg); min-width: 0; width: auto; }
.field input { flex: 1; }
.field .go { background: var(--accent); border: 0; color: #fff;
  font: 700 .8125rem var(--sans); border-radius: 7px; padding: .4375rem .875rem;
  cursor: pointer; }
.field .go:hover { background: var(--accent-ink); }
.hint { color: var(--dim); font-size: var(--t-sm); margin: .375rem 0 0; }

/* The way out of the register and into the instrument. Deliberately a link on
   a wash rather than a button: `site.css` styles every `button` accent-on-ink,
   which at this size and this position on the page would outshout the mast's
   own name. */
.handoff { margin: .5rem 0 1.6rem; padding: .55rem .75rem;
  background: var(--accent-wash); border: 1px solid var(--accent-edge);
  border-radius: var(--radius); font-size: var(--t-sm); }
.handoff a { font-weight: 600; }
.handoff .dim { display: block; padding-left: 0; margin-top: .1rem; }
/* Docked over the map rather than under it: the field belongs to the picture
   it moves, and a control below a full-height map is off the screen. */
.locate { margin: 0 0 var(--s-3); }
.map + .locate { margin-top: var(--s-3); }

/* The header search. Global rather than page-scoped because it is in the header
   of every page; scoped tightly under .find for the same reason. */
.find { position: relative; }
.find input[type=search] { width: 11rem; padding: .32rem var(--s-3); font-size: var(--t-sm); }
.find input[type=search]:focus { width: 15rem; }
/* Over the page, not in it. The header is a flex row, and a results list that
   took part in that layout would shove the navigation about on every keystroke. */
.find ul { position: absolute; z-index: 40; top: 100%; right: 0; min-width: 17rem;
  max-height: 21rem; overflow-y: auto; margin: .3rem 0 0; padding: 0;
  list-style: none; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 6px 20px rgba(22, 32, 46, .16); }
.find ul:empty { display: none; }
.find li { border-bottom: 1px solid var(--line); }
.find li:last-child { border-bottom: 0; }
.find a { display: block; padding: .4rem .7rem; text-decoration: none;
  color: var(--ink); font-size: var(--t-sm); }
.find li.on a, .find a:hover { background: var(--panel); }
.find .where { color: var(--dim); font-size: .85em; padding-left: .4em; }
/* ---------------------------------------------------------------------------
   Narrow screens.

   Two breakpoints, and only two, so that a rule's width is a decision anyone
   can look up rather than a number someone picked:

     50rem (800px)  NARROW  — a large phone or a small tablet. Side-by-side
                              stops fitting: the toolbox rail becomes a strip
                              and the header's navigation becomes a row of its
                              own.
     34rem (544px)  PHONE   — one hand. Anything still sitting beside
                              something else goes full width.

   `tools.css` uses the same two numbers for the same reasons. A third
   breakpoint needs a reason written next to it.

   The site's audience is "my telly has stopped working", asked from a sofa
   with a phone. Mobile is the common case here, not the degraded one.
   --------------------------------------------------------------------------- */

/* A label that says less on a phone. Both halves ship in the markup and the
   stylesheet chooses, because the alternative — one label short enough for
   393px — makes the desktop worse to save the phone. Used where a control's
   name is a sentence: the map's fill switch, the tool strip's guides.
   "Transmitters only" is 148px and there are three of them in one pill. */
.lbl-phone { display: none; }

@media (max-width: 50rem) {
  /* The navigation stops being a tail on the wordmark's row and becomes its
     own row: `margin-left: auto` is what pinned it right, and at this width
     there is no room to its left to push it into.

     It scrolls sideways rather than wrapping. Between 544px and 800px the
     seven links fit across one row and it never has to, so what this rule
     really does is *contain* the row: whatever will not fit scrolls inside
     the nav instead of widening the document. Below 544px it did have to,
     and the phone block undoes it — see there. */
  header.top .wrap { gap: .55rem var(--s-4); }
  header.top nav { margin-left: 0; flex-basis: 100%; flex-wrap: nowrap;
    overflow-x: auto; overscroll-behavior-x: contain;
    /* Room for the last link to clear the edge, and a scrollbar that does not
       draw a grey bar across the header on a trackpad Mac. */
    padding-bottom: .1rem; scrollbar-width: none; }
  header.top nav::-webkit-scrollbar { display: none; }
  /* A thumb, not a mouse pointer. 44px is the tap target; the links are text
     in a row, so the height has to come from padding. `.5rem` measured 37px,
     which is the kind of near-miss that only shows up if you measure it. */
  header.top nav a { flex: none; padding: .65rem 0; }
  /* The wordmark is a link to the front door and it was the shortest thing in
     the header at 27px. It sits on the same row as the search box, so the
     padding it gains is padding the row already had. */
  header.top .name { padding: .45rem 0; }
  /* Search before the links: on a phone it is both the fastest way to a mast
     and the smallest thing to hit. DOM order puts it last so a keyboard
     reaches the links first, which is still right — this reorders the
     picture, not the document. */
  header.top .find { order: 2; }
  header.top nav { order: 3; }

  /* A table in a 390px viewport is the one place `nowrap` stops being
     protection and starts being the problem. These are already inside
     `.scroller`, so the document never widened — but a two-column
     label-and-value table that has to be dragged sideways to read its own
     labels is a table nobody reads. Cells wrap; a table that still cannot
     fit still scrolls, which is what `.scroller` was for. */
  th, td { white-space: normal; }
  /* Except the ones that are genuinely a grid of numbers, where a wrapped
     cell costs more than the drag: a channel number broken over two lines
     reads as two numbers. */
  td.num, th.num, td.right, th.right { white-space: nowrap; }

  /* Three columns of names is one column of names on a phone, and `columns`
     already does that on its own. What it does not do is make each name big
     enough to hit — these lists are the directory, 2,193 of them, and every
     row was a 20px line of text. */
  /* The height goes on the link, not on the row: the row carries the name and
     often a dim data column beside it, and only the name is the target. At
     `.25rem` the link measured 33px, which is the size the whole directory —
     2,193 masts and 1,358 stations — is tapped at. The row keeps a little
     padding of its own so two 42px targets do not touch. */
  .cols { columns: 1; font-size: var(--t-md); }
  .cols > span { padding: .15rem 0; }
  .cols > span a { display: inline-block; padding: .55rem 0; }

  /* The document column's side padding is doing nothing on a phone except
     making the measure narrower. Keep enough to clear the rounded corners of
     the cards inside it. */
  .wrap { padding-left: .85rem; padding-right: .85rem; }

  /* A grid of `minmax(15rem, 1fr)` is one column below 15rem plus gap
     anyway; saying so keeps the cards from sitting at an awkward 15rem
     inside a 390px viewport with the page scrolled to reach them. */
  .cards { grid-template-columns: 1fr; }
}

@media (max-width: 34rem) {
  /* The header is a quarter of a phone screen, so every row in it is paid for.

     The wordmark is 85px and the search box does not need the other 300, so
     they share the first row and the caveat and the nav take one each: three
     rows, 151px, measured. And the nav **wraps** here rather than scrolling.
     A scrolling strip is the right answer at 50rem and the wrong one at
     393px, where the row wanted 502px and hid 136 of them — the link it cut
     said "Meth", which is what a visitor sees and reads as a broken page.
     Jake read it exactly that way. A second row of links that are all there
     beats one row of links that are not.

     The links keep their 40px target across the wrap — `.6875rem` measured
     40.0, so the nav is two 40px bands and the header is 168px. That is 17px
     more than the same nav at 32px, and it buys back the site's own tap rule
     on the seven links every page carries: a phone layout whose navigation
     has to be aimed at is not a phone layout. */
  header.top .wrap { gap: .45rem .75rem; }
  header.top .name { order: 1; }
  header.top .find { order: 2; flex: 1 1 auto; width: auto; min-width: 0; }
  header.top .app-note { order: 3; flex-basis: 100%; }
  header.top nav { order: 4; flex-wrap: wrap; overflow-x: visible;
    gap: .05rem .8rem; font-size: .78rem; }
  header.top nav a { padding: .6875rem 0; }
  /* A box that grows on focus would make the header taller as you type, and
     the page would jump down under your thumb. */
  .find input[type=search], .find input[type=search]:focus { width: 100%; }
  /* The dropdown was pinned to the box's right edge and given a 17rem floor,
     which on a 390px phone is wider than the field it hangs from. */
  .find ul { left: 0; right: 0; min-width: 0; }
  /* Both of these are 34px tall at the desktop padding, and both are hit
     with a thumb: the field itself, and every suggestion under it. A search
     result you keep missing is worse than no search. */
  .find input[type=search] { padding: .5rem var(--s-3); font-size: var(--t-md); }
  .find a { padding: .6rem .7rem; }

  /* Headlines set for a 62rem column are shouting in a 390px one, and the
     long ones ("Something has stopped working") were taking three lines
     before the answer started. */
  h1 { font-size: var(--t-2xl); }
  h2 { font-size: var(--t-lg); margin-top: 1.8rem; }

  .lbl-wide { display: none; }
  .lbl-phone { display: inline; }

  /* A full-width control is easier to hit than a centred one, and the
     location field is the single most important thing to hit on the site. */
  .field { flex-wrap: wrap; }
  .field input { flex: 1 1 100%; }
  .field .go { flex: 1 1 auto; padding-top: .8125rem; padding-bottom: .8125rem; }
  /* 35 px at the desktop padding, and on `/transmitters/` this row is how a
     phone filters 2,193 masts. Padding rather than a height: a visitor who
     has raised their text size gets a taller control, not a clipped one. */
  .field input, .field select { padding: .6875rem .625rem; }

  /* Navigation, not prose. The footer's last two lines are a list of links
     with middots between them and they are the smallest targets on the page;
     the sentence above them keeps its inline links, because a paragraph whose
     links are each 40 px tall has stopped being a paragraph — and a link
     inside running text is the case the tap-target rule exempts. */
  footer .ends a { display: inline-block; padding: .7rem 0; }

  /* Every explainer on the site folds into one of these, so it is the most
     tapped control here after the search box, and it was 22 px. */
  .more summary { padding: .55rem 0; }

  /* The way back up. Two links per mast page at 22px, and the only ones on
     the page that are neither prose nor a list row. */
  nav.crumbs a { display: inline-block; padding: .55rem 0; }

  /* The way across to the instrument. It reads as a sentence, so the tap
     -target exemption for prose would cover it — but it is a card with a
     border and a background, and the whole card is what a thumb aims at.
     Block rather than inline-block so the target is the width of the card
     and not the width of the words. */
  .handoff a { display: block; padding: .4rem 0; }

  /* The value half of a definition list is a link often enough — the region,
     the aerial group — and it was 18px. `.5rem` of padding only reached
     36px, still short of the ~40px target reached elsewhere on the page;
     `.68rem`, the same figure that gets `td:not(.prose) a` there, does.
     The term stays as it is: it is a label, not a control. */
  dd > a { display: inline-block; padding: .68rem 0; }

  /* A station name in a services table is how you get from a mast to what it
     carries, and it was a 17px line of text inside a 30px cell. Grow the cell
     and let the link fill it: the padding and the matching negative margin
     make the whole cell the target without moving anything on the screen,
     which is the same trick `.cand.sel` plays sideways in the toolbox. Prose
     links inside `td.prose` are excluded — a sentence in a cell is still a
     sentence, and that is the case the tap-target rule exempts. */
  th, td { padding-top: .68rem; padding-bottom: .68rem; }
  td:not(.prose) a { display: inline-block; padding: .68rem 0;
    margin: -.68rem 0; }

  /* `max-content` in the first column is a promise a 390px viewport cannot
     keep: the longest term in the list sets the column, and the definitions
     get whatever is left — which on the glossary is about twelve characters.
     The term goes above its definition instead. The grid stays a grid so
     `dd > :first-child { margin-top: 0 }` still has something to cancel. */
  dl { grid-template-columns: 1fr; gap: 0; }
  dt { margin-top: .8rem; }
  dt:first-child { margin-top: 0; }
}

/* Nothing on this site may scroll the document sideways. This is the guard
   rather than the fix — every horizontal overflow above has been fixed where
   it happened, and each one was invisible in a screenshot because the thing
   that overflows is off the right edge by definition. If this rule ever
   starts doing work, something upstream of it has regressed. */
html { overflow-x: hidden; }

@font-face { font-family: 'Jost'; font-style: normal; font-weight: 400; font-display: swap; src: url(/assets/jost-400.f94cffda1651.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Jost'; font-style: normal; font-weight: 700; font-display: swap; src: url(/assets/jost-700.81da4d711250.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
