/* 🤖 carlosframework.com/docs — the documentation skin.

   Loaded after site.css, never instead of it: every colour, measure and
   type stack here comes from that file's tokens, so light and dark, the
   focus ring, the scrollbars and the selection colour are all inherited
   rather than restated. What this file adds is the shape site.css has no
   page for — a sidebar, a reference column, and fenced code.

   Same rules as the rest of the site: nothing fetched, no @import, no
   JavaScript. Hairline rules divide. The only cards are the index's nav
   entries, because a label with a blurb is what a card is for. */

/* ---------------------------------------------------------------- tokens -- */

/* The docs sit under the platform, so they take the platform's blue —
   the same values platform/index.html sets inline, by the same
   mechanism, so the two pages are visibly one pair. site.css defines
   these; this is the sanctioned per-page override, not a redefinition. */
:root {
  --accent:      #0d5f88;
  --accent-deep: #094761;
  --accent-soft: rgba(13, 95, 136, 0.10);
  --on-accent:   #ffffff;
}
@media (prefers-color-scheme: dark) {
  :root {
    --accent:      #59bfe8;
    --accent-deep: #93d8f5;
    --accent-soft: rgba(89, 191, 232, 0.13);
    --on-accent:   #04202e;
  }
}

:root {
  /* The one measure site.css lacks. Body copy still sets at 36rem and
     headings at --prose (40rem), but a reference page also carries
     command lines, and the longest in the corpus is 72 characters —
     just past --prose in the mono stack. The column is --prose plus
     that allowance, so the ordinary command sits in its box without
     scrolling and only a genuinely long one has to. */
  --docs-column: 46rem;
}

/* ------------------------------------------------------------ page frame -- */

/* .docs-body carries nothing of its own: site.css's body rule already
   sets the ground, the gutters and the voice, and inventing a
   declaration so the class appears here would be worse than leaving the
   hook alone. Same for .language-sh, further down. */

/* Where you are, in words, above the rule. The masthead's drawn wordmark
   belongs to the pages that are a destination; a reference page gets a
   line of text and gets out of the way. */
.brandline {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-block: 1.5rem 0.9rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.875rem;
  color: var(--muted);
}
.brandline a { color: var(--muted); text-decoration: none; }
.brandline a:hover { color: var(--accent); }
.brandline b { font-weight: 650; letter-spacing: 0.02em; color: inherit; }
.brandline a:hover b { color: inherit; }
.brandline .here { color: var(--ink); font-weight: 600; }

/* The folio is an address, so it sets as data and it is the first thing
   a narrow viewport loses. */
.folio {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.775rem;
  letter-spacing: 0.06em;
  color: var(--muted);
}
@media (max-width: 40rem) { .folio { display: none; } }

/* The sidebar carries 40+ links before the article on every page, and
   there is no search to route around them, so a keyboard user needs a
   way past it. Hidden via the shared .visually-hidden utility (site.css)
   until it receives focus — the idiom that class already establishes —
   at which point every property it hides behind is reasserted visible
   so the link becomes the first thing on the page a sighted keyboard
   user sees. */
.skip-link:focus {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 10;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0.6rem 1rem;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  background: var(--surface);
  color: var(--accent);
  border: 1px solid var(--rule);
  border-radius: 7px;
  box-shadow: var(--shadow-2);
  font-weight: 600;
}

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

.docs-shell {
  max-width: var(--wrap);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2rem;
  padding-block: clamp(1.75rem, 4vw, 3rem);
  align-items: start;
}

/* Wide screens (Paul, 2026-11-06, after Stripe's docs): the nav is pinned
   hard-left at full height, a fixed head (title and search) over a list
   that scrolls on its own, so nothing moves as you go between pages. The
   page's scrollbar gutter is always reserved for the same reason. Below
   this the nav keeps its document order and stacks above the content,
   with only the current section's pages listed. */
html { scrollbar-gutter: stable; }
@media (min-width: 60rem) {
  .docs-body { padding-inline: 0; --page-gutter: 0px; }
  .docs-body .masthead { padding-inline: 1.25rem clamp(2rem, 5vw, 4.5rem); }
  .docs-shell {
    max-width: none;
    margin: 0;
    padding: 0;
    gap: 0;
    grid-template-columns: 17rem minmax(0, 1fr);
  }
  .docs-nav {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-right: 1px solid var(--rule);
    background: var(--bg);
  }
  .nav-head { flex: none; padding: 1.5rem 1.25rem 1rem; border-bottom: 1px solid var(--rule-soft); }
  .docs-nav .nav-groups { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0.4rem 1.25rem 3rem; }
  .docs-body main { padding: clamp(1.75rem, 4vw, 3rem) clamp(2rem, 5vw, 4.5rem) 4rem; min-width: 0; }
}

