/* FullClass help center — modern documentation layout */

/* Inter, served from our own origin rather than Google Fonts, which sent every
   reader's IP address to Google (GDPR). Latin and Latin Extended, split the way
   Google split them so a page with no extended characters loads only the first.
   SIL Open Font License, see /static/fonts/LICENSE-Inter.txt. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/inter-latin-variable.woff2") format("woff2");
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212,
    U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/inter-latin-ext-variable.woff2") format("woff2");
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
    U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: #f8fafc;
  --panel: #ffffff;
  --panel-2: #f1f5f9;
  --ink: #0b1220;
  --ink-2: #1e293b;
  --muted: #64748b;
  /* Decorative only: separators and idle borders. It is 2.5:1 on the page
     background, so nothing anybody has to read may use it. The uppercase
     labels that used to did so at 12px, the smallest type here. */
  --muted-2: #94a3b8;
  /* The label color those moved to: 4.6:1, which 12px uppercase needs. */
  --label: #5b6879;
  --line: #e2e8f0;
  --line-2: #cbd5e1;
  /* The app's violet (static/css/input.css --color-primary-*), so the help
     center reads as part of FullClass rather than a site of its own. */
  --brand: #7c3aed;
  --brand-soft: #f5f3ff;
  --brand-ink: #5b21b6;
  --accent: #a78bfa;
  /* Three callouts, three jobs, three palettes that say which is which.
     A note is a neutral remark, so it is grey: it was green, on the same
     --ok-* success palette a confirmation uses, which told every reader that
     an ordinary aside had gone well. Green is now spent only where something
     genuinely succeeded, and this file no longer has such a place. */
  --note-bg: #f1f5f9;
  --note-border: #94a3b8;
  --note-ink: #334155;
  --tip-bg: #eff6ff;
  --tip-border: #60a5fa;
  --tip-ink: #1e40af;
  --warn-bg: #fffbeb;
  --warn-border: #f59e0b;
  --warn-ink: #92400e;
  /* Tokens for what used to be literals in the rules below. Every one of them
     had to become a variable before a dark theme could exist, because a rule
     that names its own color cannot be re-themed. The hero keeps its literals
     on purpose: it is a dark gradient with white text in either theme. */
  --code-bg: #0b1220;
  --code-ink: #e2e8f0;
  --line-brand: #ddd6fe;
  --row-hover: rgba(241, 245, 249, 0.55);
  --done-ink: #6b7280;
  --done-rule: rgba(0, 0, 0, 0.25);

  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04);
  --shadow-md:
    0 4px 14px -4px rgba(15, 23, 42, 0.08),
    0 2px 6px -2px rgba(15, 23, 42, 0.04);
  --radius: 10px;
  --radius-lg: 14px;
  --sidebar-w: 280px;

  /* Three widths, because an article is not one column of one width.
     --content-max is the reading measure: prose, lists and callouts stop
     there (about 80 characters at the base size) rather than running the
     width of the page. --wide-max is what tables, card grids and code
     blocks get, since those want room and are scanned, not read. --toc-w is
     the "On this page" rail, which only appears when there is space for it
     beside the article. */
  --content-max: 640px;
  --wide-max: 900px;
  --toc-w: 232px;
  --shell-max: 1180px;
}

/* ---------- Dark ----------
   The admin has a full dark theme and the help center had none, so an operator
   working in a dark admin clicked Help and got a white page in a new tab.

   The shell puts the operator's own choice on <html> as data-theme-pref, read
   from the same fc_theme cookie the admin writes, so the two agree rather than
   the help center guessing. "system" is left to the media query below, which
   is why there is no theme script here and no flash of the wrong theme: the
   answer is in the markup before the first paint either way.

   Only the tokens change. Not one rule below this block knows which theme it
   is in, which is the reason every literal color had to be tokenized first. */
