/* Ryker — product site.
   Shared typography, navigation and docs. No framework, CDN or runtime request: the
   site must render with the network off, from file:// or any static host.

   The identity is Ryker's own (brand/ryker/README.md, .agent/kb/rules/ryker-brand.md):
   graphite #111315, mint #36E6A5, ivory #F2EEE5, the supplied logo files, and
   the bundled, unmodified IBM Plex Sans (Regular, SemiBold) and IBM Plex Mono
   (Regular). Every colour below is one of the product's own tokens in
   priv/static/ryker-tokens.css, so the site and the control plane are one
   palette; test/ryker/public_site_brand_test.exs fails on any other colour,
   font family, weight or logo file.

   - Graphite is the canvas and ivory the reading colour. Mint lives on
     graphite: primary buttons, focus rings, the current place, a few markers.
     Links take the lighter mint tint and an underline, so colour is never
     the only signal.
   - Status colours (success, error) keep their own meaning and
     always sit beside a word. Mint is never evidence that something worked.
   - Hairlines over borders, flat colour, no glows or shadows. Panels use 8px
     corners and compact controls 4px.
   - Mono is for identifiers, sources, timestamps and code: the things you read
     token by token rather than as a sentence.
   - The logo is always the supplied SVG. The name is never typed as a logo.

   ---------------------------------------------------------------------------
   THE RHYTHM.

   1. STRUCTURE is 8px: section bands, grid gaps, the space around headings
      and the wrap's gutters all come from --s-1 … --s-9. Sections sit 48 to
      96px apart and related elements 16 to 24px, as the brand's layout guide
      asks, rather than the old 160px editorial bands.
   2. COMPONENT INTERNALS are optically set against their own text. A button
      is 10px/20px because 14px on a 24px line needs a 46px box; a list row is
      9px because 13px on 24px needs 42. They sit on the 4px sub-grid and are
      always inside a component, never between two of them.
   3. FLUID values are 8px-anchored at both clamp endpoints and interpolate
      in between.

   LEADING is on the 4px sub-grid: 24/28/32. Display type is fluid and takes
   a ratio instead. A heading owns the space above it: twice what it leaves
   below, so a section begins at its title.
   --------------------------------------------------------------------------- */

/* Fonts ------------------------------------------------------------------- */

/* The three supplied faces, byte for byte from brand/assets/fonts, with their
   SIL Open Font License beside them in fonts/LICENSE.txt. Nothing else is
   loaded: there is no italic and no bold, so emphasis is SemiBold and no
   weight is ever synthesised (see font-synthesis-weight below). */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/IBMPlexSans-Regular.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/IBMPlexSans-SemiBold.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/IBMPlexMono-Regular.woff2") format("woff2");
}

/* Tokens ------------------------------------------------------------------ */

