:root {
  --ink: #413f42;
  --teal: #00939a;
  --teal-deep: #005f61;
  --paper: #f6f3ee;
  --panel: #fff;
  --line: #dde5ed;
  /* Brand Slate, PMS 7544, a "muted support gray-blue". It is 3.71:1 on
     --panel and 3.35:1 on --paper, so it is not a text colour: AA wants
     4.5:1 for normal text. Its value stays exactly what the brand guide
     prints, because that guide states its hexes match this stylesheet.
     Support jobs only. Decision 0036, 2026-09-20. */
  --muted: #758796;
  /* Slate at the same hue and saturation (hsl 207, 14%) with lightness
     lowered 52% to 43%. That is the lightest whole step that clears AA on
     --paper, the harder of the two backgrounds: 43% measures 4.69:1 and
     44% measures 4.49:1. Every muted piece of prose reads this. */
  --muted-ink: #5e6f7d;
  --mark: #ce0058;
  /* --ink and --teal-deep mixed 55 to 45, written as a hex so the contrast walk
     can mix text over it. The Naming showcase on the default page is its only
     fill (LG, 2026-10-10): related to --ink, and a different service. */
  --ink-teal: #234d50;
  --sans: "graphie", "Graphie", "Figtree", Arial, sans-serif;
  --slab: "mokoko", "Mokoko", "Zilla Slab", "Times New Roman", serif;
  /* One band for every signed-in page. The chrome and the content line
     up because both read this. Statement was already 80rem; that is
     now the product. A stylesheet cannot prove the pixel.

     It is still a fixed column rather than a percentage, so leftover
     monitor is gutter. Do not make this track the viewport with a
     min-width query, 100%, 100vw, or a max(). Login .gate stays
     28rem: a card, not a page. */
  --band: 80rem;
  --gutter: 1.75rem;
  /* The gap between one section of a page and the next, and between one segment
     of a group and the next. One value, named once, for the same reason --band
     is: the client page had five different gaps down it on 2026-09-20 (17, 23,
     25, 34 and 34 pixels, measured in Chromium), because each section carried
     its own margin, several carried one at both ends, and adjacent siblings then
     collapsed to whichever was larger. LG: "Consistent spacing between
     segments."

     1rem is not a new number. Fourteen of that page's sixteen gaps were already
     1rem, from .panel, so this is the value the product had already chosen
     everywhere it had chosen anything; the exceptions were the two blocks at the
     top of the page. Set it as margin-top only, never at both ends, or
     collapsing reintroduces a second value nobody wrote down. */
  --section-gap: 1rem;
  /* A card's corner and the room inside it, named once (T-177, 2026-10-05). LG:
     "The cards are too bare and too square." The corner was Open Props'
     --radius-2, 5px, on .panel alone, while the Query form, the describe card,
     the Account meters and the rebate starter were cards drawn with no corner and
     no shadow at all. 0.75rem is 12px: soft enough not to read as square, well
     short of a pill. The padding was four values (1.2rem 1.3rem, 1.4rem 1.5rem,
     1.1rem 1.2rem, 1rem 1.2rem) for one surface. Phones take less, below. */
  --card-radius: 0.75rem;
  --card-pad: 1.35rem 1.5rem;
  color-scheme: light;
}
@media (max-width: 40rem) {
  :root { --card-pad: 1.1rem 1.15rem; }
}

/* Leftover class names cannot reopen a second measure. Do not put
   class="wide" or class="full" on a new template. */
body.wide,
body.full { --band: 80rem; }

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

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.05rem;
  line-height: 1.45;
}

.skip {
  position: absolute;
  left: -999px;
  top: 0;
}
.skip:focus {
  left: 1rem;
  top: 1rem;
  z-index: 2;
  background: var(--panel);
  padding: 0.4rem 0.7rem;
}

.wordmark {
  margin: 0;
  font-weight: 650;
  letter-spacing: -0.03em;
  font-size: 1.15rem;
  white-space: nowrap;
}
/* On a signed-in page the wordmark is the way to the default page (T-194), so it
   is a link that keeps the logotype's colours. It takes no underline at rest and
   one under the product name on hover, so the mark itself never changes. */
a.wordmark {
  display: inline-block;
  text-decoration: none;
  border-radius: 0.35rem;
}
a.wordmark:hover .product { text-decoration: underline; }
.wordmark .domains { color: var(--ink); }
.wordmark .bot { color: var(--teal); }
.wordmark .product {
  font-family: var(--slab);
  font-weight: 500;
  color: var(--muted-ink);
  margin-left: 0.55rem;
}
/* A stamp after the product name (Emiliano, 2026-10-09). Outline only, so it
   does not become a second chip beside the account badge. It sits level: a
   tilt read as crooked rather than as a stamp (LG, 2026-10-09). It stays on
   the wordmark's line.
   The gap before it is its own word space: the box and the tilt eat a plain
   margin, and Domainsbot, Meridian and Beta have to read as three words
   (LG, 2026-10-09). It is the gap before Meridian, measured: at 1rem it was
   16.8px against 12.9px and read as a few pixels too far right (LG,
   2026-10-10). */
.wordmark .beta {
  display: inline-block;
  margin-left: 0.75rem;
  padding: 0.12rem 0.38rem 0.08rem;
  border: 1.5px solid var(--teal-deep);
  border-radius: 0.2rem;
  color: var(--teal-deep);
  font-family: var(--sans);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1;
  text-transform: uppercase;
  vertical-align: 0.35em;
}

/* The rule under the header runs the full width; what sits above it does not.
   The inline padding grows to whatever is left over once the band is centred,
   so the wordmark starts exactly where the page heading below it starts. */
.top {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding-block: 0.75rem;
  padding-inline: max(var(--gutter), calc((100% - var(--band)) / 2));
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
/* The menu is a compact dock, not a flex-grow strip. flex: 1 was what made
   three or seven links look like they owned the whole bar. margin-inline-start
   auto puts the dock on the right, opposite the wordmark. */
.top nav {
  display: flex;
  gap: 0.2rem;
  flex: 0 1 auto;
  align-items: center;
  flex-wrap: wrap;
  margin-inline-start: auto;
  padding: 0.2rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 999px;
}
/* The account's badge sits after the dock, furthest right, never a chip.
   nav.html is its one home. It is not a link and it does not take
   current/hover the way Query and Account do. It reads the display name,
   or the slug when none is set (2026-10-02), and a name has no length
   a slug kept to, so it is clamped and ends in an ellipsis: up to a
   quarter of the window between 8rem and 16rem, and on a phone the
   width of the header's row. It is a block because text-overflow does
   not reach the text of a flex container. */
.top .who {
  display: block;
  flex-shrink: 0;
  max-inline-size: clamp(8rem, 25vw, 16rem);
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
  padding: 0.38rem 0.75rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--teal) 12%, white);
  border: 1px solid color-mix(in srgb, var(--teal) 28%, var(--line));
  color: var(--teal-deep);
  font-size: 0.8rem;
  font-weight: 650;
  line-height: 1;
  white-space: nowrap;
}
/* A staff person's session is in a client (decision 0082). The header wraps
   only while the banner is there, and the banner takes the whole second row,
   so the dock and the badge stay on the first exactly as they were. Amber, the
   mark colour, because it is a state to notice and not an action result. */
.top:has(> .entered) { flex-wrap: wrap; }
.top > .entered { flex-basis: 100%; }
.entered {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  padding: 0.6rem 0.9rem;
  border-radius: 0.55rem;
  background: color-mix(in srgb, var(--mark) 10%, white);
  border: 1px solid color-mix(in srgb, var(--mark) 35%, white);
}
.entered p {
  flex: 1 1 22rem;
  margin: 0;
  line-height: 1.45;
}
.entered form { margin: 0; }
.entered button {
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.entered button:hover { background: color-mix(in srgb, var(--mark) 14%, white); }
.top nav .intelligence > summary,
.top nav .staff > summary,
.top nav .services > summary,
.top nav .account > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.38rem 0.8rem;
  border-radius: 999px;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.92rem;
  line-height: 1;
}
.top nav .intelligence > summary:hover,
.top nav .staff > summary:hover,
.top nav .services > summary:hover,
.top nav .account > summary:hover {
  color: var(--teal-deep);
  background: color-mix(in srgb, var(--teal) 10%, white);
}
.top nav .intelligence.current > summary,
.top nav .intelligence[open] > summary,
.top nav .staff.current > summary,
.top nav .staff[open] > summary,
.top nav .services.current > summary,
.top nav .services[open] > summary,
.top nav .account.current > summary,
.top nav .account[open] > summary {
  color: var(--teal-deep);
  background: var(--panel);
  box-shadow: 0 0 0 1px var(--line);
}
/* Every entry in the dock is a disclosure: Intelligence, Naming, Staff and
   Account. No script, no Alpine, and not a button (a typeless one would
   submit Sign out). The menus are positioned so opening one does not
   grow the header. Account's menu hangs from the right edge of that
   pill; the slug badge sits after the dock. */
.top nav .intelligence,
.top nav .staff,
.top nav .services,
.top nav .account { position: relative; }
.top nav .intelligence > summary,
.top nav .staff > summary,
.top nav .services > summary,
.top nav .account > summary {
  list-style: none;
  cursor: pointer;
}
.top nav .intelligence > summary::-webkit-details-marker,
.top nav .staff > summary::-webkit-details-marker,
.top nav .services > summary::-webkit-details-marker,
.top nav .account > summary::-webkit-details-marker { display: none; }
.top nav .intelligence > summary::after,
.top nav .staff > summary::after,
.top nav .services > summary::after,
.top nav .account > summary::after {
  content: "";
  width: 0.32em;
  height: 0.32em;
  margin-left: 0.05em;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translateY(-0.08em);
}
.top nav .intelligence[open] > summary::after,
.top nav .staff[open] > summary::after,
.top nav .services[open] > summary::after,
.top nav .account[open] > summary::after {
  transform: rotate(-135deg) translateY(-0.08em);
}
.top nav .intelligence-menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 0;
  z-index: 4;
  min-width: 14.5rem;
  padding: 0.35rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--ink) 10%, transparent);
}
.top nav .staff-menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 0;
  z-index: 4;
  min-width: 14.5rem;
  padding: 0.35rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--ink) 10%, transparent);
}
.top nav .services-menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 0;
  z-index: 4;
  min-width: 14.5rem;
  padding: 0.35rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--ink) 10%, transparent);
}
.top nav .account-menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  z-index: 4;
  min-width: 14.5rem;
  padding: 0.35rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--ink) 10%, transparent);
}
.top nav .intelligence-menu a,
.top nav .staff-menu a,
.top nav .services-menu a,
.top nav .account-menu a,
.top nav .account-menu .signout button {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.55rem 0.7rem;
  border-radius: 0.55rem;
  color: var(--ink);
  text-decoration: none;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  text-align: start;
  background: transparent;
  border: 0;
  cursor: pointer;
  width: 100%;
}
.top nav .intelligence-menu a:hover,
.top nav .intelligence-menu a[aria-current="page"],
.top nav .staff-menu a:hover,
.top nav .staff-menu a[aria-current="page"],
.top nav .services-menu a:hover,
.top nav .services-menu a[aria-current="page"],
.top nav .account-menu a:hover,
.top nav .account-menu a[aria-current="page"],
.top nav .account-menu .signout button:hover {
  background: color-mix(in srgb, var(--teal) 10%, white);
  color: var(--teal-deep);
}
.top nav .staff-menu strong,
.top nav .services-menu strong { font-size: 0.95rem; }
.top nav .staff-menu span {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--muted-ink);
}
.top nav .account-menu .signout {
  margin: 0.2rem 0 0;
  padding-top: 0.2rem;
  border-top: 1px solid var(--line);
}
a.inspect {
  display: inline-flex;
  align-items: center;
  padding: 0.32rem 0.7rem;
  border: 1px solid var(--teal);
  border-radius: 0.4rem;
  color: var(--teal-deep);
  text-decoration: none;
  font-weight: 650;
  font-size: 0.88rem;
  background: transparent;
}
a.inspect:hover {
  background: color-mix(in srgb, var(--teal) 12%, white);
}

main {
  padding: 2.25rem var(--gutter) 4rem;
  max-width: calc(var(--band) + var(--gutter) * 2);
  margin-inline: auto;
}

/* Signing in is a step on a surface, not a heading floating on the paper. The
   body centres it in the viewport rather than the old 18vh margin, so the card
   sits in the middle of a laptop screen and still scrolls on a short one. */
body.signed-out {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: 2rem 0;
}
.gate {
  max-width: 28rem;
  width: 100%;
  margin: 0;
  padding: 0 1.5rem;
}
/* The acceptance step is the one gate wider than the sign-in card (LG,
   2026-10-08). The heading is wider than the two buttons, so 33.5rem is
   that heading plus the padding this card already has, and no more. The
   description under it is free to wrap. Login and the other steps stay 28rem. */
.gate.accept { max-width: 33.5rem; }
.gate .wordmark { margin-bottom: 0.9rem; padding-left: 0.1rem; }
/* The design page draws the acceptance step inside a panel, which already pads
   it; the gate's own side padding there squeezed the card to 235px at 390px. */
.panel > .gate { padding: 0; }
/* One card for every step of signing in, including redeem. The teal edge is
   the only ornament: it ties the gate to the one teal control on it, and it
   is the accent the brand already uses. */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-top: 3px solid var(--teal);
  border-radius: var(--card-radius);
  padding: 1.6rem 1.7rem 1.8rem;
  box-shadow: 0 1px 2px rgb(65 63 66 / 4%), 0 8px 24px -12px rgb(65 63 66 / 18%);
}
.gate h1 {
  font-family: var(--slab);
  font-weight: 500;
  font-size: 1.9rem;
  line-height: 1.15;
  letter-spacing: -0.03em;
  margin: 0 0 0.5rem;
}
.lead { color: var(--muted-ink); }
.gate .lead { margin: 0; }
.gate .err { margin: 0.6rem 0 0; color: var(--mark); }
.signin {
  display: grid;
  gap: 0.55rem;
  margin: 1.4rem 0 0;
}
.signin label {
  font-weight: 650;
  font-size: 0.92rem;
}
.signin input[type="email"] {
  width: 100%;
}
.g_id_signin { margin-top: 1.1rem; }
/* The acceptance step (decision 0062) is this card too: the two texts under
   the lead, the draft note under them, then Accept and Reject on one row.
   Accept is the primary fill. Reject is the secondary outline and signs out.
   Each label stays one line. On a viewport narrower than the card the second
   button drops under the first, whole, rather than breaking "Sign out". */
.gate .texts { margin: 1rem 0 0; }
.gate .texts + .meta { margin: 0.6rem 0 0; }
.gate-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.6rem;
  margin-top: 1.4rem;
}
.gate-actions .signin { margin: 0; flex: 1 1 auto; min-width: max-content; }
.gate-actions .signin button {
  width: 100%;
  height: 100%;
  justify-self: stretch;
  white-space: nowrap;
  text-align: center;
}
/* One quiet line under the page, centred on the content. Copyright, and the
   Terms of Use and Privacy Policy when texts are configured. No rule above it:
   the hairline footer is /docs, which has a job of its own. Smaller than the
   page, in the text grey, and the links stay whole if the line wraps. */
.site-foot {
  margin-top: 2.25rem;
  text-align: center;
  font-size: 0.8rem;
  line-height: 1.45;
}
.gate .site-foot { margin-top: 0.9rem; }
.page-foot + .site-foot { margin-top: 0.85rem; }
.site-foot p {
  margin: 0;
  color: var(--muted-ink);
}
.site-foot a {
  color: var(--muted-ink);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  white-space: nowrap;
}
.site-foot a:hover { color: var(--teal-deep); }
code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
  font-size: 0.92em;
}

/* Title on the paper, work in a raised card. The hairline is the
   split. A stylesheet cannot prove the pixel gap; surfaces_test.go
   names the declarations that make it. Do not nest this in .panel.
   Do not put pills or forms here. */
/* No divider under a head (LG, 2026-10-10): what follows is a raised panel or a
   titled group, which already says where the head ends. It was dropped on
   Clients first, by a class of its own, and then everywhere. */
.pagehead {
  margin-bottom: 1.35rem;
}
.pagehead h1 {
  font-family: var(--slab);
  font-weight: 500;
  font-size: 2rem;
  letter-spacing: -0.03em;
  margin: 0.2rem 0 0.5rem;
}
/* Account puts the plan on the title's line, on the right. nowrap is the
   point: a badge that drops under the title is a second line, which is what
   the lead used to be. The colours are the account badge in the header. */
.account-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: nowrap;
}
.account-head h1 { margin: 0; font-size: 2rem; }
.plan-badge {
  flex-shrink: 0;
  margin: 0;
  padding: 0.38rem 0.75rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--teal) 12%, white);
  border: 1px solid color-mix(in srgb, var(--teal) 28%, var(--line));
  color: var(--teal-deep);
  font-size: 0.8rem;
  font-weight: 650;
  line-height: 1;
  white-space: nowrap;
}
/* Whatever comes straight after the page head takes no top margin of its own,
   because the head already carries the gap under itself. This was two rules
   naming .panel and .empty, which left every other first block (the client
   page's facts, a meters grid, a notice) adding --section-gap on top of the
   head's 1.35rem. The rule lives at the foot of this sheet instead, because
   .pagehead + * ties .panel and .config on specificity and has to win on
   order. */
/* .eyebrow is gone. Every page head now says where it is with .crumbs or says
   nothing, and a rule kept for no template is a rule the next page reaches for. */

.meters {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: var(--section-gap) 0 0;
}
main section.meters:has(article:only-child) {
  grid-template-columns: minmax(0, 32rem);
}
.meters article {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
}
/* One group label. It names a set of controls, a figure, or a set of facts, and it
   was drawn four ways: 0.8rem muted on the Account meters and the Query form labels,
   0.88rem teal-deep with tighter tracking on a Services guide, 0.82rem at weight 650
   with tracking again in the Query picker.

   The colour is --teal-deep and that is an accessibility decision, not a brand one.
   Measured in Chromium on 2026-09-19 against --panel #fff: --muted #758796 gives
   **3.71:1** and --teal-deep #005f61 gives **7.47:1**. At 0.8rem these labels are
   normal text under WCAG (large is 18.66px bold or 24px), so they need 4.5:1, and
   --muted has been failing that on every Query form label and both Account meter
   labels. service_layout_test.go already required the darker token here for exactly
   this reason; the Services guide was the one place that had it right.

   So the label is quieter than its values by size and weight rather than by being
   washed out. Proof: headingscale_test.go. The wider --muted problem (.meta, .lead,
   p.empty are all below 4.5:1) is a separate card. */
.meters h2,
.query-examples h3,
.output-group h3,
.query label,
.mint label,
.chart-pick label,
.hero-label,
.kicker,
.qv2-label,
.qv2-kicker,
.qv2-picker-title {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--teal-deep);
}
/* .mint label joined on 2026-09-20, which is the rest of T-082: /query labelled
   its controls in this small-caps micro-type and Members, Integrations and the two
   staff pages used sentence case, so the product had two ways to label a control.
   Query is the page a customer spends time on, so its treatment is the one that
   sets the vocabulary.

   The card this came from had it waiting on the checkbox standard, because
   uppercasing .mint label renders the product name "Name Suggestion" as "NAME
   SUGGESTION". That is resolved rather than carved out, and the distinction was
   already written down in .checks label: a label that NAMES A CONTROL gets the
   small caps, and a label whose text IS THE CHOICE reads as words. A product chip
   is the second kind. Both .check labels say so below.
   
   .query label is deliberately untouched by this change. --control-h is derived
   from the 0.8rem that label passes to the box inside it, so moving its size moves
   every control height on the Query form, and that pair has drifted once already
   (44px buttons against 38px boxes). The card's guess that moving Query would be
   "a far larger diff" was right, for that reason rather than the one it gave. */
.mint label.check,
.product-choices label.check {
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
}

.meters h2 {
  margin: 0;
}
/* Figure is the total remaining only. Pots sit on .meta. nowrap is
   safe because that line is short; the full 0017 sentence here
   overflowed a 1fr track. A stylesheet test cannot prove the pixel. */
.figure {
  font-family: var(--slab);
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  font-weight: 500;
  letter-spacing: -0.04em;
  margin: 0.35rem 0 0.15rem;
  color: var(--teal-deep);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.meta { margin: 0; color: var(--muted-ink); font-size: 0.92rem; }
/* A way to another page that is not a bare link on the paper. Pills
   sit in a row; each one is the control. */
.pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0 0 1rem;
}
/* Unsigned /docs has no dock. The Sign in pill sits where the dock would. */
.top > .pills {
  margin-inline-start: auto;
  margin-block: 0;
}
/* A link pill wraps between words when it alone is wider than its line, and only
   then: in a wrapping flex row a pill moves to the next line first. .pill below is
   nowrap, and "Open AI Name Suggestion API documentation" measured 346px against a
   286px guide column at 390px, so the column widened and its three facts ran 38px
   past the panel (2026-10-03). a.pill outranks .pill, so this wins wherever it is. */
