/* #264 — the public guide (/guide, /guide/<section>), rendered by
   `server/src/guide.rs`.

   Its OWN token universe, like the landing page's inline CSS and `/terms`: this
   sheet ships to a page that carries no bundle, so it defines every colour it
   uses and inherits nothing from the app's `styles.css`. Dark only, for the same
   reason the landing is (CLAUDE.md → #90 theming).

   Class prefix is `g-` throughout so nothing here can be confused with the app's
   `.guide-*` rules, which style the SAME content inside the SPA. `table.gset`
   and its chips are the one deliberate overlap: the print-settings table is one
   design in two places, and copying the class names keeps them recognisably the
   same table. */

:root {
  --ink: #17181c;
  --surface: #1e2025;
  --surface-2: #26282e;
  --bone: #f4f2ec;
  --muted: #a2a49f;
  --border: #34363d;
  --rule: #43454d;
  --accent: #ee5a45;
  --accent-ink: #f4765f;
  --accent-soft: #3a221e;
  --teal: #11a597;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px -14px rgba(0, 0, 0, 0.7);
  --crumb-h: 52px;
  color-scheme: dark;
}

@font-face {
  font-family: "Space Grotesk";
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/space-grotesk-400.woff2") format("woff2");
}
@font-face {
  font-family: "Space Grotesk";
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/space-grotesk-600.woff2") format("woff2");
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: "Space Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;
  font-size: var(--fs-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

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

h1,
h2,
h3 {
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}
h1 {
  font-size: var(--fs-display);
  line-height: 1.12;
}
h3 {
  font-size: var(--fs-h3);
  margin: 20px 0 6px;
}
p {
  margin: 0 0 14px;
  max-width: 68ch;
}
strong {
  font-weight: 600;
}
/* The app paints <em> as a chip for UI names; the public pages do the same, so
   the same sentence reads the same way in both places. */
em {
  font-style: normal;
  font-weight: 600;
  font-size: 0.92em; /* relative on purpose — a chip inside running text */
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.05em 0.36em;
  white-space: nowrap;
}

:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 2px;
  border-radius: 4px;
}

.g-skip {
  position: absolute;
  left: -9999px;
}
.g-skip:focus {
  left: 12px;
  top: 12px;
  z-index: 20;
  background: var(--surface);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 8px 14px;
}

/* ---------------------------------------------------------------- masthead */

/* #264 (David's decision 3): the header is `public.css`'s `.p-top` now — the
   landing's, shared rather than copied. This maps the guide's palette onto the
   tokens that component references, and supplies the one button style it needs.
   `public.css` still defines no colour of its own. */
:root {
  --hdr-bg: color-mix(in srgb, var(--ink) 82%, transparent);
  --hdr-line: color-mix(in srgb, var(--border) 60%, transparent);
  --hdr-text: var(--bone);
  --hdr-mut: var(--muted);
}
.p-top .btn.primary {
  background: var(--accent);
  color: var(--ink);
  font-weight: var(--w-head);
  font-size: var(--fs-small);
  border-radius: 999px;
  padding: 0 16px;
  min-height: 34px;
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  white-space: nowrap;
}
.p-top .btn.primary:hover {
  filter: brightness(1.06);
  text-decoration: none;
}

/* ------------------------------------------------- A, and its breadcrumb form

   ONE scroll threshold with hysteresis (on at 90px, off at 60px), so a trackpad's
   sub-pixel scrolling cannot flicker the bar. `guide.js` owns the numbers; this
   sheet only knows the two states. */

.g-crumb {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(23, 24, 28, 0.94);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  /* Trimmed from 11px when the steps grew their own vertical padding, so the bar
     stays inside `--crumb-h` and the scroll-margin offsets below stay honest. */
  padding: 7px 24px;
  display: flex;
  align-items: center;
  gap: 14px;
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
  transition: opacity 0.24s ease, transform 0.24s ease;
}
body.scrolled .g-crumb {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.g-crumb-home {
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--muted);
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 30px;
}
.g-crumb ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  flex: 1;
  min-width: 0;
  max-width: 780px;
}
.g-crumb-step {
  display: flex;
  align-items: center;
  font-size: var(--fs-micro);
  font-weight: 600;
  min-width: 0;
}
.g-crumb-step:not(:last-child) {
  flex: 1;
}
.g-crumb-step a {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* WCAG 2.5.8 (AA) wants 24x24. The step was 21px tall, which is the one target
     on the page that missed the AA floor rather than the AAA one, and it is the
     primary way between stages once the cards have scrolled away. */
  min-height: 30px;
  padding: 4px 0;
}
.g-crumb-step:not(:last-child)::after {
  content: "";
  flex: 1;
  height: 2px;
  background: var(--border);
  margin: 0 10px;
  border-radius: 2px;
}
.g-crumb-dot {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 21px;
  height: 21px;
  border-radius: 999px;
  border: 2px solid var(--rule);
  font-size: var(--fs-label);
}
.g-crumb-step.on a {
  color: var(--bone);
}
.g-crumb-step.on .g-crumb-dot {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--ink);
}
.g-crumb-step.done .g-crumb-dot {
  border-color: var(--accent);
  color: var(--accent-ink);
}
.g-crumb-step.done::after {
  background: var(--accent);
}