:root {
  /* The supplied identity. */
  --graphite: #111315;
  --mint: #36e6a5;
  --ivory: #f2eee5;

  /* Roles, each valued from priv/static/ryker-tokens.css. */
  --bg: var(--graphite);   /* ryker-surface: the canvas */
  --panel: #181c1e;        /* ryker-surface-raised: panels, cards, Slack windows */
  --panel-2: #202623;      /* ryker-surface-emphasis: hover */
  --sunken: #0d0f10;       /* ryker-surface-sunken: code */
  --line: #2d3431;         /* ryker-stroke: decorative hairlines */
  --line-strong: #626d67;  /* ryker-stroke-strong: control edges and marks, 3:1 */
  --ink: var(--ivory);     /* ryker-text: reading, headings, navigation */
  --dim: #a5ada8;          /* ryker-text-secondary: captions, metadata (8.1:1) */
  --accent: var(--mint);   /* ryker-accent: fills, focus, the current place */
  --accent-hover: #6df0bd; /* ryker-control-primary-hover-bg */
  --accent-text: #6df0bd;  /* ryker-accent-strong: links and mint words (13:1) */
  --accent-soft: #19392e;  /* ryker-accent-soft: text selection */
  --good: #8bd6a7;         /* ryker-success */
  --bad: #ff9a90;          /* ryker-error */
  --info: #8fc7ee;         /* ryker-info */

  --sans: "IBM Plex Sans", sans-serif;
  --mono: "IBM Plex Mono", monospace;

  /* Space: one unit, eight pixels. */
  --u: 8px;
  --s-1: 8px;
  --s-2: 16px;
  --s-3: 24px;
  --s-4: 32px;
  --s-5: 40px;
  --s-6: 48px;
  --s-7: 64px;
  --s-8: 80px;
  --s-9: 96px;

  /* The section band: 48px on a phone, 96px on a desktop. */
  --band: clamp(3rem, 2rem + 4vw, 6rem);

  /* Type, named by job. Plex SemiBold for headings, Regular for reading,
     Mono for metadata and code; compact sizes rather than marketing ones. */
  --t-micro: 0.75rem;                                        /* 12  mono labels   */
  --t-meta: 0.8125rem;                                       /* 13  meta, rows    */
  --t-small: 0.875rem;                                       /* 14  controls      */
  --t-body: clamp(1rem, 0.965rem + 0.16vw, 1.0625rem);       /* 16 → 17           */
  --t-body-lg: clamp(1.0625rem, 1.03rem + 0.16vw, 1.125rem); /* 17 → 18           */
  --t-lead: clamp(1.125rem, 1.08rem + 0.2vw, 1.25rem);       /* 18 → 20           */
  --t-h4: clamp(1.0625rem, 1.03rem + 0.16vw, 1.125rem);      /* 17 → 18           */
  --t-h3: clamp(1.25rem, 1.2rem + 0.22vw, 1.375rem);         /* 20 → 22           */
  --t-h2: clamp(1.75rem, 1.55rem + 0.9vw, 2.25rem);          /* 28 → 36  sections */
  --t-h1: clamp(2rem, 1.8rem + 0.9vw, 2.5rem);               /* 32 → 40  doc h1   */
  --t-display: clamp(2.25rem, 1.7rem + 2.45vw, 3.5rem);      /* 36 → 56  hero h1  */

  /* Leading, on the 4px sub-grid. */
  --lh-tight: 24px;
  --lh-body: 28px;
  --lh-loose: 32px;

  /* Measure. Prose never exceeds this; it is the reason the docs page has a
     third column instead of a wider second one. */
  --measure: 68ch;
  --measure-narrow: 60ch;
  --wrap: 1240px;
  /* The lockup needs 176px of canvas to show its 160px minimum, and 8px of
     clear space around it; the bar is sized for that. */
  --nav-h: 80px;
}

/* Base -------------------------------------------------------------------- */

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

html {
  color-scheme: dark;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Only Regular and SemiBold exist. A synthesised bold or a Mono smeared
     to 600 is not the supplied typeface, so weight is never faked. */
  font-synthesis-weight: none;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}

::selection { background: var(--accent-soft); color: var(--ink); }

/* Mint on graphite, 11.5:1; every surface on this site is graphite or one
   step above or below it. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Thin theme scrollbars: the OS default grey bar reads as a foreign widget
   inside a dark surface. */
* { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 9999px; }
::-webkit-scrollbar-track { background: transparent; }

a { color: var(--accent-text); text-decoration: none; }
a:hover { color: var(--accent-text); text-decoration: underline; text-underline-offset: 3px; }

img, svg { max-width: 100%; }

h1, h2, h3, h4, h5, h6 {
  margin: 0;
  color: var(--ink);
  font-weight: 600;
  text-wrap: balance;
}

p { margin: 0; }
p, li { text-wrap: pretty; }
b, strong { font-weight: 600; }

code, kbd, samp, pre { font-family: var(--mono); font-weight: 400; font-variant-numeric: tabular-nums; }

/* One inline code treatment everywhere prose names a path, flag or command:
   mono on the raised surface, with padding tight enough that a following
   comma or period does not float away from it. */
:not(pre) > code {
  padding: 1px 4px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  font-family: var(--mono);
  font-size: .875em;
}
/* In 13px rows the chip keeps a readable size. */
:is(.doc dt, .doc dd, .install-note) code { font-size: .9375em; }

/* Anything numeric or clock-shaped lines up. */
time, .tag { font-variant-numeric: tabular-nums; }

.skip {
  position: absolute;
  left: var(--s-2);
  top: calc(var(--s-1) * -8);
  z-index: 100;
  padding: var(--s-1) var(--s-2);
  border: 1px solid var(--accent);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  font-size: var(--t-meta);
  transition: top .14s ease;
}
.skip:focus { top: var(--s-2); text-decoration: none; }