a.pill {
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--teal-deep);
  font-weight: 650;
  font-size: 0.9rem;
  text-decoration: none;
  white-space: normal;
}
a.pill:hover {
  border-color: color-mix(in srgb, var(--teal) 45%, white);
  background: color-mix(in srgb, var(--teal) 9%, white);
}
span.pill {
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.85rem;
  border: 1px solid color-mix(in srgb, var(--teal) 45%, white);
  border-radius: 999px;
  background: var(--panel);
  color: var(--teal-deep);
  font-weight: 700;
  font-size: 0.9rem;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
  margin-top: var(--section-gap);
}
.panel h2 { margin: 0 0 0.6rem; font-size: 1.05rem; }
/* The padding is the room at both ends of a card, so nothing inside adds its own
   margin there: a paragraph or a form last in a panel put another 1rem under it,
   and the bottom of a card read deeper than the top. */
.panel > :first-child { margin-top: 0; }
.panel > :last-child { margin-bottom: 0; }

/* Prose takes a reading line-height and the whole of its card's content box. The
   only inset is the card's own padding: a paragraph that stops part way across a
   card, with empty card beside it, is the defect decision 0079 removed. */
.lead,
.notice,
.panel > p:not(.pills),
section.empty > p,
.service-part p,
.describe > .meta {
  line-height: 1.55;
}
/* Titles take a heading's line-height rather than the body's 1.45, and break
   into balanced lines. Size stays with the five steps; this sets none. */
.pagehead h1,
.config > h2,
.panels > h2,
.panel h2,
.panel > h3,
section.empty h2,
.describe h2 {
  line-height: 1.25;
  text-wrap: balance;
}

/* Service pages read top to bottom: try it, what it does, its documentation,
   then how to get your own access (decision 0068, 2026-10-03; it was guide first
   until then). One column of sections at every width, so there is no second
   layout to get right and no empty card beside a cramped one. Decision 0037,
   2026-09-20. What it does is the explainer's split variant since 2026-10-11,
   under Content patterns, with its two facts stacked. service_layout_test.go
   names these declarations. */
/* Suggested names, one to a line and ten at most, with the hairline the pager
   already uses between them (decision 0068). A name has no
   spaces, so a long one breaks where it must rather than running off a 390px
   screen. */
.service-names {
  margin-top: 0.6rem;
}
.service-names li {
  padding-block: 0.4rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92rem;
  overflow-wrap: break-word;
}
.service-names li + li {
  border-top: 1px solid var(--line);
}

/* One try, two accounts (T-201): each account's answer is a column, with the
   editorial items' hairline between them rather than a card in the try's card,
   and one column under 40rem, where two lists of names would each be a word
   wide. Every name carries its place in that account's order, so the two
   columns read across by rank. The place is hidden from a screen reader,
   which already hears the list as ordered. Each column's head, lead and list
   share the grid's rows, so a lead that wraps on one side does not push its
   first name below the other side's. */
.try-compare {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-top: 1rem;
  border-top: 1px solid var(--line);
}
.try-set {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  align-content: start;
  align-items: start;
  min-width: 0;
  padding-block: 0.9rem 0;
}
.try-set:first-child { padding-inline-end: 1.5rem; }
.try-set + .try-set {
  padding-inline-start: 1.5rem;
  border-inline-start: 1px solid var(--line);
}
.try-set-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.try-set-count {
  margin: 0;
  color: var(--muted-ink);
  font-size: 0.85rem;
  white-space: nowrap;
}
.try-set-lead {
  margin: 0.3rem 0 0;
  color: var(--muted-ink);
  line-height: 1.5;
}
.try-set > .notice,
.try-set > .empty {
  margin-top: 0.9rem;
}
.try-compare-foot {
  margin: 1.1rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
  line-height: 1.55;
}
.try-compare .service-names {
  counter-reset: rank;
}
.try-compare .service-names li {
  display: grid;
  grid-template-columns: 1.6rem minmax(0, 1fr);
  counter-increment: rank;
}
.try-compare .service-names li::before {
  content: counter(rank) / "";
  color: var(--muted-ink);
  font-variant-numeric: tabular-nums;
}
/* While the next try is on its way, the last answer steps back, so a reader
   does not compare two columns that are about to be replaced. */
.try-result[aria-busy="true"] > * {
  opacity: 0.45;
}
@media (max-width: 40rem) {
  .try-compare { grid-template-columns: minmax(0, 1fr); }
  .try-set:first-child { padding-inline-end: 0; }
  .try-set + .try-set {
    margin-top: 1.1rem;
    padding-inline-start: 0;
    border-inline-start: 0;
    border-top: 1px solid var(--line);
  }
}

/* A try in flight (T-133). htmx puts htmx-request on the form while the
   request runs and disables the button through hx-disabled-elt, so a second
   click cannot call the service twice; the spinner says the first one landed.
   It is drawn in the button's own colour. Reduced motion stops the turn and
   leaves the ring, which still reads as working beside a disabled button. */
/* The same spinner rides every other submit that waits on a service: Run, Design
   the query and Next page on Query, which carry data-wait. /static/wait.js marks
   the pressed one .waiting and disables it once the request has left, because
   Query does not load htmx (TestOnlyTheServicePagesLoadHtmx). Two selectors per
   rule, one drawing, so the try and the rest cannot come to look different. */
.try .spinner,
button[data-wait] .spinner {
  display: none;
}
.try.htmx-request .spinner,
button.waiting .spinner {
  display: inline-block;
  inline-size: 0.85em;
  block-size: 0.85em;
  margin-inline-end: 0.45em;
  border: 2px solid currentColor;
  border-inline-end-color: transparent;
  border-radius: 50%;
  vertical-align: -0.1em;
  animation: try-turn 0.8s linear infinite;
}
.try button:disabled,
button.waiting {
  cursor: progress;
}
@keyframes try-turn {
  to { transform: rotate(360deg); }
}

/* Home for a labelled control. The look is the shared text-entry
   treatment below. Forms keep their layout. A stylesheet cannot
   prove pixels. Scoped by type so picker checkboxes stay out. */
.field {
  display: grid;
  gap: 0.4rem;
}
/* One labelled control with its submit on the same row. The label spans, so it
   still sits above the control the way every other field does; the button is a
   sibling rather than inside the label, because a label may not contain one.
   It exists because a lone submit under a one-line query box read as a second
   step (LG, 2026-09-20: "The test-form looks bad with the button on a separate
   line"). minmax(0, 1fr) rather than 1fr, or a long placeholder widens the
   track and pushes the button off the panel. */
.field.with-action {
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 0.5rem;
}
.field.with-action > label {
  grid-column: 1 / -1;
}
/* No height is declared, deliberately. Grid stretches both items to the row,
   so the button is exactly as tall as the box beside it and stays that way if
   the input's padding changes. The filter row next to the query form had to
   write its height down in a custom property because those controls are not
   siblings in one row; these are, so stating a measurement twice is how the
   pair drifts. Never reintroduce one here as an em. */
.field.with-action > button {
  white-space: nowrap;
}
.field input[type="text"],
.field input[type="email"],
.field input[type="number"],
.field input[type="search"],
.field textarea,
.mint input[type="text"],
.mint input[type="email"],
/* A password box is a typed box. It was missing from this list, so the one on the
   staff HTTP Basic form rendered as the user agent's own control beside four that
   did not (LG, 2026-09-21). Listing types rather than a bare `.mint input` is
   deliberate: that would also match every checkbox in a product-choices fieldset. */
.mint input[type="password"],
.mint input[type="number"],
.mint input[type="date"],
.mint input[type="search"],
.mint textarea,
.mint select,
.signin input[type="email"],
.query input[type="text"],
.query input[type="number"],
.query input[type="search"],
.qv2 input[type="text"],
.qv2 input[type="number"],
.qv2 input[type="search"],
.qv2 select,
.qv2 textarea,
.query select,
.describe-query textarea {
  font: inherit;
  font-family: var(--sans);
  font-weight: 500;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  padding: 0.5rem 0.65rem;
}
.field input[type="text"]:hover,
.field input[type="email"]:hover,
.field input[type="number"]:hover,
.field input[type="search"]:hover,
.field textarea:hover,
.mint input[type="text"]:hover,
.mint input[type="email"]:hover,
.mint input[type="password"]:hover,
.mint input[type="number"]:hover,
.mint input[type="date"]:hover,
.mint input[type="search"]:hover,
.mint textarea:hover,
.mint select:hover,
.signin input[type="email"]:hover,
.query input[type="text"]:hover,
.query input[type="number"]:hover,
.query input[type="search"]:hover,
.qv2 input[type="text"]:hover,
.qv2 input[type="number"]:hover,
.qv2 input[type="search"]:hover,
.qv2 select:hover,
.qv2 textarea:hover,
.query select:hover,
.describe-query textarea:hover {
  border-color: color-mix(in srgb, var(--ink) 28%, var(--line));
}
.field input[type="text"]:focus,
.field input[type="email"]:focus,
.field input[type="number"]:focus,
.field input[type="search"]:focus,
.field textarea:focus,
.mint input[type="text"]:focus,
.mint input[type="email"]:focus,
.mint input[type="password"]:focus,
.mint input[type="number"]:focus,
.mint input[type="date"]:focus,
.mint input[type="search"]:focus,
.mint textarea:focus,
.mint select:focus,
.signin input[type="email"]:focus,
.query input[type="text"]:focus,
.query input[type="number"]:focus,
.query input[type="search"]:focus,
.qv2 input[type="text"]:focus,
.qv2 input[type="number"]:focus,
.qv2 input[type="search"]:focus,
.qv2 select:focus,
.qv2 textarea:focus,
.query select:focus,
.describe-query textarea:focus {
  outline: 2px solid var(--teal);
  outline-offset: 1px;
  border-color: var(--teal);
}
.field input[type="text"]:disabled,
.field input[type="email"]:disabled,
.field input[type="number"]:disabled,
.field input[type="search"]:disabled,
.field textarea:disabled,
.mint input[type="text"]:disabled,
.mint input[type="email"]:disabled,
.mint input[type="password"]:disabled,
.mint input[type="number"]:disabled,
.mint input[type="search"]:disabled,
.mint textarea:disabled,
.mint select:disabled,
.signin input[type="email"]:disabled,
.query input[type="text"]:disabled,
.query input[type="number"]:disabled,
.query input[type="search"]:disabled,
.qv2 input[type="text"]:disabled,
.qv2 input[type="number"]:disabled,
.qv2 input[type="search"]:disabled,
.qv2 select:disabled,
.qv2 textarea:disabled,
.query select:disabled,
.describe-query textarea:disabled {
  color: var(--muted-ink);
  background: color-mix(in srgb, var(--paper) 70%, var(--line));
}
.field input[type="text"]::placeholder,
.field input[type="email"]::placeholder,
.field input[type="number"]::placeholder,
.field input[type="search"]::placeholder,
.field textarea::placeholder,
.mint input[type="text"]::placeholder,
.mint input[type="email"]::placeholder,
.mint input[type="password"]::placeholder,
.mint input[type="number"]::placeholder,
.mint input[type="search"]::placeholder,
.mint textarea::placeholder,
.signin input[type="email"]::placeholder,
.query input[type="text"]::placeholder,
.query input[type="number"]::placeholder,
.query input[type="search"]::placeholder,
.qv2 input[type="text"]::placeholder,
.qv2 input[type="number"]::placeholder,
.qv2 input[type="search"]::placeholder,
.qv2 textarea::placeholder,
.describe-query textarea::placeholder {
  color: var(--muted-ink);
}

/* One line under the table: how many rows are on this page at the left, the
   control that turns it at the right, separated from the rows by a hairline.

   This replaces two blocks, the second of which was a <form class="query">.
   That class is the question form's card, so a search that paged ended in an
   empty white slab with one teal button in its top-left corner, which reads as
   a second question rather than as the foot of an answer. */
.panel-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-block-start: 0.9rem;
  padding-block-start: 0.8rem;
  border-block-start: 1px solid var(--line);
}
/* Pushed to the end as well as spaced apart, so the control still sits at the
   right when there is no count beside it. */
.pager { margin-inline-start: auto; }
.pager button {
  font: inherit;
  font-weight: 650;
  padding: 0.5rem 0.85rem;
  border-radius: 0.4rem;
  cursor: pointer;
}

.list {
  width: 100%;
  border-collapse: collapse;
  background: var(--panel);
  border: 1px solid var(--line);
}
.list th,
.list td {
  text-align: left;
  padding: 0.7rem 1rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  /* Never break inside a word here. A domain name has no spaces, so breaking
     anywhere puts one character on each line once the table has more columns
     than the band is wide. A wide table scrolls in .list-wrap instead, which
     keeps every value readable left to right. */
  overflow-wrap: normal;
  min-width: 6rem;
}
.list th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-ink);
}
.list tr:last-child td { border-bottom: 0; }
.list .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.list .when { white-space: nowrap; color: var(--muted-ink); font-size: 0.92rem; }
.list-wrap { overflow-x: auto; }
/* A frame that may be wider than a phone is a focusable region, so arrow keys scroll it
   where the browser would not, and its .meta line says so only while the table is wider
   than the frame (/static/scrollhint.js). The price ladders are the first. */
.scroll-hint { margin-bottom: 0.5rem; }
/* A filter above a list, on Activity and Clients: the box, Filter and Reset on
   one row at the right-hand edge of the list, the box no wider than an email
   address needs (LG, 2026-10-10). The box has no visible label, because the
   list below says what it filters; aria-label names it. Each control is its own
   column, so a row without Reset leaves no empty column at the edge, and the
   row stretches all three to the tallest, so they are one height without a
   height written down to drift. On a phone the box takes what the two buttons
   leave. */
.list-filter {
  grid-template-columns: minmax(0, 28rem);
  grid-auto-flow: column;
  grid-auto-columns: auto;
  justify-content: end;
  align-items: stretch;
  column-gap: 0.75rem;
}
.list-filter-clear {
  display: inline-flex;
  align-items: center;
  padding: 0 0.9rem;
  border-radius: 0.4rem;
  font-weight: 650;
  text-decoration: none;
}
@media (max-width: 40rem) {
  .list-filter { grid-template-columns: minmax(0, 1fr); justify-content: stretch; }
}
/* A list's title and its filter on one row, on Activity (LG, 2026-10-10). The
   form takes what the title leaves, and .list-filter right-aligns its controls
   in it, so the box ends at the list's right-hand edge as it does on Clients.
   When the two do not fit, the filter wraps under the title at full width. */
.list-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  margin-bottom: 0.75rem;
}
.list-head > * { margin: 0; }
.list-head > .list-filter { flex: 1 1 20rem; }
/* A statement's filter (T-220), on the statement and on a client's usage lines.
   Closed it is one line, Filter lines, so the lines start just under the period
   at every width; it renders open while a filter or a page size is applied, so
   what is applied is always in view. Open, the labelled controls share a row on a
   wide screen and two columns on a phone, with Filter and Reset last. No card of
   its own: it sits on whatever the lines sit on. */
.statement-filters { margin: 0 0 0.9rem; }
.statement-filters > summary {
  inline-size: fit-content;
  cursor: pointer;
  font-weight: 650;
  color: var(--teal-deep);
}
.statement-filters[open] > summary { margin-bottom: 0.6rem; }
.statement-filter {
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  align-items: end;
  column-gap: 0.75rem;
  margin: 0;
}
/* A date box draws its picker taller than a select, so the row states one height
   for both, as Query does for its own row of mixed controls. */
.statement-filter select,
.statement-filter input[type="date"],
.statement-filter-actions > * { block-size: 2.4rem; }
.statement-filter-actions button { padding-block: 0; }
.statement-filter-actions {
  display: flex;
  align-items: stretch;
  gap: 0.6rem;
}
@media (max-width: 40rem) {
  .statement-filter { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .statement-filter-actions { grid-column: 1 / -1; }
}
/* A sortable heading is the link. Only the sorted one is coloured and carries an
   arrow, and aria-sort says the same to a screen reader. */
.list th a.sort {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}
.list th a.sort:hover {
  color: var(--teal-deep);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.list th[aria-sort] { color: var(--teal-deep); }
.sort-mark { margin-inline-start: 0.3em; }
/* A pager of links, for a list that is read by GET (the statement): Previous, the
   first and last pages and two either side of this one, then Next. It sits at the
   right of .panel-foot, where the Query pager's one button sits, and the page you
   are on is the filled one. */
.page-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin-inline-start: auto;
}
.page-links a,
.page-links span {
  min-inline-size: 2.4rem;
  padding: 0.4rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  text-align: center;
  font-size: 0.9rem;
  font-weight: 650;
  text-decoration: none;
}
.page-links a {
  color: var(--teal-deep);
  background: var(--panel);
}
.page-links a:hover {
  border-color: color-mix(in srgb, var(--teal) 45%, white);
  background: color-mix(in srgb, var(--teal) 9%, white);
}
.page-links a[aria-current="page"] {
  color: #fff;
  background: var(--teal-deep);
  border-color: var(--teal-deep);
}
.page-links span[aria-disabled="true"] { color: var(--muted-ink); }
.page-links .gap {
  min-inline-size: 0;
  padding-inline: 0.2rem;
  border-color: transparent;
  color: var(--muted-ink);
}
.activity-summary { margin: 0 0 var(--section-gap); }
/* Nothing in these tables wraps: a name, an email, a header or a time is one
   line, and a second line is a <br> the template chose, such as an email under
   a name (LG, 2026-10-09: "Line-wrapping in anything but running text is never
   OK"). The columns are sized for a 32-character client name and a 40-character
   email at 1280px; narrower than that, the table scrolls in its .list-wrap.
   .one-line is the same rule for every other operational table (T-213), and a
   cell holding a sentence, such as an export's file note or a grant's reason,
   is .prose: it wraps, from a width that reads as a line of text rather than a
   column of words. */
.list.activity th,
.list.activity td,
.list.clients th,
.list.clients td,
.list.one-line th,
.list.one-line td { white-space: nowrap; }
.list.one-line td.prose {
  white-space: normal;
  min-width: 10rem;
}
.list.one-line .row-actions { flex-wrap: nowrap; }
.list.activity thead th { vertical-align: bottom; }
/* A group header names what the columns under it count, centred over them,
   with a rule so it reads as belonging to all of them. */
.list.activity thead th.group {
  text-align: center;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--line);
}
.list.activity thead tr + tr th { padding-top: 0.35rem; }
.activity-note { margin: 0 0 1rem; }
/* A client's name opens its page. In the product's link colour, not the user
   agent's blue, and underlined on hover the way the crumbs are. */
.list.activity td a {
  color: var(--teal-deep);
  font-weight: 600;
  text-decoration: none;
}
.list.activity td a:hover { text-decoration: underline; }
/* A price ladder is a list read across: one plan a row, and the plan's name is
   the row's header (decision 0069). The small capitals above name columns, so
   the name is drawn as a word rather than as one of them, and it stays in view
   while a narrow screen scrolls the figures, the way a domain name does on the
   grid. A column header wraps: held on one line, "AI Name Suggestion Requests
   at the same time" made its column wider than the screen. */
.list.ladder thead th { vertical-align: bottom; }
.list.ladder thead th.num { white-space: normal; }
.list.ladder th[scope="row"] {
  font-size: 1rem;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
  font-weight: 700;
}
.list.ladder thead th:first-child,
.list.ladder th[scope="row"] {
  position: sticky;
  inset-inline-start: 0;
  background: var(--panel);
  box-shadow: inset -1px 0 0 var(--line);
}
.list.ladder tbody tr:last-child th { border-bottom: 0; }

/* A list of domains is a grid: many columns, many rows, and a name at the left
   that every other cell is about. Three properties make it one, and all three
   are CSS, because a grid library, client-side sorting and virtual rows are
   three dependencies to solve a problem this page does not have.

   The wrapper is the scroll box. It needs a bounded height or nothing can
   scroll inside it, and a sticky header sticks to a container that never
   scrolls, which is to say it does nothing. */
.gridwrap {
  max-block-size: 70vh;
  overflow: auto;
}
/* Denser than the rest of the tables here. This one is read by scanning down a
   column rather than by reading a row, so the rows are tight and the header is
   what separates them. */
.grid th,
.grid td {
  padding: 0.32rem 0.7rem;
  vertical-align: middle;
}
/* Sticky wants a painted background, or the rows show through as they pass
   under it, and a border-bottom on a sticky cell scrolls away with the border
   rather than staying: the shadow is the rule that stays. */
.grid thead th {
  position: sticky;
  inset-block-start: 0;
  z-index: 2;
  background: var(--panel);
  box-shadow: inset 0 -1px 0 var(--line);
  border-bottom: 0;
  white-space: nowrap;
}
/* The name column stays while the rest scrolls sideways. A row of dates and
   status codes with the domain scrolled off the left is a row about nothing. */
.grid th:first-child,
.grid td:first-child {
  position: sticky;
  inset-inline-start: 0;
  background: var(--panel);
  box-shadow: inset -1px 0 0 var(--line);
}
/* The corner is sticky on both axes, so it has to outrank both. */
.grid thead th:first-child { z-index: 3; }
.grid tbody td:first-child { z-index: 1; font-weight: 600; }
/* One line per cell, clipped, with the whole value in the title. The ellipsis
   needs a block box with a width to happen in: max-inline-size on the cell
   itself is advisory under automatic table layout and a registrar name simply
   widens the column instead. This is also why overflow-wrap on a table cell
   stays normal: breaking inside a domain name put one character on each line. */
