/* gitdns
 *
 * The page is set like a piece of technical documentation: paper, ink, and one
 * red used only where the checker says no. Section labels are written as fully
 * qualified names, trailing dot and all, because that dot is the thing every
 * zone file forgets.
 */

:root {
  --paper:      #ECEDE7;
  --card:       #F7F8F4;
  --ink:        #171C22;
  --ink-soft:   #59646E;
  --ink-faint:  #8B949B;
  --rule:       #D3D6CC;
  --rule-soft:  #E2E4DC;
  --signal:     #B32B23;
  --signal-bg:  #F7E9E7;
  --ok:         #216B4B;
  --ok-bg:      #E4EDE6;
  --warn:       #8A6410;
  --warn-bg:    #F4EEDD;
  --link:       #2C4A7C;
  --merge-bg:   #E7E9F2;

  /* A diff is read a page at a time, so its grounds are quieter than the
     checker's red: the alarm colour keeps meaning "this will not serve". */
  --add-bg:     #E6EFE7;
  --add-rule:   #7C9E82;
  --add-ink:    #1F5E3D;
  --del-bg:     #F3E7E5;
  --del-rule:   #C29993;
  --del-ink:    #8E332C;

  --display: "Newsreader", Georgia, "Times New Roman", serif;
  --label: "Martian Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --code: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --measure: 62ch;
  --page: 74rem;

  /* What a button's text sits on when the button is filled. Its own token
     because in the dark it is not white. */
  --on-signal: #FFFFFF;

  color-scheme: light;
}

/* The same page after dark.
 *
 * Not the light palette inverted. Inverting gives you a grey page with shouting
 * colours on it, and the whole point of the light one is that it reads like
 * paper with one red on it. So the ink and paper swap ends and everything else
 * is re-picked at the new contrast: the alarm red lightens, because a dark red
 * on a dark page is unreadable, and the diff grounds get quieter rather than
 * louder, because a diff is read a page at a time and a glowing green line is
 * the wrong kind of loud.
 *
 * Declared twice on purpose. The media query is what somebody who has never
 * touched the toggle sees; the attribute is what somebody who has chosen sees,
 * and it has to win in both directions -- dark on a light system, light on a
 * dark one. Guarding the media query on `:not([data-theme="light"])` is what
 * makes choosing light stick on a machine set to dark.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper:      #14181C;
    --card:       #1B2026;
    --ink:        #E4E7E4;
    --ink-soft:   #A7B0B8;
    --ink-faint:  #79848D;
    --rule:       #2E353C;
    --rule-soft:  #242A30;
    --signal:     #F0837A;
    --signal-bg:  #33201E;
    --ok:         #7FC49C;
    --ok-bg:      #182A22;
    --warn:       #D9AE5C;
    --warn-bg:    #2C2617;
    --link:       #8FB2E8;
    --merge-bg:   #1F2433;

    --add-bg:     #17271D;
    --add-rule:   #3E6B4C;
    --add-ink:    #86C79C;
    --del-bg:     #2B1B1A;
    --del-rule:   #7A4741;
    --del-ink:    #E39189;

    --on-signal:  #14181C;

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --paper:      #14181C;
  --card:       #1B2026;
  --ink:        #E4E7E4;
  --ink-soft:   #A7B0B8;
  --ink-faint:  #79848D;
  --rule:       #2E353C;
  --rule-soft:  #242A30;
  --signal:     #F0837A;
  --signal-bg:  #33201E;
  --ok:         #7FC49C;
  --ok-bg:      #182A22;
  --warn:       #D9AE5C;
  --warn-bg:    #2C2617;
  --link:       #8FB2E8;
  --merge-bg:   #1F2433;

  --add-bg:     #17271D;
  --add-rule:   #3E6B4C;
  --add-ink:    #86C79C;
  --del-bg:     #2B1B1A;
  --del-rule:   #7A4741;
  --del-ink:    #E39189;

  --on-signal:  #14181C;

  color-scheme: dark;
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--display);
  font-size: 1.0625rem;
  line-height: 1.6;
  font-synthesis-weight: none;
}

a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--signal); }

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

h1, h2, h3 { font-weight: 500; letter-spacing: -0.015em; line-height: 1.1; margin: 0; }

/* The gutter is set here and nowhere else. Anything worn alongside `page`
   sets only its top and bottom -- `padding-block`, never the `padding`
   shorthand, which silently takes the sides back to zero. That is what put
   the marketing pages hard against the edge of every phone: on a wide window
   the centring margin stands in for the gutter, so it only shows once the
   window is narrower than the page. */
.page { max-width: var(--page); margin: 0 auto; padding-inline: 1.5rem; }
.narrow { max-width: 34rem; }
.prose { max-width: var(--measure); }
/* A line saying a section is empty, rather than a line saying something. */
.prose--quiet { color: var(--ink-faint); font-size: 0.9375rem; }

/* ---------------------------------------------------------------- labels */

/* Section names are fully qualified, the way a zone file writes them. */
.fqdn {
  font-family: var(--label);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: lowercase;
  color: var(--ink-soft);
  margin: 0 0 0.75rem;
}
.fqdn .dot { color: var(--signal); }

.eyebrow {
  font-family: var(--label);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ------------------------------------------------------------------- nav */

.masthead {
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}
.masthead__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 4rem;
  max-width: var(--page);
  margin: 0 auto;
  padding: 0 1.5rem;
}
.wordmark {
  font-family: var(--label);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}
.wordmark:hover { color: var(--ink); }
.wordmark .dot { color: var(--signal); }

.masthead nav { margin-left: auto; display: flex; align-items: center; gap: 1.25rem; }
.masthead nav a, .masthead nav button {
  font-family: var(--label);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-decoration: none;
}
.masthead nav a:hover { color: var(--signal); }
/* "Create account" is one thing to press, not two words to wrap between. */
.masthead nav a, .masthead nav button { white-space: nowrap; }

/* Signed out there are four things up here -- the switch, the prices and the
   two ways in -- and on a phone they do not fit beside the wordmark. They
   take a second line rather than each breaking in half. */
@media (max-width: 34rem) {
  .masthead__inner {
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    padding-block: 0.7rem;
    min-height: 0;
  }
  .masthead nav { gap: 0.9rem; }

  /* Four things do not fit across a phone, and wrapping them made a masthead
     three rows deep with the way in stranded on the last one. "Create
     account" is the one to drop: it is the page's own call to action and it
     is already in the hero, beside every plan, and in the closer -- whereas
     nothing else offers the switch, the prices or the way back in. */
  /* Scoped to the masthead so it outranks `.button`, which sets a display of
     its own further down the file and would otherwise win the tie. */
  .masthead .masthead__join { display: none; }
}
.masthead__who { font-family: var(--code); font-size: 0.8rem; color: var(--ink-faint); }

/* --------------------------------------------------------------- buttons */