.vh {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* A monospaced source tag: the label a panel or caption wears. */
.tag {
  display: inline-block;
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: .02em;
  white-space: nowrap;
}

/* Layout ------------------------------------------------------------------ */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--s-3);
}

@media (min-width: 720px) {
  .wrap { padding-inline: var(--s-5); }
}

.band { padding-block: var(--band); }

/* A hairline is the only thing that ever separates two sections. */
.band + .band { border-top: 1px solid var(--line); }

.section-head { max-width: 46ch; margin-bottom: var(--s-6); }
.section-head h2 {
  font-size: var(--t-h2);
  line-height: 1.1;
  letter-spacing: -.025em;
}
/* The child combinator keeps the subtitle rule from reaching anything else
   the head holds. */
.section-head > p {
  margin-top: var(--s-3);
  max-width: var(--measure);
  color: var(--dim);
  font-size: var(--t-body-lg);
  line-height: var(--lh-loose);
}

/* Nav --------------------------------------------------------------------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid transparent;
  background: var(--bg);
  transition: border-color .18s ease;
}
/* The hairline arrives only once the page has moved, so the header is part
   of the page at rest and part of the chrome in use. */
.nav.is-stuck { border-bottom-color: var(--line); }

.nav-in {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  height: var(--nav-h);
}

/* The supplied dark-surface lockup, never retyped. lockup-color.svg is a
   950-unit canvas whose visible artwork spans 878 units, so 176px of canvas
   shows the logo at 162px, over its 160px minimum. The link's 8px of padding
   is the clear space — a quarter of the lowercase height is 6.4px at this
   size — kept outside the canvas, because the canvas's own transparent
   margin does not count; the negative margin puts the canvas back on the
   column's left edge. The 77px link is also the tap target. */
.wordmark {
  display: inline-flex;
  align-items: center;
  flex: none;
  margin-left: calc(var(--s-1) * -1);
  padding: 8px;
}
.wordmark:hover { text-decoration: none; }
.wordmark img { display: block; width: 176px; height: auto; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 28px;
  margin-left: auto;
}
.nav-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--dim);
  font-size: var(--t-small);
  transition: color .12s ease;
}
.nav-links a:hover { color: var(--ink); text-decoration: none; }
/* Every interactive thing on this site answers a press, not just a hover: a
   touch screen has no hover state at all. */
.nav-links a:active { color: var(--accent-text); }
/* Where you are is carried by the mint rule under the word, not by colour
   alone. */