.grid .cell {
  display: block;
  max-inline-size: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.grid tbody tr:hover td { background: color-mix(in srgb, var(--teal) 5%, white); }
.grid tbody tr:hover td:first-child { background: color-mix(in srgb, var(--teal) 9%, white); }
.list tfoot th,
.list tfoot td {
  border-bottom: 0;
  font-weight: 600;
}
.list tr.muted td { color: var(--muted-ink); }
.empty { color: var(--muted-ink); }
section.empty {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
  margin-top: var(--section-gap);
  color: inherit;
}
section.empty h2 {
  margin: 0 0 0.45rem;
  font-size: 1.05rem;
}
section.empty > p {
  color: var(--muted-ink);
  margin: 0;
}
section.empty .pills {
  margin: 1rem 0 0;
}

/* A notice is a tinted box with a hairline of its own colour all round. It was a
   4px bar down the left edge, which made the one rounded thing on a card a square
   stripe beside it (T-177). The fills are unchanged, so every text colour on them
   measures what it did. */
.notice {
  background: color-mix(in srgb, var(--mark) 8%, white);
  border: 1px solid color-mix(in srgb, var(--mark) 30%, white);
  border-radius: 0.55rem;
  padding: 0.85rem 1rem;
}
.notice[role="status"] {
  background: color-mix(in srgb, var(--teal) 8%, white);
  border-color: color-mix(in srgb, var(--teal) 35%, white);
}

.query {
  display: grid;
  gap: 1rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
  /* One control height for the whole form, so a button beside an input cannot
     drift from it. Every term traces to a declaration below: 1.45 is the
     inherited line-height, 0.8rem the font-size a .query label passes to the
     box inside it, 0.5rem the input's block padding doubled, and 2px the two
     borders. Anything that has to line up with an input reads this rather than
     repeating the arithmetic.

     The font-size is written in rem rather than as an em of the inherited one,
     which is not pedantry. A custom property holding an em resolves against
     the font-size of whatever element *uses* it, and the filter buttons are
     siblings of the labels rather than children, so they never inherit the
     0.8rem. Written as 1.45em this measured 44px on the buttons against 38px
     on the boxes beside them, and the comment above claimed they could not
     drift while they were visibly drifting. */
  --control-h: calc(1.45 * 0.8rem + 0.5rem * 2 + 2px);
}
.query .row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
.query label {
  display: grid;
  gap: 0.3rem;
}
/* A label with an explanation on it needs its text and the glyph on ONE line. The
   label is a grid, so an inline trigger after the text becomes its own grid row and
   the glyph lands centred between the label and the input, which reads as a stray
   control rather than as part of the label (measured 2026-09-19 on Groups shown,
   Then group by and Band width). The span is that line. */
.query label > .label-text {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.query input,
.query select {
  text-transform: none;
  letter-spacing: 0;
  min-width: 10rem;
}
/* The boxes read the same height as the buttons, by type so the hundred and
   fifty checkboxes in the two pickers are not caught by it. A select is the
   reason this is here: Chromium ignores line-height on one, so it computed
   36px from its own metrics while the text input beside it computed 38px, and
   a row of controls two pixels out of step is the kind of thing that reads as
   unfinished without a reader being able to say why. Stating it makes the row
   one height by declaration instead of by three controls happening to agree. */
.query input[type="text"],
.query input[type="number"],
.query input[type="search"],
.query select {
  block-size: var(--control-h);
}
/* THE PRIMARY SUBMIT, ONCE. Six forms each carried this same block of seven
   declarations: the query form, Design a query, Save this query, the sign-in card,
   the staff .mint forms and the rebate quarter starter. They were identical apart from
   justify-self, so the product had one button drawn six times and a seventh form
   meant a seventh copy (LG, 2026-09-20: one way to do a control).

   :not(.infotip) is load-bearing on the two that can contain a glyph. An
   explanation glyph can sit inside a form, on a legend or a label, and a form's
   own button rule would paint it as a teal submit: measured on the grant legend,
   where the glyph came out as a filled chip (2026-09-19). The glyph is not a
   control of the form it sits in.

   justify-self keeps a submit at the start of a grid row rather than stretched
   across it. It is harmless on the two forms that are not grids.

   The fill is --teal-deep, under white at 7.47:1. It was --teal until
   2026-10-01, which is 3.72:1, below AA's 4.5:1 for a label this size, on
   every primary button in the product while the contrast test was green: it
   measured text against the page and never against a fill. Hover underlines
   the label instead of moving the fill, because the fill that clears AA is
   already the dark one, and a lighter teal on hover takes the label below AA
   at the moment someone is looking at it. Decision 0049. */
.query button:not(.infotip),
.describe-query button,
.save-query button,
.signin button,
.start-quarter button,
.qv2 .qv2-primary,
.mint button:not(.infotip) {
  justify-self: start;
  font: inherit;
  font-weight: 650;
  padding: 0.6rem 0.9rem;
  border: 0;
  border-radius: 0.4rem;
  background: var(--teal-deep);
  color: #fff;
  cursor: pointer;
  transition: transform 90ms ease-out, box-shadow 120ms ease-out;
}
.query button:not(.infotip):hover,
.describe-query button:hover,
.save-query button:hover,
.signin button:hover,
.start-quarter button:hover,
.qv2 .qv2-primary:hover,
.mint button:not(.infotip):hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
/* A press answers the finger (T-177, LG 2026-10-05: "Buttons should feel
   responsive"). It moves the control down a pixel and sinks its face, and it sets
   no colour: the fill stays --teal-deep, so the label keeps its 7.47:1 at the
   moment it is pressed (decision 0049). The transform leaves the hit area where
   it was. Reduced motion drops the transition and keeps the state. */
.query button:not(.infotip):active,
.describe-query button:active,
.save-query button:active,
.signin button:active,
.start-quarter button:active,
.qv2 .qv2-primary:active,
.mint button:not(.infotip):active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 3px rgb(0 0 0 / 22%);
}
.query button:not(.infotip):disabled:active,
.describe-query button:disabled:active,
.qv2 .qv2-primary:disabled:active,
.mint button:not(.infotip):disabled:active {
  transform: none;
  box-shadow: none;
}
/* The secondary button and the pills take the same press, without the sunk face,
   which on a white control reads as a smudge. */
.query button.secondary:active,
.pager button.secondary:active,
.signin button.secondary:active,
a.pill:active,
a.inspect:active,
.list-filter-clear:active,
.query button.rowbtn:active,
.qv2 .qv2-btn:active,
.qv2 .qv2-icon-btn:active {
  transform: translateY(1px);
  box-shadow: none;
}
.query .actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
/* One secondary language, named once. This was scoped to `.query`, which
   selects on the form's class, so the pager could not simply be handed the
   class: the attribute would have been in the markup doing nothing, which a
   test reading the class name passes and a browser does not. Broadened rather
   than copied, or there are two secondary buttons that drift. */
.list-filter-clear,
.query button.secondary,
.pager button.secondary,
.qv2 .qv2-btn,
.signin button.secondary {
  background: transparent;
  color: var(--teal-deep);
  border: 1px solid var(--teal);
}
.list-filter-clear:hover,
.query button.secondary:hover,
.pager button.secondary:hover,
.qv2 .qv2-btn:hover,
.signin button.secondary:hover {
  background: color-mix(in srgb, var(--teal) 12%, white);
  color: var(--teal-deep);
}
.output-fields,
.export-fields,
.filters,
.segments {
  margin: 0;
  padding: 0.8rem 0 0;
  border: 0;
  border-top: 1px solid var(--line);
}
.output-fields legend,
.export-fields legend,
.filters legend,
.segments legend {
  padding: 0;
  font-weight: 650;
}
.segments {
  display: grid;
  gap: 1.2rem;
}
.segment {
  display: grid;
  gap: 0.9rem;
}
.segment + .segment {
  padding-top: 0.8rem;
  border-top: 1px solid var(--line);
}
.then td:first-child {
  padding-inline-start: 1.5rem;
}
.segment-result {
  margin-top: 1.2rem;
}
/* Unsized, this inherited the user agent's 1.17em and rendered at 20.6px, larger
   than the .panel h2 above it, so a compare segment's sub-heading outranked the
   heading it sat under. It is a title on a surface, so it takes the h3 title size. */
.segment-result h3 {
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
}
.filters {
  display: grid;
  gap: 0.9rem;
}
/* The condition and the value sit beside the field, and the two icons sit at the
   bottom of the row so they line up with the inputs rather than with their
   labels. */
.filter-row {
  align-items: end;
}
/* A pair of square controls at the end of each row, so minus sits under minus
   down the list and the plus on the last row closes the column. The gap is
   smaller than the form's, because these two act on the same row and the inputs
   beside them do not. */
.rowbtns {
  display: flex;
  gap: 0.35rem;
}
/* Square, and exactly as tall as the input beside it. Both numbers come from
   --control-h, which the form derives from the inputs' own padding and border,
   so a change to the input padding moves the buttons with it instead of leaving
   a row where the icons float half a line above the boxes. */
.query button.rowbtn {
  display: grid;
  place-items: center;
  inline-size: var(--control-h);
  block-size: var(--control-h);
  padding: 0;
  background: transparent;
  color: var(--muted-ink);
  border: 1px solid var(--line);
  border-radius: 0.35rem;
}
.query button.rowbtn:hover {
  background: color-mix(in srgb, var(--teal) 8%, white);
  color: var(--teal-deep);
  border-color: var(--teal);
}
/* Filled in currentColor and sized in em, so one rule covers every glyph in
   every state: the icon takes the colour and the size of the control it is in,
   rather than needing a matching rule per button.

   FILLED, NOT STROKED, AND THIS IS THE TRAP. Phosphor's regular weight encodes
   its stroke look as a filled path, so `fill: none; stroke: currentColor;
   stroke-width: 1.6` (what this said while the set was Lucide) renders every
   glyph as an outline traced around that shape, or as nothing at all. Do not put
   stroke-width back. Set 2026-09-20; see templates/icons.html and decision
   0043 for why the set is drawn on a 16-unit grid. */
.icon {
  inline-size: 1.15em;
  block-size: 1.15em;
  fill: currentColor;
  stroke: none;
}
/* One checkbox, everywhere. LG, 2026-09-19: "The checkboxes could still look
   better, and we should establish a UI-wide standard for them." Before this every
   box on every page was the browser default with accent-color on top, so a form
   read as designed until you looked at the one control you were about to operate.

   Nothing decided that checkboxes could not be styled. AGENTS.md carried "Do not
   restyle picker checkboxes", which was a scoping note in one pull request about
   text-box typography, hardened into an imperative; it is gone (decision 0025) and
   the picker's hundred and fifty are in scope like the rest.

   Four properties, and each is a constraint rather than a preference:

   - It is still a native input. No hidden box with a styled sibling, no
     JavaScript, so the keyboard, the label click, the form reset and every
     assistive technology behave as they always did.
   - The checked state is a tick, not a colour. A teal fill alone leaves somebody
     who cannot separate the two hues reading an unchecked box. The mark is the
     icon set's own check, at the bold weight, which is Phosphor's since
     2026-09-20 (decision 0043).
   - The label is the hit area, which the markup already did by wrapping the input.
   - Keyboard focus is the teal ring the rest of the product uses.

   A stylesheet cannot prove a pixel, so the three states were read back from a
   browser at desktop and phone width. */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  inline-size: 1.05em;
  block-size: 1.05em;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0.25em;
  background-color: var(--panel);
  background-position: center;
  background-repeat: no-repeat;
  background-size: 0.78em;
  cursor: pointer;
}
input[type="checkbox"]:hover { border-color: var(--teal); }
input[type="checkbox"]:checked {
  border-color: var(--teal-deep);
  background-color: var(--teal-deep);
  /* Phosphor's bold check, the same shape and weight the copied state uses, as a
     data URI because a background-image cannot be a template. It was Lucide's
     stroked check until 2026-09-20; a filled path needs no stroke attributes,
     which is why they are gone rather than merely retuned. This box renders at
     about 16 pixels, which is the grid Phosphor is drawn on. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23ffffff'%3E%3Cpath d='M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z'/%3E%3C/svg%3E");
}
input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}
/* The Export CSV boxes are disabled until that disclosure first opens, so the
   disabled state is a real state here rather than a theoretical one. It keeps the
   tick when checked: a disabled box that loses its mark reads as unchecked. */
input[type="checkbox"]:disabled {
  border-color: var(--line);
  background-color: var(--paper);
  cursor: not-allowed;
}
input[type="checkbox"]:disabled:checked {
  border-color: var(--muted);
  background-color: var(--muted);
}

.checks {
  display: grid;
  gap: 0.4rem 1.2rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  margin-top: 0.6rem;
}
/* These are choices, not field labels, so they read as words rather than in the
   small caps the rest of the form uses. */
.checks label {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  min-width: 0;
  font-size: 1rem;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
}
/* The box itself is the one shared rule above. What is left here is only what
   this grid needs: a box that does not shrink beside a long label. */
.checks input[type="checkbox"] { min-width: 0; }

/* An explanation, opened beside the thing it explains. The trigger is an info
   glyph; the words are a [popover] panel, so they sit above the page instead of
   pushing it down, and the control can live inline next to a label rather than
   taking a line of its own. This replaced .about (a <details> whose open state
   reflowed everything below it) on 2026-09-19; see decision 0027.

   The panel is in the DOM either way. The popover API gives the click, the tap,
   Enter, Space, Escape and light dismiss for free, with no script; hover is the
   extra route and /static/infotip.js is the only thing that needs JavaScript.

   Anchored where the browser can (position-area beside the trigger), centred
   where it cannot, which is what the UA already does with a popover. Both routes
   then present the same panel in the same place in any one browser, so the
   difference is the browser's capability rather than how the person opened it. */
.infotip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: none;
  color: var(--teal-deep);
  cursor: pointer;
  vertical-align: -0.12em;
}
.infotip:hover { color: var(--teal); }

.infotip-body {
  max-inline-size: min(30rem, calc(100vw - 2rem));
  /* The UA stylesheet pins a popover with inset: 0 and margin: auto. margin: 0
     on its own leaves that inset, which fights the anchor, so the panel can
     paint in the top-left corner before it finds the glyph (LG, 2026-10-09).
     inset: auto lets position-area own the place. Hover still has to pass the
     glyph as showPopover's source, or there is no anchor to own. */
  inset: auto;
  margin: 0;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--panel);
  box-shadow: var(--shadow-2);
  font-size: 0.92rem;
  color: var(--muted-ink);
}
.infotip-body::backdrop { background: none; }
.infotip-body > p { margin: 0.5rem 0 0; }
.infotip-body > p:first-of-type { margin-top: 0; }
.infotip-title {
  margin: 0 0 0.4rem;
  font-weight: 600;
  color: var(--ink);
}
/* No anchor-name and no position-anchor on purpose. A popover opened by
   popovertarget already has that button as its implicit anchor, which is what
   position-anchor: auto resolves to, so naming an anchor would give every
   trigger on the page the same name and the panel would hang off whichever one
   came last in the document. */
@supports (position-area: block-end) {
  .infotip-body {
    position-area: block-end span-inline-end;
    position-try-fallbacks: block-start span-inline-end, block-end span-inline-start, block-start span-inline-start;
    margin: 0.35rem 0;
  }
  /* On a phone, anchoring is the wrong answer: the room from the glyph to the
     edge of a 390px screen measured 215px, which turns a four-line paragraph
     into a tall thin column. Below the breakpoint it is a sheet at the foot of
     the screen instead, the full width less a gutter, which is where a phone
     puts this kind of panel anyway. */
  @media (max-width: 40rem) {
    .infotip-body {
      position-area: none;
      inset: auto 0.75rem 0.75rem;
      max-inline-size: none;
      margin: 0;
    }
  }
}

/* Saved queries: a closed disclosure, painted only when there is one.
   Closed it is one teal line, like the field pickers. Open it borrows
   the panel surface. Do not pad the closed state: that is the empty
   card this replaced. Do not flex the whole control: that is one
   wrapping row of summary plus list. */
/* The saved-query list lives in the page head and opens over the page, not into
   it. It used to be a bare teal disclosure between the head and the first card,
   which read as a leftover rather than as a control (LG, 2026-09-20: "hanging
   around like a expandable sore thumb"). This is the dock's own menu device:
   position: absolute so opening it does not push the form down, hanging from the
   right because the head's title takes the left. Decision 0038. */
.query-head {
  display: flex;
  align-items: start;
  gap: 1rem;
}
.query-head .pagehead-title {
  flex: 1 1 auto;
  min-width: 0;
}
.notebook {
  position: relative;
  flex: 0 0 auto;
  margin: 0.45rem 0 0;
  font-size: 0.95rem;
}
.notebook > summary {
  cursor: pointer;
  font-weight: 650;
  color: var(--teal-deep);
  width: fit-content;
  white-space: nowrap;
}
.notebook > summary:hover { text-decoration: underline; }
.notebook-menu {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  z-index: 4;
  inline-size: min(26rem, calc(100vw - 2 * var(--gutter)));
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  padding: 0.85rem 1rem 1rem;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--ink) 10%, transparent);
}
.notebook-menu > .meta { margin: 0 0 0.65rem; }
/* Under 40rem the head stacks, so the menu goes static: anchored to the right of
   a full-width summary on a 390px screen it would hang off the edge, which is the
   same measurement that moved the info tips to a sheet. */
@media (max-width: 40rem) {
  .query-head { flex-direction: column; gap: 0.35rem; }
  .notebook { margin: 0; }
  .notebook-menu {
    position: static;
    inline-size: auto;
    margin-top: 0.5rem;
    box-shadow: none;
  }
}
.describe {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
  margin: 0 0 1rem;
  font-size: 0.95rem;
}
.describe h2 {
  margin: 0 0 0.5rem;
  font-size: 1.05rem;
}
.describe > .meta { margin: 0 0 0.7rem; }
.describe-query {
  display: grid;
  gap: 0.75rem;
}
.describe-query label {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-ink);
}
.describe-query textarea {
  display: block;
  width: 100%;
  min-height: 5rem;
  margin-top: 0.35rem;
  resize: vertical;
}
/* Save is a line under the answer: a name, a button, and what loading it will
   do. It replaced a disclosure at the foot of the page, which kept a result
   ending with the answer and also meant the way to keep a question you had just
   got right was a summary nobody opened. */
/* Save is one of the four named surfaces now, and it is `.field.with-action`: a
   labelled control with its submit on the same row. That class is on the form
   itself, which works because a hidden input is display: none and creates no grid
   item, so the form's only grid children are the label, the box, the button and
   the note.

   It was none of the four before 2026-09-20. It carried its own panel background,
   border and padding with no heading, so it was not a panel; its own three-column
   grid, so it was not a field; its own label treatment in `--muted-ink`, where the
   shared group label is `--teal-deep`; its own input styling; and its own copy of
   the primary submit. `save_name` was the only labelled control on the page
   outside a field wrapper. Everything in that list is now the product's own rule,
   so the only thing left here is the note spanning the row.

   No panel and no heading, deliberately: a heading would repeat the label, which
   is "Save this query as" and is held by three absence assertions, and that is the
   same defect as the client page's Client details legend. It sits on the paper as
   a thing you can do with the answer above it. */
.save-query {
  margin: 1.25rem 0 0;
}
.save-query .meta { grid-column: 1 / -1; }
.start-quarter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin: var(--section-gap) 0 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
}
.start-quarter p {
  margin: 0;
  flex: 1 1 18rem;
  color: var(--muted-ink);
}
.send-pack {
  display: block;
  margin-block-start: 0.45rem;
}
.send-pack button {
  font: inherit;
  font-size: 0.85em;
  padding: 0.25rem 0.55rem;
}
/* A link, not a form: Stop opens the confirmation that names the client and
   the quarter, and only the button there stops anything. */
.stop-run-link {
  margin-block-start: 0.45rem;
}
/* Every disclosure on the question form wears one look, and this is the only rule
   that states it: How the answer comes back, the field count and Choose the CSV
   columns are all "open this if you want to change it", and two looks for one idea
   is how a page ends up with three kinds of disclosure (decision 0039). A look
   stated per class has to be remembered for every new class, which is how the CSV
   one came to be plain ink. Each keeps its own margin, because that is where it
   sits rather than what it is. querydisclosure_test.go holds both halves. */
.query details > summary {
  cursor: pointer;
  font-weight: 650;
  color: var(--teal-deep);
  width: fit-content;
}
.query details > summary:hover { text-decoration: underline; }
/* Output stays one compact line until a person edits the result shape or opens
   the export flow. The groups then follow the Field select's order. */
.picker > summary { margin: 0.5rem 0; }
/* One disclosure for every control that already works without being touched, so
   the path from job to Run holds only the job, the input it needs, and the
   filters. Decision 0039. */
.refine {
  margin-block: 0.75rem 0;
  padding-block-start: 0.65rem;
  border-top: 1px solid var(--line);
}
.refine > summary {
  margin: 0.35rem 0 0.5rem;
}
.output-fields {
  margin-block: 0.75rem 0;
}
.output-fields .output-fixed {
  margin: 0.35rem 0 0.5rem;
}
.output-picker > summary,
.export-flow > summary {
  margin: 0.35rem 0 0.5rem;
}
/* Export is its own segment now, so the hairline that used to separate it from
   the result picker inside one fieldset separates the two fieldsets. It takes the
   shared query-fieldset reset above, which is what removes the browser's default
   fieldset border: without that it drew a box with the legend notched into its top
   edge, a surface nothing else on the page has. Decision 0041. */