.button {
  display: inline-block;
  font-family: var(--label);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.7rem 1.15rem;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
  color: var(--paper);
  text-decoration: none;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.button:hover { background: var(--signal); border-color: var(--signal); color: var(--on-signal); }
.button--ghost { background: transparent; color: var(--ink); }
.button--ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.button--small { padding: 0.45rem 0.8rem; font-size: 0.66rem; }

.button-row { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }

/* ------------------------------------------------------------------ hero */

.hero { padding-block: 5rem 3.5rem; }
.hero h1 {
  font-size: clamp(2.75rem, 7vw, 4.75rem);
  line-height: 0.98;
  letter-spacing: -0.03em;
  max-width: 16ch;
}
.hero h1 .dot { color: var(--signal); }
.hero p.lede {
  margin: 1.5rem 0 2rem;
  font-size: 1.1875rem;
  color: var(--ink-soft);
  max-width: 52ch;
}

/* --------------------------------------------------------------- console */

/* The product's own output, reproduced rather than illustrated. */
.console {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  font-family: var(--code);
  font-size: 0.8125rem;
  line-height: 1.55;
  overflow-x: auto;
  box-shadow: 0 1px 0 var(--rule-soft), 0 12px 32px -24px rgba(23, 28, 34, 0.5);
}
.console__bar {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  padding: 0.55rem 1rem;
  border-bottom: 1px solid var(--rule);
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.console__body { padding: 1rem 1.25rem 1.25rem; margin: 0; white-space: pre; }
.console .cmd { color: var(--ink); font-weight: 500; }
.console .cmd::before { content: "$ "; color: var(--ink-faint); }
.console .remote { color: var(--ink-soft); }
.console .bad { color: var(--signal); }
.console .good { color: var(--ok); }
.console .muted { color: var(--ink-faint); }

/* ------------------------------------------------------------- diagnostic */

.diag {
  font-family: var(--code);
  font-size: 0.8125rem;
  line-height: 1.5;
  border-left: 2px solid var(--rule);
  padding: 0 0 0 1rem;
  margin: 0 0 1.5rem;
  overflow-x: auto;
}
.diag--error { border-left-color: var(--signal); }
.diag--warning { border-left-color: var(--warn); }
.diag__head { font-weight: 500; }
.diag--error .diag__sev { color: var(--signal); }
.diag--warning .diag__sev { color: var(--warn); }
.diag__code { color: var(--ink-faint); }
.diag__loc { color: var(--ink-faint); margin: 0.15rem 0 0.5rem; }
.diag__snippet { white-space: pre; }
.diag__gutter { display: inline-block; min-width: 3ch; text-align: right; color: var(--ink-faint); margin-right: 0.9rem; }
.diag__carets { color: var(--signal); }
.diag--warning .diag__carets { color: var(--warn); }
.diag__carets--secondary { color: var(--ink-faint); }
.diag__aside { margin-top: 0.5rem; color: var(--ink-soft); white-space: normal; }
.diag__aside b { font-weight: 500; color: var(--ink); }

/* -------------------------------------------------------------- sections */

.band { padding-block: 4rem; border-top: 1px solid var(--rule); }
.band h2 { font-size: clamp(1.75rem, 3.5vw, 2.5rem); max-width: 24ch; }
.band p { color: var(--ink-soft); }

.pipeline { display: grid; gap: 1.25rem; grid-template-columns: repeat(3, 1fr); margin-top: 2.5rem; }
.stage { border-top: 2px solid var(--ink); padding-top: 0.9rem; }
.stage h3 { font-family: var(--label); font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; }
.stage p { margin: 0.5rem 0 0; font-size: 0.95rem; }
.stage__arrow { color: var(--ink-faint); }

.checks { width: 100%; border-collapse: collapse; margin-top: 2rem; font-size: 0.95rem; }
.checks th, .checks td { text-align: left; padding: 0.85rem 1rem 0.85rem 0; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
.checks th { font-family: var(--label); font-size: 0.66rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); font-weight: 500; }
.checks td.code { font-family: var(--code); color: var(--signal); white-space: nowrap; }
.checks td.what { color: var(--ink); width: 30%; }
.checks td.eg { color: var(--ink-soft); font-family: var(--code); font-size: 0.8125rem; }

.closer { padding-block: 5rem 6rem; border-top: 1px solid var(--rule); text-align: center; }
.closer h2 { margin: 0 auto 1.5rem; }
.closer .button-row { justify-content: center; }

.colophon {
  border-top: 1px solid var(--rule);
  padding-block: 2rem 3rem;
  font-size: 0.85rem;
  color: var(--ink-faint);
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
}

/* ------------------------------------------------------------------ app */

.app { padding-block: 2.5rem 5rem; }
.app__head { display: flex; align-items: flex-end; gap: 1.5rem; flex-wrap: wrap; margin-bottom: 2rem; }
.app__head h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); }
.app__head .button-row { margin-left: auto; }

.crumbs { font-family: var(--label); font-size: 0.68rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.5rem; }
.crumbs a { color: var(--ink-soft); text-decoration: none; }
.crumbs a:hover { color: var(--signal); }

.zone-list { border-top: 1px solid var(--rule); }
.zone-row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--rule-soft);
  text-decoration: none;
  color: inherit;
}
.zone-row:hover { color: inherit; background: linear-gradient(90deg, var(--card), transparent); }
.zone-row__name { font-family: var(--code); font-size: 1.0625rem; overflow-wrap: anywhere; }
.zone-row:hover .zone-row__name { color: var(--signal); }
.zone-row__meta { margin-left: auto; font-family: var(--label); font-size: 0.68rem; letter-spacing: 0.05em; color: var(--ink-faint); text-transform: uppercase; }

/* A phone is narrower than a row of these. Laid out side by side, a long
   domain name takes the line and leaves the record count, the commit and the
   date to stack one word at a time down a column an inch wide -- and then
   run off the edge of it. Stacked, each says its piece on one line. */
@media (max-width: 40rem) {
  .zone-row { flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; }
  .zone-row__name { flex: 1 1 100%; }
  .zone-row__meta { margin-left: 0; }

  /* The same for the heading above it: a title and the button that acts on
     the page fit side by side on a laptop and crowd each other on a phone. */
  .app__head { gap: 1rem; }
  /* Its own line, at its own width. Stretched across the page it is louder
     than the heading above it, and a page with two of them stretches both. */
  .app__head .button-row { margin-left: 0; width: 100%; }
}

.status { font-family: var(--label); font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; padding: 0.2rem 0.5rem; border-radius: 2px; white-space: nowrap; }
.status--live { background: var(--ok-bg); color: var(--ok); }
.status--empty { background: var(--rule-soft); color: var(--ink-soft); }
.status--warn { background: var(--warn-bg); color: var(--warn); }
.status--bad { background: var(--signal-bg); color: var(--signal); }
.status--merged { background: var(--merge-bg); color: var(--link); }

.card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}
.card__head { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1rem; }
.card__head h2, .card__head h3 { font-family: var(--code); font-size: 1rem; font-weight: 500; }
.card__head .status { margin-left: auto; }

/* The rest of a commit message, wrapped by whoever wrote it. It is set like
   the message it is, not like a zone file: no frame, no scrolling. */
.commit-message {
  margin: 0 0 2rem;
  font-family: var(--code);
  font-size: 0.8125rem;
  line-height: 1.65;
  color: var(--ink-soft);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-width: 72ch;
}

.facts { display: flex; flex-wrap: wrap; gap: 2rem 3rem; margin: 0 0 2rem; padding: 0; }
.facts div { margin: 0; min-width: 0; }
.facts dt { font-family: var(--label); font-size: 0.64rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); }
.facts dd { margin: 0.3rem 0 0; font-family: var(--code); font-size: 0.9rem; overflow-wrap: anywhere; }

/* The account menu.
   A `details` element, so the panel is a sibling of the trigger rather than a
   thing positioned by script. Everything here is about making that look like
   a menu: the marker off, the panel out of the flow, and rows that fill it. */
.menu { position: relative; }

.menu__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.45rem;
  border: 1px solid transparent;
  border-radius: 3px;
  cursor: pointer;
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  list-style: none;
}

/* Both, because Safari uses one and everybody else uses the other. */
.menu__trigger::-webkit-details-marker { display: none; }
.menu__trigger::marker { content: ""; }

.menu__trigger:hover { color: var(--ink); border-color: var(--rule); }
.menu[open] .menu__trigger { color: var(--ink); border-color: var(--rule); background: var(--card); }
.menu__caret { font-size: 0.55rem; opacity: 0.7; }

.menu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.35rem);
  z-index: 20;
  min-width: 14rem;
  padding: 0.35rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 4px;
  box-shadow: 0 4px 14px rgb(0 0 0 / 0.12);
}

.menu__group { display: contents; }

.menu__item {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  width: 100%;
  padding: 0.4rem 0.5rem;
  border: none;
  border-radius: 3px;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: var(--code);
  font-size: 0.82rem;
  color: var(--ink);
  text-decoration: none;
}

/* The masthead shouts, because a handful of tabs read better that way. A list
   of sentences does not: "MANAGE ACCOUNT" and "NEW ORGANIZATION…" are harder
   to read than the words. Written at the nav's own specificity, because the
   rule being undone is `.masthead nav a, .masthead nav button`. */
.masthead nav .menu__item, .masthead nav .menu__item:link {
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--code);
  font-size: 0.82rem;
  color: var(--ink);
}

.menu__item:hover { background: var(--rule-soft); }
.menu__item:focus-visible { outline: 2px solid var(--link); outline-offset: -2px; }

/* Indented under their heading, so the list reads as belonging to it. */
.menu__item--org { padding-left: 1.1rem; }
.menu__item--here { font-weight: 500; }
.menu__item--here::before { content: "•"; margin-left: -0.7rem; margin-right: 0.2rem; }