:root[data-theme-pref="dark"] {
  --bg: #0f141c;
  --panel: #161c26;
  --panel-2: #1e2632;
  --ink: #e8edf5;
  --ink-2: #c7d2e0;
  --muted: #97a4b8;
  --muted-2: #5c6a7d;
  --label: #9aa8bc;
  --line: #26303d;
  --line-2: #384453;
  --brand: #c4b5fd;
  --brand-soft: #241b3d;
  --brand-ink: #ddd6fe;
  --accent: #a78bfa;

  --note-bg: #1b232e;
  --note-border: #64748b;
  --note-ink: #cbd5e1;
  --tip-bg: #152238;
  --tip-border: #3b82f6;
  --tip-ink: #bfdbfe;
  --warn-bg: #2a2113;
  --warn-border: #d97706;
  --warn-ink: #fcd34d;

  --code-bg: #0a0e15;
  --code-ink: #dbe4f0;
  --line-brand: #4a3a78;
  --row-hover: rgba(148, 163, 184, 0.08);
  --done-ink: #7c8899;
  --done-rule: rgba(255, 255, 255, 0.3);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md:
    0 4px 14px -4px rgba(0, 0, 0, 0.55), 0 2px 6px -2px rgba(0, 0, 0, 0.4);
}

/* An operator who never chose, following the operating system. */
@media (prefers-color-scheme: dark) {
  :root[data-theme-pref="system"] {
    --bg: #0f141c;
    --panel: #161c26;
    --panel-2: #1e2632;
    --ink: #e8edf5;
    --ink-2: #c7d2e0;
    --muted: #97a4b8;
    --muted-2: #5c6a7d;
    --label: #9aa8bc;
    --line: #26303d;
    --line-2: #384453;
    --brand: #c4b5fd;
    --brand-soft: #241b3d;
    --brand-ink: #ddd6fe;
    --accent: #a78bfa;

    --note-bg: #1b232e;
    --note-border: #64748b;
    --note-ink: #cbd5e1;
    --tip-bg: #152238;
    --tip-border: #3b82f6;
    --tip-ink: #bfdbfe;
    --warn-bg: #2a2113;
    --warn-border: #d97706;
    --warn-ink: #fcd34d;

    --code-bg: #0a0e15;
    --code-ink: #dbe4f0;
    --line-brand: #4a3a78;
    --row-hover: rgba(148, 163, 184, 0.08);
    --done-ink: #7c8899;
    --done-rule: rgba(255, 255, 255, 0.3);

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md:
      0 4px 14px -4px rgba(0, 0, 0, 0.55), 0 2px 6px -2px rgba(0, 0, 0, 0.4);
  }
}

/* Tells the browser to paint its own furniture dark too: form controls, the
   scrollbar, and the canvas behind a short page. */
:root[data-theme-pref="dark"] {
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root[data-theme-pref="system"] {
    color-scheme: dark;
  }
}

* {
  box-sizing: border-box;
}
html,
body {
  margin: 0;
  padding: 0;
}
body {
  background: var(--bg);
  color: var(--ink);
  font-family:
    "Inter",
    ui-sans-serif,
    system-ui,
    -apple-system,
    "Segoe UI",
    Roboto,
    "Helvetica Neue",
    Arial,
    sans-serif;
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a {
  color: var(--brand);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

/* ---------- App shell ---------- */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
}

/* ---------- Sidebar ---------- */
.sidebar {
  background: var(--panel);
  border-right: 1px solid var(--line);
  position: sticky;
  /* Sticky always makes a stacking context, so the search panel's own z-index
     only counts inside the sidebar. Without one here the hero, positioned and
     later in the page, painted over the results wherever they overhung it. */
  z-index: 20;
  top: 0;
  align-self: start;
  height: 100vh;
  overflow-y: auto;
  padding: 1.25rem 1rem 2rem;
}
.sidebar .brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.25rem 0.5rem 1rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1rem;
  color: var(--ink);
}
.sidebar .brand:hover {
  text-decoration: none;
}
.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}
.sidebar-head .brand {
  flex: 1;
  min-width: 0;
}
/* Shown only once help.js has taken charge of the nav, so a browser that never
   runs it keeps the nav open rather than losing it behind a dead button. */