/* On this page: the page's ## headings in a rail, once there is room. */
.docs-toc { display: none; }
@media (min-width: 80rem) {
  .docs-shell.has-toc { grid-template-columns: 17rem minmax(0, 1fr) 15rem; }
  .docs-toc {
    display: block;
    position: sticky;
    top: 0;
    max-height: 100vh;
    overflow-y: auto;
    padding: clamp(1.75rem, 4vw, 3rem) 1.5rem 3rem 0;
    font-size: 0.86rem;
  }
  .docs-toc-title { margin: 0 0 0.5rem; font-size: 0.715rem; font-weight: 600; letter-spacing: 0.11em; text-transform: uppercase; color: var(--muted); }
  .docs-toc ul { list-style: none; margin: 0; padding: 0; }
  .docs-toc li + li { margin-top: 0.3rem; }
  .docs-toc a { color: var(--ink-2); text-decoration: none; }
  .docs-toc a:hover { color: var(--accent); }
}

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

.docs-nav { font-size: 0.94rem; }
.docs-nav ul { list-style: none; }
.docs-nav li { margin-top: 0.15rem; }

.docs-nav a {
  display: block;
  padding: 0.22rem 0 0.22rem 0.7rem;
  border-left: 2px solid transparent;
  color: var(--ink-2);
  text-decoration: none;
}
.docs-nav a:hover { color: var(--ink); border-left-color: var(--rule); }

/* The page you are on, marked where the eye scans for it. Keyed to the
   class the template stamps alongside aria-current. */
.docs-nav a.active {
  color: var(--accent);
  border-left-color: var(--accent);
  font-weight: 620;
}

.docs-nav-title {
  margin: 0 0 1.1rem;
  font-size: 1rem;
  font-weight: 650;
  letter-spacing: -0.012em;
}
.docs-nav-title a { color: var(--ink); padding-left: 0; border-left: 0; }
.docs-nav-title a:hover { border-left: 0; color: var(--accent); }
.docs-nav-title a.active { border-left: 0; }

/* A section label, not a heading and not data — so it is tracked small
   caps in the voice face, never mono. */
.docs-nav-section {
  margin: 1.5rem 0 0.45rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--rule-soft);
  font-size: 0.715rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--muted);
}
.docs-nav-title + .docs-nav-section { margin-top: 0; padding-top: 0; border-top: 0; }

/* The open page's own sections, indented under it against a hairline. */
.docs-subnav {
  margin: 0.3rem 0 0.65rem 0.7rem;
  padding-left: 0.55rem;
  border-left: 1px solid var(--rule);
  font-size: 0.875rem;
}
.docs-subnav li { margin-top: 0; }
.docs-subnav a {
  padding: 0.16rem 0 0.16rem 0.45rem;
  border-left: 0;
  color: var(--muted);
}
.docs-subnav a:hover { border-left: 0; color: var(--accent); }

/* --------------------------------------------------------------- article -- */

.docs-article { max-width: var(--docs-column); min-width: 0; }

.docs-article h1 {
  font-size: clamp(2rem, 4.4vw, 2.9rem);
  letter-spacing: -0.035em;
  line-height: 1.05;
  font-weight: 700;
}
.docs-article h1 + p { margin-top: 1.25rem; font-size: 1.1rem; color: var(--ink-2); }

/* A group of commands opens on a full rule; the reference reads as a
   run of divided entries rather than a stack of boxes. */
.docs-article h2 {
  margin-top: clamp(3rem, 6vw, 4.5rem);
  padding-top: clamp(1.75rem, 3.5vw, 2.5rem);
  border-top: 1px solid var(--rule);
  font-size: clamp(1.5rem, 2.8vw, 2rem);
  max-width: var(--prose);
}

/* Every h3 on this page is a command — something you type — so it sets
   in the mono stack under the house rule that mono carries identifiers.
   That is the whole licence: the prose beneath it stays in the voice. */