.nav-links a[aria-current] {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

.nav-links .nav-start { padding: 0 16px; border: 1px solid var(--line-strong); border-radius: 6px; color: var(--ink); gap: 16px; }
.nav-links .nav-start:hover { background: var(--panel); border-color: var(--dim); }
.nav-drawer a[aria-current] { color: var(--ink); text-decoration: underline; text-underline-offset: 4px; }
@media (max-width: 1100px) { .nav-links { gap: 16px; } }

.nav-menu { margin-left: auto; display: none; }
.nav-menu > summary {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ink);
  list-style: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu > summary:hover, .nav-menu > summary:active { color: var(--accent-text); }
.menu-icon { display: block; }
.menu-stroke:first-child { transform-origin: 14px 10px; }
.menu-stroke:last-child { transform-origin: 14px 18px; }
.nav-menu[open] .menu-stroke:first-child { transform: translateY(4px) rotate(45deg); }
.nav-menu[open] .menu-stroke:last-child { transform: translateY(-4px) rotate(-45deg); }

.nav-drawer {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  max-height: calc(100dvh - var(--nav-h) - 1px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px var(--s-3) 28px;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.nav-drawer a {
  display: flex;
  align-items: center;
  min-height: 60px;
  padding: 10px 0;
  color: var(--ink);
  font-size: 24px;
  line-height: 32px;
  letter-spacing: -.025em;
}
.nav-drawer a:hover, .nav-drawer a:active { color: var(--accent-text); text-decoration: none; }
.nav-drawer .nav-drawer-start { justify-content: center; min-height: 52px; margin-top: 16px; padding: 12px 20px; border-radius: 6px; color: var(--bg); background: var(--accent); font-size: 16px; line-height: 24px; font-weight: 600; letter-spacing: 0; }
.nav-drawer .nav-drawer-start:hover, .nav-drawer .nav-drawer-start:active { color: var(--bg); background: var(--accent-hover); }
@media (min-width: 720px) { .nav-drawer { padding-inline: var(--s-5); } }
@media (prefers-reduced-motion: no-preference) {
  .menu-stroke { transition: transform .18s ease; }
  .nav-menu[open] .nav-drawer { animation: nav-reveal .16s ease-out; }
  @keyframes nav-reveal { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
}

@media (max-width: 780px) {
  .nav-in { gap: 8px; height: auto; min-height: var(--nav-h); flex-wrap: wrap; }
  .nav-links { display: none; }
  .nav-menu { display: block; }
}

/* Buttons ----------------------------------------------------------------- */

/* One shape: 4px corners, a 46px box, SemiBold. The primary action is the
   mint fill with graphite text (11.5:1); the secondary is an outline whose
   edge clears 3:1 against graphite. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  min-height: 44px;
  padding: 10px 20px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  font-size: var(--t-small);
  font-weight: 600;
  line-height: var(--lh-tight);
  white-space: nowrap;
  transition: transform .12s ease, border-color .12s ease, background-color .12s ease;
}
.btn:hover {
  transform: translateY(-1px);
  border-color: var(--ink);
  color: var(--ink);
  text-decoration: none;
}
/* Pressed, not bounced: the hover lifts one pixel, so the press puts it back
   down and one further, and a tap on a touch screen still gets an answer. */
.btn:active { transform: translateY(1px); }
.btn.go {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--graphite);
}
.btn.go:hover { border-color: var(--accent-hover); background: var(--accent-hover); color: var(--graphite); }
.btn.line { background: transparent; }

/* The third action is not a button: it is where you go when neither of the
   first two is what you wanted. Padded to the buttons' height so the row
   keeps one baseline and one tap height. */
.btn-quiet {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-height: 44px;
  padding: 10px 4px;
  color: var(--dim);
  font-size: var(--t-small);
  line-height: var(--lh-tight);
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 4px;
  transition: color .12s ease, transform .12s ease;
}
.btn-quiet:hover { color: var(--ink); text-decoration-color: currentColor; }
.btn-quiet:active { transform: translateY(1px); }

.arr { opacity: .7; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }

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

/* Each action belongs to the code block it copies. Without JavaScript the
   original pre remains readable and selectable, with no inactive controls. */
.copy-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 44px; align-items: start; gap: 0 12px; min-width: 0; padding: 12px 16px; border-radius: 4px; background: var(--sunken); }
.copy { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 4px; background: transparent; color: var(--dim); cursor: pointer; transition: color .12s ease; }
.copy:hover { color: var(--ink); }
.copy.done { color: var(--good); }
.copy svg { display: block; }
.copy-check, .copy.done .copy-symbol { display: none; }
.copy.done .copy-check { display: block; }
.copy-status:not(.vh) { grid-column: 1 / -1; padding-bottom: 8px; color: var(--dim); font: 12px/20px var(--sans); }
.doc .copy-wrap pre, .install .copy-wrap pre { width: 100%; max-width: none; margin: 0; padding: 10px 0; text-indent: 0; border: 0; border-radius: 0; background: transparent; }

/* Footer ------------------------------------------------------------------ */

.foot { border-top: 1px solid var(--line); padding-block: 64px 24px; color: var(--dim); font-size: 14px; line-height: 24px; }
.foot-main { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: 64px; }
.foot-brand { max-width: 28ch; }
.foot-lockup { display: block; width: 176px; height: auto; }
.foot-brand p { margin-top: 16px; font-size: 16px; line-height: 26px; }
.foot-contact { display: inline-block; min-height: 44px; margin-top: 16px; padding-block: 10px; }
.foot a { color: var(--dim); }
.foot a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.foot a:active { color: var(--accent-text); }
.foot .wordmark:hover { text-decoration: none; }
.foot-contact, .foot-bottom a { text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 3px; }
.foot-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; padding-top: 16px; }
.foot-group h2 { font-size: 14px; line-height: 24px; font-weight: 600; }
.foot-group ul { list-style: none; padding: 0; margin: 16px 0 0; }
.foot-group a { display: flex; align-items: center; min-height: 44px; width: fit-content; max-width: 100%; }
.foot-bottom { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 24px; margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--line); font-size: 12px; line-height: 24px; }
.foot-bottom a { display: inline-flex; align-items: center; min-height: 44px; }
@media (max-width: 959px) {
  .foot-main { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .foot-brand { max-width: 38ch; }
  .foot-links { padding-top: 0; }
}
@media (max-width: 600px) {
  .foot { padding-top: 40px; }
  .foot-links { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
  .foot-bottom { display: block; margin-top: 32px; }
  .foot-bottom > span { display: block; }
}

/* Docs shell -------------------------------------------------------------- */

.docs {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 var(--s-6);
  align-items: start;
}
/* The sidebar gives up width and gutter so the content column keeps room for
   72 monospace characters before example code wraps. */
@media (min-width: 900px) {
  .docs { grid-template-columns: 12rem minmax(0, 1fr); gap: 0 var(--s-5); }
}
@media (min-width: 1180px) {
  .docs { grid-template-columns: 15rem minmax(0, 1fr) 11rem; gap: 0 var(--s-6); }
  .doc-toc { display: none; }
}

.docs-nav {
  padding-block: var(--s-3) 0;
  align-self: start;
}
/* Full viewport height, not content height: a border on a box that ends
   where its list ends stops halfway down the page. */
@media (min-width: 900px) {
  .docs-nav {
    position: sticky;
    top: var(--nav-h);
    height: calc(100vh - var(--nav-h));
    overflow-y: auto;
    border-right: 1px solid var(--line);
    padding-right: var(--s-3);
    padding-block: var(--s-6) var(--s-4);
  }
}

.docs-nav .grp {
  margin: var(--s-4) 0 var(--s-1);
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.docs-nav .grp:first-child { margin-top: 0; }
.docs-nav ul { margin: 0; padding: 0; list-style: none; }
.docs-nav a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: var(--s-1) 0 var(--s-1) 14px;
  border-left: 2px solid var(--line);
  color: var(--dim);
  font-size: var(--t-meta);
  line-height: var(--lh-tight);
  transition: color .12s ease, border-color .12s ease;
}
.docs-nav a:hover { color: var(--ink); border-left-color: var(--line-strong); text-decoration: none; }
.docs-nav a:active { color: var(--accent-text); }
/* The open page: mint rule, ivory, SemiBold — never colour alone. */
.docs-nav a.on {
  color: var(--ink);
  border-left-color: var(--accent);
  font-weight: 600;
}

/* On small screens the whole sidebar collapses into one disclosure so the
   page still opens at its own first heading. */
.docs-nav > details > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  font-size: var(--t-meta);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}
.docs-nav > details > summary::-webkit-details-marker { display: none; }
.docs-nav > details > summary::after { content: "\25BE"; color: var(--dim); font-size: 10px; }
.docs-nav > details[open] > summary::after { transform: rotate(180deg); }
.docs-nav > details > div { padding-top: var(--s-2); }

/* On desktop the disclosure is not a disclosure: the list is always open and
   the summary is gone. Both rules are needed: older engines hide a closed
   <details>'s children directly, newer ones through ::details-content. */
@media (min-width: 900px) {
  .docs-nav > details > summary { display: none; }
  .docs-nav > details > div { display: block; padding-top: 0; }
  .docs-nav > details::details-content { content-visibility: visible; block-size: auto; }
}

/* Docs content ------------------------------------------------------------ */

.doc {
  min-width: 0;
  padding-block: var(--s-6) var(--s-9);
  max-width: 72ch;
}

.doc > h1 {
  font-size: var(--t-h1);
  line-height: 1.1;
  letter-spacing: -.025em;
}

/* One flow rule, not a margin per element. A heading takes twice the space
   above it that it gives below, so the section owns its title. */
.doc > * + * { margin-top: var(--s-3); }
.doc > * + h2 { margin-top: var(--s-6); }
.doc > h2 + * { margin-top: var(--s-3); }
.doc > * + h3 { margin-top: var(--s-4); }
.doc > h3 + * { margin-top: var(--s-3); }   /* … 24 below */
.doc > * + h4 { margin-top: var(--s-4); }   /* 32 above … */
.doc > h4 + * { margin-top: var(--s-2); }   /* … 16 below */
/* A code label belongs to the block under it. */
.doc > .code-label + * { margin-top: var(--s-1); }

.doc h2 {
  font-size: clamp(1.5rem, 1.35rem + 0.6vw, 1.875rem);
  line-height: 1.15;
  letter-spacing: -.02em;
  scroll-margin-top: calc(var(--nav-h) + var(--s-4));
}
.doc h3 {
  font-size: var(--t-h3);
  line-height: 1.25;
  letter-spacing: -.01em;
  scroll-margin-top: calc(var(--nav-h) + var(--s-4));
}
.doc h4 {
  font-size: var(--t-h4);
  line-height: var(--lh-tight);
  letter-spacing: -.01em;
  scroll-margin-top: calc(var(--nav-h) + var(--s-4));
}

/* A heading links to itself, from a hash that appears on hover or on keyboard
   focus, the case a hover-only affordance always forgets. */
.doc h2 .anchor,
.doc h3 .anchor {
  margin-left: .4em;
  color: var(--dim);
  font-family: var(--mono);
  font-size: .7em;
  font-weight: 400;
  text-decoration: none;
  opacity: 0;
  transition: opacity .12s ease, color .12s ease;
}
.doc h2:hover .anchor,
.doc h3:hover .anchor,
.doc .anchor:focus-visible { opacity: 1; }
.doc .anchor:hover { color: var(--accent-text); text-decoration: none; }

/* :where() keeps the prose rule at one class of weight, so the crumb and the
   code label, which are paragraphs too, keep their own mono size. */
.doc :where(p) { max-width: var(--measure); font-size: var(--t-body); line-height: var(--lh-body); }

.doc > .lede {
  margin-top: var(--s-3);
  max-width: var(--measure);
  color: var(--dim);
  font-size: var(--t-lead);
  line-height: 1.55;
}

.crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-1);
  margin-bottom: var(--s-3);
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: .04em;
}
.crumb a { color: var(--dim); text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 3px; }
.crumb a:hover { color: var(--ink); text-decoration-color: currentColor; }