.nav-toggle {
  display: none;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.7rem;
  margin-bottom: 1rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--ink-2);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.nav-toggle:hover {
  border-color: var(--line-2);
}
.nav-toggle svg {
  width: 16px;
  height: 16px;
}
.sidebar .brand-mark {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  flex: none;
  box-shadow: var(--shadow-sm);
}
/* The way out of the docs and back into the admin. */
.app-link {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: -0.25rem 0 0.75rem;
  padding: 0.4rem 0.5rem;
  border-radius: 8px;
  color: var(--brand);
  font-size: 0.88rem;
  font-weight: 600;
}
.app-link:hover {
  background: var(--brand-soft);
  text-decoration: none;
}
.app-link svg {
  width: 16px;
  height: 16px;
}
.sidebar .brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}
.sidebar .brand-text strong {
  font-size: 0.98rem;
  color: var(--ink);
}
.sidebar .brand-text span {
  font-size: 0.78rem;
  color: var(--muted);
}

/* ---------- Search ---------- */
.help-search {
  position: relative;
  margin: 0 0 0.75rem;
}
.help-search input {
  width: 100%;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
}
.help-search input::placeholder {
  color: var(--muted);
}
.help-search input:focus {
  outline: 2px solid var(--brand);
  outline-offset: -1px;
  background: var(--panel);
}
.help-search-results {
  /* Fixed, not absolute, and placed by help.js. The sidebar scrolls, so it is
     a clipping context: an absolutely positioned panel wider than the sidebar
     gets its right-hand side cut off, which truncated every result mid-word. */
  position: fixed;
  z-index: 30;
  /* Wider than the sidebar that holds it: a result is a heading, a page name
     and a line of the prose it matched, and none of that fits in 248px. */
  width: min(30rem, 78vw);
  max-height: min(28rem, 70vh);
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 0.3rem;
}
.help-search-results a {
  display: block;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  color: var(--ink);
}
.help-search-results a:hover,
.help-search-results a:focus,
.help-search-results a[aria-selected="true"] {
  background: var(--brand-soft);
  text-decoration: none;
  outline: none;
}
.help-search-results .hit-heading {
  display: block;
  font-weight: 600;
  font-size: 0.9rem;
}
.help-search-results .hit-page {
  display: block;
  font-size: 0.74rem;
  color: var(--label);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 0.1rem;
}
.help-search-results .hit-text {
  display: block;
  font-size: 0.82rem;
  color: var(--muted);
  line-height: 1.45;
  margin-top: 0.25rem;
}
.help-search-empty {
  margin: 0;
  padding: 0.6rem;
  font-size: 0.86rem;
  color: var(--muted);
}

.sidebar-section {
  margin-top: 1rem;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--label);
  font-weight: 600;
  padding: 0 0.5rem 0.35rem;
}
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.sidebar-nav a {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  font-size: 0.92rem;
  color: var(--ink-2);
  font-weight: 500;
  transition:
    background 0.15s,
    color 0.15s;
}
.sidebar-nav a:hover {
  background: var(--panel-2);
  text-decoration: none;
}
.sidebar-nav a.active {
  background: var(--brand-soft);
  color: var(--brand-ink);
}
.sidebar-nav .ico {
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  flex: 0 0 18px;
}
.sidebar-nav a.active .ico {
  color: var(--brand);
}

/* A split article, with its pages listed under it. The toggle and the folding
   are switched on by help.js (.has-subnav), so with no script every list is
   simply open. */
.nav-row {
  display: flex;
  align-items: center;
  gap: 0.15rem;
}
.nav-row > a {
  flex: 1;
  min-width: 0;
}
/* The highlight belongs to the whole row. On the link alone it stopped short
   of the chevron, so an open section's pill was 30px narrower than every
   other one in the list and the chevron hung outside it. */