.menu__heading {
  margin: 0.5rem 0 0.15rem;
  padding: 0 0.5rem;
  font-family: var(--label);
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.menu__tag {
  font-family: var(--label);
  font-size: 0.5rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.menu__rule { margin: 0.35rem 0; border: none; border-top: 1px solid var(--rule-soft); }
.menu__item--out { color: var(--ink-soft); }

/* Organisations: a list of rows, each a name and what you are to it. Plain,
   because this is a page somebody visits to change one thing and leave. */
.orgs { display: flex; flex-direction: column; gap: 0.25rem; }

.orgs__row {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--rule-soft);
}

.orgs__name { flex: 1 1 14rem; font-family: var(--code); font-size: 0.9rem; }
.orgs__meta { color: var(--ink-faint); font-size: 0.8rem; }
/* Only the font was set here, so in dark mode this was the one control on
   the page the browser drew in its own light colours. */
.orgs__role select {
  font-family: var(--code);
  font-size: 0.8rem;
  padding: 0.3rem 0.4rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
}

/* A list of people, where every row has the same four things to say: who,
   their address, what they may do, and the way to stop them. As flex rows
   each one measured itself, so an address of one length and an address of
   another put their roles in different places, and the row with the longest
   middle pushed its button onto a line of its own. The columns are declared
   once here instead, and a row with nothing to put in a slot leaves it
   empty rather than closing it up. */
.orgs--people {
  /* Four short columns. Given the width of the page they would sit a name at
     one edge and everything else at the other, which reads as a row with
     something missing from the middle rather than as a list. */
  max-width: 48rem;
}
.orgs--people .orgs__row {
  display: grid;
  grid-template-columns: minmax(6rem, 1fr) minmax(0, auto) 7rem 6rem;
  gap: 0.35rem 1rem;
  align-items: center;
}
.orgs--people .orgs__meta { justify-self: end; overflow-wrap: anywhere; }
.orgs--people .orgs__role,
.orgs--people .orgs__role select { width: 100%; }
/* The last column is fixed, so the buttons in it stack in a line down the
   page rather than each sizing itself to its own word. */
.orgs--people .orgs__act { justify-self: stretch; }
.orgs--people .orgs__act .button { width: 100%; }

/* Below this the four columns cannot hold their content, so the row becomes
   what it is on a phone: the name and the way to act on it on one line, and
   everything else stacked underneath. */
@media (max-width: 46rem) {
  .orgs--people .orgs__row { grid-template-columns: 1fr auto; }
  .orgs--people .orgs__name { grid-column: 1; grid-row: 1; }
  .orgs--people .orgs__meta { grid-column: 1; justify-self: start; }
  .orgs--people .orgs__role { grid-column: 1; width: auto; }
  .orgs--people .orgs__role select { width: auto; }
  .orgs--people .orgs__act {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
    align-self: start;
  }
  .orgs--people .orgs__act .button { width: auto; }
}

.orgs__tag, .orgs__here {
  font-family: var(--label);
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-left: 0.4rem;
}

/* The switcher in the masthead. Quiet: it says where you are, and is only
   worth noticing when it is not where you expected. */

/* An address nobody has proved yet. Warning rather than alarm: nothing is
   broken and nothing has failed, there is just one step left, and the red is
   kept for the checker saying a zone will not serve. */
.unconfirmed {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 1.25rem 0 0;
  padding: 0.9rem 1.1rem;
  background: var(--warn-bg);
  border: 1px solid var(--rule);
  border-radius: 4px;
}

.unconfirmed p { margin: 0; flex: 1 1 24rem; font-size: 0.88rem; max-width: 58ch; }

/* The theme switch: a pill with a thumb that slides between a sun and a moon.
   The familiar shape on purpose -- a control for something this incidental
   should not need learning, and there is no version of this that is better for
   being different. */
.switch {
  --switch-w: 3.1rem;
  --switch-h: 1.55rem;
  --switch-pad: 0.16rem;

  position: relative;
  width: var(--switch-w);
  height: var(--switch-h);
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--card);
  cursor: pointer;
  flex: none;
}

.switch:hover { border-color: var(--ink-faint); }
.switch:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }

.switch__track {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 0.34rem;
  color: var(--ink-faint);
}

/* The one the thumb is not sitting on is the one worth reading, so the other
   steps back rather than being hidden: a control that shows one icon is a
   picture of its state, and a picture does not say there is a second setting. */
.switch__icon { flex: none; opacity: 0.45; transition: opacity 0.18s ease; }
/* Which icon is lit, and where the thumb sits, come from the theme itself
   rather than from `aria-checked`.
   That attribute is set by a controller, and a controller connects after the
   first paint: on a dark page the switch rendered in its light position and
   then jumped. These are the same selectors the palette uses, so the switch
   is right in the same frame the colours are. `aria-checked` stays as what it
   is for, which is telling a screen reader the state. */
.switch .switch__icon:first-of-type { opacity: 1; color: var(--ink); }
.switch .switch__icon:last-of-type { opacity: 0.45; color: inherit; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .switch .switch__icon:first-of-type { opacity: 0.45; color: inherit; }
  :root:not([data-theme="light"]) .switch .switch__icon:last-of-type { opacity: 1; color: var(--ink); }
}

:root[data-theme="dark"] .switch .switch__icon:first-of-type { opacity: 0.45; color: inherit; }
:root[data-theme="dark"] .switch .switch__icon:last-of-type { opacity: 1; color: var(--ink); }

:root[data-theme="light"] .switch .switch__icon:first-of-type { opacity: 1; color: var(--ink); }
:root[data-theme="light"] .switch .switch__icon:last-of-type { opacity: 0.45; color: inherit; }

.switch__thumb {
  position: absolute;
  top: var(--switch-pad);
  left: var(--switch-pad);
  width: calc(var(--switch-h) - var(--switch-pad) * 2 - 2px);
  height: calc(var(--switch-h) - var(--switch-pad) * 2 - 2px);
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--rule);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
  transition: transform 0.18s ease;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .switch__thumb {
    transform: translateX(calc(var(--switch-w) - var(--switch-h)));
  }
}

:root[data-theme="dark"] .switch__thumb {
  transform: translateX(calc(var(--switch-w) - var(--switch-h)));
}

:root[data-theme="light"] .switch__thumb { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .switch__thumb, .switch__icon { transition: none; }
}

/* Zone file syntax.
   Restrained on purpose. A zone file is mostly names and addresses, and a
   scheme that colours those loudly leaves nothing for the parts that actually
   want finding: the comment explaining why a record is there, the type that
   says what kind of record it is, and the string whose quoting is the thing
   most likely to be wrong. So data is the ordinary ink and everything else is
   a shade off it. */
.zl--data { color: var(--ink); }
.zl--owner { color: var(--ink); font-weight: 500; }
.zl--type { color: var(--link); font-weight: 500; }
.zl--class { color: var(--ink-faint); }
.zl--number { color: var(--warn); }
.zl--string { color: var(--ok); }
.zl--directive { color: var(--signal); font-weight: 500; }
.zl--comment { color: var(--ink-faint); font-style: italic; }
.zl--paren { color: var(--ink-faint); }

/* A changed line is already carrying a background and a sign, so the syntax
   underneath it steps back rather than competing. */
.dl--added .zl--comment, .dl--removed .zl--comment { font-style: italic; }
.dl--added .zl--type { color: var(--add-ink); }
.dl--removed .zl--type { color: var(--del-ink); }
.dl--added .zl--number, .dl--added .zl--string,
.dl--removed .zl--number, .dl--removed .zl--string { color: inherit; }

/* The one page somebody opens when they think something is wrong. Two panes
   side by side because the two questions fail independently: publishing is
   whether git reaches the log, the fleet is whether the log reaches the
   servers, and a healthy fleet serving yesterday's zone is the failure that
   looks fine in either one alone. */
.glass { margin: 0 0 2.5rem; }

.glass__verdict {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.9rem 1.1rem;
  border-radius: 4px;
  border: 1px solid var(--rule);
  font-family: var(--code);
  font-size: 0.9rem;
}