.export-what {
  margin: 0.35rem 0 0;
}
.export-flow {
  margin-block-start: 0.75rem;
}
.output-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.75rem 1rem;
  margin-block: 0.5rem 0.75rem;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-1);
  background: var(--paper);
}
.output-search {
  flex: 1 1 12rem;
  min-width: 0;
}
.output-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.output-actions button {
  font: inherit;
  font-size: 0.85em;
  padding: 0.3rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-1);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
}
.output-actions button:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}
.output-groups {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem 1.25rem;
}
@media (max-width: 40rem) {
  .output-groups { grid-template-columns: 1fr; }
}
.output-group h3 {
  margin: 0 0 0.35rem;
}
.export-flow > button[type="submit"] {
  margin-block-start: 0.75rem;
}
.describe-feedback {
  margin-block: 0.5rem 0.75rem;
}
/* What the description was understood to mean: one row per control it moved. The
   same two-column shape a domain record uses for a fact, because it is the same
   object, a label and the value it holds, and a second treatment for it would be a
   second way to read a pair (LG, 2026-09-20: the form was filled and nothing said
   which controls had moved). The label takes the group-label colour rather than
   --muted, which carries no text anywhere (decision 0036). */
.describe-changes {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: 0.35rem 1rem;
  margin: 0 0 1rem;
  font-size: 0.9rem;
}
.describe-changes dt {
  margin: 0;
  font-weight: 600;
  color: var(--teal-deep);
}
.describe-changes dd {
  margin: 0;
  overflow-wrap: anywhere;
}
@media (max-width: 40rem) {
  /* Two columns of 11rem and the rest is one short label beside a wrapped value
     on a 390px screen. One column, label above value, the way the record's own
     facts list already collapses. */
  .describe-changes { grid-template-columns: 1fr; gap: 0 0; }
  .describe-changes dd { margin-bottom: 0.5rem; }
}
/* The worked examples on Query (T-170, 2026-10-03): the use case as a group label,
   the question, and the link that puts it in the form. One column, with a hairline
   above each after the first, the device the guide facts and the connect steps
   already use. Named ul rather than the bare class so it outranks .plain, which
   comes later in this sheet. */
ul.query-examples {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem;
  margin: 0;
}
.query-examples li + li {
  border-top: 1px solid var(--line);
  padding-top: 0.9rem;
}
.query-examples h3 { margin: 0 0 0.3rem; }
/* The question and its link share a row, the link at the right-hand end where
   each example's sits in the same place, and the link wraps under the question
   when the row is too narrow for both. */
.query-examples .example-ask {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}
.query-examples p { margin: 0; }
/* After an example has filled the form, the list of what it filled ends where the
   examples begin, with the same hairline that separates the examples. */
.describe-changes + .query-examples {
  border-top: 1px solid var(--line);
  padding-top: 0.9rem;
}
.notebook > .meta { margin-bottom: 0.7rem; }
.saved-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0.55rem;
}
.saved-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1rem;
}
.saved-list a { font-weight: 650; color: var(--teal-deep); }
.saved-delete { margin: 0; }
.saved-delete button {
  font: inherit;
  font-size: 0.92rem;
  background: none;
  border: 0;
  padding: 0;
  color: var(--mark);
  cursor: pointer;
  text-decoration: underline;
}
/* The job picker is radios, so the keyboard and the no-JS path work without
   help; the card look is entirely CSS over the native control. */
.jobs {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}
.jobs legend {
  padding: 0;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-ink);
}
.jobs-row,
.match-rows {
  display: grid;
  gap: 0.6rem;
  margin-top: 0.6rem;
}
/* Pinned rather than auto-fit. At the wide band auto-fit gives five columns, so
   a fourth job would sit alone on a second row, which is worse than the narrow
   band it replaced. The meaning is carried by the two .job-group blocks now
   rather than by which row a job lands in: the grid's shape said nothing when
   Discover, which returns names, sat between Breakdown and Trend, which do not
   (decision 0040). */
.jobs-row { grid-template-columns: repeat(3, 1fr); }
/* The group label is the shared 0.8rem group-label declaration, so this only
   places it. A hairline above the second group, the same device the service
   guide and the pager use, rather than a third kind of divider. */
.job-group + .job-group {
  margin-top: 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
}
/* The surface sub-title step, not the group label step. The fieldset's own legend
   is already the group label here, and two stacked uppercase labels read as a
   heading arguing with itself; a sub-title inside a surface is the role these
   actually have, and it is an existing step rather than a sixth. Sized here
   because an unsized heading takes the user agent's 1.17em, which is how a
   compare segment's h3 once rendered above the h2 over it. */
.job-group > h3 { margin: 0; font-size: 0.95rem; }
.job-group-note {
  margin: 0.2rem 0 0;
  color: var(--muted-ink);
  font-size: 0.92rem;
}
/* Nine entries in one popover, so it scrolls rather than growing past the
   viewport on a phone. Each answer is two blocks: what to hand it, then the
   thing people get wrong, which reads as a caveat rather than as more of the
   same sentence. */
.job-help {
  margin: 0.5rem 0 0;
  max-block-size: 26rem;
  overflow-y: auto;
}
.job-help dt {
  font-weight: 700;
  margin-top: 0.7rem;
}
.job-help dt:first-of-type { margin-top: 0; }
.job-help dd {
  margin: 0.15rem 0 0;
  display: grid;
  gap: 0.2rem;
}
.job-help-refuses { color: var(--muted-ink); }
.match-rows { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 46rem) {
  .jobs-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 30rem) {
  .jobs-row,
  .match-rows { grid-template-columns: 1fr; }
}
.jobs-row label,
.match-rows label {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.1rem 0.6rem;
  align-content: start;
  cursor: pointer;
  color: var(--ink);
  font-size: 1rem;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.jobs-row > label {
  border: 1px solid var(--line);
  background: var(--paper);
  padding: 0.6rem 0.75rem;
}
/* How the rows combine is a choice about the list, not a seventh and eighth job.
   With the same border and tint as the cards above, the two blocks read as one
   twelve-option question, so these carry the tint when chosen and no border at
   all. Both labels and both blurbs stay: About filters names them. */
.match-rows > label {
  border: 0;
  padding: 0.35rem 0.5rem;
}
.jobs-row input[type="radio"],
.match-rows input[type="radio"] {
  grid-row: 1 / span 2;
  align-self: start;
  margin: 0.3rem 0 0;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  accent-color: var(--teal);
}
.jobs-row .job-name,
.match-rows .job-name {
  grid-column: 2;
  font-weight: 650;
}
.jobs-row .job-blurb,
.match-rows .job-blurb {
  grid-column: 2;
  color: var(--muted-ink);
  font-size: 0.85rem;
}
.jobs-row label:has(input:checked) {
  border-color: var(--teal);
  background: color-mix(in srgb, var(--teal) 8%, white);
}
.match-rows label:has(input:checked) {
  background: color-mix(in srgb, var(--teal) 8%, white);
}
.jobs-row label:focus-within,
.match-rows label:focus-within {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}

.facts {
  display: grid;
  gap: 1rem 2rem;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  margin: 0 0 2rem;
}
.facts dt {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-ink);
}
.facts dd { margin: 0.25rem 0 0; }

/* Where you are, in the pagehead. Not an eyebrow word plus a pill floating
   above the title, which said the same thing twice and made the way back look
   like an action (LG, 2026-09-19; decision 0028). A step is a link or a plain
   label; the separator is its own aria-hidden element rather than a
   pseudo-element, so the same characters a sighted reader sees are the ones a
   screen reader is spared. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem;
  margin: 0 0 0.35rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-ink);
}
.crumbs a { color: var(--teal-deep); }
/* Hover underlines rather than lightening. --teal is 3.72:1 and this is a link
   with words in it, so going lighter on hover took the one state a reader is
   deliberately looking at below AA. Measured 2026-09-20; decision 0036. */
.crumbs a:hover { text-decoration: underline; }
/* Was --line, which is 1.27:1 on --panel: a separator nobody could see, so the
   trail read as two words jammed together. */
.crumb-sep { color: var(--muted-ink); }

/* What is true about a client, as chips. LG: "the info could be made into pills.
   The information should also agree on it's formatting." A chip is a value, so
   it is bordered rather than filled: fifteen filled pills in a grid read as
   fifteen controls. A door that is on takes a teal border and the word still
   says On, because a state must not rest on colour alone. */
/* Configuration is one titled group of segments, not one card holding eleven
   forms. The title is on the paper like a pagehead, and each segment is a panel
   with its own heading, which is exactly how the lower half of the page already
   reads (LG, 2026-09-19; decision 0030).

   .panels is the same object on customer pages, where the group is a service or
   a channel rather than the client's configuration: Intelligence and Naming on
   /docs, Intelligence MCP and Intelligence API on /console/keys (2026-09-29). One
   rule under two names, a selector list, because a copy of these three
   declarations is how a second group title would drift from the first. */
.config, .panels { margin: var(--section-gap) 0 0; }
/* A section title sits on the paper above panels, so it outranks a panel's own
   title deliberately rather than by accident: unsized it took the user agent's
   1.17em (20.6px measured), which happened to look about right and was nobody's
   decision. 1.2rem is the same size, chosen. */
.config > h2,
.panels > h2 {
  margin: 0 0 0.9rem;
  font-size: 1.2rem;
}
.config > .panel + .panel,
.panels > .panel + .panel { margin-top: var(--section-gap); }
.panel > h3 {
  margin: 0 0 0.9rem;
  font-size: 1.05rem;
}
/* A try's count of suggestions sits under the panel's own title, inside the result
   block, so .panel > h3 never reached it and it took the user agent's 1.17em, larger
   than the title above it (T-198). It is a sub-title on that surface. It follows
   .panel > h3 because the design page draws the partial as a panel's direct child,
   where the two tie on specificity and order decides. */
h3.try-count {
  margin: 0.9rem 0 0;
  font-size: 0.95rem;
}
/* Each account's title in a comparing try is the same sub-title step, for the
   same reason: the partial is answered alone (T-201). */
h3.try-set-title {
  margin: 0;
  font-size: 0.95rem;
}

.client-facts { margin: var(--section-gap) 0 0; }
.client-facts .facts { margin: 0; }
/* Thirteen facts one per row is 880px of phone before the first figure. Every
   value but one is a short chip, so two columns fit on a phone. A label is one
   line: "AI Name Suggestion" measured 160px in a 157px track at 390px, so the
   phone's gap and spacing are a little tighter. */
.client-facts .facts dt { white-space: nowrap; }
@media (max-width: 40rem) {
  .client-facts .facts {
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: 0.9rem 0.75rem;
  }
  .client-facts .facts dt { letter-spacing: 0.06em; }
}
/* The billing email is the one long fact, and it is given the room of one line
   rather than wrapped in a 12rem track (LG, 2026-10-09: emiliano+namecheap@
   domainsbot.com broke across lines, T-211). Two tracks from 48rem, which is
   three tracks or more, so the span never adds a column; a row of its own below
   that. The short facts keep the other tracks. */
.client-facts .facts > .fact-wide { grid-column: 1 / -1; }
@media (min-width: 48rem) {
  .client-facts .facts > .fact-wide { grid-column: span 2; }
}
/* A chip is one line. The wide fact's chip may still break where it is wider
   than a phone's whole row, which is the last resort that keeps the page from
   scrolling sideways, never the layout. */
.fact {
  display: inline-block;
  padding: 0.12rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  font-size: 0.85rem;
  line-height: 1.5;
  max-inline-size: 100%;
  white-space: nowrap;
}
.fact-wide .fact {
  white-space: normal;
  overflow-wrap: anywhere;
}
.fact.on { border-color: color-mix(in srgb, var(--teal) 45%, white); }
.fact-empty {
  display: inline-block;
  padding: 0.12rem 0;
  color: var(--muted-ink);
}
.fact-note {
  font-size: 0.78rem;
  color: var(--muted-ink);
}
a.fact { color: var(--teal-deep); }
a.fact:hover { border-color: color-mix(in srgb, var(--teal) 45%, white); }
.fact.current {
  background: color-mix(in srgb, var(--teal) 9%, white);
  border-color: color-mix(in srgb, var(--teal) 45%, white);
  font-weight: 600;
}
/* The period row sits in the facts block rather than under it, so it reads as
   which period these figures belong to. Its label matches a dt. */
.period-pills {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 1rem 0 0;
}
.period-pills-label {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-ink);
}
.plain {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
}
/* One client per row, each under its own name, because a person is scanning for
   the name of the one they use and then reading that one instruction. They sat
   two abreast until 2026-09-20, which made each a narrow column and made the
   pair read as a comparison between two clients rather than as two separate
   things to do (LG: "The examples should likely not be in columns but rather
   have a proper segment each.").

   The hairline is what separates them, the same device the stacked guide facts
   and the results pager already use, rather than a third kind of divider. */
.steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.9rem;
  margin: 1rem 0 0;
}
.steps .step + .step {
  border-top: 1px solid var(--line);
  padding-top: 0.9rem;
}
/* h4 since 2026-09-29: each client's step sits inside a segment whose own title
   became an h3 under the Intelligence MCP group. Same size, one level down. */
.step h4 {
  margin: 0 0 0.25rem;
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 650;
  color: var(--ink);
}
.step p { margin: 0; }
/* A step is a grid item, and a grid item does not shrink below its widest
   content, so the Cursor configuration's long line widened the page at 390px
   instead of scrolling inside its box. */
.step { min-width: 0; }
/* What a company plan needs before that client can connect. Quieter, the same
   size and ink as the notes under both steps, so it reads as a footnote to its
   own instruction rather than as a second instruction. */
.step .step-note {
  margin-top: 0.35rem;
  font-size: 0.9rem;
  color: var(--muted-ink);
}
/* The notes that apply to both clients. Quieter and smaller, so they read as
   footnotes to the two steps rather than as a third client. */
.aside {
  margin: 1.1rem 0 0;
  padding: 0.9rem 0 0;
  border-top: 1px solid var(--line);
  font-size: 0.9rem;
}
.aside li { margin: 0 0 0.4rem; color: var(--muted-ink); }
.aside li:last-child { margin-bottom: 0; }
/* A form is separated from whatever is above it as well as below it. With a
   bottom margin only, a segment that explains itself first had its prose touching
   its first label: measured 0px in Chromium on Trial, Capacity, Limits and
   Billing period on 2026-09-20, against 15px under a heading and 17px between two
   forms. Adjacent margins collapse, so stating the top end costs nothing where
   the neighbour already states one and fixes it where nobody did. */
.mint {
  display: grid;
  gap: 0.6rem;
  margin: 1rem 0;
}
/* Except first in a panel, where the panel's own padding is the gap. */
.panel > .mint:first-child,
.panel > form.mint:first-of-type:first-child { margin-top: 0; }
/* Two writes in one segment are two separate things to do, so there is a line
   between them. Without it the boundary between two forms looked like the
   boundary inside one: Subscription holds three independent writes, and 1rem
   between a submit and the next label against 0.6rem between a label and its own
   control read as one long form with buttons scattered through it (LG,
   2026-09-20: "Segment clearity and clutter").

   The hairline is the device the stacked guide facts, the connect steps and the
   results pager already use, rather than a fourth kind of divider. The space
   above the line comes from the previous form's own margin, so the two sides of
   it match. */
.panel > .mint + .mint {
  border-top: 1px solid var(--line);
  padding-top: 1rem;
}
.mint label {
  display: grid;
  /* align-content, and it is the fix for a real misalignment rather than tidiness.
     A two-column fieldset stretches both labels to the taller one's height. On a
     grid whose rows are auto-sized, the default align-content of `normal` behaves
     as `stretch` and hands that extra height out among the rows, so Client
     identifier (label, box, hint) and Name (label, box) put their boxes at
     different heights and on different baselines: the hint under one field moved
     the box beside it (LG, 2026-09-21: "the explainer for identifier makes them
     unaligned. This looks real bad"). With `start` the rows keep their own height
     and every box in a row sits directly under its own label. */
  align-content: start;
  gap: 0.3rem;
}
/* A control inside the label does not inherit the label's small caps. Without
   this a typed client name renders UPPERCASE in the box while the database holds
   what was typed, which is the same trap .query input already carries a reset
   for. text-transform is inherited and applies to the value, not just to the
   markup, so this is a correctness reset rather than a style choice. */
.mint input,
.mint select,
.mint textarea {
  min-width: 0;
  text-transform: none;
  letter-spacing: 0;
}
.mint fieldset {
  margin: 0;
  padding: 0.85rem 0 0;
  border: 0;
  border-top: 1px solid var(--line);
  display: grid;
  /* Row gap then column gap, and they are deliberately different. One value put
     0.75rem between two boxes sitting side by side, which read as cramped because
     a column gap has to separate two whole fields rather than a label from its own
     control (LG, 2026-09-21: "The Identifier and name are cramped"). The row gap
     is unchanged. */
  gap: 0.75rem 1.6rem;
}
.mint fieldset:first-of-type {
  padding-top: 0;
  border-top: 0;
}
.mint legend {
  padding: 0;
  font-weight: 650;
}
.mint label.check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
}
/* Helper text under a control, inside its own label so a screen reader reads it
   with the field rather than as loose prose after it. Lighter than the label and
   not bold, because it explains rather than names. */
.mint .hint {
  font-weight: 400;
  font-size: 0.82rem;
  color: var(--muted-ink);
  /* A sentence, so it does not inherit the label's small caps. */
  text-transform: none;
  letter-spacing: 0;
}
/* Create a client starts collapsed. The summary is the panel heading. */
details.create > summary {
  cursor: pointer;
  font-size: 1.05rem;
  font-weight: 650;
}
details.create[open] > summary {
  margin-block-end: 0.5rem;
}
details.create .err {
  color: var(--mark);
  margin: 0 0 0.8rem;
}
/* A staff form with several fields sits in two columns on the wide band and one
   on a phone, so a set of boxes cannot collapse into a single wrapping row. Each
   form is named rather than styling every .mint fieldset, because the one-control
   forms beside them read better as a single column. */