.nav-row {
  border-radius: 8px;
  transition: background 0.15s;
}
.nav-row:has(> a:hover) {
  background: var(--panel-2);
}
.nav-row:has(> a.active) {
  background: var(--brand-soft);
}
.nav-row > a:hover,
.nav-row > a.active {
  background: transparent;
}
.subnav-toggle {
  display: none;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.subnav-toggle:hover {
  background: var(--panel-2);
  color: var(--ink-2);
}
.subnav-toggle svg {
  transition: transform 0.15s;
}
.subnav-toggle[aria-expanded="true"] svg {
  transform: rotate(90deg);
}
.sidebar.has-subnav .subnav-toggle {
  display: inline-flex;
}
.sidebar.has-subnav .subnav:not(.open) {
  display: none;
}
.subnav {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin: 0.15rem 0 0.4rem 1.45rem;
  padding-left: 0.55rem;
  border-left: 1px solid var(--line);
}
.sidebar-nav .subnav a {
  padding: 0.35rem 0.6rem;
  font-size: 0.86rem;
}

.sidebar-foot {
  margin-top: 2rem;
  padding: 0.75rem 0.6rem 0;
  border-top: 1px solid var(--line);
  font-size: 0.82rem;
  color: var(--muted);
}

/* ---------- Main content ---------- */
.main {
  min-width: 0;
  padding: 2rem clamp(1rem, 4vw, 3rem) 4rem;
}
.main-inner {
  max-width: var(--wide-max);
  margin: 0 auto;
}
.article {
  min-width: 0;
  max-width: var(--wide-max);
}

/* The reading measure. Everything an operator reads a sentence at a time is
   held to --content-max; everything they scan (tables, card grids, code) keeps
   the full article width. Both levels are listed because the articles put
   these blocks either straight into .main-inner or one <section> down, and
   nowhere deeper, so this never reaches inside a card or a table cell.

   h2 is deliberately absent: its rule (h2::before) is the divider between
   sections, and a divider that stopped short of the table beneath it would
   read as a mistake. */
.article > :is(p, ul, ol, dl, h3, h4, .tip, .note, .warning, .toc, .page-lede),
.article section > :is(p, ul, ol, dl, h3, h4, .tip, .note, .warning, .toc) {
  max-width: var(--content-max);
}

.breadcrumbs {
  font-size: 0.85rem;
  color: var(--muted);
  margin-bottom: 0.8rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
}
.breadcrumbs a {
  color: var(--muted);
}
.breadcrumbs a:hover {
  color: var(--brand);
}
.breadcrumbs .sep {
  color: var(--muted-2);
}

.page-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--brand);
  background: var(--brand-soft);
  padding: 0.25rem 0.55rem;
  border-radius: 999px;
  margin-bottom: 0.9rem;
}

.page-title {
  font-size: clamp(1.85rem, 3vw, 2.4rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 700;
  margin: 0 0 0.6rem;
  color: var(--ink);
}
.page-lede {
  font-size: 1.06rem;
  color: var(--muted);
  margin: 0 0 1.8rem;
  max-width: 68ch;
}

/* ---------- Sections ---------- */
section {
  margin: 2.2rem 0;
  /* Clears the sticky header a phone puts over the top of the page when the
     reader jumps to a heading. */
  scroll-margin-top: 5rem;
}
@media (min-width: 901px) {
  section {
    scroll-margin-top: 1.5rem;
  }
}
section + section {
  padding-top: 0.25rem;
}

h2 {
  font-size: 1.35rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  font-weight: 700;
  margin: 0 0 0.9rem;
  color: var(--ink);
  position: relative;
}
h2::before {
  content: "";
  display: block;
  height: 1px;
  background: var(--line);
  margin: 0 0 1.1rem;
}
section:first-of-type > h2::before {
  display: none;
}

h3 {
  font-size: 1.04rem;
  font-weight: 650;
  margin: 1.2rem 0 0.35rem;
  color: var(--ink);
  letter-spacing: -0.005em;
}
h4 {
  font-size: 0.92rem;
  font-weight: 650;
  margin: 0.8rem 0 0.25rem;
  color: var(--ink-2);
}

p {
  margin: 0.5rem 0;
}

/* ---------- Lists ---------- */
ul,
ol {
  padding-left: 1.25rem;
  margin: 0.5rem 0;
}
ul li,
ol li {
  margin: 0.25rem 0;
}
.steps,
.checklist {
  padding-left: 0;
  list-style: none;
  counter-reset: step;
}
.steps li {
  counter-increment: step;
  position: relative;
  padding: 0.35rem 0 0.35rem 2.2rem;
}
.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0.4rem;
  width: 1.55rem;
  height: 1.55rem;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand-ink);
  font-size: 0.8rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-brand);
}
.checklist li {
  position: relative;
  padding: 0.25rem 0 0.25rem 1.85rem;
  cursor: pointer;
  user-select: none;
}
.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5rem;
  width: 1.05rem;
  height: 1.05rem;
  border-radius: 5px;
  border: 1.5px solid var(--line-2);
  background: var(--panel);
  background-position: center;
  background-repeat: no-repeat;
  background-size: 0.85rem 0.85rem;
  transition:
    background-color 0.12s,
    border-color 0.12s;
}
.checklist li:hover::before {
  border-color: var(--brand);
}
.checklist li.checked::before {
  background-color: var(--brand);
  border-color: var(--brand);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
}
.checklist li.checked {
  color: var(--done-ink);
  text-decoration: line-through;
  text-decoration-color: var(--done-rule);
}