.docs-article h3 {
  margin-top: 2.5rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--rule-soft);
  font-family: var(--font-mono);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.docs-article h2 + h3 { margin-top: 1.75rem; padding-top: 0; border-top: 0; }

.docs-article h4 {
  margin-top: 1.9rem;
  font-size: 0.98rem;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.docs-article :is(h1, h2, h3, h4) { scroll-margin-top: 1.5rem; }

.docs-article p {
  margin-top: 1.05rem;
  color: var(--ink-2);
  max-width: 36rem;
}
.docs-article :is(h1, h2, h3, h4) + p { margin-top: 0.85rem; }
.docs-article em { color: var(--ink-2); }

/* Markdown the current corpus does not use yet but the next page will:
   lists, tables and rules, in the same hairline world. Kept short on
   purpose — this is the floor, not a theme. */
.docs-article ul:not(.docs-cards),
.docs-article ol {
  margin-top: 1rem;
  padding-left: 1.25rem;
  max-width: 36rem;
  color: var(--ink-2);
}
.docs-article li + li { margin-top: 0.35rem; }
.docs-article blockquote {
  margin-top: 1.15rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: color-mix(in srgb, var(--ink) 3%, transparent);
  color: var(--muted);
  max-width: 36rem;
}
.docs-article hr {
  margin-block: 2.25rem;
  border: 0;
  border-top: 1px solid var(--rule);
}
.docs-article table {
  margin-top: 1.25rem;
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}
.docs-article :is(th, td) {
  text-align: left;
  padding: 0.6rem 0.9rem 0.6rem 0;
  border-top: 1px solid var(--rule-soft);
  vertical-align: baseline;
}
.docs-article th { font-weight: 620; color: var(--ink); }

/* ------------------------------------------------------------------ code -- */

/* A fence is a box that scrolls itself. The page must never scroll
   sideways because a command line was long, and site.css's body
   overflow-x: hidden would clip it rather than let the reader see it —
   so the overflow belongs here, on the pre. */
.docs-article pre {
  margin-top: 1.15rem;
  max-width: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding: 0.9rem 1.05rem;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--bg-sunk);
  -webkit-overflow-scrolling: touch;
}
.docs-article p + pre { margin-top: 0.9rem; }

/* site.css gives inline code an accent chip; inside a fence that chip
   would tile the whole block, so it is undone here. */
.docs-article pre code {
  display: block;
  background: none;
  color: var(--ink);
  padding: 0;
  border-radius: 0;
  font-size: 0.855rem;
  line-height: 1.6;
  white-space: pre;
}

/* The class markdown-it stamps on a fence's language is left unstyled
   on purpose: the site ships no highlighter, and a reference page reads
   better as plain text than as pretend syntax colour. */

/* ------------------------------------------------------------- the index -- */

/* The one deliberate card on either page: an entry per doc, a label and
   a line saying what is inside it. Nothing else here is a card. */
.docs-cards {
  margin-top: 1.25rem;
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 1fr);
  list-style: none;
}
@media (min-width: 46rem) {
  .docs-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.docs-cards li {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 1.25rem 1.3rem 1.35rem;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--surface);
  transition: border-color 160ms, box-shadow 160ms, transform 160ms cubic-bezier(.2,.7,.3,1);
}
.docs-cards li:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-2);
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .docs-cards li, .docs-cards li:hover { transform: none; transition: none; }
}
.docs-cards a { text-decoration: none; }
.docs-cards a strong { font-size: 1.05rem; letter-spacing: -0.015em; color: var(--accent); }
.docs-cards a:hover strong { text-decoration: underline; text-underline-offset: 0.18em; }
.docs-cards span { font-size: 0.955rem; color: var(--ink-2); }

/* The index's card sections are dividers like any other h2, but they
   head a grid rather than prose, so they need less air under them. */
.docs-article h2 + .docs-cards { margin-top: 1.5rem; }

/* ------------------------------------------------------------------ feet -- */

.docs-foot {
  margin-top: clamp(3rem, 6vw, 4.5rem);
  padding-top: 1.15rem;
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
  color: var(--muted);
  max-width: 36rem;
}

/* site.css already gives <footer> the wrap, the rule and the muted
   voice; only the provenance line needs anything of its own. */