.create-client fieldset,
.bind-services fieldset,
.grant-units fieldset,
.client-data fieldset,
.mint-basic fieldset,
.limit-override fieldset,
.agreement-price fieldset {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.create-client legend,
.bind-services legend,
.grant-units legend,
.client-data legend,
.mint-basic legend,
.limit-override legend,
.agreement-price legend {
  grid-column: 1 / -1;
}
@media (max-width: 40rem) {
  .create-client fieldset,
  .bind-services fieldset,
  .grant-units fieldset,
  .client-data fieldset,
  .mint-basic fieldset,
  .limit-override fieldset,
  .agreement-price fieldset {
    grid-template-columns: 1fr;
  }
}
/* Additional requests (T-199), closed at the foot of the create form (LG,
   2026-10-10). The disclosure takes the hairline and the legend's weight that a
   fieldset in this form has, so closed it reads as one more group with a marker.
   Inside, the three choices are one per line, and the reason runs the row, so
   the two grant amounts sit side by side under them. */
.create-extra {
  padding-top: 0.85rem;
  border-top: 1px solid var(--line);
}
.create-extra > summary {
  cursor: pointer;
  font-weight: 650;
}
.create-extra[open] > summary { margin-bottom: 0.75rem; }
.create-extra label.check,
.create-extra .grant-reason {
  grid-column: 1 / -1;
}
/* The five product doors, as one compact group rather than five full-width
   lines. Scoped to this fieldset on purpose: the detail page's entitle form and
   the "Apply a downgrade now" box are plain .mint label.check and must not
   change. `.create-client .check` used to span 1 / -1, which is what stacked
   them; the labels are flex items of .choices now, so there is no grid column to
   span and that declaration is gone rather than overridden.

   The checkbox and its text stay, so the checked state never rests on colour
   alone, and the whole label is the hit area because the text is inside it. No
   JavaScript: :has() does the checked border. */
.product-choices .choices {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.product-choices label.check {
  gap: 0.45rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  background: var(--paper);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
}
.product-choices label.check:hover {
  border-color: var(--teal);
}
.product-choices label.check:has(input:checked) {
  border-color: var(--teal);
  background: #fff;
  color: var(--teal-deep);
}
/* The ring goes on the label rather than the box, so keyboard focus is visible
   at the size of the thing being operated. */
.product-choices label.check:has(input:focus-visible) {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}
/* User cap (decision 0086). The number box means something only for At most a
   number, so it shows only then, and a count of people needs a few digits, not
   the panel's width. The fact above the chips is the cap in force, so it sits
   tight to them rather than a facts block's 2rem away. */
.user-cap-now { margin-bottom: 1rem; }
.user-cap .user-cap-number { max-width: 12rem; }
.user-cap:not(:has(#users-mode-number:checked)) .user-cap-number { display: none; }
/* The actions on one table row, one or several. A wrapping list of small forms,
   each its own POST, so a narrow screen stacks them instead of pushing the table
   sideways. Four bare forms in a cell is the jammed row this exists to avoid. A
   lone action sits in one too, because the chip rules below name this list. */
.row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.row-action {
  display: inline-block;
  margin: 0;
}
/* A chip, and it wins by specificity, never by its place in the file.
   `.list form button:not(.infotip)` further down paints a table-row submit as
   bare teal text, which is right for the one action in the Keys table and wrong
   for several beside each other: "Make member Remove Revoke credentials" reads
   as one sentence.

   That rule is (0,2,2): two classes, because a `:not()` does not count itself but
   its argument does, and two elements. It reached (0,2,2) on 2026-09-19, when
   the infotip guard was added, and overtook this rule, then
   `.list .row-action button` at (0,2,1). The repair on 2026-09-21 added `td` and
   said it made (0,2,3). It made (0,2,2), because `td` is an element: a tie, lost
   on order. So these chips were bare text from 2026-09-19 until 2026-10-01
   while this comment said they were fixed.

   This is (0,3,1). The third class is the row's list of actions, and classes are
   compared before elements, so no number of elements on the other rule overtakes
   it. specificity_test.go computes every rule in this sheet that reaches these
   buttons and fails unless this family outranks it, which a comment cannot do. */
.list .row-actions .row-action button {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 650;
  padding: 0.3rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  background: var(--paper);
  color: var(--teal-deep);
  cursor: pointer;
  white-space: nowrap;
}
.list .row-actions .row-action button:hover {
  border-color: var(--teal);
  background: #fff;
}
/* A destructive action drawn as a glyph, which is the one row action that is not
   worded (LG, 2026-09-21, on removing a mail host: "put a garbage bin icon on the
   same line instead of a button next to the domain name?"). It keeps the chip's
   hit area and loses its border and its wrapping, because a bordered box around a
   bin reads as two controls. The square matters: without a padding of its own the
   control measured 20 by 28 pixels for an action that deletes something, and it is
   the accessible name rather than any visible word that says what it removes.
   It is a chip underneath, so it takes the chip's selector plus `.glyph`. */
.list .row-actions .row-action button.glyph {
  padding: 0.35rem;
  border-color: transparent;
  background: none;
  line-height: 1;
}
.list .row-actions .row-action button.glyph:hover {
  border-color: var(--line);
  background: var(--paper);
  color: var(--mark);
}
.snippet {
  overflow-x: auto;
  background: var(--paper);
  border: 1px solid var(--line);
  padding: 0.85rem 1rem;
  font-size: 0.92rem;
}
/* A chat client wants one URL and nothing else, so the URL is the artifact and
   gets the same paper panel a snippet does: it is the thing to copy rather than
   prose about the thing to copy. A URL has no spaces, so it may break inside the
   token instead of pushing the panel wider than the band. */
.connect-url {
  margin: 0.5rem 0 0;
  padding: 0.85rem 1rem;
  background: var(--paper);
  border: 1px solid var(--line);
  font-size: 0.92rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.75rem;
}
.connect-url code { overflow-wrap: anywhere; }
/* The control sits at the right-hand end of the box it copies, on both of
   these, because the box is the artifact and the button is a thing you do to
   it. Inline after the <code> the icon landed mid-line wherever the URL
   happened to stop, which reads as punctuation; parked under the <pre> it read
   as a button hanging off the corner of the panel above, and on a short
   snippet it was closer to the next heading than to the code.

   The URL is a grid so the address takes the room and the icon is pinned to
   the end. The snippet cannot use the same trick: it scrolls sideways for a
   long line and would carry the button off the edge, so .boxed is a positioned
   wrapper and the control floats over the top-right corner, padded clear of
   the text and of the scrollbar the box grows when it needs one. */
.boxed { position: relative; }
.boxed > .snippet { padding-right: 3rem; }
.boxed > .copy {
  position: absolute;
  inset-block-start: 0.5rem;
  inset-inline-end: 0.6rem;
}
.endpoint code,
.api-params code,
.api-errors code {
  font-family: ui-monospace, "SFMono-Regular", Menlo, monospace;
}
.list form { margin: 0; }
.list form button:not(.infotip) {
  font: inherit;
  font-weight: 600;
  background: none;
  border: 0;
  padding: 0;
  color: var(--teal-deep);
  cursor: pointer;
}
.notice code { overflow-wrap: anywhere; }

/* The canvas sits in the panel and grows with Query's full band. The table
   below it is the accessible answer. Height for a horizontal bar is one row
   per label so twenty TLDs do not squash. Hidden until charts.js adds
   .drawn after new Chart succeeds, so a missing library leaves no hole. */
.chart-wrap:not(.drawn) {
  display: none;
}
/* A column, so the type chooser can sit above the canvas without either of them
   needing to know the other's height. The figure keeps its definite block-size,
   which is what Chart.js measures against with maintainAspectRatio off; the canvas
   takes whatever is left as a flex item rather than height: 100%, which would have
   been 100% of the figure including the caption. min-block-size: 0 on the canvas is
   the flex rule that lets it shrink; without it a flex item refuses to go below its
   content size and the figure grows instead. */
.chart-wrap {
  margin: 0 0 1.3rem;
  position: relative;
  display: flex;
  flex-direction: column;
  block-size: min(22rem, 60vh);
  min-block-size: 12rem;
}
.chart-wrap.chart-y {
  block-size: max(12rem, calc(var(--n, 6) * 1.7rem + 3rem));
}
.chart-wrap canvas {
  display: block;
  width: 100%;
  flex: 1 1 auto;
  min-block-size: 0;
}
/* "Draw as" and its select. A row above the picture, right-aligned, because it is
   a thing you do to the chart rather than part of the answer. The label takes the
   group-label treatment the rest of the product uses for a small label beside a
   control, so this does not become a fifth way to label something. */
.chart-pick {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  margin: 0 0 0.5rem;
  flex: 0 0 auto;
}
.chart-pick label {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--teal-deep);
}
.chart-pick select {
  font: inherit;
  font-size: 0.9rem;
  padding: 0.2rem 0.4rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-1, 4px);
  background: var(--panel);
  color: var(--ink);
}

/* A lookup is one domain's record, so it reads down the page as label and
   value. Long values (a page title, a list of name servers) get the whole
   band to wrap in, which is the room the table never had. */

/* The masthead: which domain this is, how fresh our copy is, and how it stands.
   It repeats nothing, it relocates: the dates were a tenth group heading at the
   bottom of the page and the three states were spread across groups six, seven
   and eight. */
.masthead { margin: 0 0 1.6rem; }
.detail + .masthead { margin-top: 2.4rem; }
/* h2.record, not .record: the record sits inside a .panel, and `.panel h2` is a
   class plus an element, so it outranks a bare class and had been setting this
   name to 1.05rem whatever the rule below said. Naming the element here ties the
   specificity, and this block is later in the sheet. */
h2.record {
  font-family: var(--slab);
  font-weight: 500;
  font-size: 2.1rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0;
  /* A name is one token with no spaces, so it can be longer than the band. It
     scrolls with the page rather than breaking a character at a time. */
  overflow-wrap: normal;
}
/* The name is 2.1rem, so the control beside it grows with it rather than sitting
   there as a 1.5rem box against a heading twice its height. */
.record .copy {
  inline-size: 1.9rem;
  block-size: 1.9rem;
  margin-left: 0.6rem;
}
.provenance {
  margin: 0.45rem 0 0;
  color: var(--muted-ink);
  font-size: 0.9rem;
}
.availability {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.8rem 0 0;
}

/* One pill: a closed-vocabulary value, with the word always written out. Colour
   is decoration on top of the word, never instead of it, so the record reads
   with no colour vision at all. */
/* ONE CHIP ON A RECORD, AND THE RULE BELOW THIS ONE IS WHY IT TOOK TWO GOES.
   LG, 2026-09-20: "There are some stuff that should be pills but are some type of
   old badges", then again on 2026-09-21 naming WHOIS status, the name and mail
   servers, the IP addresses and the applications rows.

   The first attempt declared the silhouette once here for .pill and .tag and gave
   them different weight and fill, on the theory that a state and an item of a list
   are one family drawn two ways. It did not take, and the reason is specificity
   rather than taste: `span.pill` higher up this sheet (the dock and page pills) is
   0,1,1 against this rule's 0,1,0, so every span.pill in the product is in fact
   0.9rem, weight 700 and teal, while .tag stayed the small grey chip declared
   here. The two rules never met, so the record went on drawing two generations of
   the same idea and the comment claiming otherwise read as settled.

   So a record now draws one chip: `span.pill`, whatever the value is. A state from
   a closed vocabulary may still take a tone; an item of a list never does, because
   a row of six coloured chips is a row with no emphasis in it, and that part of the
   earlier reasoning held.

   .tag survived for the service page's suggested names until 2026-10-03, when
   those became a list one name to a line (decision 0068), so it is gone and
   nothing draws a second chip. Before adding one back, check where `span.pill`
   is declared first, or the next attempt will fail the same way. */
.pill {
  display: inline-block;
  padding: 0.16rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.85rem;
  background: var(--panel);
  font-weight: 600;
  white-space: nowrap;
}
.pill.more { border-style: dashed; color: var(--muted-ink); font-weight: 400; }
.pill.good {
  border-color: color-mix(in srgb, var(--teal) 45%, white);
  background: color-mix(in srgb, var(--teal) 9%, white);
  color: var(--teal-deep);
}
.pill.warn {
  border-color: color-mix(in srgb, var(--mark) 40%, white);
  background: color-mix(in srgb, var(--mark) 8%, white);
  color: var(--mark);
}

/* A set of values and the one control that copies all of them. The control was
   the last item of the same flex container as the values, so it landed wherever
   the final chip happened to stop and read as another value rather than as a
   control on the set (LG, 2026-09-20: "There are some stuff that should be pills
   but are some type of old badges", and the placement went with it). The row is a
   grid and the control is pinned to its end, which is the device the connect URL
   already uses. align-items keeps it at the top of a wrapped set rather than
   centred against three lines of chips, and it stops a flex control stretching to
   the width of the longest TXT record, which is what the rule it replaces was
   for. */
.facts-list dd.values {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 0.5rem;
}
/* One chip per item, where the source held a list. A count of them is worth
   more than the count field beside it, which is why those rows are muted. */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  align-items: baseline;
}
/* A chip in a record holds whatever the source held, and .pill is nowrap.
   markedo.com's keywords are one item of 186 characters, which drew a chip
   1,355px wide: 1,046px past the panel at 390px, 260px past it at desktop, and
   the whole page scrolled sideways (2026-10-04). So a chip in a record wraps
   when it alone is wider than its line, between words first. anywhere rather
   than break-word because only anywhere lets a flex item shrink below its
   longest word. In a wrapping row a chip still moves to the next line before it
   wraps. The corner is capped just above a one-line chip's half height, so a
   one-line chip is still fully round and a wrapped one keeps its text inside
   the curve. The
   dock's and page's pills are not in a record and do not change.
   record_pill_test.go computes what wins for both. */
.facts-list .pill {
  white-space: normal;
  overflow-wrap: anywhere;
  border-radius: 1.2rem;
}
.lines {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
}

/* Hex, hashes and machine ids, read a character at a time by a person checking
   one against another. This is the only place overflow-wrap may break inside a
   token: a fingerprint has no spaces and is wider than the band, and it is not
   a value anybody reads as a word. Never on a table cell. */
.facts-list dd.mono,
.facts-list .mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}

/* A row the row beside it already answered: the IDN spelling of an ASCII name,
   a length, the count of a list that is now countable as pills. Present because
   the corpus holds it, quiet because it is not why anybody looked. */
.facts-list dt.muted,
.facts-list dd.muted { color: var(--muted-ink); font-size: 0.9rem; }
/* The label loses its weight too. A demoted row in bold reads as emphasis, which
   is the opposite of the point. */
.facts-list dt.muted { font-weight: 500; }

/* An icon, not the word. A record carries thirty of these beside the values
   they belong to, and thirty grey boxes reading COPY down the page read as
   content rather than as controls on it. The accessible name is unchanged, so
   this is a change to what is drawn and not to what is announced. */
.copy {
  display: inline-grid;
  place-items: center;
  inline-size: 1.55rem;
  block-size: 1.55rem;
  margin-left: 0.4rem;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--panel);
  color: var(--muted-ink);
  font: inherit;
  cursor: pointer;
  vertical-align: middle;
}
.copy:hover { color: var(--teal-deep); border-color: var(--teal); }
/* The listener adds .copied for a moment and takes it off again. Swapping the
   glyph here rather than in the script is what lets the script stay one
   delegated listener: writing "Copied" into the button would erase the svg it
   was drawn with. Both icons ship in the button and one of them is hidden. */
.copy .tick { display: none; }
.copy.copied {
  color: var(--teal-deep);
  border-color: var(--teal);
  background: color-mix(in srgb, var(--teal) 10%, white);
}
.copy.copied .sheets { display: none; }
.copy.copied .tick { display: block; }

.detail + .detail { margin-top: 1.4rem; }
.detail h3 {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted-ink);
}
.facts-list {
  display: grid;
  grid-template-columns: minmax(8rem, 12rem) 1fr;
  gap: 0.1rem 1.5rem;
  margin: 0.5rem 0 0;
  align-items: baseline;
}
.facts-list dt {
  font-weight: 650;
  font-size: 0.95rem;
  padding: 0.35rem 0;
  border-top: 1px solid var(--line);
}
.facts-list dd {
  margin: 0;
  padding: 0.35rem 0;
  border-top: 1px solid var(--line);
  min-width: 0;
  overflow-wrap: break-word;
}
.facts-list dt:first-of-type,
.facts-list dd:first-of-type { border-top: 0; }

@media (max-width: 34rem) {
  .facts-list { grid-template-columns: 1fr; gap: 0; }
  .facts-list dd { border-top: 0; padding-top: 0; }
}
.pagehead a { color: var(--teal-deep); }
/* The staff design page (/console/design). Only what laying out samples needs:
   every sample on it is drawn by the rules above, and none of these sets a
   colour, so nothing here can move a measured contrast. A swatch is a square
   with no text on it; the token's text sample sits beside it on each
   background. Hover and focus stay live rather than frozen with a class. */
.design-swatch {
  display: inline-block;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  vertical-align: middle;
}
.design-text { font-weight: 650; }
/* A token name breaks at its hyphens, which leaves "--" alone on a line in a
   narrow column at 390px. The table scrolls in its wrap instead. Every token
   name on the page is one of these, the column headers included, and it reads
   as written: a custom property's name is case-sensitive, so the uppercase a
   table header gives its words would misname it. */
.design-token { white-space: nowrap; text-transform: none; }
.design-on-paper {
  background: var(--paper);
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-2);
}
/* A text-on-fill sample is shaped like the control it measures. Its colours are
   the rule's own, in the style attribute, so this sets none. */
.design-fill {
  display: inline-block;
  padding: 0.3rem 0.7rem;
  border-radius: 0.4rem;
}
/* A content pattern on the design page: its one line, then the sample at the
   width the page that uses it draws it, never inside a panel. */