/* Hanging bullets: the marker sits in the gutter and the text keeps one
   straight left edge with the paragraphs above it. Only the bottom margin is
   zeroed; the flow rule above owns the top. */
.doc ul, .doc ol {
  max-width: var(--measure);
  margin-bottom: 0;
  padding-left: 0;
  list-style: none;
}
.doc li {
  position: relative;
  padding-left: var(--s-3);
  font-size: var(--t-body);
  line-height: var(--lh-body);
}
.doc li + li { margin-top: var(--s-1); }
.doc ul > li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 12px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--line-strong);
}
.doc ol { counter-reset: n; }
.doc ol > li { counter-increment: n; padding-left: var(--s-4); }
.doc ol > li::before {
  content: counter(n) ".";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-meta);
  font-variant-numeric: tabular-nums;
}
.doc li > ul { margin-top: var(--s-1); }

/* Definition rows: a term on the left, its one line on the right. */
.doc dl {
  max-width: var(--measure);
  margin-bottom: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}
.doc dl > div {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  gap: var(--s-2);
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--line);
}
.doc dl > div:first-child { border-top: 1px solid var(--line); }
.doc dt {
  font-size: var(--t-meta);
  font-weight: 600;
  line-height: var(--lh-tight);
}
.doc dd {
  margin: 0;
  color: var(--dim);
  font-size: var(--t-meta);
  line-height: var(--lh-tight);
}
@media (max-width: 620px) {
  .doc dl > div { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}

/* A link inside running prose is underlined at rest: colour alone is not an
   affordance. The rule stays out of the card links (.doc-next, .next-grid),
   which are whole clickable surfaces. */
.doc a { text-underline-offset: 3px; }
.doc p:not(.crumb):not(.code-label) a,
.doc li a,
.doc dd a,
.doc dt a,
.doc td a,
.callout a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
  transition: text-decoration-color .12s ease, color .12s ease;
}
.doc p:not(.crumb):not(.code-label) a:hover,
.doc li a:hover,
.doc dd a:hover,
.doc dt a:hover,
.doc td a:hover,
.callout a:hover { text-decoration-color: currentColor; }
.doc a:active { opacity: .7; }