.docs-sitefoot { margin-top: clamp(2rem, 5vw, 3.5rem); }
.docs-provenance { font-size: 0.85rem; }
.docs-provenance code { font-size: 0.8rem; }

/* Let the article shrink inside the grid; wide code scrolls within its block. */
.docs-shell > main { min-width: 0; width: 100%; }
.docs-article { overflow-wrap: anywhere; }

/* -------------------------------------------------------------- diagrams -- */

/* Figures from ```diagram and ```stepper fences (hack/docs-markdown.mjs).
   Their SVGs are inlined, so shapes take these colours: an SVG marks its
   parts with class="shape", "shape group", "shape dim" or "shape on";
   lines with "line", "line dim" or "line on"; text with "small", "dim"
   or "on". Nothing else is styled, so a diagram reads in light and dark. */
.docs-article .diagram { margin: 1.75rem 0; }
.docs-article .diagram svg { display: block; width: 100%; height: auto; }
.diagram .shape { fill: var(--surface); stroke: var(--rule); stroke-width: 1.5; }
.diagram .shape.group { fill: none; stroke-dasharray: 5 4; }
.diagram .shape.dim { stroke: var(--rule-soft); fill: var(--bg-sunk); }
.diagram .shape.on { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; }
.diagram .line { stroke: var(--ink-2); stroke-width: 1.5; fill: none; }
.diagram .line.on { stroke: var(--accent); stroke-width: 2.5; }
.diagram .line.dim { stroke: var(--rule); }
.diagram text { fill: var(--ink); font-family: var(--font-sans); font-size: 14px; }
.diagram text.small { fill: var(--ink-2); font-size: 12px; }
.diagram text.dim { fill: var(--muted); }
.diagram text.on { fill: var(--accent-deep); font-weight: 600; }
.docs-article .diagram figcaption { margin-top: 0.6rem; color: var(--ink-2); font-size: 0.95rem; }

/* A stepper without JavaScript: every frame, numbered, in order. */
.docs-article ol.frames { margin: 0; padding: 0; list-style: none; counter-reset: frame; }
.docs-article ol.frames > li.frame { counter-increment: frame; margin: 0 0 1.5rem; padding: 0.9rem 1rem; border: 1px solid var(--rule); }
.docs-article ol.frames > li + li { margin-top: 0; }
.docs-article li.frame figcaption::before { content: "Step " counter(frame) ". "; font-weight: 600; color: var(--ink); }
.stepper-controls { display: none; }

/* With docs-stepper.js: one frame at a time, Back and Next. */
.stepper.is-enhanced li.frame { display: none; margin: 0; }
.stepper.is-enhanced li.frame.is-current { display: block; animation: frame-in 180ms ease-out; }
.stepper.is-enhanced li.frame figcaption { display: none; }
.stepper.is-enhanced .stepper-controls { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.75rem; }
.stepper-controls button { padding: 0.4rem 0.9rem; border: 1px solid var(--ink-2); background: var(--surface); color: var(--ink); font: inherit; cursor: pointer; }
.stepper-controls button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-deep); }
.stepper-controls button:disabled { opacity: 0.4; cursor: default; }
.stepper-controls .stepper-count { color: var(--muted); font-size: 0.9rem; }
.stepper-caption { flex-basis: 100%; margin: 0.25rem 0 0; color: var(--ink-2); }
@keyframes frame-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .stepper.is-enhanced li.frame.is-current { animation: none; }
  .stepper * { transition-duration: 0s !important; animation-duration: 0s !important; }
}
@media print {
  .stepper.is-enhanced li.frame { display: block; margin: 0 0 1rem; }
  .stepper.is-enhanced li.frame figcaption { display: block; }
  .stepper-controls { display: none !important; }
}
/* Narrow screens: a diagram keeps a readable size and scrolls sideways in
   its own box, never the page. */
@media (max-width: 30rem) {
  .docs-article .diagram figure, .docs-article figure.diagram { overflow-x: auto; }
  .docs-article .diagram svg { min-width: 36rem; }
}

/* ------------------------------------------------- nav head and search -- */

.nav-head .docs-nav-title { margin: 0 0 0.35rem; }
.nav-head .docs-nav-title + .docs-nav-title { margin-bottom: 0; }

/* Search: a button-like box. Without JavaScript it goes to the page index
   on /docs/; with docs-search.js, a click or "/" opens a dialog. */