/* ---------- Code & inline ---------- */
code {
  background: var(--panel-2);
  color: var(--ink-2);
  border-radius: 5px;
  padding: 0.08rem 0.35rem;
  font-size: 0.88em;
  font-family:
    ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  border: 1px solid var(--line);
  /* A chip that wraps used to lose its border down the middle: the box was
     drawn once around both halves. Cloning gives each line its own. The
     wrapping rules keep a long path or URL breakable while stopping short
     tokens splitting at a hyphen (YYYY-MM- / DD HH:MM). */
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  word-break: keep-all;
  overflow-wrap: break-word;
}
pre {
  background: var(--code-bg);
  color: var(--code-ink);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  overflow-x: auto;
  font-size: 0.88rem;
  line-height: 1.55;
  border: 1px solid var(--code-bg);
}
pre code {
  background: transparent;
  color: inherit;
  border: none;
  padding: 0;
}

/* ---------- Definition rows ---------- */
/* These groups are a name plus a description: "Revenue", and what the revenue
   report contains. They used to be a grid of bordered cards, which read badly
   at any column width. Short and long entries sat side by side, so either
   every card stretched to the tallest in its row and the short ones trailed
   hundreds of pixels of blank, or they kept their own heights and the row
   ended in a ragged line of boxes at four different depths. That mismatch is
   not something a column width can fix.

   As rows it stops mattering: a one-line entry is a one-line row, a long one
   is a tall row, and every name still lines up down one left edge to be
   scanned. It is the same treatment as the dl on the payment setup pages, so
   it introduces no new look, and the markup did not have to change in any of
   the four languages to get it.

   .card-link below is a different thing and keeps its boxes: those are the
   navigation tiles on the overview, where the box is the click target. */
/* .grid holds two different components, and that is the whole trap here. Four
   articles fill it with .card rows, which want to be one panel with hairlines
   between them; the overview fills it with .card-link tiles, which want to be
   separate boxes with space around each. Styling .grid itself for either one
   silently wrecks the other, which is what happened when the rows were built:
   the tiles kept their own styling and lost the layout underneath them, so the
   overview stacked seven boxes edge to edge with no gap.

   So .grid carries only what both want, and each shape is asked for by what is
   actually inside it. TestGridHoldsExactlyTwoComponents fails if a third kind
   of child appears without a variant here. */
.grid {
  margin: 0.9rem 0 1.1rem;
}

/* Rows: one panel, divided. */
.grid:has(> .card) {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow-sm);
  /* Holds the row borders inside the rounded corners. */
  overflow: hidden;
}

/* Tiles: separate boxes, laid out with room between them. Tiles in a row
   stretch to the tallest one, so a short tile beside a long one does not
   leave a ragged gap under it. */
.grid:has(> .card-link) {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  align-items: stretch;
}
.card {
  display: grid;
  grid-template-columns: minmax(9rem, 12rem) 1fr;
  gap: 0 1.5rem;
  padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--line);
}
.card:last-child {
  border-bottom: none;
}
/* The name holds the left column and everything else stacks in the right one,
   which is what lets a row carry a list or a second paragraph without the two
   columns interleaving. */