.g-main {
  max-width: 1080px;
  margin: 0 auto;
  padding: 34px 24px 90px;
}
.g-lede {
  font-size: var(--fs-lede);
  color: var(--muted);
  max-width: 62ch;
  margin: 10px 0 26px;
}

.g-stagea {
  transition: opacity 0.28s ease;
}
body.scrolled .g-stagea {
  opacity: 0.55;
}
body.scrolled .g-stagea:hover,
body.scrolled .g-stagea:focus-within {
  opacity: 1;
}

.g-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.g-card {
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  background: var(--surface);
  color: var(--bone);
}
.g-card:hover {
  border-color: var(--rule);
  text-decoration: none;
}
.g-card.on {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.g-card-n {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}
.g-card.on .g-card-n {
  color: var(--accent-ink);
}
.g-card-t {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.g-card-d {
  font-size: var(--fs-micro);
  color: var(--muted);
  line-height: 1.45;
}

/* the index page's two reference cards */
.g-refs {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin: 12px 0 0;
}
/* On the INDEX the cards sit outside `.g-stagea` with only prose after them, so
   they keep their old breathing room. On a section page they are inside it and
   the block that follows brings its own margin. */
.g-stagea + .g-refs {
  margin-bottom: 22px;
}
.g-ref.on {
  border-color: var(--accent);
  background: var(--accent-soft);
}
.g-ref {
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 14px;
  background: var(--surface);
  color: var(--bone);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.g-ref:hover {
  border-color: var(--rule);
  text-decoration: none;
}
.g-ref span {
  font-size: var(--fs-micro);
  color: var(--muted);
}

/* ------------------------------------------------------------ C: track pills */

.g-tracks {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-top: 26px;
}
.g-tracks-l {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}
.g-pills {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.g-pill {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 15px;
  font: inherit;
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  cursor: pointer;
}
.g-pill:hover {
  border-color: var(--rule);
}
.g-pill.on {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--ink);
}
.g-tracks-h {
  font-size: var(--fs-micro);
  color: var(--muted);
}

/* --------------------------------------------------- D: nav + folded articles */

.g-body {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr);
  gap: 30px;
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
  align-items: start;
}
.g-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  top: calc(var(--crumb-h) + 12px);
}
/* #264 G4/A2 option A. On desktop the `<details>` is invisible machinery: the
   summary is hidden and the list renders exactly as it always did, because a
   sidebar was never the problem. The whole of the collapse lives in the
   max-width: 900px block at the foot of this file. */
.g-nav-d {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.g-nav-d > summary {
  display: none;
}
.g-nav-d > summary::-webkit-details-marker {
  display: none;
}
.g-nav-g {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 2px 6px 4px;
  opacity: 0.75;
}
.g-nav-i {
  /* **Blockified here, not by the flex container.** Before G4/A2 these were
     direct children of a `display: flex` `<nav>`, which blockified them for
     free. They are inside a `<details>` now, and Chrome slots a details' content
     into `::details-content` — a block box — so they are children of THAT, not
     flex items of `.g-nav-d`, and they went back to `display: inline` and
     reflowed as a paragraph of link text. The same `::details-content`
     mechanism that makes `getClientRects()` lie about a closed article
     (`useDialogFocus`). Setting it on the item itself works in every engine and
     does not depend on which box the content ends up in. */
  display: block;
  margin-bottom: 2px;
  font-size: var(--fs-micro);
  color: var(--muted);
  padding: 5px 8px;
  border-radius: 5px;
}
.g-nav-i:hover {
  background: var(--surface);
  color: var(--bone);
  text-decoration: none;
}
.g-nav-i.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 600;
}
.g-away {
  font-size: var(--fs-label);
  color: var(--accent-ink);
  white-space: nowrap;
}

.g-arts {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.g-art {
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--surface);
  /* Clears the sticky breadcrumb when a deep link lands on this article. */
  scroll-margin-top: calc(var(--crumb-h) + 14px);
}
.g-art > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  cursor: pointer;
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.01em;
  list-style: none;
}
.g-art > summary::-webkit-details-marker {
  display: none;
}
/* The article title is a real `<h2>` inside the summary (the accessible
   disclosure pattern), so it has to be reset to the summary's own type rather
   than arriving at h2 metrics. */