.glass__verdict--well { background: var(--ok-bg); border-color: var(--add-rule); color: var(--ok); }
.glass__verdict--unwell { background: var(--signal-bg); border-color: var(--del-rule); color: var(--signal); }

.glass__asked {
  margin-left: auto;
  font-family: var(--label);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.glass__panes {
  display: grid;
  /* `min(...)` rather than the bare minimum: a track with a floor of 22rem
     cannot shrink below it, so on a narrow phone the grid is wider than the
     page and takes the whole layout with it. */
  grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
}

.glass__pane {
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 1.1rem 1.25rem 1.25rem;
}

.glass__pane h3 {
  margin: 0 0 1rem;
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.glass__facts {
  display: grid;
  /* Three across on a screen with room, however many fit on one without. */
  grid-template-columns: repeat(auto-fit, minmax(min(6.5rem, 100%), 1fr));
  gap: 1rem;
  margin: 0;
}
.glass__facts div { margin: 0; }
.glass__facts dt {
  font-family: var(--label);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.glass__facts dd { margin: 0.25rem 0 0; font-family: var(--code); font-size: 0.95rem; }

.glass__unit { display: block; font-size: 0.7rem; color: var(--ink-faint); }
.glass__bad { color: var(--signal); font-weight: 500; }

.glass__fleet { width: 100%; border-collapse: collapse; font-family: var(--code); font-size: 0.8rem; }
.glass__fleet th {
  text-align: left;
  font-family: var(--label);
  font-size: 0.56rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--rule-soft);
}
.glass__fleet td { padding: 0.4rem 0.6rem 0.4rem 0; border-bottom: 1px solid var(--rule-soft); }
.glass__row--bad td { color: var(--signal); }

.glass__list { margin: 1rem 0 0; padding-left: 1.1rem; font-family: var(--code); font-size: 0.78rem; }
.glass__list li { margin-bottom: 0.3rem; }

.glass__quiet, .glass__why {
  margin: 1rem 0 0;
  font-size: 0.82rem;
  color: var(--ink-faint);
  max-width: 44ch;
}

/* A branch that was pushed and has nowhere to go yet. Loud enough to be seen
   on the way past, quiet enough not to look like something went wrong: this is
   an offer, and the merge notice colour is the one already used for a change
   waiting on somebody. */
.pushed { margin: 0 0 2rem; }

.pushed__row {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.85rem 1rem;
  background: var(--merge-bg);
  border: 1px solid var(--rule);
  border-radius: 4px;
}

.pushed__row + .pushed__row { margin-top: 0.5rem; }

.pushed__what { flex: 1 1 20rem; font-family: var(--code); font-size: 0.85rem; }

.pushed__meta {
  display: block;
  margin-top: 0.2rem;
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* A value with a copy button beside it. The button holds its own width from
   the start -- it is only ever revealed, never inserted -- so the line does not
   jump when JavaScript connects or when the confirmation appears. */
.copyable { display: inline-flex; align-items: center; gap: 0.4rem; }

.copyable__button {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.3rem;
  border: 1px solid transparent;
  border-radius: 3px;
  background: none;
  color: var(--ink-faint);
  cursor: pointer;
  line-height: 1;
}

.copyable__button:hover { color: var(--ink); border-color: var(--rule); }
.copyable__button:focus-visible { outline: 2px solid var(--link); outline-offset: 1px; }

/* The word only exists once it is true, and it is taken out of the flow so its
   arrival does not move the value it is confirming. */
.copyable__said {
  font-family: var(--label);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-width 0.15s ease, opacity 0.15s ease;
}

.copyable--copied .copyable__button { color: var(--ok); border-color: transparent; }
.copyable--copied .copyable__said { max-width: 5rem; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .copyable__said { transition: none; }
}

.zonefile {
  font-family: var(--code);
  font-size: 0.8125rem;
  line-height: 1.6;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  padding: 1rem 0;
  overflow-x: auto;
}
.zonefile ol { margin: 0; padding: 0; list-style: none; counter-reset: line; }
.zonefile li { counter-increment: line; white-space: pre; padding: 0 1.25rem; }
.zonefile li::before {
  content: counter(line);
  display: inline-block;
  min-width: 3ch;
  margin-right: 1.25rem;
  text-align: right;
  color: var(--ink-faint);
}
.zonefile li.flagged { background: var(--signal-bg); }
.zonefile li.flagged--warning { background: var(--warn-bg); }

.records {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--code);
  font-size: 0.8125rem;
  /* The panel around it scrolls, which only helps if the table declines to
     shrink. With `width: 100%` alone, five columns squeeze into a phone until
     the data column is an inch wide and `overflow-wrap: anywhere` breaks
     every value one character to a line. */
  min-width: 34rem;
}
.records th, .records td { text-align: left; padding: 0.5rem 1rem 0.5rem 0; border-bottom: 1px solid var(--rule-soft); white-space: nowrap; }
.records td.ttl { color: var(--ink-soft); }
.records th { font-family: var(--label); font-size: 0.62rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-faint); font-weight: 500; }
.records td.type { color: var(--signal); }
/* A CERT or a DNSKEY is one token hundreds of characters long. It has to be
   allowed to break, or the table drags the whole page sideways. */
.records td.data { white-space: normal; overflow-wrap: anywhere; }

.history { border-top: 1px solid var(--rule); }
.history__row { display: flex; gap: 1rem; align-items: baseline; padding: 0.9rem 0; border-bottom: 1px solid var(--rule-soft); }
.history__sha { font-family: var(--code); font-size: 0.8125rem; }
.history__summary { flex: 1; min-width: 12rem; }
.history__when { font-family: var(--label); font-size: 0.66rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-faint); }
.history__row .status { align-self: center; }

/* Three columns of commit on a phone leaves the summary a 12rem minimum it
   cannot have and pushes the author and date off the side. The summary takes
   its own line and the rest reads across. */
@media (max-width: 40rem) {
  .history__row { flex-wrap: wrap; align-items: center; gap: 0.4rem 0.75rem; }
  .history__summary { flex: 1 1 100%; min-width: 0; }
}

/* -------------------------------------------------------------- settings */

/* A setting is a sentence about the zone with a switch in front of it, not a
   field with a value, so this borrows the panel's ground and none of .field:
   that caption treatment is for naming an input, and reads as shouting when
   it lands on prose. */
.settings {
  /* The panel is as wide as the sentence inside it. A full-width card with a
     measure-constrained paragraph in the corner reads as a layout that has
     gone wrong rather than as one column of prose. */
  max-width: 44rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
}

.setting {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 0.85rem;
  padding: 1.5rem;
  cursor: pointer;
}
.setting + .setting { border-top: 1px solid var(--rule-soft); }

.setting input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  /* Optically on the first line of the name rather than flush to its top. */
  margin: 0.28rem 0 0;
  /* The red means "this will not serve" everywhere else on the page, and a
     ticked box means the opposite of that. */
  accent-color: var(--ink);
}

.setting__name { font-size: 1.0625rem; }
.setting__what {
  grid-column: 2;
  max-width: var(--measure);
  margin: 0.35rem 0 0;
  color: var(--ink-soft);
  font-size: 0.9375rem;
  line-height: 1.55;
}
/* The caveat that only matters once somebody is about to act on the setting. */
.setting__caveat {
  grid-column: 2;
  max-width: var(--measure);
  margin: 0.6rem 0 0;
  color: var(--ink-faint);
  font-size: 0.875rem;
  line-height: 1.5;
}