.card > h3 {
  grid-column: 1;
  grid-row: 1;
  margin: 0;
  font-size: 0.95rem;
  font-weight: 650;
}
.card > :not(h3) {
  grid-column: 2;
}
.card > :nth-child(2) {
  margin-top: 0;
}
.card > :last-child {
  margin-bottom: 0;
}
.card ul,
.card ol {
  padding-left: 1.1rem;
}

.card-link {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  box-shadow: var(--shadow-sm);
  color: var(--ink);
  transition:
    border-color 0.15s,
    box-shadow 0.15s,
    transform 0.15s;
}
.card-link:hover {
  text-decoration: none;
  border-color: var(--line-brand);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.card-link h3 {
  margin: 0 0 0.25rem;
  font-size: 1rem;
  color: var(--ink);
}
/* A tile with no summary under its title would otherwise sit its title above
   the middle, with the gap meant for the summary still under it. */
.card-link h3:last-child {
  margin-bottom: 0;
}
.card-link p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--muted);
}
.card-link .card-ico {
  display: inline-flex;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--brand-soft);
  color: var(--brand-ink);
  align-items: center;
  justify-content: center;
  margin-bottom: 0.55rem;
}

/* ---------- Tables ---------- */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin: 0.8rem 0;
  background: var(--panel);
  box-shadow: var(--shadow-sm);
}
table {
  width: 100%;
  border-collapse: collapse;
}
th,
td {
  padding: 0.65rem 0.85rem;
  text-align: left;
  vertical-align: top;
  font-size: 0.92rem;
  border-bottom: 1px solid var(--line);
}
th {
  background: var(--panel-2);
  font-weight: 650;
  color: var(--ink-2);
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
tbody tr:last-child td {
  border-bottom: none;
}
tbody tr:hover {
  background: var(--row-hover);
}

/* ---------- Callouts ---------- */
.tip,
.note,
.warning {
  border-left: 4px solid var(--tip-border);
  background: var(--tip-bg);
  color: var(--tip-ink);
  padding: 0.8rem 1rem;
  border-radius: 8px;
  margin: 1rem 0;
  font-size: 0.94rem;
}
.tip {
  border-left-color: var(--tip-border);
  background: var(--tip-bg);
  color: var(--tip-ink);
}
.note {
  border-left-color: var(--note-border);
  background: var(--note-bg);
  color: var(--note-ink);
}
.warning {
  border-left-color: var(--warn-border);
  background: var(--warn-bg);
  color: var(--warn-ink);
}
.tip strong,
.note strong,
.warning strong {
  color: inherit;
}
.tip a,
.note a,
.warning a {
  color: inherit;
  text-decoration: underline;
}

/* ---------- TOC pills ---------- */
.toc {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.25rem 0 0.25rem;
}
.toc a {
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--ink-2);
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
  font-size: 0.85rem;
  font-weight: 500;
  transition:
    border-color 0.15s,
    color 0.15s,
    background 0.15s;
}
.toc a:hover {
  text-decoration: none;
  border-color: var(--line-brand);
  color: var(--brand-ink);
  background: var(--brand-soft);
}

/* ---------- Definition list ---------- */
/* A dl and a .grid of .card rows are the same component: a panel of rows, each
   a name beside its description. They were built separately and agreed on
   nothing — 220px label column against 192, 16px label against 15.2, grey
   description text against near-black — so two pages showed the same pattern
   in two slightly different ways. They share the metrics now, and the .card
   rules above set them once. */