.g-art > summary h2 {
  font: inherit;
  letter-spacing: inherit;
  margin: 0;
  min-width: 0;
}
.g-art > summary::after {
  content: "›";
  margin-left: auto;
  color: var(--muted);
  font-size: 17px; /* the disclosure marker glyph, not type */
  transition: transform 0.18s ease;
}
.g-art[open] > summary::after {
  transform: rotate(90deg);
}
.g-art[open] > summary {
  border-bottom: 1px solid var(--border);
}
.g-art-b {
  padding: 14px 16px 4px;
  font-size: var(--fs-body);
  color: var(--bone);
}
.g-art-b > :last-child {
  margin-bottom: 12px;
}
.g-art-b ul,
.g-art-b ol {
  margin: 0 0 14px;
  padding-left: 22px;
  max-width: 68ch;
}
.g-art-b li {
  margin-bottom: 8px;
}
.g-art-b li::marker {
  color: var(--accent-ink);
}
.g-note {
  color: var(--muted);
  font-size: var(--fs-small);
  border-left: 2px solid var(--rule);
  padding-left: 12px;
}
.g-check {
  list-style: none;
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 6px;
}
.g-check li {
  font-size: var(--fs-small);
  padding-left: 22px;
  position: relative;
}
.g-check li::before {
  content: "✓";
  position: absolute;
  left: 0;
  color: var(--teal);
  font-weight: 600;
}

.g-badge {
  font-size: var(--fs-label);
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 4px;
  background: var(--accent-soft);
  color: var(--accent-ink);
  white-space: nowrap;
}
.g-badge.away {
  background: transparent;
  border: 1px solid var(--accent);
}

/* An article that lives on another page: it NAVIGATES, and it looks like it. */
.g-art-away {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 13px 16px;
  color: var(--bone);
}
.g-art-away:hover {
  border-color: var(--accent);
  text-decoration: none;
}
.g-art-away-h {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-small);
  font-weight: 600;
}
.g-art-away > span:last-child {
  font-size: var(--fs-micro);
  color: var(--muted);
}

/* -------------------------------------------------------------- the sign-up */

.g-signup {
  margin-top: 16px;
  border: 1px solid var(--accent);
  border-radius: 9px;
  background: var(--accent-soft);
  padding: 18px;
}
.g-signup b {
  font-size: var(--fs-h3);
}
.g-signup p {
  margin: 6px 0 12px;
  font-size: var(--fs-small);
  color: var(--bone);
}
.g-cta {
  display: inline-block;
  background: var(--accent);
  color: var(--ink);
  border-radius: 7px;
  padding: 9px 17px;
  font-size: var(--fs-small);
  font-weight: 600;
}
.g-cta:hover {
  text-decoration: none;
  filter: brightness(1.06);
}

/* ------------------------------------------------------- the style reference */

.g-styles {
  list-style: none;
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
}
.g-style {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.g-style img {
  width: 100%;
  aspect-ratio: 1;
  height: auto;
  border-radius: 7px;
  border: 1px solid var(--border);
  background: var(--surface-2);
}
.g-style b {
  font-size: var(--fs-small);
}
.g-style span {
  font-size: var(--fs-micro);
  color: var(--muted);
  line-height: 1.5;
}

/* ------------------------------------------------------------- data tables

   `.g-tablewrap` is load-bearing, not decoration: `table.gset` carries a
   min-width, and a bare one overflows the PAGE on a phone (the 2026-08-11 audit
   measured 302px of overflow at 375). Every .gset goes inside one. */

.g-tablewrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 0 0 16px;
}
table.gset {
  border-collapse: collapse;
  width: 100%;
  min-width: 640px;
  font-size: var(--fs-small);
  table-layout: fixed;
}
table.gset th,
table.gset td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
  white-space: normal;
}
table.gset th {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
  border-bottom-color: var(--rule);
}
table.gset tbody tr:last-child td {
  border-bottom: 0;
}
table.gset .gset-grp td {
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-ink);
  background: var(--surface-2);
}
.gset-s {
  width: 26%;
  font-weight: 600;
}
.gset-c {
  width: 17%;
}
.gset-why {
  color: var(--muted);
}
.gset-chip {
  display: inline-block;
  font-size: var(--fs-micro);
  font-weight: 600;
  border-radius: 4px;
  padding: 2px 7px;
  border: 1px solid var(--border);
  color: var(--muted);
}
.gset-chip.auto {
  border-color: var(--teal);
  color: var(--teal);
}
.gset-chip.tune {
  border-color: var(--accent);
  color: var(--accent-ink);
}