.settings__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--rule);
}
.settings__when {
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ------------------------------------------------------------------- keys */

.keys { border-top: 1px solid var(--rule); }
.keys__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.25rem 1rem;
  align-items: baseline;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--rule-soft);
}
.keys__what { font-size: 0.95rem; }
.keys__print {
  grid-column: 1;
  font-family: var(--code);
  font-size: 0.8125rem;
  color: var(--ink-soft);
  overflow-wrap: anywhere;
}
.keys__when {
  grid-column: 1;
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
/* Beside the key it removes, on its own row of the grid so a long
   fingerprint wraps under the name rather than pushing the button away. */
.keys__row form.keys__remove { grid-column: 2; grid-row: 1 / span 3; align-self: center; }

/* A key is pasted, not typed: it is one long line and wraps badly. */
.field textarea {
  width: 100%;
  font-family: var(--code);
  font-size: 0.85rem;
  line-height: 1.5;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
  resize: vertical;
}
.field textarea:focus { border-color: var(--ink); outline: 2px solid var(--signal); outline-offset: 1px; }

/* ---------------------------------------------------------------- billing */

/* What the organisation is on, before anything about changing it. The plan
   is the answer; where it came from is the sentence under it, because
   "granted" and "renews on the 3rd" are the same size of fact. */
.plan-now {
  border-left: 3px solid var(--ok);
  background: var(--card);
  padding: 1.25rem 1.5rem;
  border-radius: 0 3px 3px 0;
  max-width: 44rem;
}
.plan-now__label {
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.plan-now__name { font-size: 1.5rem; margin: 0.25rem 0 0; }
.plan-now__why { margin: 0.35rem 0 0; color: var(--ink-soft); font-size: 0.9375rem; }

/* Choosing one, which is not the pricing page's job of comparing all four --
   `.plans` is that one, and taking its name here meant the billing page was
   laid out in four narrow columns by a rule written for a different page. */
.buy {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: 1rem;
  max-width: 40rem;
}
.buy__one {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 1.5rem;
}
.buy__name { font-size: 1.125rem; margin: 0; }
.buy__price { font-size: 1.75rem; margin: 0.35rem 0 0; }
.buy__price span { font-size: 0.875rem; color: var(--ink-faint); }
.buy__who { color: var(--ink-soft); font-size: 0.9375rem; margin: 0.6rem 0 1.25rem; }
.buy__how { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.buy__year { margin: 0.75rem 0 0; font-size: 0.8125rem; color: var(--ink-faint); }

/* --------------------------------------------------------- admin: who pays */

.ledger { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.ledger th, .ledger td {
  text-align: left;
  padding: 0.7rem 1rem 0.7rem 0;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: middle;
}
.ledger th {
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 500;
}
.ledger__name { font-family: var(--code); }
.ledger__note { color: var(--ink-faint); font-size: 0.8125rem; margin-left: 0.4rem; }
.ledger__act { text-align: right; padding-right: 0; }

/* Choosing a plan, saying why, and doing it, on one line. The reason is a
   required part of the gesture rather than a thing to fill in later: a grant
   nobody wrote a reason on is one nobody can judge afterwards. */
.grant { display: flex; gap: 0.5rem; justify-content: flex-end; align-items: center; }
.grant select, .grant__note {
  font-family: var(--code);
  font-size: 0.8rem;
  padding: 0.3rem 0.4rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
}
.grant__note { width: 9rem; }

@media (max-width: 52rem) {
  .ledger, .ledger tbody, .ledger tr, .ledger td { display: block; width: 100%; }
  .ledger thead { display: none; }
  .ledger tr { border-bottom: 1px solid var(--rule); padding: 0.75rem 0; }
  .ledger td { border: 0; padding: 0.15rem 0; }
  .ledger__act { text-align: left; padding-top: 0.6rem; }
  .grant { justify-content: flex-start; flex-wrap: wrap; }

  /* Stacked, the header row is gone and every cell is a bare value: a plan
     name, a chip, and a number that could be anything. Each carries its own
     column name down with it. */
  .ledger td[data-label]::before {
    content: attr(data-label);
    display: inline-block;
    width: 6.5rem;
    font-family: var(--label);
    font-size: 0.62rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-faint);
  }
}

/* ------------------------------------------------------------------ fleet */

.fleet { border-top: 1px solid var(--rule); }
.fleet__node {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--rule-soft);
  border-left: 3px solid var(--ok);
  padding-left: 0.9rem;
}
/* Not answering is the one thing on this page worth the alarm colour: it is
   the only row where something is wrong rather than merely different. */
.fleet__node--down { border-left-color: var(--signal); }
.fleet__label { font-family: var(--label); font-size: 0.8rem; }
.fleet__url { flex: 1; font-family: var(--code); font-size: 0.8125rem; color: var(--ink-faint); }
.fleet__state {
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.fleet__node--down .fleet__state { color: var(--signal); }
.fleet__why {
  margin: 0.5rem 0 0 0.9rem;
  font-family: var(--code);
  font-size: 0.8125rem;
  color: var(--ink-soft);
}
.fleet__verdict { margin-top: 1.5rem; color: var(--ink-soft); }
.fleet__verdict--agreed { color: var(--ok); }

.fleet__zones { border-collapse: collapse; margin-top: 1rem; width: 100%; }
.fleet__zones th, .fleet__zones td {
  text-align: left;
  padding: 0.55rem 1rem 0.55rem 0;
  border-bottom: 1px solid var(--rule-soft);
  font-family: var(--code);
  font-size: 0.8125rem;
}
.fleet__zones th {
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.fleet__missing { color: var(--signal); }

/* --------------------------------------------------------------- choices */

.setup__lede { max-width: 58ch; margin: 1rem 0 2.5rem; font-size: 1.0625rem; color: var(--ink-soft); }

.choices { display: grid; gap: 1.5rem; }
.choice {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 1.75rem;
}
/* The one option that is actually available reads first. */
.choice--offered { border-color: var(--ink); box-shadow: inset 3px 0 0 var(--ok); }
.choice h2 { font-size: 1.35rem; margin-bottom: 0.5rem; }
.choice p { color: var(--ink-soft); max-width: 62ch; margin: 0 0 1.25rem; }
.choice .help { font-size: 0.9rem; color: var(--ink-faint); }
.choice details { margin: 0 0 1.25rem; }
.choice summary { cursor: pointer; }
.choice .zonefile { margin-top: 0.75rem; max-height: 24rem; overflow: auto; }
.choice .zoneview__panel--records { max-height: 24rem; overflow: auto; }
.choice__retry { margin-top: 1.5rem; border-top: 1px solid var(--rule); padding-top: 1.25rem; }
.choice__retry .field input { max-width: 24rem; }
.choice .button_to { display: inline-block; }
.choice .attempts { margin-bottom: 1.25rem; }

/* -------------------------------------------------------------- zoneview */

/* Two views of one file, switched by a pair of radio buttons: no script, and
   every file on a page keeps its own state. */
.zoneview { margin-top: 0.5rem; }
.zoneview__radio {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}
.zoneview__tabs {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 0.75rem;
}
.zoneview__tab {
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding: 0.5rem 0.75rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  cursor: pointer;
}
.zoneview__tab:hover { color: var(--ink); }
.zoneview__panel { display: none; }
.zoneview__panel--records { overflow-x: auto; }
.zoneview__radio--records:checked ~ .zoneview__panel--records,
.zoneview__radio--raw:checked ~ .zoneview__panel--raw { display: block; }
.zoneview__radio--records:checked ~ .zoneview__tabs .zoneview__tab--records,
.zoneview__radio--raw:checked ~ .zoneview__tabs .zoneview__tab--raw {
  color: var(--ink);
  border-bottom-color: var(--signal);
}
/* The radio is invisible, so its focus ring has to land on the tab. */
.zoneview__radio:focus-visible ~ .zoneview__tabs .zoneview__tab--records,
.zoneview__radio--raw:focus-visible ~ .zoneview__tabs .zoneview__tab--raw {
  outline: 2px solid var(--signal);
  outline-offset: -2px;
}

/* One colour per kind of value, the same in every record. */
/* `pre-wrap` keeps the spacing inside a quoted string, which is part of the
   value; `anywhere` still lets an unbroken blob of base64 wrap. */
.tok { white-space: pre-wrap; overflow-wrap: anywhere; }
.tok--name { color: var(--link); }
.tok--addr { color: var(--ok); }
.tok--text { color: var(--warn); }
.tok--num { color: var(--ink-soft); }
.tok--word { color: var(--ink); }
.tok[title] { cursor: help; }

.records__name { color: var(--ink); }
.records__line { text-align: right; color: var(--ink-faint); width: 3rem; }
.records tbody tr:hover { background: var(--paper); }

/* ---------------------------------------------------------------- import */

.attempts { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.attempts td { padding: 0.4rem 1rem 0.4rem 0; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
.attempts__who { font-family: var(--code); font-size: 0.8125rem; white-space: nowrap; }
.attempts__what { color: var(--ink-soft); }

.dropped { margin-top: 1.5rem; border-left: 2px solid var(--warn); background: var(--warn-bg); padding: 1rem 1rem 0.5rem; }
.dropped__head { margin: 0 0 0.5rem; font-size: 0.95rem; }
.dropped .attempts td { border-bottom-color: rgba(138, 100, 16, 0.2); }

.import__retry { margin-top: 1.5rem; border-top: 1px solid var(--rule); padding-top: 1.5rem; }
.import__retry .field input { max-width: 26rem; }

/* ----------------------------------------------------------------- forms */

.panel {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: 2rem;
  /* Every panel used to sit inside a `narrow` page, so it never needed a
     width of its own. On a page that is not narrow -- one with a list of
     people on it as well as a form -- a form stretched to the full width
     puts the label a long way from the field it names. */
  max-width: 44rem;
}
.field { margin-bottom: 1.25rem; }
.field label {
  display: block;
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.4rem;
}
.field input {
  width: 100%;
  font-family: var(--code);
  font-size: 0.95rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
}
.field input:focus { border-color: var(--ink); outline: 2px solid var(--signal); outline-offset: 1px; }

/* The line under a field explaining it. Unstyled, it fell back to the page's
   serif and set itself at reading width, so a note about a text box arrived
   looking like a paragraph of the manual -- wider than the field it belongs
   to, in a different typeface, with `code` spans a size too big. */
.field__note {
  display: block;
  margin-top: 0.4rem;
  font-family: var(--code);
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-faint);
  max-width: 52ch;
}

.field__note code {
  font-family: var(--code);
  font-size: 1em;
  color: var(--ink-soft);
}
.field .help { font-size: 0.85rem; color: var(--ink-faint); margin-top: 0.4rem; }


.form-aside { margin-top: 1.5rem; font-size: 0.9rem; color: var(--ink-soft); }

.notice, .alert, .errors {
  border-left: 2px solid var(--ok);
  background: var(--ok-bg);
  padding: 0.75rem 1rem;
  margin-bottom: 1.5rem;
  font-size: 0.95rem;
}
.alert, .errors { border-left-color: var(--signal); background: var(--signal-bg); }
.errors ul { margin: 0.25rem 0 0; padding-left: 1.25rem; }

.empty {
  border: 1px dashed var(--rule);
  border-radius: 3px;
  padding: 2.5rem;
  text-align: center;
  color: var(--ink-soft);
}
.empty h2 { font-size: 1.4rem; margin-bottom: 0.75rem; color: var(--ink); }

/* The commands to type. Every one of these in the app is a `pre` that *is*
   `.setup`, so a rule for a `pre` inside one matched nothing anywhere and
   all three snippets -- the home page's, the zone setup page's and the push
   instructions' -- have been unstyled monospace running off the side of the
   page with nothing to scroll them. */
.setup {
  margin: 1.5rem 0 0;
  font-family: var(--code);
  font-size: 0.8125rem;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  padding: 1rem 1.25rem;
  overflow-x: auto;
  text-align: left;
}

@media (max-width: 52rem) {
  .pipeline { grid-template-columns: 1fr; }
  .hero { padding-block: 3rem 2rem; }
  .app__head .button-row { margin-left: 0; }
  .facts { gap: 1.25rem 2rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ================================================================= changes */

/* A heading between sections of a page, in the display face but small enough
   not to compete with the page's own title. */
.section-head {
  font-size: 1.15rem;
  margin: 3rem 0 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--rule);
}

/* ---------------------------------------------------------------- listings */

.pulls { border-top: 1px solid var(--rule); margin-bottom: 2rem; }
.pull-row {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1rem 0;
  border-bottom: 1px solid var(--rule-soft);
}
.pull-row__number {
  font-family: var(--code);
  font-size: 0.875rem;
  color: var(--ink-faint);
  min-width: 3.5rem;
}
.pull-row__number a { color: var(--ink); text-decoration: none; }
.pull-row__number a:hover { color: var(--signal); }
.pull-row__title { flex: 1; min-width: 14rem; }
.pull-row__title a { color: inherit; text-decoration: none; }
.pull-row__title a:hover { color: var(--signal); }
.pull-row__meta {
  display: block;
  font-family: var(--label);
  font-size: 0.64rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-top: 0.3rem;
}
.pull-row .status { align-self: center; white-space: nowrap; }
.pull-row .button { align-self: center; }

/* ------------------------------------------------------------- one change */

.pull__byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 1.5rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
}
.pull__byline code {
  font-family: var(--code);
  font-size: 0.85rem;
  background: var(--card);
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  padding: 0.1rem 0.4rem;
}
.pull__dot { color: var(--ink-faint); }
.pull__body {
  max-width: var(--measure);
  margin: 0 0 2rem;
  padding-left: 1rem;
  border-left: 2px solid var(--rule);
  color: var(--ink-soft);
}

/* The one loud thing on the page: whether this can land, and what happens if
   it does. */
.merge {
  display: flex;
  gap: 2rem;
  align-items: center;
  flex-wrap: wrap;
  background: var(--card);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink-faint);
  border-radius: 3px;
  padding: 1.5rem 1.75rem;
  margin: 0 0 2rem;
}
.merge--ready { border-left-color: var(--ok); }
.merge--failing, .merge--conflict { border-left-color: var(--signal); }
.merge--merged { border-left-color: var(--link); }
.merge__say { flex: 1; min-width: 18rem; }
.merge__say h2 { font-size: 1.5rem; margin-bottom: 0.4rem; }
.merge__say p { margin: 0; color: var(--ink-soft); max-width: 58ch; }
.merge__what { margin-top: 0.6rem !important; font-size: 0.9rem; color: var(--ink-faint) !important; }
.merge__do { display: flex; gap: 0.75rem; align-items: center; }
.merge__do form { margin: 0; }

/* --------------------------------------------------------------- the build */

.build {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ok);
  border-radius: 3px;
  background: var(--card);
  padding: 1rem 1.25rem;
  margin: 0 0 2rem;
}
.build--warning { border-left-color: var(--warn); }
.build--failing { border-left-color: var(--signal); }
.build--empty { border-left-color: var(--ink-faint); }
.build__head { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; }
.build__state {
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ok);
}
.build--warning .build__state { color: var(--warn); }
.build--failing .build__state { color: var(--signal); }
.build--empty .build__state { color: var(--ink-faint); }
.build__summary { color: var(--ink-soft); font-size: 0.95rem; }
.build__diagnostics { margin-top: 1.25rem; }
.build__diagnostics .diag:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- the diff */

.diff .card__head { margin-bottom: 0.5rem; }
.diffstat {
  margin-left: auto;
  font-family: var(--code);
  font-size: 0.8rem;
  display: flex;
  gap: 0.6rem;
}
.diffstat__add { color: var(--add-ink); }
.diffstat__del { color: var(--del-ink); }

/* Records: what the change does to DNS. */
.recdiff td, .recdiff th { vertical-align: top; }
.recdiff__mark {
  width: 1.5rem;
  font-family: var(--code);
  text-align: center !important;
  padding-right: 0.5rem !important;
  color: var(--ink-faint);
}
.recdiff__row--added { background: var(--add-bg); }
.recdiff__row--added .recdiff__mark { color: var(--add-ink); }
.recdiff__row--removed { background: var(--del-bg); }
.recdiff__row--removed .recdiff__mark { color: var(--del-ink); }
.recdiff__row--changed { background: var(--card); }
.recdiff__row--quiet { opacity: 0.55; }
.recdiff tbody tr:hover { background: var(--paper); }
.recdiff__row--added:hover { background: var(--add-bg); }
.recdiff__row--removed:hover { background: var(--del-bg); }
.recdiff .was {
  text-decoration: line-through;
  text-decoration-color: var(--del-rule);
  opacity: 0.7;
}
.recdiff .arrow { color: var(--ink-faint); padding: 0 0.35rem; }
.recdiff__why {
  font-family: var(--label);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-left: 0.75rem;
}
.recdiff__note { width: 2rem; text-align: right !important; }

/* Raw: what the change does to the file. */
.hunk {
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  margin-bottom: 1rem;
  overflow-x: auto;
  background: var(--paper);
}
.hunk__head {
  font-family: var(--code);
  font-size: 0.75rem;
  color: var(--ink-faint);
  background: var(--card);
  border-bottom: 1px solid var(--rule-soft);
  padding: 0.35rem 1rem;
}
.hunk__lines { margin: 0; padding: 0.5rem 0; list-style: none; }
.dl {
  font-family: var(--code);
  font-size: 0.8125rem;
  line-height: 1.55;
  white-space: pre;
  padding-right: 1rem;
}
.dl--added { background: var(--add-bg); }
.dl--removed { background: var(--del-bg); }
.dl__n {
  display: inline-block;
  min-width: 3ch;
  padding: 0 0.5rem;
  text-align: right;
  color: var(--ink-faint);
  user-select: none;
}
.dl__sign {
  display: inline-block;
  width: 2ch;
  text-align: center;
  color: var(--ink-faint);
  user-select: none;
}
.dl--added .dl__sign { color: var(--add-ink); }
.dl--removed .dl__sign { color: var(--del-ink); }
.dl__text { white-space: pre-wrap; word-break: break-word; }
.dl__note { white-space: normal; }

/* ------------------------------------------------------------------ notes */

/* A comment on one line or one record. Closed it is a single glyph; open it
   is a small card, and it needs no script either way. */
.note { display: inline-block; }
.note > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.35rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--card);
  font-family: var(--label);
  font-size: 0.62rem;
  color: var(--ink-faint);
}
.note > summary::-webkit-details-marker { display: none; }
.note > summary:hover { border-color: var(--ink); color: var(--ink); }
.note--said > summary { border-color: var(--link); color: var(--link); background: var(--merge-bg); }
.note__body {
  position: relative;
  z-index: 1;
  margin: 0.5rem 0 0.75rem;
  padding: 0.9rem 1rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 3px;
  width: min(34rem, 70vw);
  white-space: normal;
  font-family: var(--display);
  font-size: 0.9rem;
}
.note__said { margin-bottom: 0.75rem; }
.note__said p { margin: 0.2rem 0 0; }
.note__who { font-weight: 500; }
.note__when {
  font-family: var(--label);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-left: 0.5rem;
}
.note__form textarea, .said textarea {
  width: 100%;
  font-family: var(--display);
  font-size: 0.95rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
  resize: vertical;
  margin-bottom: 0.6rem;
}