.docs-nav a.docs-search {
  display: flex; align-items: center; gap: 0.55rem;
  margin: 0.9rem 0 0; padding: 0.5rem 0.65rem;
  border: 1px solid var(--rule); border-radius: 6px;
  background: var(--surface); color: var(--muted);
  font-size: 0.9rem; line-height: 1.2; text-decoration: none;
}
.docs-nav a.docs-search:hover, .docs-nav a.docs-search:focus-visible { border-color: var(--ink-2); color: var(--ink); }
.docs-search svg { flex: none; }
.docs-search span { flex: 1; }
.docs-search kbd {
  padding: 0.05rem 0.4rem; border: 1px solid var(--rule); border-radius: 4px;
  font: 0.78rem/1.4 var(--font-mono); color: var(--muted); background: var(--bg-sunk);
}

/* Section labels are links to their part of /docs/, lined up with the
   title rather than indented like the pages under them. */
.docs-nav a.docs-nav-section { display: block; padding-left: 0; border-left: 0; color: var(--muted); }
.docs-nav a.docs-nav-section:hover { color: var(--ink); border-left: 0; }
.docs-nav .nav-group:first-child .docs-nav-section { margin-top: 0.9rem; padding-top: 0; border-top: 0; }
.docs-nav .nav-group ul { margin: 0; padding: 0; }

/* Narrow screens (Paul's mockup review): the nav collapses to one row of
   section labels that scrolls sideways in its own box, each linking to its
   part of /docs/, so the article starts near the top of the screen. */
@media (max-width: 59.99rem) {
  .docs-nav .nav-groups { display: flex; gap: 1.1rem; overflow-x: auto; margin-top: 0.9rem; padding-bottom: 0.4rem; white-space: nowrap; scrollbar-width: thin; }
  .docs-nav .nav-group ul { display: none; }
  .docs-nav .nav-group .docs-nav-section,
  .docs-nav .nav-group:first-child .docs-nav-section { margin: 0; padding: 0.3rem 0; border-top: 0; }
  .docs-nav .nav-group.is-current .docs-nav-section { color: var(--accent); }
}

/* The page index on /docs/: every page, A to Z, with its section. */
.docs-article ul.docs-page-index { columns: 2 16rem; padding-left: 0; list-style: none; }
.docs-article ul.docs-page-index > li + li { margin-top: 0.3rem; }
.docs-page-index span { color: var(--muted); font-size: 0.82rem; }

/* --------------------------------------------------------- search dialog -- */

dialog.search-dialog {
  width: min(36rem, calc(100vw - 2rem)); margin: 12vh auto auto; padding: 0;
  border: 1px solid var(--rule); border-radius: 10px;
  background: var(--surface); color: var(--ink); box-shadow: var(--shadow-2);
}
dialog.search-dialog::backdrop { background: rgb(0 0 0 / 0.35); }
.search-dialog form { display: flex; align-items: center; border-bottom: 1px solid var(--rule); }
.search-dialog input { flex: 1; min-width: 0; padding: 0.9rem 1rem; border: 0; background: transparent; color: var(--ink); font: inherit; font-size: 1.05rem; outline: none; }
.search-close { flex: none; margin-right: 0.5rem; width: 2rem; height: 2rem; border: 0; border-radius: 6px; background: transparent; color: var(--muted); font-size: 1.35rem; line-height: 1; cursor: pointer; }
.search-close:hover, .search-close:focus-visible { background: var(--bg-sunk); color: var(--ink); }
.search-dialog ul { margin: 0; padding: 0.4rem; list-style: none; max-height: 50vh; overflow-y: auto; }
.search-dialog li { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.search-dialog li a { flex: 1; padding: 0.45rem 0.6rem; border-radius: 6px; color: var(--ink); text-decoration: none; }
.search-dialog li a:hover, .search-dialog li a:focus-visible { background: var(--accent-soft); color: var(--accent-deep); outline: none; }
.search-dialog li span { padding-right: 0.6rem; color: var(--muted); font-size: 0.82rem; white-space: nowrap; }
.search-dialog .search-empty { padding: 0.6rem; color: var(--muted); }
.search-dialog .search-hint { margin: 0; padding: 0.5rem 1rem; border-top: 1px solid var(--rule-soft); color: var(--muted); font-size: 0.8rem; }