dl {
  display: grid;
  grid-template-columns: minmax(9rem, 12rem) 1fr;
  gap: 0 1.5rem;
  margin: 0.9rem 0 1.1rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
dt,
dd {
  padding: 0.85rem 0 0.85rem;
  border-top: 1px solid var(--line);
}
dt {
  padding-left: 1.1rem;
  font-size: 0.95rem;
  font-weight: 650;
  color: var(--ink);
}
dd {
  margin: 0;
  padding-right: 1.1rem;
  color: var(--ink);
}
/* The first row carries the panel edge, not a divider. */
dl > dt:first-of-type,
dl > dt:first-of-type + dd {
  border-top: none;
}

/* ---------- Page nav (prev / next) ---------- */
.page-nav {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin: 3rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  flex-wrap: wrap;
}
.page-nav a {
  flex: 1 1 280px;
  display: flex;
  flex-direction: column;
  padding: 0.8rem 1rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.page-nav a:hover {
  text-decoration: none;
  border-color: var(--line-brand);
  box-shadow: var(--shadow-md);
}
.page-nav a.next {
  text-align: right;
}
.page-nav .label {
  font-size: 0.76rem;
  color: var(--muted);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 600;
}
.page-nav .title {
  font-weight: 600;
  color: var(--ink-2);
  margin-top: 0.15rem;
}

/* ---------- Footer ---------- */
.footer {
  margin: 3rem 0 0;
  padding: 1.5rem 0;
  color: var(--muted);
  font-size: 0.85rem;
  border-top: 1px solid var(--line);
}

/* ---------- On this page ---------- */
/* The rail is server-rendered but filled by help.js, so it stays hidden until
   there is a list in it — and on any window too narrow to give it a column
   without squeezing the article. The .toc pill row some articles carry in
   their own markup says the same thing, so exactly one of the two shows. */
.on-this-page {
  display: none;
}
.on-this-page-title {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--label);
  font-weight: 600;
  margin-bottom: 0.6rem;
}
.on-this-page ul {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--line);
}
.on-this-page li {
  margin: 0;
}
.on-this-page a {
  display: block;
  padding: 0.3rem 0 0.3rem 0.8rem;
  margin-left: -1px;
  border-left: 2px solid transparent;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--muted);
}
.on-this-page a:hover {
  color: var(--ink-2);
  text-decoration: none;
}
.on-this-page a[aria-current="true"] {
  color: var(--brand-ink);
  border-left-color: var(--brand);
  font-weight: 550;
}

/* 1300, not 1240. The rail costs the article its own width plus the gap, so
   below this the article came out narrower WITH the rail than without it: at
   1239px it was 863px, and one pixel wider it collapsed to 592, dragging the
   prose under its 640px measure. A window getting wider must not make the
   reading column smaller. 1288px is where the sums balance; 1300 is the round
   number above it. */
@media (min-width: 1300px) {
  .main-inner.has-toc {
    max-width: var(--shell-max);
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--toc-w);
    column-gap: 2.5rem;
    align-items: start;
  }
  .main-inner.has-toc .on-this-page {
    display: block;
    position: sticky;
    top: 2rem;
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
  }
  .main-inner.has-toc .toc {
    display: none;
  }
}

/* ---------- See also ---------- */
/* The tie between the complete manual and the article covering the same
   subject at length. Quiet on purpose: it is a signpost beside the prose, not
   a call to action, and there is one in every section of the manual.

   Block-level, at its own width. As an inline-flex it sat in a line box of its
   own, so its margins could never merge with the block next to it, and it left
   a gap of two blank lines between the link and whatever came next. */
.see-also {
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 0.3rem;
  margin: 0 0 0.9rem;
  font-size: 0.85rem;
  font-weight: 550;
  color: var(--brand);
}
.see-also::after {
  content: "→";
  font-weight: 400;
}
.see-also.see-also-lede {
  margin-top: -1rem;
  margin-bottom: 1.8rem;
}
/* On a subpage, which has no lede, the link sits straight under the title. */
.page-title + .see-also-lede {
  margin-top: 0;
}
/* The tiles under a split article's landing page. */
.subpages-heading {
  margin-top: 2.2rem;
}

/* ---------- Anchor links on headings ---------- */
/* These rules sat here styling a feature nobody had built: no fragment carries
   an .anchor. help.js adds them now, which it can because the "On this page"
   rail already has to give every section a stable id. On articles that run to
   five thousand words, being able to link a colleague to the paragraph rather
   than the page is worth the four lines.

   Shown on hover, and always while focused, or a keyboard could reach a
   permanently invisible link. */