/* Code blocks: Plex Mono on the sunken surface, line-height 1.7, and four
   hand-applied token classes — no highlighter, because a highlighter would
   need a script. */
.doc pre {
  max-width: 78ch;
  margin: 0;
  padding: var(--s-3);
  border: 0;
  border-radius: 4px;
  background: var(--sunken);
  color: var(--ink);
  font-size: .8125rem;
  line-height: 1.7;
  overflow-x: auto;
  tab-size: 2;
  /* A code block never hides a character: where the column is too narrow it
     wraps rather than scrolling something off the right edge. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

/* Messages read as conversation; terminal commands retain Plex Mono. */
.doc pre[data-copy-kind="message"] { font-family: var(--sans); font-size: 15px; line-height: 1.6; text-indent: 0; }
.doc pre[data-copy-kind="message"] code { font: inherit; }

/* And when it does wrap, it says so: the continuation is indented under its
   own line instead of impersonating the next one. */
@supports (text-indent: -16px each-line) {
  .doc > pre:not([data-copy-kind="message"]) {
    padding-left: calc(var(--s-3) + var(--s-2));
    text-indent: -16px each-line;
  }
}

.tok-c { color: var(--dim); }         /* comment */
.tok-k { color: var(--dim); }         /* key, flag, structure */
.tok-v { color: var(--ink); }         /* value you can leave alone */
.tok-y { color: var(--info); }        /* value YOU must supply */
.tok-p { color: var(--dim); }         /* punctuation */
.tok-x { color: var(--accent-text); } /* the command itself */

.code-label {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  margin-bottom: var(--s-1);
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: .04em;
}

/* Callouts: a mono label and prose-size text, because the callouts carry the
   rules that matter most. */
.callout {
  max-width: var(--measure);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-left: 2px solid var(--line-strong);
  border-radius: 0 8px 8px 0;
  background: var(--panel);
}
.callout > .lbl {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 6px;
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  line-height: var(--lh-tight);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.callout > .lbl::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--line-strong); }
.callout p + p { margin-top: var(--s-2); }
.callout.good { border-left-color: var(--accent); }
.callout.good > .lbl { color: var(--accent-text); }
.callout.good > .lbl::before { background: var(--accent); }