/* ----------------------------------------------------------- conversation */

.thread { max-width: var(--measure); }
.said {
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: var(--card);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
.said header { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.35rem; }
.said__when {
  font-family: var(--label);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.said p { margin: 0.3rem 0 0; }
.said--new { background: var(--paper); border-style: dashed; }
.thread__elsewhere { color: var(--ink-faint); font-size: 0.9rem; margin: 0 0 1rem; }

/* --------------------------------------------------------------- the form */

/* A form that reads like the file it writes to: monospace, in columns, with
   nothing between the fields but the rules of a table. */
.editor { margin-bottom: 2rem; }
.rows {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 0.75rem;
  /* The columns are fixed so that nothing typed into one moves another. A
     table that lays itself out from its contents re-flows every row on every
     keystroke, which is unusable to type into. */
  table-layout: fixed;
}
.rows th {
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 500;
  text-align: left;
  padding: 0 0.5rem 0.4rem;
  border-bottom: 1px solid var(--rule);
}
.rows td { padding: 0; border-bottom: 1px solid var(--rule-soft); }
.rows__n {
  width: 2.5rem;
  font-family: var(--code);
  font-size: 0.75rem;
  color: var(--ink-faint);
  text-align: right;
  padding-right: 0.75rem !important;
}
.rows__name { width: 16rem; }
.rows__ttl { width: 6rem; }
.rows__type { width: 7rem; }
/* Data takes whatever is left, and a value longer than that scrolls inside
   its own field rather than widening the column. */
.rows input {
  width: 100%;
  font-family: var(--code);
  font-size: 0.8125rem;
  padding: 0.55rem 0.5rem;
  border: 0;
  background: transparent;
  color: var(--ink);
}
.rows input:focus { outline: 2px solid var(--signal); outline-offset: -2px; background: var(--card); }
.rows input::placeholder { color: var(--ink-faint); opacity: 0.7; }
.rows tr:hover td { background: var(--card); }
.rows__del { width: 3rem; text-align: center !important; }
.rows__del input { width: auto; accent-color: var(--signal); cursor: pointer; }
/* A row on its way out reads as struck through, so the form says what it will
   do before it is submitted. */
.rows tr:has(.rows__del input:checked) td { background: var(--del-bg); }
.rows tr:has(.rows__del input:checked) input[type="text"] {
  text-decoration: line-through;
  text-decoration-color: var(--del-rule);
  color: var(--ink-faint);
}
.rows__row--new .rows__n { color: var(--ink-faint); opacity: 0.6; }
.editor__hint {
  max-width: var(--measure);
  font-size: 0.875rem;
  color: var(--ink-faint);
  margin: 0 0 2rem;
}
.editor__hint code {
  font-family: var(--code);
  font-size: 0.8rem;
  color: var(--ink-soft);
}
.editor .field { max-width: 34rem; }
.editor textarea {
  width: 100%;
  font-family: var(--display);
  font-size: 0.95rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
  resize: vertical;
}
.editor select, .panel select {
  width: 100%;
  font-family: var(--code);
  font-size: 0.9rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--paper);
  color: var(--ink);
}

/* A role is two words, and a select sized to the card reads as a text field
   that has lost its text. The editor's own selects keep the full width,
   because a record type sits above a value that uses it. */
.field--tight select { width: auto; min-width: 9rem; }

.push {
  font-family: var(--code);
  font-size: 0.8125rem;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  padding: 0.75rem 1rem;
  display: inline-block;
  margin-top: 1rem;
}

@media (max-width: 52rem) {
  .merge { gap: 1rem; }
  .pull-row { flex-wrap: wrap; }
  .rows__name { width: 8rem; }
  .rows__ttl { width: 4.5rem; }
  .rows__type { width: 5.5rem; }
  .note__body { width: min(28rem, 80vw); }
}

/* Warnings fold away; the summary line is the affordance. */
.build__more { margin-top: 0.75rem; }
.build__more > summary {
  cursor: pointer;
  font-family: var(--label);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.build__more > summary:hover { color: var(--ink); }
.build__more[open] > summary { margin-bottom: 1rem; }

/* The checker's running answer, above the form it is about. */
.verdict {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin: 0 0 1.5rem;
  padding: 0.6rem 1rem;
  border-left: 2px solid var(--ok);
  background: var(--ok-bg);
  font-size: 0.95rem;
  color: var(--ink-soft);
}
.verdict--warning { border-left-color: var(--warn); background: var(--warn-bg); }
.verdict--failing { border-left-color: var(--signal); background: var(--signal-bg); }
.verdict__state {
  font-family: var(--label);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ok);
}
.verdict--warning .verdict__state { color: var(--warn); }
.verdict--failing .verdict__state { color: var(--signal); }

/* A row the checker is complaining about. The mark is on the line number,
   which is the one cell it can replace without touching what is being typed. */
.rows tr:has(.rows__n--bad) td { background: var(--del-bg); }
.rows__n--bad { color: var(--del-ink) !important; font-weight: 700; }

/* --------------------------------------------------- inside a TXT record */

/* SPF, DMARC and the rest are languages of their own, so they get colours of
   their own: the key, what it was set to, and where it points. */
.tok--version { color: var(--signal); font-weight: 500; }
.tok--key { color: var(--link); }
.tok--value { color: var(--ok); }
.tok--qualifier { color: var(--signal); font-weight: 500; }
.tok--target { color: var(--ink); }
.tok--separator { color: var(--ink-faint); }
.tok--unknown { color: var(--warn); text-decoration: underline wavy var(--warn); text-underline-offset: 3px; }

/* What a record is and what it does, under the field it is typed into. */
.reading:empty { display: none; }
.reading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.15rem 0.5rem 0.4rem;
  font-family: var(--code);
  font-size: 0.75rem;
}
.reading__what { display: flex; align-items: baseline; gap: 0.4rem; }