.design-pattern { margin-top: 2rem; }
.design-pattern > p:first-child { margin: 0 0 0.75rem; }
.design-icons {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: 0.9rem 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.design-icons li {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
/* One gap between sections, from one token, applied at one end. See --section-gap
   on :root for the five measured values this replaced. Nothing here sets a bottom
   margin: two sections each carrying one is how adjacent siblings collapse into a
   number nobody chose. */
main > section { margin-top: var(--section-gap); }
.pagehead + * { margin-top: 0; }

/* A page footer. One page has one: /docs, which is the Google OAuth application
   home page and so has to carry the privacy policy. It was a bare <p><a> taking
   the user agent's blue underline, on a page otherwise made of styled pills, which
   read as something half finished rather than as a footer (LG, 2026-09-20).

   It takes the section gap like everything else, a hairline above it because that
   is how this product ends a region, and --muted-ink rather than --muted, because
   it carries text and --muted is a support colour (decision 0036). The link is
   --teal-deep and underlined: quieter than a pill, still obviously a link, and it
   leaves the site, which a pill does not usually do. */
.page-foot {
  margin-top: var(--section-gap);
  padding-top: 1rem;
  border-top: 1px solid var(--line);
  font-size: 0.85rem;
}
.page-foot p {
  margin: 0;
  color: var(--muted-ink);
}
/* An address written in a policy text is the one bare link in a panel's prose;
   without this it took the browser's blue. */
.page-foot a,
.policy a {
  color: var(--teal-deep);
  text-decoration: underline;
}
/* A policy text (decision 0062) runs the width of its card like every other
   paragraph in one (decision 0079). Its section headings are the panel's own h2,
   so the type scale has nothing new to size. */
.policy > p,
.policy > ul {
  margin: 0 0 1rem;
}
.policy > ul { padding-left: 1.2rem; }
.policy li + li { margin-top: 0.35rem; }
.policy > :last-child { margin-bottom: 0; }

@media (max-width: 40rem) {
  .meters { grid-template-columns: 1fr; }
  .top { flex-wrap: wrap; }
  /* Account hangs from the right of its pill. On a wrap that pill
     sits first on the second row, so right: 0 puts the menu off the
     left edge. Static lets the header grow. A stylesheet cannot
     prove the pixel. */
  .top nav .intelligence-menu, .top nav .account-menu, .top nav .staff-menu, .top nav .services-menu {
    position: static;
    left: 0;
    right: auto;
    box-shadow: none;
  }
  /* An open menu in flow makes the dock tall, and a 999px radius on a tall box
     is a circle drawn behind the menu. */
  .top nav:has(details[open]) { border-radius: 1rem; }
  /* The header wraps here, so the badge may take a whole row, and no more. */
  .top .who { max-inline-size: 100%; }
}

a:focus-visible,
button:focus-visible,
summary:focus-visible,
.list-wrap[tabindex]:focus-visible,
.skip:focus {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}

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

/* ---- The default page (/console/services) ----------------------------------
   Two showcases, one per service (LG, 2026-10-10, replacing a Meridian hero
   above two plainer sections): a person who lands here should see that
   Domainsbot knows its material, and the next action should be obvious. These
   rules are this page's only, with one exception: a.hero-start is also the
   filled way in on the content patterns' .feature, below, so a filled way in on
   a dark panel is declared once.
   Intelligence is the dark hero: its words, its three ways to ask and its
   actions opposite one pale curve, three facts along its foot. Naming is a
   second dark block in a different composition: its words beside its two
   engines stacked, with a disc and a ring rising from its foot. Decision 0081.

   Each block is one solid fill, never a gradient or an image, and every rule
   that colours text on one restates that fill: the contrast walk measures a
   text colour against a fill declared in the same rule, and against the paper
   otherwise, where light text fails. A filled way in is --ink on --paper,
   because white on --teal-deep is the primary submit and is declared once.
   Both share one inner edge, 3.5rem, and one headline size. */
.hero {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  grid-template-areas: "words curve" "facts facts";
  column-gap: 3rem;
  row-gap: 2.5rem;
  margin-top: 0;
  padding: 3rem 3.5rem 2.25rem;
  border-radius: var(--card-radius);
  background-color: var(--ink);
  color: #fff;
}
.hero-words { grid-area: words; align-self: center; }
.hero-label {
  margin: 0;
  color: color-mix(in srgb, var(--teal) 50%, #fff);
  background-color: var(--ink);
}
.hero h1,
.naming-hero h2 {
  margin: 0.85rem 0 0;
  font-family: var(--slab);
  font-weight: 500;
  font-size: 3rem;
  line-height: 1.05;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.hero h1 {
  color: #fff;
  background-color: var(--ink);
}
.hero-lead {
  max-inline-size: 44ch;
  margin: 1.1rem 0 0;
  font-size: 1.1rem;
  line-height: 1.55;
  color: color-mix(in srgb, #fff 80%, var(--ink));
  background-color: var(--ink);
}
.hero-state {
  margin: 1.1rem 0 0;
  color: color-mix(in srgb, #fff 80%, var(--ink));
  background-color: var(--ink);
}
/* The three ways to ask, one line of marks under the lead: enough to say that
   the same answers come in a browser, from a program and from an assistant,
   without turning the hero into the overview. */
.hero-ways {
  display: flex;
  flex-wrap: wrap;
  gap: 0.65rem 1.6rem;
  margin: 1.5rem 0 0;
}
.hero-ways > li {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
}
.hero-way-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 2.75rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid color-mix(in srgb, var(--teal) 55%, var(--ink));
  border-radius: 0.35rem;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  color: color-mix(in srgb, var(--teal) 50%, #fff);
  background-color: var(--ink);
}
.hero-way-name {
  font-size: 0.95rem;
  color: color-mix(in srgb, #fff 80%, var(--ink));
  background-color: var(--ink);
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin: 2rem 0 0;
}
.hero-start,
.hero-second {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.9rem;
  padding: 0 1.25rem;
  border-radius: 0.4rem;
  font-weight: 650;
  text-decoration: none;
}
.hero-start {
  color: var(--ink);
  background-color: var(--paper);
}
.hero-start:hover,
.hero-second:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.hero-start:active,
.hero-second:active { transform: translateY(1px); }
.hero-second {
  border: 1px solid color-mix(in srgb, #fff 40%, var(--ink));
  color: #fff;
  background-color: var(--ink);
}
.hero-second:hover { border-color: #fff; }
.hero-more {
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, #fff 45%, var(--ink));
  text-underline-offset: 0.3em;
  color: #fff;
  background-color: var(--ink);
}
.hero-more:hover { text-decoration-color: #fff; text-decoration-thickness: 2px; }
.hero a:focus-visible,
.naming-hero a:focus-visible,
.naming-hero button:focus-visible { outline-color: #fff; }
/* One shape: a ribbon lit along its outer edge, opposite the words. */
.hero-curve {
  grid-area: curve;
  align-self: center;
  justify-self: end;
  inline-size: 100%;
  max-inline-size: 27rem;
  block-size: auto;
}
.hero-curve-body { fill: color-mix(in srgb, var(--paper) 8%, var(--ink)); }
.hero-curve-edge {
  fill: none;
  stroke: color-mix(in srgb, var(--teal) 25%, var(--paper));
  stroke-width: 2.5;
  stroke-linecap: round;
}
.hero-facts {
  grid-area: facts;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2rem;
  margin: 0;
  padding-top: 1.9rem;
  border-top: 1px solid color-mix(in srgb, #fff 16%, var(--ink));
}
.hero-figure {
  display: block;
  font-family: var(--slab);
  font-weight: 500;
  font-size: 2rem;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #fff;
  background-color: var(--ink);
}
.hero-fact-label {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.92rem;
  line-height: 1.4;
  color: color-mix(in srgb, #fff 80%, var(--ink));
  background-color: var(--ink);
}

/* Naming: --ink-teal, its words on the left and its two engines stacked on the
   right, so it is not the hero's composition twice. The disc and the ring
   are the two engines, one solid and one drawn, rising from the block's foot,
   which is why the block has no bottom padding of its own: the engines carry it. */
.naming-hero {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  grid-template-rows: auto 1fr;
  grid-template-areas: "words engines" "rise engines";
  column-gap: 4.5rem;
  margin-top: 1.5rem;
  padding: 3rem 3.5rem 0;
  border-radius: var(--card-radius);
  color: #fff;
  background-color: var(--ink-teal);
}
.naming-words { grid-area: words; }
.naming-hero h2 {
  color: #fff;
  background-color: var(--ink-teal);
}
.naming-hero .headline-line { display: block; }
.naming-hero .hero-label {
  color: color-mix(in srgb, var(--teal) 40%, #fff);
  background-color: var(--ink-teal);
}
.naming-hero .hero-lead,
.naming-hero .hero-state {
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}
.naming-hero .hero-more {
  text-decoration-color: color-mix(in srgb, #fff 45%, var(--ink-teal));
  color: #fff;
  background-color: var(--ink-teal);
}
.naming-hero .hero-more:hover { text-decoration-color: #fff; }
.naming-more { margin: 1.6rem 0 0; }
.naming-rise {
  grid-area: rise;
  align-self: end;
  display: block;
  inline-size: 100%;
  max-inline-size: 18rem;
  block-size: auto;
  margin-top: 1.25rem;
}
.naming-rise-body { fill: color-mix(in srgb, var(--paper) 13%, var(--ink-teal)); }
.naming-rise-edge {
  fill: none;
  stroke: var(--paper);
  stroke-width: 2.5;
  stroke-linecap: round;
}
.engines {
  grid-area: engines;
  align-self: center;
  padding-bottom: 3rem;
}
.service-part {
  display: grid;
  grid-template-columns: 1.4rem minmax(0, 1fr);
  column-gap: 1.1rem;
  padding: 1.85rem 0;
}
.service-part:first-child { padding-top: 0; }
.service-part:last-child { padding-bottom: 0; }
.service-part + .service-part { border-top: 1px solid color-mix(in srgb, #fff 18%, var(--ink-teal)); }
.service-part > * { grid-column: 2; }
.service-part > .engine-mark {
  grid-column: 1;
  grid-row: 1 / span 4;
  inline-size: 100%;
  block-size: auto;
  margin-top: 0.35rem;
}
.engine-mark circle { fill: color-mix(in srgb, var(--teal) 40%, #fff); }
.engine-mark.drawn circle {
  fill: none;
  stroke: color-mix(in srgb, var(--teal) 40%, #fff);
  stroke-width: 2.5;
}
.service-part > h3 {
  margin: 0;
  font-family: var(--slab);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1.2;
  color: #fff;
  background-color: var(--ink-teal);
}
.service-part > p,
.service-part > .mint { margin: 0.5rem 0 0; }
.engine-lead {
  line-height: 1.55;
  text-wrap: pretty;
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}
.service-part > .engine-actions,
.service-part > .mint { margin-top: 1.2rem; }
.naming-hero .meta {
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}
/* Ask for access records a request and switches nothing on, so it is quieter
   than Open: a text control, not the filled submit. */
.service-part .mint button.secondary {
  min-block-size: 2.75rem;
  padding: 0;
  border: 0;
  font-weight: 650;
  text-decoration: underline;
  text-underline-offset: 0.25em;
  color: color-mix(in srgb, var(--teal) 40%, #fff);
  background-color: var(--ink-teal);
}
.service-part .mint button.secondary:hover { text-decoration-thickness: 2px; }
.service-part .mint button.secondary:active { box-shadow: none; }
/* A tablet keeps both compositions and gives Naming's words the width: the
   engines go side by side under them and the disc and the ring rise at the foot. */
@media (max-width: 60rem) {
  .hero { column-gap: 2rem; padding-inline: 2.5rem; }
  .hero h1,
  .naming-hero h2 { font-size: 2.5rem; }
  .hero-ways { flex-direction: column; gap: 0.6rem; }
  .naming-hero {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: "words" "engines" "rise";
    padding-inline: 2.5rem;
  }
  .engines {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-top: 2.5rem;
    padding-bottom: 0;
  }
  .service-part,
  .service-part:first-child,
  .service-part:last-child { padding: 0 2rem 0 0; }
  .service-part + .service-part {
    padding: 0 0 0 2rem;
    border-top: 0;
    border-inline-start: 1px solid color-mix(in srgb, #fff 18%, var(--ink-teal));
  }
  .naming-rise { justify-self: end; max-inline-size: 12rem; }
}
/* Under 52rem "Open AI Name Suggestion" no longer fits beside its sibling, so
   the engines stack again, and the curve gives the hero's words the width. */
@media (max-width: 52rem) {
  .hero { grid-template-columns: minmax(0, 1fr) 8rem; }
  .hero-curve { align-self: start; }
  .hero-facts { gap: 1.25rem; }
  .hero-figure { font-size: 1.65rem; }
  .engines { grid-template-columns: minmax(0, 1fr); }
  .service-part,
  .service-part:first-child { padding: 0 0 1.6rem; }
  .service-part + .service-part,
  .service-part:last-child {
    padding: 1.6rem 0 0;
    border-inline-start: 0;
    border-top: 1px solid color-mix(in srgb, #fff 18%, var(--ink-teal));
  }
}
@media (max-width: 40rem) {
  .hero {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "words" "curve" "facts";
    row-gap: 1.75rem;
    padding: 2rem 1.35rem 1.75rem;
  }
  /* "Convert the search." keeps to one line down to a 360px screen. */
  .hero h1 { font-size: clamp(1.6rem, 7.6vw, 2rem); }
  .naming-hero h2 { font-size: clamp(1.6rem, 7.6vw, 2rem); }
  .hero-lead { font-size: 1.05rem; }
  .hero-actions { gap: 0.6rem; }
  .hero-curve { max-inline-size: 11rem; }
  .hero-facts { grid-template-columns: minmax(0, 1fr); gap: 1.1rem; padding-top: 1.5rem; }
  .hero-figure { font-size: 2rem; }
  .naming-hero {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "words" "engines" "rise";
    padding: 2rem 1.35rem 0;
  }
  .engines { grid-template-columns: minmax(0, 1fr); margin-top: 2rem; }
  .service-part,
  .service-part:first-child {
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 0.7rem;
    padding: 0 0 1.6rem;
  }
  .service-part + .service-part,
  .service-part:last-child { padding: 1.6rem 0 0; }
  .service-part > * { grid-column: 1 / -1; }
  .service-part > .engine-mark {
    grid-column: 1;
    grid-row: 1;
    align-self: center;
    inline-size: 1.1rem;
    margin-top: 0;
  }
  .service-part > h3 { grid-column: 2; grid-row: 1; }
  .service-part + .service-part {
    border-inline-start: 0;
    border-top: 1px solid color-mix(in srgb, #fff 18%, var(--ink-teal));
  }
  .naming-rise { max-inline-size: 10rem; margin-top: 2rem; }
}
/* ---- End of the default page ---------------------------------------------- */

/* ---- Content patterns -------------------------------------------------------
   Four panels for a page that explains a product rather than does a job (LG,
   2026-10-10), first used on the Intelligence overview and drawn on the design
   page. Each has one purpose, and a page uses only the ones its content needs:

   .feature     opens a page: a kicker, a headline, one sentence and one way in
                on --ink (.teal: on --ink-teal), with a mark at its foot. The
                compact sibling of the default page's showcases, which are the
                full variant.
   .editorial   a few related things under one head: .editorial-items side by
                side for things a reader compares, or .editorial-rows for things
                a reader scans, each row a name, its text and an aside. On a
                light tint; .bare drops the tint and keeps the inner edge, for a
                quiet stretch between two panels; .bare.flush drops the edge too,
                for documentation under a page head. .wide-text on the rows
                gives the text the widest track, for rows of instructions.
   .evidence    the facts behind a product on --ink-teal: one dominant figure,
                the facts that make it credible beside it, a credit at its foot.
   .explainer   how something works or is counted, white with a hairline: the
                quietest of the four. .split puts its head beside stacked facts;
                .explainer-facts.pairs sets four or more facts two to a row.

   Type: a feature's headline is the 2.5rem display step, between the page title
   and the showcase headline; a panel's title is the 2rem page-title step (1.4rem
   on the explainer); an item's or a row's name is the 1.4rem name step. Under a
   2rem page head (.flush), a section head takes 1.4rem and a row's h3 1.2rem, so
   the title stays the largest heading. The design page lists them in its type
   table.

   None is a .panel or holds one, because a panel inside these is a card in a
   card. Their edge is a fill or a hairline, because they explain rather than hold
   work; a shadow is the raised card's, and a pattern that someday holds work may
   take one. Every multi-track layout here collapses at its own breakpoint, so a
   page adds no media query of its own. Each paragraph runs the whole track it
   sits in (decision 0079), and the grid gives the track a comfortable width.
   Every rule that colours text on a dark fill restates the fill, as the default
   page's showcases do, because the contrast walk measures a text colour against
   the fill in its own rule. */
.kicker { margin: 0; }

/* A link that belongs to the text above it, on a light surface. The block
   padding makes the target about 30px tall without moving the text. */
.text-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.5rem;
  margin: 0.6rem 0 0;
}
.text-links a {
  display: inline-block;
  padding-block: 0.3rem;
  font-weight: 650;
  color: var(--teal-deep);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}
.text-links a:hover { text-decoration-thickness: 2px; }
/* Every such link takes the reader on to a page that continues the thought, so
   each ends in an arrow (one rule since 2026-10-11; it was an a.onward modifier
   that half the links had). The arrow has empty alternative text, so a screen
   reader reads the link alone. */
.text-links a::after {
  content: "\2192" / "";
  margin-inline-start: 0.35em;
  text-decoration: none;
  display: inline-block;
}

/* The feature: the words in the wider track, the mark standing on the foot of
   the narrower one and running off its edge. One way in, the default page's
   filled a.hero-start. Its headline is a step of its own, between the page
   title and the showcase headline, because it opens a page without being the
   default page's pitch. */
.feature {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 3fr);
  column-gap: 3rem;
  overflow: hidden;
  margin-top: 0;
  padding: 2.75rem 3rem;
  border-radius: var(--card-radius);
  color: #fff;
  background-color: var(--ink);
}
.feature-words { align-self: center; }
.feature .kicker {
  color: color-mix(in srgb, var(--teal) 50%, #fff);
  background-color: var(--ink);
}
.feature-title {
  margin: 0.75rem 0 0;
  font-family: var(--slab);
  font-weight: 500;
  font-size: 2.5rem;
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
  color: #fff;
  background-color: var(--ink);
}
.feature-title .headline-line { display: block; }
.feature-lead {
  margin: 1rem 0 0;
  font-size: 1.1rem;
  line-height: 1.55;
  text-wrap: pretty;
  color: color-mix(in srgb, #fff 80%, var(--ink));
  background-color: var(--ink);
}
.feature-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin: 1.75rem 0 0;
}
.feature a:focus-visible,
.evidence a:focus-visible { outline-color: #fff; }
/* Rings from the corner, one lit, with a few points found on it: an index
   reaching outwards. Drawn in the showcase curve's two tones. */
.feature-mark {
  align-self: end;
  justify-self: end;
  inline-size: calc(100% + 3rem);
  max-inline-size: 26rem;
  block-size: auto;
  margin: 1.5rem -3rem -2.75rem 0;
}
.feature-mark circle {
  fill: none;
  stroke: color-mix(in srgb, var(--paper) 16%, var(--ink));
  stroke-width: 1.5;
}
.feature-mark .feature-mark-lit {
  stroke: color-mix(in srgb, var(--teal) 25%, var(--paper));
  stroke-width: 2.5;
}
.feature-mark .feature-mark-found {
  fill: color-mix(in srgb, var(--teal) 25%, var(--paper));
  stroke: none;
}
.feature-mark .feature-mark-seen {
  fill: color-mix(in srgb, var(--paper) 32%, var(--ink));
  stroke: none;
}
.feature-mark .feature-mark-disc {
  fill: color-mix(in srgb, var(--paper) 10%, var(--ink));
  stroke: none;
}
/* The feature on --ink-teal, for a service whose showcase on the default page is
   that teal (Naming, 2026-10-11). Same composition; every rule that colours text
   restates the fill, and the mark takes the showcase's two tones. */
.feature.teal { background-color: var(--ink-teal); }
.feature.teal .kicker {
  color: color-mix(in srgb, var(--teal) 40%, #fff);
  background-color: var(--ink-teal);
}
.feature.teal .feature-title {
  color: #fff;
  background-color: var(--ink-teal);
}
.feature.teal .feature-lead {
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}
.feature.teal .feature-mark circle { stroke: color-mix(in srgb, var(--paper) 18%, var(--ink-teal)); }
.feature.teal .feature-mark .feature-mark-disc {
  fill: color-mix(in srgb, var(--paper) 13%, var(--ink-teal));
  stroke: none;
}
.feature.teal .feature-mark .feature-mark-lit { stroke: var(--paper); }

/* The editorial panel. The tint is --teal at 7% in --paper, #e3ebe7, and
   nothing on it is lighter than --teal-deep, which is 6.1:1 there by the same
   arithmetic as the contrast test. --rule is the hairline for this surface. */
.editorial {
  --rule: color-mix(in srgb, var(--teal) 18%, var(--paper));
  margin-top: 1.5rem;
  padding: 2.5rem;
  border-radius: var(--card-radius);
  background-color: color-mix(in srgb, var(--teal) 7%, var(--paper));
}
.editorial.bare {
  --rule: color-mix(in srgb, var(--ink) 14%, var(--paper));
  padding-block: 1.5rem;
  background-color: transparent;
}
/* Bare and flush: the rows start at the page head's edge rather than at the
   inner edge of the panels around them, for a page whose head is on the paper
   and whose sections are not panels (the documentation, 2026-10-12). Inset,
   its rows stood 2.5rem in from the title above them. */
.editorial.bare.flush { padding-inline: 0; }
/* Under a page title on the paper the section heads step down to the
   explainer's size, so the title stays the largest heading on the page: a 2rem
   head under a 2rem title read as the page's real title. */
.editorial.flush > .editorial-head > h2 { font-size: 1.4rem; font-weight: 600; letter-spacing: -0.01em; }
/* Over wide-text rows the head takes their tracks, so the heading stands over
   the names and its paragraph over the text it introduces. */
.editorial.flush > .editorial-head:has(+ .editorial-rows.wide-text) {
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
  column-gap: 2.5rem;
  align-items: baseline;
}
.editorial-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 4rem;
  align-items: end;
}
.editorial-head > h2 {
  margin: 0;
  font-family: var(--slab);
  font-weight: 500;
  font-size: 2rem;
  line-height: 1.15;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.editorial-head .headline-line { display: block; }
.editorial-head > p {
  margin: 0;
  line-height: 1.55;
  text-wrap: pretty;
}
/* Items side by side, as many as there are, with a hairline between. */
.editorial-items {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  margin-top: 2.25rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
}
.editorial-item { padding-inline: 2rem; }
.editorial-item:first-child { padding-inline-start: 0; }
.editorial-item:last-child { padding-inline-end: 0; }
.editorial-item + .editorial-item { border-inline-start: 1px solid var(--rule); }
.editorial-item > p {
  margin: 0.5rem 0 0;
  line-height: 1.55;
  text-wrap: pretty;
}
.editorial-item > .way-mark { margin: 0; }
.editorial-item > .text-links,
.editorial-row > .text-links { margin-top: 0.6rem; }
.editorial-item > h3,
.editorial-row > h3 {
  margin: 0.9rem 0 0;
  font-family: var(--slab);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.editorial-row > h3 { margin-top: 0; }
/* The channel's name, the mark the default page puts beside each way to ask. */
.way-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 2.75rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid color-mix(in srgb, var(--teal) 45%, var(--paper));
  border-radius: 0.35rem;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  color: var(--teal-deep);
}
/* An item's shape, where the item has one rather than a channel's name: the
   default page draws Naming's two services as a solid disc and a drawn ring. */
.editorial-item > .item-mark {
  display: block;
  inline-size: 1.4rem;
  block-size: 1.4rem;
}
.item-mark circle { fill: var(--teal-deep); }
.item-mark.drawn circle {
  fill: none;
  stroke: var(--teal-deep);
  stroke-width: 2.5;
}
/* An item's one-sentence proposition, between its name and its text. */
.editorial-item > .editorial-lead {
  margin-top: 0.6rem;
  font-size: 1.1rem;
  font-weight: 600;
  line-height: 1.45;
}
/* What an item says in place of its action when this account cannot take it.
   Quieter by size, not by colour: --muted-ink is about 4.3:1 on the tint. */
.editorial-item > .editorial-state {
  margin-top: 0.75rem;
  font-size: 0.95rem;
}
/* Rows under the head, read left to right: a name, what it is about, and an
   aside (an example and its link, a figure, a note). Hairlines separate the
   rows; no row has a surface of its own. A row with no aside leaves that track
   empty rather than stretching its text across it. (Until 2026-10-10 the rows
   stood beside a sticky head, which left a tall empty column; LG: "unnecessary
   empty space and an awkward reading experience".) */
.editorial-rows {
  margin-top: 2rem;
  border-top: 1px solid var(--rule);
}
/* Rows with no head above them start at the section's own edge. */
.editorial-rows:first-child { margin-top: 0; }
.editorial-row {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 4fr) minmax(0, 4fr);
  column-gap: 2.5rem;
  row-gap: 0.5rem;
  align-items: baseline;
  padding-block: 1.4rem;
}
.editorial-row + .editorial-row { border-top: 1px solid var(--rule); }
.editorial-row > p {
  margin: 0;
  line-height: 1.6;
  text-wrap: pretty;
}
.editorial-aside > * { margin: 0; }
.editorial-aside > * + * { margin-top: 0.35rem; }
/* Rows whose text is an instruction rather than a sentence: documentation
   (2026-10-12). The text takes the widest track, about 80 characters at 1440px,
   and the name and the aside keep narrow ones; across the whole band a
   paragraph would run past 120. div.editorial-name holds a channel's mark
   above the name, and div.editorial-text holds paragraphs, a list or code. The
   aside holds the row's notes, a step smaller, and its links. Under 68rem the
   aside goes under the text; under 52rem the row is one column. */
.editorial-rows.wide-text > .editorial-row {
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
}
.editorial-name > .way-mark { margin: 0 0 0.75rem; }
/* The name is an h2 where the rows are the page's sections (the documentation
   index), at the name step, and an h3 under a section head, a step down, so the
   row reads as part of the section above it. */
.editorial-name > h2,
.editorial-name > h3 {
  margin: 0;
  font-family: var(--slab);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.editorial-name > h3 { font-size: 1.2rem; }
.editorial-text > * { margin: 0; }
.editorial-text > * + * { margin-top: 0.75rem; }
.editorial-text > p,
.editorial-text li {
  line-height: 1.6;
  text-wrap: pretty;
}
.editorial-text > ol { padding-inline-start: 1.4rem; }
.editorial-text li + li { margin-top: 0.3rem; }
/* Code sits on the paper with a hairline, never on a tint, and scrolls inside
   its own box rather than widening the page. */
.editorial-text > pre {
  overflow-x: auto;
  padding: 0.8rem 1rem;
  border: 1px solid var(--rule);
  border-radius: 0.4rem;
  font-size: 0.95rem;
  line-height: 1.55;
}
.editorial-rows.wide-text .editorial-aside > p:not(.text-links) {
  font-size: 0.95rem;
  line-height: 1.55;
  text-wrap: pretty;
}
/* In the narrow aside the links are a list, one to a line, rather than a row
   that breaks wherever the track runs out. */
.editorial-rows.wide-text .editorial-aside > .text-links {
  flex-direction: column;
  align-items: flex-start;
}
.editorial-example q {
  font-family: var(--slab);
  font-size: 1.05rem;
  line-height: 1.45;
}
/* The evidence panel: the label and the figure in the narrower track, the facts
   beside them from the top, the credit across the foot. */
.evidence {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
  grid-template-rows: auto 1fr auto;
  grid-template-areas: "label facts" "figure facts" "foot foot";
  column-gap: 4rem;
  margin-top: 1.5rem;
  padding: 3rem;
  border-radius: var(--card-radius);
  color: #fff;
  background-color: var(--ink-teal);
}
.evidence > .kicker {
  grid-area: label;
  color: color-mix(in srgb, var(--teal) 40%, #fff);
  background-color: var(--ink-teal);
}
.evidence-figure {
  grid-area: figure;
  margin: 1.1rem 0 0;
}
.evidence-number {
  display: block;
  font-family: var(--slab);
  font-weight: 500;
  font-size: 5.5rem;
  line-height: 0.95;
  letter-spacing: -0.045em;
  color: #fff;
  background-color: var(--ink-teal);
}
.evidence-caption {
  display: block;
  margin-top: 0.9rem;
  font-size: 1.1rem;
  line-height: 1.5;
  text-wrap: pretty;
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}
.evidence-facts {
  grid-area: facts;
  margin: 0;
}
.evidence-facts > div + div {
  margin-top: 1.35rem;
  padding-top: 1.35rem;
  border-top: 1px solid color-mix(in srgb, #fff 18%, var(--ink-teal));
}
.evidence-facts dt {
  font-weight: 650;
  font-size: 1.05rem;
  color: #fff;
  background-color: var(--ink-teal);
}
.evidence-facts dd {
  margin: 0.35rem 0 0;
  line-height: 1.55;
  text-wrap: pretty;
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}
.evidence-foot {
  grid-area: foot;
  margin: 2.25rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid color-mix(in srgb, #fff 18%, var(--ink-teal));
  font-size: 0.95rem;
  color: color-mix(in srgb, #fff 80%, var(--ink-teal));
  background-color: var(--ink-teal);
}

/* The explainer: its head, the two things being told apart with "or" standing
   on the hairline between them, then the short facts under both. */
.explainer {
  margin-top: 1.5rem;
  padding: 2rem 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background-color: var(--panel);
}
.explainer-head > h2 {
  margin: 0;
  font-family: var(--slab);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.explainer-head > p {
  margin: 0.4rem 0 0;
  line-height: 1.55;
  color: var(--muted-ink);
}
.explainer-compare {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  column-gap: 2rem;
  margin-top: 1.6rem;
}
.explainer-item > h3 {
  margin: 0.3rem 0 0;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.3;
}
.explainer-item > p:last-child {
  margin: 0.4rem 0 0;
  line-height: 1.55;
  text-wrap: pretty;
}
.explainer-or {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-ink);
}
.explainer-or::before,
.explainer-or::after {
  content: "";
  flex: 1;
  inline-size: 1px;
  background-color: var(--line);
}
.explainer-facts {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  column-gap: 2rem;
  margin: 1.75rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  font-size: 0.92rem;
}
.explainer-facts dt { font-weight: 700; }
.explainer-facts dd {
  margin: 0.25rem 0 0;
  line-height: 1.5;
  color: var(--muted-ink);
}
/* Facts two to a row, for four or more of a sentence or two each (the counting
   on /docs/intelligence, 2026-10-12): four abreast would be narrow ragged
   blocks, and stacked across the panel their lines would run past 120
   characters. They are the rules a reader came for, so they read in --ink. */
.explainer-facts.pairs {
  grid-auto-flow: row;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.25rem 2.5rem;
  font-size: 0.95rem;
}
.explainer-facts.pairs dd { color: var(--ink); }
.explainer > .text-links { margin-top: 1rem; }
/* The head beside its facts, stacked with a hairline between them, for an
   explanation whose facts are a few sentences each rather than a line (a
   service's guide, 2026-10-11). Side by side they would be narrow ragged
   blocks (decision 0037); stacked across the whole panel their lines would run
   past 120 characters. Two equal tracks hold about 75 at 1440px. The head's
   paragraph and the facts are the explanation itself here, not footnotes, so
   both read in --ink. The two sides are about the same height, so neither
   leaves an empty column. */
.explainer.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 3rem;
  align-items: start;
}
.explainer.split > .explainer-head > p:not(.text-links) {
  margin-top: 0.6rem;
  color: var(--ink);
}
.explainer.split > .explainer-head > .text-links { margin-top: 0.75rem; }
.explainer.split > .explainer-facts {
  grid-auto-flow: row;
  margin: 0;
  padding-top: 0;
  border-top: 0;
  font-size: 0.95rem;
}
.explainer.split > .explainer-facts dd { color: var(--ink); }
.explainer.split > .explainer-facts > div + div {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
/* An explainer among raised panels (a service page) takes the content gap on
   both sides, so the explanation stands apart from the tools around it. */
.explainer + .panel { margin-top: 1.5rem; }

/* A row's three tracks need about 68rem of screen before its text track holds a
   comfortable line (at 1024px it held about 35 characters), so below that the
   name goes across the top, with the text and the aside side by side under it. */
@media (max-width: 68rem) {
  .editorial-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 2rem; }
  .editorial-row > h3 { grid-column: 1 / -1; }
  .editorial-rows.wide-text > .editorial-row,
  .editorial.flush > .editorial-head:has(+ .editorial-rows.wide-text) { grid-template-columns: minmax(0, 1fr) minmax(0, 3fr); }
  .editorial.flush > .editorial-head:has(+ .editorial-rows.wide-text) { column-gap: 2rem; }
  .editorial.flush > .editorial-head:has(+ .editorial-rows.wide-text) > p { margin-top: 0; }
  .editorial-rows.wide-text .editorial-aside > .text-links { flex-direction: row; }
  .editorial-rows.wide-text .editorial-aside { grid-column: 2; margin-top: 0.35rem; }
}
/* A tablet keeps the feature's mark and stacks every head over what it heads:
   two tracks of prose at this width are each too narrow. */
@media (max-width: 60rem) {
  .feature { column-gap: 2rem; padding: 2.25rem 2.5rem; }
  .feature-mark { inline-size: calc(100% + 2.5rem); margin: 1.5rem -2.5rem -2.25rem 0; }
  .feature-title { font-size: 2.2rem; }
  .editorial { padding: 2.25rem 2.5rem; }
  .editorial.bare { padding-block: 1.25rem; }
  .editorial-head { grid-template-columns: minmax(0, 1fr); }
  .editorial-head > p { margin-top: 0.75rem; }
  .editorial-rows { margin-top: 1.5rem; }
  .evidence {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: "label" "figure" "facts" "foot";
    padding: 2.5rem;
  }
  .evidence-facts { margin-top: 2rem; }
  .explainer.split { grid-template-columns: minmax(0, 1fr); }
  .explainer.split > .explainer-facts { margin-top: 1.25rem; }
}
/* Under 52rem items and comparisons stack, and the feature's mark goes under
   its words. */
@media (max-width: 52rem) {
  .feature { grid-template-columns: minmax(0, 1fr); }
  .feature-mark { max-inline-size: 18rem; }
  .editorial-items { grid-auto-flow: row; }
  .editorial-item,
  .editorial-item:first-child,
  .editorial-item:last-child { padding-inline: 0; }
  .editorial-item + .editorial-item {
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    border-inline-start: 0;
    border-top: 1px solid var(--rule);
  }
  .explainer-compare { grid-template-columns: minmax(0, 1fr); row-gap: 0.9rem; }
  .explainer-or { flex-direction: row; }
  .explainer-or::before,
  .explainer-or::after { inline-size: auto; block-size: 1px; }
  .explainer-facts { grid-auto-flow: row; row-gap: 1rem; }
  .explainer-facts.pairs { grid-template-columns: minmax(0, 1fr); }
  .editorial-rows.wide-text > .editorial-row,
  .editorial.flush > .editorial-head:has(+ .editorial-rows.wide-text) { grid-template-columns: minmax(0, 1fr); }
  .editorial.flush > .editorial-head:has(+ .editorial-rows.wide-text) > p { margin-top: 0.5rem; }
  .editorial-rows.wide-text .editorial-aside { grid-column: auto; }
}
@media (max-width: 40rem) {
  .feature { padding: 2rem 1.35rem; }
  /* The showcase headlines' phone size, at which "Convert the search." keeps to
     one line down to a 360px screen. */
  .feature-title { font-size: clamp(1.6rem, 7.6vw, 2rem); }
  .feature-lead { font-size: 1.05rem; }
  .feature-mark {
    inline-size: calc(100% + 1.35rem);
    max-inline-size: 13rem;
    margin: 1.25rem -1.35rem -2rem 0;
  }
  .editorial { padding: 1.75rem 1.35rem; }
  .editorial.bare { padding-block: 1rem; }
  .editorial-head > h2 { font-size: 1.6rem; }
  .editorial-row { grid-template-columns: minmax(0, 1fr); padding-block: 1.2rem; }
  .editorial-aside { margin-top: 0.35rem; }
  .evidence { padding: 2rem 1.35rem; }
  .evidence-number { font-size: 3.75rem; }
  .explainer { padding: 1.5rem 1.35rem; }
}
/* ---- End of the content patterns ------------------------------------------- */

/* ===== Intelligence UI (/query), the page called Query V2 in the code =====
   Every selector here starts at .qv2, the page's <main>, so nothing reaches Query
   Classic's rules. The controls and buttons join the shared rules above rather than copying
   them; what follows is layout and the few objects only this page has. */
.qv2 [x-cloak] { display: none !important; }
.qv2 {
  /* One control height, from the 0.95rem the boxes here use, for the same reason
     .query derives its own: a button beside a box cannot drift from it. */
  --qv2-control-h: calc(1.45 * 0.95rem + 0.5rem * 2 + 2px);
}
.qv2 .qv2-sr {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.qv2 .qv2-nowrap { white-space: nowrap; }

/* The head: the title at the left and the saved queries at the right, on one line. */
.qv2-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.qv2-head h1 { margin: 0; font-size: 2rem; }
.qv2-title {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.qv2-head-actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.qv2 .qv2-quiet-link {
  color: var(--teal-deep);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  white-space: nowrap;
}
.qv2 .qv2-quiet-link:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.qv2 .qv2-count {
  display: inline-block;
  min-inline-size: 1.5em;
  margin-inline-start: 0.35rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--teal) 12%, white);
  color: var(--teal-deep);
  font-size: 0.8rem;
  font-weight: 700;
  text-align: center;
}
/* What the page says about a run, quietest first. A note is one line with no box,
   for a routine confirmation. The last answer is a white strip with a way back to
   it. A state is the same white box with a title, for a receipt with no answer to
   show or an answer the form has moved away from. A failure is that box on the
   alert tint .notice uses. The shared .notice is left as it is: only the boot
   notes on this page still use it, and its links take Meridian's colour here. */
.qv2 .notice a,
.qv2 .qv2-note a,
.qv2 .qv2-state a:not(.qv2-btn) {
  color: var(--teal-deep);
  font-weight: 600;
  text-underline-offset: 0.2em;
}
.qv2 a.qv2-btn { text-decoration: none; }
.qv2 .qv2-note {
  margin: 0;
  color: var(--ink);
  font-size: 0.95rem;
  line-height: 1.5;
}
.qv2 .qv2-note::before {
  content: "";
  display: inline-block;
  inline-size: 0.45rem;
  block-size: 0.45rem;
  margin-inline-end: 0.55rem;
  border-radius: 50%;
  background: var(--teal);
  vertical-align: 0.12em;
}
/* The inline half of --card-pad, so a state's words start where a card's do. */
.qv2 { --qv2-inset: 1.5rem; }
.qv2-state,
.qv2-recent {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1.25rem;
  flex-wrap: wrap;
  padding: 0.7rem var(--qv2-inset);
  border: 1px solid var(--line);
  border-radius: 0.55rem;
  background: var(--panel);
  color: var(--ink);
}
.qv2 > .qv2-note,
.qv2 > .qv2-state,
.qv2 > .qv2-recent { margin: 0 0 1rem; }
.qv2-state.is-warn {
  border-color: color-mix(in srgb, var(--mark) 30%, white);
  background: color-mix(in srgb, var(--mark) 8%, white);
  color: var(--ink);
}
.qv2-state-text,
.qv2-recent-text {
  flex: 1 1 24rem;
  min-inline-size: 0;
}
.qv2-state-text p { margin: 0; line-height: 1.5; }
.qv2-state-text p + p { margin-top: 0.1rem; }
.qv2 .qv2-state-title {
  color: var(--teal-deep);
  font-weight: 650;
}
.qv2 .qv2-state.is-warn .qv2-state-title { color: var(--ink); }
.qv2 .qv2-recent .qv2-kicker { margin: 0; }
.qv2-recent-line { margin: 0.1rem 0 0; line-height: 1.45; }
.qv2-recent-sentence { font-weight: 600; }
/* The two short sentences after the query go to the next line together. */
.qv2-recent-meta {
  color: var(--muted-ink);
  font-size: 0.88rem;
  white-space: nowrap;
}
/* An onward link, in the words of .text-links on the content pages: underlined,
   with an arrow that a screen reader skips. */
.qv2 .qv2-onward {
  display: inline-block;
  padding-block: 0.3rem;
  color: var(--teal-deep);
  font-size: 0.95rem;
  font-weight: 650;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  white-space: nowrap;
}
.qv2 .qv2-onward:hover { text-decoration-thickness: 2px; }
.qv2 .qv2-onward::after {
  content: "\2192" / "";
  display: inline-block;
  margin-inline-start: 0.35em;
  text-decoration: none;
}

/* Buttons. The primary and the secondary are the shared rules; these are sizes and
   the quiet text button. */
.qv2 .qv2-primary,
.qv2 .qv2-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 650;
  min-block-size: var(--qv2-control-h);
  padding: 0.45rem 0.95rem;
  border-radius: 0.4rem;
  cursor: pointer;
  white-space: nowrap;
}
.qv2 .qv2-btn { transition: transform 90ms ease-out; }
.qv2 .qv2-btn .icon,
.qv2 .qv2-add .icon { inline-size: 1em; block-size: 1em; }
.qv2 .qv2-quiet-btn,
.qv2 .qv2-add {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.1rem;
  border: 0;
  background: transparent;
  color: var(--teal-deep);
  font: inherit;
  font-size: 0.92rem;
  font-weight: 650;
  cursor: pointer;
  white-space: nowrap;
}
.qv2 .qv2-quiet-btn:hover,
.qv2 .qv2-add:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.qv2 .qv2-add { justify-self: start; margin-top: 0.5rem; }
.qv2 .qv2-danger { color: var(--mark); }
.qv2 .qv2-icon-btn {
  display: grid;
  place-items: center;
  inline-size: var(--qv2-control-h);
  block-size: var(--qv2-control-h);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  background: var(--panel);
  color: var(--muted-ink);
  cursor: pointer;
}
.qv2 .qv2-icon-btn:hover {
  border-color: var(--teal);
  background: color-mix(in srgb, var(--teal) 8%, white);
  color: var(--teal-deep);
}
.qv2 .qv2-icon-btn:disabled { visibility: hidden; }
.qv2 button:focus-visible,
.qv2 a:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}
.qv2 .qv2-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.6rem;
  flex-wrap: wrap;
}

/* The card that holds the question. One surface; inside it, sections are divided by
   hairlines, never by cards of their own. */
.qv2-card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--shadow-2);
  padding: var(--card-pad);
}

.qv2-ran {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.5rem;
  flex-wrap: wrap;
}
.qv2-ran-text { min-inline-size: 0; flex: 1 1 24rem; }
.qv2 .qv2-kicker { margin: 0 0 0.2rem; }
.qv2-ran-sentence,
.qv2-review-sentence {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 550;
  line-height: 1.45;
}

/* The four ways in, as one segmented row, and the editor switch at its end. */
.qv2-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  flex-wrap: wrap;
}
.qv2-tasks,
.qv2-mode,
.qv2 .qv2-seg {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 0.55rem;
  background: var(--paper);
}
.qv2 .qv2-task,
.qv2 .qv2-mode-btn,
.qv2 .qv2-seg-btn,
.qv2 .qv2-seg-item > span {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 0.9rem;
  border: 1px solid transparent;
  border-radius: 0.4rem;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 550;
  white-space: nowrap;
  cursor: pointer;
}
.qv2 .qv2-mode-btn { padding: 0.35rem 0.75rem; font-size: 0.88rem; }
/* Inline rather than flex, so the space before a label's tail survives. */
.qv2 .qv2-task { display: inline-block; }
.qv2 .qv2-task:hover,
.qv2 .qv2-mode-btn:hover,
.qv2 .qv2-seg-btn:hover,
.qv2 .qv2-seg-item:hover > span { background: color-mix(in srgb, var(--teal) 7%, white); }
.qv2 .qv2-task[aria-selected="true"],
.qv2 .qv2-mode-btn[aria-pressed="true"],
.qv2 .qv2-seg-btn[aria-pressed="true"],
.qv2 .qv2-seg-item > input:checked + span {
  background: var(--panel);
  border-color: color-mix(in srgb, var(--teal) 40%, var(--line));
  color: var(--teal-deep);
  font-weight: 650;
  box-shadow: var(--shadow-1);
}
.qv2 .qv2-seg-item { position: relative; }
.qv2 .qv2-seg-item > input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.qv2 .qv2-seg-item > input:focus-visible + span {
  outline: 2px solid var(--teal);
  outline-offset: 1px;
}
.qv2 .qv2-seg-sm .qv2-seg-item > span,
.qv2 .qv2-seg-sm .qv2-seg-btn { padding: 0.3rem 0.65rem; font-size: 0.88rem; }
.qv2-kind {
  display: grid;
  gap: 0.35rem;
  justify-items: start;
}
.qv2-hint {
  margin: 0.6rem 0 0;
  color: var(--muted-ink);
  font-size: 0.92rem;
}

/* Three worked examples, one line each: a quiet way in, not a panel. */
.qv2-examples {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.5rem 1.25rem;
  margin: 0.9rem 0 0;
  padding: 0.75rem 0 0;
  border-top: 1px solid var(--line);
}
.qv2-examples a {
  display: grid;
  gap: 0.1rem;
  color: var(--ink);
  text-decoration: none;
}
.qv2-examples a:hover .qv2-example-q { text-decoration: underline; text-underline-offset: 0.2em; }
.qv2-example-case {
  color: var(--muted-ink);
  font-size: 0.85rem;
}
.qv2-example-q { color: var(--teal-deep); font-size: 0.95rem; font-weight: 600; line-height: 1.4; }

/* Describe a question. */
.qv2-describe {
  display: grid;
  gap: 0.75rem;
  margin-top: 1rem;
}
.qv2-describe textarea {
  inline-size: 100%;
  min-block-size: 5.5rem;
  resize: vertical;
  font-size: 1rem;
  line-height: 1.5;
}
.qv2-describe-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  flex-wrap: wrap;
}
.qv2-describe-foot .meta { flex: 1 1 20rem; }

/* What the query holds, read back after a description, an example or a load. */
.qv2-review {
  margin-top: 1rem;
  padding: 1rem 1.15rem;
  border: 1px solid color-mix(in srgb, var(--teal) 30%, white);
  border-radius: 0.6rem;
  background: color-mix(in srgb, var(--teal) 5%, white);
  color: var(--ink);
}
.qv2-facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.6rem 1.25rem;
  margin: 0.8rem 0 0;
}
.qv2-facts dt {
  color: var(--muted-ink);
  font-size: 0.8rem;
  font-weight: 650;
}
.qv2-facts dd {
  margin: 0.1rem 0 0;
  font-weight: 550;
  overflow-wrap: anywhere;
}
.qv2-review-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.9rem;
}

/* The form: sections divided by hairlines, then the run bar. */
.qv2-form { margin-top: 0.25rem; }
.qv2-elsewhere {
  display: grid;
  gap: 0.5rem;
  justify-items: start;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.qv2-elsewhere p { margin: 0; }
.qv2-sec {
  display: grid;
  gap: 0.75rem;
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
}
.qv2-sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  flex-wrap: wrap;
}
.qv2 .qv2-sec-title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 650;
}
.qv2 .qv2-sec-title .label-text,
.qv2 .qv2-label .label-text {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.qv2-sec-head .meta { margin: 0; }
.qv2-jobs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
}
.qv2-jobgroup { display: grid; gap: 0.35rem; }
.qv2-blurb {
  margin: 0;
  color: var(--muted-ink);
  font-size: 0.95rem;
}
.qv2 .qv2-label { display: block; }
.qv2-lookup {
  display: grid;
  gap: 0.35rem;
  max-inline-size: 36rem;
}
.qv2-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.9rem 1.25rem;
  align-items: start;
}
.qv2-control {
  display: grid;
  gap: 0.35rem;
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.qv2-control-wide { grid-column: 1 / -1; }
.qv2-control > .qv2-seg { justify-self: start; }
.qv2-control .meta { font-size: 0.85rem; }
.qv2-more:empty { display: none; }

/* Boxes, selects and the field button are one height and one face. */
.qv2 .qv2-input,
.qv2 .qv2-select,
.qv2 .qv2-picker-btn {
  inline-size: 100%;
  min-inline-size: 0;
  block-size: var(--qv2-control-h);
  font-size: 0.95rem;
}
.qv2 .qv2-input-num { max-inline-size: 10rem; }
.qv2 .qv2-input-lg {
  --qv2-control-h: calc(1.45 * 1.15rem + 0.6rem * 2 + 2px);
  font-size: 1.15rem;
  padding: 0.6rem 0.8rem;
}
.qv2 .qv2-picker-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-2);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 500;
  text-align: start;
  cursor: pointer;
}
.qv2 .qv2-picker-btn > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.qv2 .qv2-picker-btn::after {
  content: "";
  flex: none;
  inline-size: 0.45rem;
  block-size: 0.45rem;
  margin-inline-end: 0.15rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-0.12rem) rotate(45deg);
}
.qv2 .qv2-picker-btn:hover { border-color: color-mix(in srgb, var(--ink) 28%, var(--line)); }
.qv2 .qv2-picker-btn.is-empty { color: var(--muted-ink); }

/* One condition per row: field, condition, value, then the control that takes the
   row away, all one height. */
.qv2-rows { display: grid; gap: 0.5rem; }
.qv2-row {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.15fr) minmax(0, 1.3fr) var(--qv2-control-h);
  gap: 0.5rem;
  align-items: center;
}
/* The condition cell is the NOT switch and the condition, side by side; the value cell
   is one box, two ends of a range, or a number of days. */
.qv2-cond,
.qv2-val,
.qv2-range,
.qv2-days {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-inline-size: 0;
}
.qv2-cond > .qv2-select,
.qv2-val > .qv2-input,
.qv2-range > .qv2-input { flex: 1 1 0; }
.qv2-range,
.qv2-days { flex: 1 1 auto; }
.qv2-days > .qv2-input { flex: 0 1 7rem; }
.qv2-range-and,
.qv2-days-unit { color: var(--muted-ink); font-size: 0.85rem; white-space: nowrap; }
.qv2 .qv2-not {
  flex: 0 0 auto;
  block-size: var(--qv2-control-h);
  padding: 0 0.55rem;
  border: 1px solid var(--line);
  border-radius: 0.4rem;
  background: transparent;
  color: var(--muted-ink);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
}
.qv2 .qv2-not[aria-pressed="true"] {
  border-color: var(--teal-deep);
  background: color-mix(in srgb, var(--teal) 12%, white);
  color: var(--teal-deep);
}
.qv2 .qv2-not:disabled { opacity: 0.45; cursor: default; }
.qv2 .qv2-not:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }
/* On a tablet one line is too narrow for two dates or "contains all of the words":
   the field and the condition share the first line, the value and remove the second. */
@media (max-width: 60rem) and (min-width: 40.01rem) {
  .qv2-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--qv2-control-h); }
  .qv2-row > .qv2-cond { grid-column: 2 / -1; }
  .qv2-row > .qv2-val { grid-column: 1 / 3; }
}
.qv2-pops { display: grid; gap: 0.9rem; }
.qv2-pop {
  display: grid;
  gap: 0.6rem;
  margin: 0;
  padding: 0.9rem 1rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
}
.qv2-pop-legend {
  padding: 0 0.35rem;
  color: var(--teal-deep);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.qv2-pop-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}
.qv2 .qv2-pop-head > .qv2-input { flex: 1 1 12rem; inline-size: auto; }
.qv2-checkrow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  padding-top: 0.2rem;
}
.qv2-checkrow label,
.qv2-inline-check {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.95rem;
  white-space: nowrap;
}

/* Columns: one line saying how many, and the control that opens the picker. */
.qv2-output-line {
  display: flex;
  align-items: baseline;
  gap: 0.4rem 1rem;
  flex-wrap: wrap;
  margin: 0;
}
.qv2-output-count { font-weight: 600; }

/* Run query sits at the foot of the question and stays on screen while a long one
   scrolls, beside the sentence saying what it will ask. */
.qv2-runbar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.25rem;
  flex-wrap: wrap;
  margin-top: 1.1rem;
  padding: 0.9rem 0 0.15rem;
  border-top: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
}
.qv2-runbar-read {
  flex: 1 1 22rem;
  min-inline-size: 0;
}
.qv2-runbar-text {
  margin: 0;
  line-height: 1.45;
}
/* A form Run cannot ask says why under the sentence, and the sentence goes quiet. */
.qv2-runbar-why {
  margin: 0.2rem 0 0;
  color: var(--mark);
  font-size: 0.92rem;
  font-weight: 600;
}
.qv2-runbar-text.is-blocked .qv2-runbar-sentence { color: var(--muted-ink); }
.qv2-runbar-text .qv2-kicker { display: inline; margin: 0 0.35rem 0 0; }
.qv2-runbar-sentence { font-weight: 550; }

/* The answer, under the question: its title and the kept line on one baseline,
   and Export at the end of the row when the answer lists domains. */
.qv2-results { margin-top: calc(var(--section-gap) * 1.5); }
.qv2-results-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  flex-wrap: wrap;
}
.qv2-results-heading {
  display: flex;
  align-items: baseline;
  gap: 0.2rem 1rem;
  flex-wrap: wrap;
  flex: 1 1 24rem;
  min-inline-size: 0;
}
.qv2-results-heading .meta { margin: 0; }
/* Download this answer, then Export all matching domains: the free copy of what is
   on screen before the separate request for every match. The menu drops under its
   control at the end of the row, and on a phone opens in the flow instead, so it
   pushes the answer down rather than covering it. */
.qv2-results-tools {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem 0.6rem;
  flex-wrap: wrap;
}
.qv2-download-wrap { position: relative; }
.qv2 .qv2-download > summary { list-style: none; }
.qv2 .qv2-download > summary::-webkit-details-marker { display: none; }
.qv2 .qv2-download[open] > summary { background: color-mix(in srgb, var(--teal) 12%, white); }
.qv2-download-menu {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + 0.35rem);
  z-index: 20;
  inline-size: min(23rem, calc(100vw - 2.5rem));
  padding: 0.85rem 0.9rem 0.6rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  box-shadow: 0 10px 28px rgb(35 77 80 / 0.14);
}
.qv2 .qv2-download-lead {
  margin: 0 0 0.45rem;
  font-size: 0.86rem;
  line-height: 1.4;
  color: var(--muted-ink);
}
.qv2 .qv2-download-edited { color: var(--ink); font-weight: 600; }
.qv2-download-list { margin: 0.35rem -0.4rem 0; }
.qv2 .qv2-download-link {
  display: grid;
  grid-template-columns: 1.6rem 1fr;
  align-items: start;
  gap: 0.55rem;
  padding: 0.5rem 0.4rem;
  border-radius: 0.4rem;
  color: var(--ink);
  text-decoration: none;
}
.qv2 .qv2-download-link .icon {
  inline-size: 1.5rem;
  block-size: 1.5rem;
  color: var(--teal-deep);
}
.qv2 .qv2-download-link:hover { background: color-mix(in srgb, var(--teal) 8%, white); }
.qv2 .qv2-download-link:hover .qv2-download-label { text-decoration: underline; text-underline-offset: 0.2em; }
.qv2 .qv2-download-link:focus-visible { outline: 2px solid var(--teal-deep); outline-offset: 1px; }
.qv2-download-text { display: grid; gap: 0.05rem; min-inline-size: 0; }
.qv2 .qv2-download-label { font-weight: 650; color: var(--teal-deep); }
.qv2 .qv2-download-blurb { font-size: 0.85rem; color: var(--muted-ink); line-height: 1.35; }
.qv2 .qv2-download-gone { margin: 0; align-self: center; }
@media (max-width: 40rem) {
  .qv2-results-tools { flex: 1 1 100%; }
  .qv2-download-wrap { flex: 1 1 100%; }
  .qv2-download-menu {
    position: static;
    inline-size: auto;
    margin-top: 0.45rem;
    box-shadow: none;
  }
}
.qv2 .qv2-results-title {
  margin: 0;
  font-size: 1.2rem;
  font-weight: 650;
}
.qv2 .qv2-results-for { margin: 0.3rem 0 0; }
.qv2-results > .qv2-stale { margin: 0.75rem 0 0; }
.qv2-results.is-stale .list-wrap,
.qv2-results.is-stale .chart-wrap { opacity: 0.72; }
.qv2 .qv2-th-sort {
  display: inline;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}
.qv2 .qv2-th-sort:hover,
.qv2 .qv2-th-sort:focus-visible { color: var(--teal-deep); }
.qv2 .list th[aria-sort]:not([aria-sort="none"]) { color: var(--teal-deep); }
/* The heading chosen for the next run, which these rows are not sorted by yet. */
.qv2 .qv2-th-sort.is-next { color: var(--teal-deep); text-decoration-style: dashed; }
/* A condition the question cannot use, said beside the conditions before Run. */
.qv2 .qv2-cannot { margin: 0.5rem 0 0; }
.qv2 .qv2-cannot::before { background: var(--mark); }
/* Previous page sits at the right with Next page, as one pair. */
.qv2 .qv2-pager-back { margin-inline-start: auto; }
.qv2 .qv2-pager-back + .pager { margin-inline-start: 0; }

/* Folded behind the query it ran, the builder shows nothing but its dialogs, which
   stay where they are in the form so their fields still post with it. */
.qv2-build.is-folded > :not(.qv2-form),
.qv2-build.is-folded > .qv2-form > :not(dialog) { display: none; }
.qv2-after {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 1rem 2rem;
  align-items: start;
  margin-top: var(--section-gap);
  padding: var(--card-pad);
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--panel);
}
.qv2-save { display: grid; gap: 0.4rem; }
.qv2-inline {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem;
}
.qv2-api > summary {
  color: var(--teal-deep);
  font-weight: 650;
  cursor: pointer;
}
.qv2-api > p { margin: 0.6rem 0; }

/* Dialogs: the field chooser, the two column pickers and the saved queries. */
.qv2 .qv2-dialog {
  inline-size: min(56rem, calc(100vw - 2rem));
  max-inline-size: none;
  block-size: min(46rem, calc(100dvh - 2rem));
  max-block-size: none;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--shadow-4);
}
.qv2 .qv2-dialog[open] {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  align-content: stretch;
  overflow: hidden;
}
.qv2 .qv2-dialog::backdrop { background: rgb(35 38 42 / 45%); }
.qv2 .qv2-dialog > * { margin: 0; padding-inline: 1.4rem; }
.qv2-dialog-head {
  display: grid;
  gap: 0.25rem;
  padding-block: 1.15rem 0.75rem;
  border-bottom: 1px solid var(--line);
}
.qv2 .qv2-dialog-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 650;
}
.qv2-dialog-foot {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  padding-block: 0.85rem;
  border-top: 1px solid var(--line);
}
.qv2 .qv2-chooser { inline-size: min(44rem, calc(100vw - 2rem)); }
.qv2 .qv2-chooser > .qv2-chooser-search {
  inline-size: auto;
  margin: 0.9rem 1.4rem 0.25rem;
}
.qv2-chooser-list {
  overflow-y: auto;
  padding-block: 0.5rem 1rem;
}
.qv2-chooser-group { margin-top: 0.75rem; }
.qv2-chooser-options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 2px 0.5rem;
}
.qv2 .qv2-option {
  display: block;
  inline-size: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 0.4rem;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  text-align: start;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.qv2 .qv2-option:hover { background: color-mix(in srgb, var(--teal) 8%, white); }
.qv2 .qv2-option[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--teal) 40%, var(--line));
  background: color-mix(in srgb, var(--teal) 12%, white);
  color: var(--teal-deep);
  font-weight: 650;
}

/* A column picker: tools, then the categories beside the checkboxes, the second
   scrolling inside the dialog. */
.qv2-export-sentence { margin: 0.2rem 0 0; font-weight: 550; }
.qv2-export-about {
  display: grid;
  gap: 0.35rem;
  padding-block: 0.85rem 0.4rem;
}
.qv2-export-about p { margin: 0; color: var(--muted-ink); font-size: 0.92rem; line-height: 1.5; }
.qv2 .qv2-export > .qv2-output-line { padding-block: 0.4rem 0.2rem; }
.qv2 .qv2-columns[open] { grid-template-rows: auto minmax(0, 1fr) auto; }
.qv2 .qv2-export[open] { grid-template-rows: auto auto auto minmax(0, 1fr) auto; }
.qv2-picker {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  min-block-size: 0;
}
.qv2-picker-tools {
  display: flex;
  align-items: center;
  gap: 0.6rem 1rem;
  flex-wrap: wrap;
  padding-block: 0.8rem;
}
.qv2-picker-tools > input[type="search"] { flex: 1 1 14rem; inline-size: auto; }
.qv2-picker-body {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  gap: 1.25rem;
  min-block-size: 0;
  border-top: 1px solid var(--line);
}
.qv2-picker-nav {
  display: grid;
  align-content: start;
  gap: 1px;
  overflow-y: auto;
  padding-block: 0.6rem;
}
.qv2-picker-nav a {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.3rem 0.5rem;
  border-radius: 0.35rem;
  color: var(--ink);
  font-size: 0.92rem;
  text-decoration: none;
  white-space: nowrap;
}
.qv2-picker-nav a:hover { background: color-mix(in srgb, var(--teal) 8%, white); }
.qv2-picker-nav .qv2-count { background: transparent; font-weight: 600; color: var(--muted-ink); }
.qv2-picker-groups {
  overflow-y: auto;
  padding-block: 0.4rem 1rem;
}
.qv2-picker-group + .qv2-picker-group { margin-top: 1rem; }
.qv2 .qv2-picker-title { margin: 0.4rem 0 0; }
.qv2-picker-group .checks { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); margin-top: 0.4rem; }
.qv2-picker-group .checks label { font-size: 0.95rem; }

/* Saved queries open as a drawer from the right. */
.qv2 .qv2-drawer {
  inline-size: min(30rem, 100vw);
  block-size: 100dvh;
  max-block-size: 100dvh;
  margin: 0 0 0 auto;
  border-radius: var(--card-radius) 0 0 var(--card-radius);
}
.qv2 .qv2-drawer > input[type="search"] { inline-size: auto; margin: 0.9rem 1.4rem 0.4rem; }
.qv2-saved-list {
  overflow-y: auto;
  padding-block: 0.25rem 1rem;
}
.qv2-saved-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-block: 0.65rem;
  border-bottom: 1px solid var(--line);
}
.qv2-saved-text { display: grid; gap: 0.1rem; min-inline-size: 0; }
.qv2-saved-text a {
  color: var(--teal-deep);
  font-weight: 650;
  text-decoration: none;
  overflow-wrap: anywhere;
}
.qv2-saved-text a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.qv2-saved-delete { margin: 0; flex: none; }

@media (max-width: 56rem) {
  .qv2-examples { grid-template-columns: 1fr; }
  .qv2-after { grid-template-columns: 1fr; }
  .qv2-picker-body { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); gap: 0; }
  .qv2-picker-nav {
    display: flex;
    overflow-x: auto;
    gap: 0.25rem;
    padding-block: 0.5rem;
  }
}
@media (max-width: 40rem) {
  .qv2 { --qv2-inset: 1.15rem; }
  .qv2-tasks {
    display: grid;
    grid-template-columns: 1fr 1fr;
    inline-size: 100%;
  }
  .qv2 .qv2-task { text-align: center; padding-inline: 0.5rem; font-size: 0.9rem; }
  .qv2 .qv2-task-tail,
  .qv2 .qv2-tail { display: none; }
  /* Three lines: the field; NOT, the condition and remove; then the value across the
     whole width, so two dates of a range are read whole and "contains all of the
     words" is not cut. */
  .qv2-row { grid-template-columns: minmax(0, 1fr) var(--qv2-control-h); }
  .qv2-row > .qv2-picker-btn { grid-column: 1 / -1; grid-row: 1; }
  .qv2-row > .qv2-cond { grid-column: 1; grid-row: 2; }
  .qv2-row > .qv2-icon-btn { grid-column: 2; grid-row: 2; }
  .qv2-row > .qv2-val { grid-column: 1 / -1; grid-row: 3; }
  /* Each condition takes two lines here, so a hairline keeps its two together. */
  .qv2-rows { gap: 0.6rem; }
  .qv2-row + .qv2-row { padding-top: 0.6rem; border-top: 1px solid var(--line); }
  /* Two-way and five-way choices fill the width in even parts rather than
     wrapping to a ragged second line. */
  .qv2-sec-head > .qv2-seg {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    inline-size: 100%;
  }
  .qv2-sec-head > .qv2-seg .qv2-seg-item > span { justify-content: center; inline-size: 100%; }
  .qv2-kind { justify-items: stretch; }
  .qv2-analyses > .qv2-seg-btn { flex: 1 1 auto; justify-content: center; }
  .qv2-recent-meta { display: block; white-space: normal; }
  /* A phone scrolls one column to the end, and a bar holding the sentence and two
     buttons would cover a sixth of the screen, so here it stays in place. Run
     query takes the width; the quieter actions sit under it. */
  .qv2-runbar { position: static; padding-bottom: 0; }
  .qv2-runbar .qv2-actions { inline-size: 100%; justify-content: center; }
  .qv2-runbar .qv2-actions > .qv2-primary { flex: 1 1 100%; justify-content: center; order: -1; }
  /* Describe's two steps take the same shape: the press that comes next is the
     widest, and the edits beside it share the line under it. */
  .qv2-describe-foot > [name="intent"] { flex: 1 1 100%; justify-content: center; }
  .qv2-review-foot .qv2-actions { inline-size: 100%; }
  .qv2-review-foot .qv2-actions > * { flex: 1 1 auto; justify-content: center; }
  .qv2-review-foot .qv2-actions > .qv2-primary { flex-basis: 100%; order: -1; }
  /* On a phone the cells give up some of their padding and the floor every table
     keeps, and the values step down to the size of a phone's other dense text, so
     more of an answer shows before its frame scrolls. */
  .qv2 .qv2-results .list th,
  .qv2 .qv2-results .list td { padding-inline: 0.5rem; min-width: 4.5rem; }
  .qv2 .qv2-results .list td { font-size: 0.9rem; }
  .qv2 .qv2-dialog,
  .qv2 .qv2-drawer {
    inline-size: 100vw;
    max-inline-size: 100vw;
    block-size: 100dvh;
    max-block-size: 100dvh;
    margin: 0;
    border-radius: 0;
  }
  .qv2 .qv2-dialog > * { padding-inline: 1rem; }
  /* The export dialog says what the file holds before its column list, which on a
     phone left the list two rows tall. Here it scrolls as one column, with its
     two buttons held at the foot. */
  .qv2 .qv2-export[open] { display: block; overflow-y: auto; }
  .qv2 .qv2-export .qv2-picker-groups { overflow-y: visible; }
  .qv2 .qv2-export .qv2-dialog-foot {
    position: sticky;
    bottom: 0;
    background: var(--panel);
  }
  .qv2 .qv2-chooser > .qv2-chooser-search,
  .qv2 .qv2-drawer > input[type="search"] { margin-inline: 1rem; }
  .qv2-chooser-options { grid-template-columns: 1fr; }
}