.doc table {
  width: 100%;
  max-width: 78ch;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--panel);
  font-size: var(--t-meta);
}
.doc th {
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  font-weight: 400;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-align: left;
}
.doc td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  line-height: var(--lh-tight);
  vertical-align: top;
}
.doc tr:last-child td { border-bottom: 0; }

/* Tables can use the reading column’s gutters. Copy cards keep their content
   inside the frame; a nested pre must never inherit a negative margin. */
@media (min-width: 720px) {
  .doc table {
    max-width: none;
    width: calc(100% + var(--s-3) * 2);
    margin-inline: calc(var(--s-3) * -1);
  }
  .doc table th:first-child,
  .doc table td:first-child { padding-left: var(--s-3); }
  .doc table th:last-child,
  .doc table td:last-child { padding-right: var(--s-3); }
}

/* flex-basis 0, so the pager reads as "back / forward" rather than as two
   more stacked sections. */
.doc-next {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-9);
  padding-top: var(--s-4);
  border-top: 1px solid var(--line);
}
.doc-next a {
  flex: 1 1 0;
  min-width: 0;
  padding: 14px var(--s-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--ink);
  transition: transform .12s ease, border-color .12s ease;
}
.doc-next a:hover { transform: translateY(-1px); border-color: var(--line-strong); text-decoration: none; }
.doc-next a:active { transform: translateY(1px); border-color: var(--line-strong); }
.doc-next .k {
  display: block;
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.doc-next .t { display: block; margin-top: 4px; font-size: var(--t-meta); font-weight: 600; }
.doc-next a.next { text-align: right; }

/* On this page ------------------------------------------------------------ */

/* Below 1180 the rail is gone, so the same list folds into a disclosure at
   the top of the page; it hides the moment the real rail appears. */
.doc-toc {
  max-width: var(--measure);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
}
.doc-toc > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 14px;
  font-size: var(--t-meta);
  font-weight: 600;
  line-height: var(--lh-tight);
  list-style: none;
  cursor: pointer;
}
.doc-toc > summary::-webkit-details-marker { display: none; }
.doc-toc > summary::after { content: "\25BE"; color: var(--dim); font-size: 10px; }
.doc-toc[open] > summary { border-bottom: 1px solid var(--line); }
.doc-toc[open] > summary::after { transform: rotate(180deg); }
.doc-toc ul { margin: 0; padding: var(--s-1) 14px var(--s-2); list-style: none; max-width: none; }
.doc-toc li { padding-left: 0; font-size: var(--t-meta); line-height: var(--lh-tight); }
.doc-toc li + li { margin-top: 0; }
.doc-toc ul > li::before { display: none; }
.doc-toc li a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: var(--s-1) 0;
  color: var(--dim);
  text-decoration: none;
}
.doc-toc li a:hover { color: var(--ink); text-decoration: none; }
.doc-toc li a:active { color: var(--accent-text); }