/* The chip and the severity are labels, and a label that wraps is not one:
   "DMARC" broke across two lines as DMAR / C because a flex item shrinks
   below its content unless it is told not to. */
.reading__label, .reading__severity { flex: none; white-space: nowrap; }

/* What is left, as one block of prose. `min-width: 0` because a flex item
   will not shrink past its longest word otherwise, which pushes the row wider
   than the table instead of wrapping inside it. */
.reading__says { flex: 1 1 auto; min-width: 0; }

.reading__label {
  font-family: var(--label);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  border-radius: 2px;
  padding: 0.1rem 0.35rem;
}
.reading__summary { color: var(--ink-soft); }
.reading__summary, .reading__problem { display: inline; }
.reading__parts { color: var(--ink-faint); }

/* A record the checker has something to say about.
   The chip changes colour and gains a word. Colour alone would say nothing to
   somebody who cannot see it and nothing at all to a screen reader, and this
   is exactly the case where the difference matters: a DMARC record that does
   nothing looks identical to a DKIM key that is fine. */
.reading__what--warning .reading__label { background: var(--warn); color: var(--warn-bg); }
.reading__what--error .reading__label { background: var(--signal); color: var(--signal-bg); }

.reading__severity {
  font-family: var(--label);
  font-size: 0.55rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.reading__what--warning .reading__severity { color: var(--warn); }
.reading__what--error .reading__severity { color: var(--signal); }

/* The problem reads before the description, because it is the half somebody
   needs. The summary stays: "failing mail is delivered anyway" is what the
   record does, and "it asks for no policy and no reports" is why that is
   worth saying. */
.reading__problem { color: var(--ink); }
.reading__what--warning .reading__problem::before,
.reading__what--error .reading__problem::before { content: "· "; color: var(--ink-faint); }

/* In a table of records, the same thing sits under the data it explains. */
.records .reading { padding-left: 0; }

/* What is wrong with one row, under the field it is wrong in. */
.note-row:empty { display: none; }
.note-row__wrong {
  margin: 0.15rem 0 0;
  padding: 0.15rem 0.5rem 0.35rem;
  font-family: var(--display);
  font-size: 0.85rem;
  color: var(--del-ink);
}
.note-row__wrong::before {
  content: "↳ ";
  color: var(--del-rule);
}

/* A button with nothing to do says so rather than doing nothing. */
.button:disabled,
.button:disabled:hover {
  background: transparent;
  border-color: var(--rule);
  color: var(--ink-faint);
  cursor: not-allowed;
}

/* ------------------------------------------------- where the domain points */

/* The one thing on the zone page that is about the world rather than about the
   store: whether queries for this domain actually arrive here. */
.pointed {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink-faint);
  border-radius: 3px;
  background: var(--card);
  padding: 1rem 1.25rem;
  margin: 0 0 2rem;
}
.pointed--here { border-left-color: var(--ok); }
.pointed--partly, .pointed--nowhere { border-left-color: var(--warn); }
.pointed--elsewhere { border-left-color: var(--signal); }
.pointed--asking { border-left-color: var(--rule); }