/* Until the script has started, the builder keeps its place but is not shown, so it
   never sits on the page as controls that do nothing. If it has not started after a
   few seconds the note says so; with no script at all, <noscript> says it at once. */
.qv2:not(.qv2-ready) .qv2-card { visibility: hidden; }
.qv2 .qv2-boot-late { display: none; }
.qv2:not(.qv2-ready) .qv2-boot-late {
  display: block;
  margin-bottom: var(--section-gap);
  animation: qv2-late 0s 5s both;
}
@keyframes qv2-late {
  from { visibility: hidden; position: absolute; }
  to { visibility: visible; position: static; }
}
.qv2 .qv2-boot-failed { margin-bottom: var(--section-gap); }

/* A box that cannot be sent says why, under the box. */
.qv2 .qv2-field-error {
  margin: 0.15rem 0 0;
  color: var(--mark);
  font-size: 0.92rem;
  font-weight: 600;
}
.qv2 .qv2-input[aria-invalid="true"] { border-color: var(--mark); }

/* While the form is being read back the sentence goes quiet and says so, because
   until the answer comes it may be describing the question before the last edit. */
.qv2-runbar-text.is-pending .qv2-runbar-sentence,
.qv2-runbar-text.is-error .qv2-runbar-sentence { color: var(--muted-ink); }