.toc { display: none; }
@media (min-width: 1180px) {
  .toc {
    display: block;
    position: sticky;
    top: var(--nav-h);
    max-height: calc(100vh - var(--nav-h));
    overflow-y: auto;
    padding-block: var(--s-6) var(--s-4);
  }
}
.toc .lbl {
  margin-bottom: var(--s-2);
  color: var(--dim);
  font-family: var(--mono);
  font-size: var(--t-micro);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.toc ul { margin: 0; padding: 0; list-style: none; }
.toc a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: var(--s-1) 0 var(--s-1) 12px;
  border-left: 1px solid var(--line);
  color: var(--dim);
  font-size: var(--t-meta);
  line-height: var(--lh-tight);
}
.toc a:hover { color: var(--ink); border-left-color: var(--line-strong); text-decoration: none; }
.toc a:active { color: var(--accent-text); }
.toc a.on { color: var(--accent-text); border-left-color: var(--accent); }

/* Doc-page index cards ---------------------------------------------------- */

.next-grid {
  display: grid;
  gap: var(--s-2);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  max-width: 78ch;
}
.next-grid a {
  padding: var(--s-2) var(--s-3) var(--s-3);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--ink);
  transition: transform .12s ease, border-color .12s ease, background-color .12s ease;
}
.next-grid a:hover {
  transform: translateY(-1px);
  border-color: var(--line-strong);
  background: var(--panel-2);
  text-decoration: none;
}
.next-grid a:active { transform: translateY(1px); background: var(--panel-2); }
.next-grid .t {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--t-meta);
  font-weight: 600;
}
.next-grid .t::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.next-grid p { margin-top: 6px; color: var(--dim); font-size: var(--t-meta); line-height: var(--lh-tight); }

/* Small screens ----------------------------------------------------------- */

/* A table cannot be made narrower than its content, so below this width it
   becomes its own scroll region rather than widening the document. */
@media (max-width: 560px) {
  .doc table { display: block; overflow-x: auto; }
}

@media (max-width: 480px) {
  .btn { width: 100%; }
  /* The tertiary link joins the stack rather than hanging off its left edge;
     it keeps no border, so it still reads as the third of three. */
  .btn-quiet { width: 100%; justify-content: center; }
  .btn-row { gap: var(--s-1); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

@media print {
  .nav, .toc, .docs-nav, .doc-toc, .doc-next, .copy, .anchor, .foot { display: none; }
  .copy-wrap { display: block; padding: 0; }
  .docs { display: block; }
  .doc { max-width: none; padding-block: 0; }
  .doc h1, .doc h2, .doc h3 { break-after: avoid; }
  .doc tr { break-inside: avoid; }

  /* Paper is a light surface: graphite type, ivory ground, and no mint at all,
     since mint belongs on graphite. Every rule reads its colour through these
     roles, so inverting them once fixes the whole document. The dark-surface
     lockup has no place on paper, and the pages name the product in their
     crumbs and titles. */
  :root {
    --bg: #f2eee5;
    --panel: #f2eee5;
    --panel-2: #f2eee5;
    --sunken: #f2eee5;
    --line: #a5ada8;
    --line-strong: #626d67;
    --ink: #111315;
    --dim: #2d3431;
    --accent: #111315;
    --accent-hover: #111315;
    --accent-text: #111315;
    --accent-soft: #f2eee5;
    --good: #2d3431;
    --bad: #2d3431;
    --info: #2d3431;
  }

  /* Browsers drop background fills on paper by default, so the primary
     button prints as the outline one rather than as graphite on nothing. */
  .btn.go { border-color: var(--line-strong); background: transparent; color: var(--ink); }

}