.anchor {
  color: var(--muted-2);
  margin-left: 0.4rem;
  opacity: 0;
  transition: opacity 0.15s;
  text-decoration: none;
  font-weight: 500;
}
h2:hover .anchor,
h3:hover .anchor,
.anchor:focus {
  opacity: 1;
}
.anchor:hover {
  color: var(--brand);
  text-decoration: none;
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  padding: 1.25rem 1.5rem 1.5rem;
  background: linear-gradient(135deg, #2e1065 0%, #4c1d95 45%, #7008e7 100%);
  color: #fff;
  border-radius: var(--radius-lg);
  margin-bottom: 2rem;
  overflow: hidden;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      800px 300px at 90% -10%,
      rgba(196, 181, 253, 0.3),
      transparent 60%
    ),
    radial-gradient(
      600px 250px at -10% 110%,
      rgba(217, 70, 239, 0.25),
      transparent 60%
    );
  pointer-events: none;
}
.hero .page-eyebrow {
  position: relative;
  background: rgba(255, 255, 255, 0.12);
  color: #ddd6fe;
}
.hero h1 {
  position: relative;
  color: #fff;
  font-size: clamp(1.9rem, 3vw, 2.5rem);
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin: 0 0 0.5rem;
}
.hero p {
  position: relative;
  color: #ddd6fe;
  font-size: 1.04rem;
  max-width: 60ch;
  margin: 0;
}

/* ---------- Mobile ---------- */
@media (max-width: 900px) {
  .app {
    grid-template-columns: 1fr;
  }
  .sidebar {
    position: sticky;
    top: 0;
    z-index: 20;
    height: auto;
    overflow: visible;
    border-right: none;
    border-bottom: 1px solid var(--line);
    padding: 0.75rem 1rem;
  }
  .sidebar .brand {
    padding: 0;
    border-bottom: none;
    margin-bottom: 0;
  }
  /* The whole nav — eleven links and three group headings — used to sit above
     the article, so a phone scrolled through a screenful of navigation before
     the first sentence. It folds behind the button now. */
  /* 44px is the touch-target floor; both of these were under it. */
  .nav-toggle {
    display: inline-flex;
    margin-bottom: 0;
    min-height: 44px;
    padding: 0.5rem 0.85rem;
  }
  .sidebar .brand {
    min-height: 44px;
  }
  .sidebar-nav a {
    min-height: 44px;
  }
  .subnav-toggle {
    width: 44px;
    height: 44px;
  }
  .sidebar.collapsible .sidebar-body {
    display: none;
    padding-top: 1rem;
    margin-top: 0.75rem;
    border-top: 1px solid var(--line);
  }
  .sidebar.collapsible.open .sidebar-body {
    display: block;
    max-height: 70vh;
    overflow-y: auto;
  }
  .sidebar-nav {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.35rem;
  }
  /* An open page list is far taller than the links beside it, so in a grid
     cell it stretched its whole row and left the cells next to it hanging
     over a screenful of blank. It takes the full row instead, and its pages
     run in columns like the links above them. */
  .sidebar:not(.has-subnav) .nav-group,
  .nav-group:has(> .subnav.open) {
    grid-column: 1 / -1;
  }
  .sidebar-nav .subnav {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  }
  .sidebar-section {
    padding-top: 0.25rem;
  }
  .sidebar-foot {
    display: none;
  }
  .main {
    padding: 1.5rem 1.1rem 3rem;
  }
  /* Stacked, a name and its text are one row: the divider goes above the
     name only, and the text keeps the panel's side padding. */
  dl {
    grid-template-columns: 1fr;
    gap: 0;
  }
  dl dt {
    padding-bottom: 0.2rem;
  }
  dl dd {
    padding-top: 0;
    padding-left: 1.1rem;
    border-top: none;
  }
  /* Same reason as the dl above it: two columns inside a phone leaves the
     description three words wide. The name sits over its text instead. */
  .card {
    grid-template-columns: 1fr;
    gap: 0.25rem;
  }
  .card > h3,
  .card > :not(h3) {
    grid-column: 1;
  }
  .card > h3 {
    grid-row: auto;
  }
  /* A three-column table squeezed into a phone gave every cell a column one
     word wide. It scrolls sideways instead, which is what .table-wrap was
     always for — width:100% just never let it happen. */
  table {
    min-width: 34rem;
  }
  .table-wrap {
    scrollbar-color: var(--line-2) transparent;
  }
}

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