.qv2 .qv2-loaded { margin: 1rem 0 0; }

.qv2-examples-wrap {
  margin-top: 1.1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
}
.qv2-examples-wrap .qv2-examples {
  margin: 0.35rem 0 0;
  padding: 0;
  border: 0;
}
.qv2 .qv2-facts-sm { margin-top: 0.5rem; gap: 0.4rem 1rem; }
.qv2-facts-sm dd { font-size: 0.95rem; }

.qv2-saved-delete {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* The one line for a request on its way, fixed at the foot of the window so it is
   seen wherever the press was made. */
.qv2 .qv2-pending {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  z-index: 20;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  max-inline-size: min(40rem, calc(100vw - 2rem));
  margin: 0;
  padding: 0.65rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--panel);
  color: var(--ink);
  box-shadow: var(--shadow-3);
  transform: translateX(-50%);
  font-size: 0.95rem;
  line-height: 1.4;
}
.qv2 .qv2-pending .qv2-quiet-btn { flex: none; }
.qv2-turn {
  flex: none;
  inline-size: 0.95rem;
  block-size: 0.95rem;
  border: 2px solid var(--teal-deep);
  border-inline-end-color: transparent;
  border-radius: 50%;
  animation: try-turn 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .qv2-turn { animation: none; }
}

/* On the design page the pending line is drawn where it is shown, not fixed to the
   window, and the run bar does not stick. */
.qv2.qv2-design .qv2-pending {
  position: static;
  transform: none;
  margin-top: 1rem;
}
.qv2.qv2-design .qv2-runbar { position: static; }
/* A segmented choice is as wide as its choices, wherever it sits. */
.qv2-sec > .qv2-seg { justify-self: start; }

/* Said only when a result table is wider than its frame (markWideTables). */
.qv2 .qv2-scroll-hint { margin: 0 0 0.5rem; font-size: 0.88rem; }
.qv2-export-sentence.is-pending { color: var(--muted-ink); }