/* One nozzle's columns at a time. Every value for every nozzle is in the markup,
   so a crawler and a no-JS reader still get all four; the tabs only change which
   is on screen. #194: exactly FOUR columns are ever visible, which is why a group
   row spans four. */
table.gset .gset-v,
table.gset .gset-c span {
  display: none;
}
table.gset.n02 .v02,
table.gset.n04 .v04,
table.gset.n06 .v06,
table.gset.n08 .v08 {
  display: table-cell;
}
table.gset.n02 .gset-c span.v02,
table.gset.n04 .gset-c span.v04,
table.gset.n06 .gset-c span.v06,
table.gset.n08 .gset-c span.v08 {
  display: inline-block;
}

.g-noztabs {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 0 0 12px;
}
.g-noztabs button {
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  border-radius: 999px;
  padding: 5px 13px;
  font: inherit;
  font-size: var(--fs-small);
  font-weight: 600;
  cursor: pointer;
}
.g-noztabs button.on {
  border-color: var(--accent);
  color: var(--accent-ink);
  background: var(--accent-soft);
}
/* No JS means no tab switching, so the tabs would be a lie. The script un-hides
   them; until then only the default nozzle's column shows, which is exactly what
   the markup already says. */
.g-noztabs {
  display: none;
}
body.js .g-noztabs {
  display: flex;
}

.g-foot {
  max-width: 1080px;
  margin: 0 auto;
  padding: 22px 24px 40px;
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: var(--fs-micro);
}
.g-foot a {
  color: var(--muted);
  /* #264 review: the AA 24x24 floor. Measured at 17px before. These four are a
     list of destinations, not links inside a sentence, so 2.5.8's inline
     exception does not cover them — the three PROSE links in the articles
     measure 18-19px and are exempt, and are deliberately left alone: padding
     them would break the line rhythm for nothing. */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

@media (max-width: 900px) {
  .g-body {
    grid-template-columns: 1fr;
    /* Tightened with the collapse (#264 G4/A2). These four numbers were spacing
       for a 363px sidebar-turned-stack; around a 44px disclosure row the same
       values read as a gap with nothing in it, and they cost 28px of the thing
       this change exists to buy. */
    gap: 10px;
    margin-top: 14px;
    padding-top: 14px;
  }
  .g-nav {
    position: static;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
  }
  /* #264 G4/A2 option A — measured: this list is 363px on a 812px-tall phone,
     and collapsing it recovers 320 of them. */
  .g-nav-d > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    /* 44px, not the 24px WCAG 2.5.8 floor: this is the control that stands
       between a reader and the page's contents, and it is the only one in the
       row. G6 fixed the crumb steps to 24; there is no reason to be tight here. */
    min-height: 44px;
    padding: 4px 2px;
    cursor: pointer;
    list-style: none;
    border-radius: 6px;
  }
  .g-nav-d > summary:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
  .g-nav-d[open] > summary {
    margin-bottom: 4px;
  }
  /* The collapsed line says WHERE YOU ARE, which the open list could only show
     by being open. `guide.js` keeps it in step with the same scroll spy that
     marks `.g-nav-i.on` (#264 review G2), so the summary is strictly more
     informative than the thing it replaces. */
  .g-nav-cur {
    font-size: var(--fs-micro);
    color: var(--bone);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }
  .g-nav-cur::before {
    content: "\2014\a0";
    color: var(--muted);
    font-weight: 400;
  }
  .g-nav-cur:empty::before {
    content: none;
  }
  .g-nav-d > summary::after {
    content: "\25be";
    margin-left: auto;
    color: var(--muted);
    transition: transform 0.15s ease;
  }
  .g-nav-d[open] > summary::after {
    transform: rotate(180deg);
  }
  .g-nav-g {
    padding-left: 0;
  }
  /* #264 G4/A2 option C — measured: stacked, the three stage cards are 310px and
     the two reference cards 171px; laid on their side they are 112 and 98, which
     recovers 271px WITHOUT moving a single cross-page link out of its position.
     That last part is why C was chosen over moving them below the articles: #163
     put these on every page on purpose. */
  .g-cards,
  .g-refs {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 78%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    /* the 22% of the next card left showing IS the affordance — a scroller whose
       last item is flush with the edge reads as a full-width card and nobody
       swipes it */
    padding-bottom: 4px;
    scrollbar-width: thin;
  }
  .g-card,
  .g-ref {
    scroll-snap-align: start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .g-crumb,
  .g-stagea,
  .g-art > summary::after {
    transition: none;
  }
}