.pointed__say { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; margin: 0; }
.pointed__state {
  font-family: var(--label);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-faint);
}
.pointed--here .pointed__state { color: var(--ok); }
.pointed--partly .pointed__state, .pointed--nowhere .pointed__state { color: var(--warn); }
.pointed--elsewhere .pointed__state { color: var(--signal); }
.pointed__say { color: var(--ink-soft); }

.pointed__what { margin-top: 1rem; }
.pointed__what p { margin: 0; color: var(--ink-soft); font-size: 0.95rem; }
.pointed__servers {
  list-style: none;
  margin: 0.5rem 0 0.75rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.pointed__servers li {
  font-family: var(--code);
  font-size: 0.8125rem;
  background: var(--paper);
  border: 1px solid var(--rule-soft);
  border-radius: 2px;
  padding: 0.2rem 0.6rem;
}
.pointed__aside { font-size: 0.875rem !important; color: var(--ink-faint) !important; }

.pointed__when {
  margin: 0.75rem 0 0;
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
}
.pointed__again { display: inline; }
/* A button that reads as the sentence it is in. The masthead's sign-out uses
   the same class and is styled by the nav around it; here there is no nav. */
.pointed__again .link-button,
.masthead .link-button {
  font-family: var(--label);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pointed__again .link-button:hover,
.masthead .link-button:hover { color: var(--signal); }

/* A column heading that sorts. It reads as a heading until it is hovered,
   because the table is worth reading whether or not anybody sorts it. */
.records__sort {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.records th:hover .records__sort { color: var(--ink); }
.records th[aria-sort]:not([aria-sort="none"]) .records__sort { color: var(--ink); }
.records__sorted .records__sort::after {
  content: " ↑";
  color: var(--signal);
}
.records__sorted--down .records__sort::after { content: " ↓"; }

/* ================================================================= pricing */

.hero--short { padding-bottom: 2rem; }
.hero--short h1 { font-size: clamp(2.25rem, 5.5vw, 3.75rem); max-width: 20ch; }

/* Four plans, laid out like the pipeline on the front page: a rule on top and
   the name under it, rather than four cards with a badge on one of them. */
.plans {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.5rem;
  margin-bottom: 1rem;
}
.plan {
  border-top: 2px solid var(--rule);
  padding-top: 1rem;
  display: flex;
  flex-direction: column;
}
/* The one most people should be on gets the ink rule. */
.plan--team { border-top-color: var(--ink); }

.plan__name {
  font-family: var(--label);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.plan__price { margin: 0.75rem 0 0; display: flex; align-items: baseline; gap: 0.4rem; }
.plan__money { font-size: 2rem; letter-spacing: -0.02em; }
.plan__cadence { color: var(--ink-faint); font-size: 0.9rem; }
.plan__annually {
  margin: 0.2rem 0 0;
  min-height: 1.2rem;
  font-family: var(--label);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.plan__who { margin: 0.9rem 0 0; color: var(--ink-soft); font-size: 0.95rem; }
.plan__limits {
  margin: 1rem 0 0;
  font-family: var(--code);
  font-size: 0.8125rem;
  color: var(--ink);
}
.plan__includes {
  list-style: none;
  margin: 0.75rem 0 1.25rem;
  padding: 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}
.plan__includes li { padding: 0.25rem 0 0.25rem 1.1rem; position: relative; }
.plan__includes li::before {
  content: "·";
  position: absolute;
  left: 0.25rem;
  color: var(--signal);
}
.plan__do { margin-top: auto; }

/* The comparison. A table, because that is what it is. */
.compare__scroll { overflow-x: auto; }
.compare {
  width: 100%;
  border-collapse: collapse;
  margin-top: 2rem;
  font-size: 0.95rem;
  /* The scroller around it only helps if the table refuses to shrink. With
     `width: 100%` alone a five-column comparison squeezes itself into a
     phone, one word per line, rather than scrolling -- which is the width
     being honoured at the cost of the thing being readable. */
  min-width: 34rem;
}
.compare th, .compare td {
  text-align: left;
  padding: 0.7rem 1rem 0.7rem 0;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: baseline;
}
.compare thead th {
  font-family: var(--label);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
.compare__price {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--code);
  font-size: 0.7rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
}
.compare tbody th {
  font-weight: 400;
  color: var(--ink);
  width: 30%;
}
.compare tbody td { color: var(--ink-soft); font-family: var(--code); font-size: 0.8125rem; }
.compare__yes { color: var(--ok); font-family: var(--code); }
.compare__none { color: var(--ink-faint); }
.compare tbody tr:hover td, .compare tbody tr:hover th { background: var(--card); }

.pipeline--four { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 62rem) {
  .plans { grid-template-columns: repeat(2, 1fr); }
  .pipeline--four { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 40rem) {
  .plans { grid-template-columns: 1fr; }
  .pipeline--four { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------- inside one zone */

/* The zone's sections. The same four on every page inside it, in the same
   place, marked where you are — the tab shape the zone view already uses,
   because it means the same thing here. */
.zonenav {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border-bottom: 1px solid var(--rule);
  margin: 0 0 2rem;
  /* Wrapping rather than scrolling. Four short labels never need to scroll,
     and `overflow-x` would make `overflow-y` compute to `auto` as well — which
     the tab's -1px bottom margin then overflows by exactly one pixel, for a
     scrollbar down the side of a row that has nothing to scroll. */
  flex-wrap: wrap;
}
.zonenav__tab {
  font-family: var(--label);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-decoration: none;
  white-space: nowrap;
  padding: 0.6rem 0.9rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
}
.zonenav__tab:hover { color: var(--ink); }
.zonenav__tab--here {
  color: var(--ink);
  border-bottom-color: var(--signal);
}
