/* ==========================================================================
   Stoneware documentation site — "celadon on stoneware"
   --------------------------------------------------------------------------
   Grey stoneware body, celadon glaze. Celadon is the jade-green glaze that
   comes out of a reduction firing, so the palette is the material the tool is
   named for.

   Every rule lives in this file on purpose. The site runs under Stoneware's default
   Content-Security-Policy (`style-src 'self'`, no unsafe-inline), which blocks
   inline <style> blocks and style="" attributes alike. Islands that need to
   drive a value at runtime write a custom property through the CSSOM instead,
   which CSP does not govern.

   Fonts are system stacks for the same reason: font-src 'self' means no CDN.
   The stacks are chosen for character, not availability alone.
   ========================================================================== */

/* --- Palette -------------------------------------------------------------- */

/* Fired and unfired: the same clay, before and after the kiln.

   One set of tokens rather than two. `light-dark()` resolves against the used
   `color-scheme`, so switching themes is a single property on <html> and no
   token is ever declared twice - there is no second palette to forget to
   update. The stylesheet already leans on `color-mix(in oklab, …)` throughout,
   which shipped in the same generation of browsers, so this adds no new floor.

   Reading order inside each: light first, then dark. */

:root {
  /* Both are supported; with neither forced, the OS preference decides. */
  color-scheme: light dark;

  /* Sampled from the brand sheet rather than approximated. The fired body is a
     cool blue-grey stone (#111724), not the green-tinted dark it used to be,
     and the glaze runs teal rather than green. */
  --stone-900: light-dark(#f4f4f3, #0d121b);
  --stone-850: light-dark(#eeeeed, #111726);
  --stone-800: light-dark(#e8e8e6, #151c2b);
  --stone-700: light-dark(#dedcdb, #1c2434);
  --stone-600: light-dark(#cfcdcb, #262f3f);
  --line: light-dark(#bdbbb9, #303a4a);
  --line-soft: light-dark(#dad8d6, #1d2534);

  /* Warm cream on cool stone - the contrast the wordmark relies on. */
  --chalk: light-dark(#16191c, #f6f0e9);
  --ash: light-dark(#5b5f63, #9aa6b2);
  --ash-dim: light-dark(#6d7176, #6b7684);

  /* Unfired, the glaze has not brightened yet: the light values run darker
     than the surface rather than lighter, which is also what keeps them
     legible on it. --mint stays the emphatic end of the range in both, so
     link hover moves further from the background either way. */
  --celadon: light-dark(#0f7a68, #5edfcc);
  --celadon-deep: light-dark(#0a5648, #26bfac);
  --jade: light-dark(#0d7a5f, #3fe0b8);
  --mint: light-dark(#0b6252, #a8eaca);
  --slate: light-dark(#41616b, #7e9aa4);

  /* Ink that sits on the glaze itself, where the surface is dark in both. */
  --on-glaze: light-dark(#f2f7f4, #06120d);
  --alarm: light-dark(#a33718, #e8836a);

  /* Gradients, declared once so they stay consistent across components. */
  --grad-glaze: linear-gradient(135deg, var(--mint) 0%, var(--celadon) 42%, var(--celadon-deep) 100%);
  --grad-glaze-soft: linear-gradient(
    135deg,
    color-mix(in oklab, var(--celadon) 22%, transparent),
    color-mix(in oklab, var(--slate) 10%, transparent)
  );
  --grad-rule: linear-gradient(90deg, var(--celadon-deep), transparent 72%);
  --grad-surface: linear-gradient(160deg, var(--stone-800) 0%, var(--stone-850) 100%);

  --font-display: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
    "Hoefler Text", Georgia, "Times New Roman", serif;
  --font-mono: "Cascadia Code", "Cascadia Mono", "JetBrains Mono", "SF Mono", "Fira Code",
    Consolas, "Liberation Mono", ui-monospace, monospace;

  --measure: 34rem;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  /* Written by the FiringGauge island through the CSSOM. 0 → 1. */
  --heat: 0;
}

/* An explicit choice, narrowing `color-scheme` to one keyword and with it every
   light-dark() above. The server writes this attribute from the theme cookie
   while it renders <html>, so a returning visitor's first paint is already
   correct; the ThemeToggle island only has to flip it. */
:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

/* --- Reset ---------------------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--stone-900);
  color: var(--chalk);
  font-family: var(--font-display);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Atmosphere: a glaze pool below, kiln light from the top-left. Fixed layers,
   so they never reflow and cost nothing to scroll. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(
      120% 62% at 50% 106%,
      color-mix(in oklab, var(--celadon) 20%, transparent),
      transparent 64%
    ),
    radial-gradient(
      64% 42% at 8% -6%,
      color-mix(in oklab, var(--slate) 18%, transparent),
      transparent 62%
    ),
    radial-gradient(
      40% 30% at 88% 12%,
      color-mix(in oklab, var(--jade) 9%, transparent),
      transparent 70%
    ),
    var(--stone-900);
}

/* Grain: layered hard-stop gradients give a fine tooth with no image file. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.4;
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.014) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.022) 0 1px, transparent 1px 4px);
  mix-blend-mode: overlay;
}

img {
  max-width: 100%;
  height: auto;
}

/* --- Typography ----------------------------------------------------------- */

h1,
h2,
h3 {
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.08;
  margin: 0;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.4rem, 1.5rem + 4.2vw, 5.2rem);
}

h2 {
  font-size: clamp(1.6rem, 1.2rem + 1.5vw, 2.4rem);
}

h3 {
  font-size: 1.2rem;
  letter-spacing: -0.01em;
}

p {
  margin: 0 0 1.1em;
  text-wrap: pretty;
}

a {
  color: var(--celadon);
  text-decoration-color: color-mix(in oklab, var(--celadon) 34%, transparent);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  transition: color 0.18s ease, text-decoration-color 0.18s ease;
}

a:hover {
  color: var(--mint);
  text-decoration-color: currentColor;
}

code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: var(--stone-700);
  border: 1px solid var(--line-soft);
  padding: 0.08em 0.36em;
  border-radius: 4px;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ash-dim);
  margin: 0 0 1.1rem;
}

.eyebrow--glaze {
  background: var(--grad-glaze);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --- Shell ---------------------------------------------------------------- */

.shell {
  max-width: 72rem;
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.masthead {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.1rem var(--gutter);
  background: color-mix(in oklab, var(--stone-900) 76%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid var(--line-soft);
}

/* The masthead's underline is a gradient that tracks the firing. */
.masthead::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px 0;
  height: 1px;
  background: var(--grad-glaze);
  transform: scaleX(var(--heat));
  transform-origin: left;
}

.wordmark {
  display: inline-flex;
  /* center, not baseline: the mark is an image now and has no baseline to sit on */
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  color: var(--chalk);
  text-decoration: none;
}

/* The aperture. This is the real logo asset rather than a CSS approximation of
   it: the mark has stone shading a radial-gradient cannot reproduce, and
   shipping one file keeps the site and the favicon provably identical. */
/* The mark is a transparent letterform, so it takes a glow rather than a tile:
   a backdrop would box in a shape that is meant to sit directly on the page. */
.wordmark__mark {
  width: 1.3rem;
  height: 1.3rem;
  display: block;
  filter: drop-shadow(0 0 7px color-mix(in oklab, var(--celadon) 40%, transparent));
  transition: filter 0.25s ease, transform 0.25s ease;
}

.wordmark:hover .wordmark__mark {
  filter: drop-shadow(0 0 13px color-mix(in oklab, var(--celadon) 70%, transparent));
  transform: translateY(-1px);
}

@keyframes breathe {
  0%, 100% { opacity: 0.7; transform: scale(0.94); }
  50% { opacity: 1; transform: scale(1.06); }
}

.masthead nav {
  display: flex;
  gap: 1.4rem;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  /* Three children now: the auto margin pushes the nav and the tools that
     follow it to the right, leaving the wordmark alone on the left. */
  margin-left: auto;
}

.masthead nav a {
  color: var(--ash);
  text-decoration: none;
}

.masthead nav a {
  /* Without this, "Quick start" breaks across two lines on a narrow screen and
     doubles the height of the header. */
  white-space: nowrap;
}

.masthead nav a:hover,
.masthead nav a[aria-current="page"] {
  color: var(--celadon);
}

@media (max-width: 30rem) {
  .masthead {
    gap: 0.75rem;
  }

  .masthead nav {
    gap: 1rem;
    font-size: 0.72rem;
  }

  /* Both tools stay - they are the two controls with no equivalent elsewhere
     on the page - but the divider and its padding are the first thing to go. */
  .tools {
    gap: 0.5rem;
    padding-left: 0;
    margin-left: 0;
    border-left: 0;
  }

  /* Quick start is one tap away from both the hero button and the docs
     sidebar, so it is the one that gives up its seat first. */
  .masthead nav a:last-child {
    display: none;
  }
}

/* --- Masthead tools (repository link, theme switch) ----------------------- */

.tools {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding-left: 1.1rem;
  margin-left: 0.35rem;
  border-left: 1px solid var(--line-soft);
}

.iconlink {
  display: inline-flex;
  color: var(--ash);
  /* The mark is the affordance; an underline under an icon reads as a smudge. */
  text-decoration: none;
  transition: color 0.18s ease;
}

.iconlink:hover {
  color: var(--celadon);
}

.iconlink svg {
  display: block;
}

/* The switch.

   Nothing here is driven by JavaScript state. The lit icon comes from the
   resolved color-scheme through light-dark(), and the knob's side from the
   three rules below - so the server renders the switch already in the correct
   position, and it follows the OS if that changes while the page is open. The
   island contributes the click and the cookie, nothing else. */
.theme {
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  padding: 0.3rem 0.4rem;
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  color: inherit;
}

.theme__track {
  position: relative;
  width: 1.95rem;
  height: 0.95rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--stone-700);
  transition: border-color 0.2s ease;
}

.theme:hover .theme__track {
  border-color: var(--celadon);
}

.theme__knob {
  position: absolute;
  left: 0.13rem;
  top: 50%;
  width: 0.63rem;
  height: 0.63rem;
  /* An explicit half-height offset rather than translateY(-50%): the transform
     below owns the horizontal travel and cannot share the property. */
  margin-top: -0.315rem;
  border-radius: 50%;
  background: var(--grad-glaze);
  box-shadow: 0 0 8px -1px color-mix(in oklab, var(--celadon) 60%, transparent);
  transform: translateX(0.98rem);
  transition: transform 0.24s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* light-dark() takes colours only, so the knob's side is stated the long way:
   dark above, light in the two cases that resolve to light. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme__knob {
    transform: translateX(0);
  }
}

:root[data-theme="light"] .theme__knob {
  transform: translateX(0);
}

/* Sun and moon: whichever theme is active lights its own icon and dims the
   other. Both are drawn from a single element - no glyph that might arrive as
   an emoji, no second request for an image. */
.theme__icon {
  width: 0.56rem;
  height: 0.56rem;
  border-radius: 50%;
  flex: none;
  transition: color 0.2s ease, box-shadow 0.2s ease;
}

.theme__icon--sun {
  color: light-dark(var(--celadon), var(--ash-dim));
  background: currentColor;
  box-shadow: 0 0 0 0.13rem color-mix(in oklab, currentColor 20%, transparent);
}

/* An offset inset shadow eats one side of the disc, leaving a crescent. */
.theme__icon--moon {
  color: light-dark(var(--ash-dim), var(--celadon));
  box-shadow: inset -0.19rem -0.05rem 0 0 currentColor;
}

/* --- Hero ----------------------------------------------------------------- */

.hero {
  position: relative;
  /* padding-block, not the shorthand: these elements also carry .shell, whose
     padding-inline provides the gutter. A shorthand here would reset it to 0. */
  padding-block: clamp(4rem, 12vh, 9rem) clamp(3rem, 8vh, 6rem);
}

.hero__title {
  max-width: 16ch;
}

/* "at build/server time" is the operative phrase — let the glaze carry it. */
.hero__title em {
  font-style: italic;
  background: var(--grad-glaze);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The tagline sits between the headline and the prose, in mono so it reads as a
   statement rather than a sentence. */
.hero__tagline {
  font-family: var(--font-mono);
  font-size: clamp(0.86rem, 0.78rem + 0.4vw, 1.02rem);
  letter-spacing: 0.02em;
  margin-top: 1.5rem;
  color: var(--ash);
}

.hero__tagline em {
  font-style: normal;
  background: var(--grad-glaze);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__lede {
  max-width: var(--measure);
  margin-top: 1.6rem;
  font-size: 1.16rem;
  color: var(--ash);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 2.2rem;
}

/* The byline under the buttons, naming the repository this site documents. */
.hero .demo-note {
  margin-top: 1.15rem;
  max-width: var(--measure);
}

/* Firing schedule under the hero: cold clay in, vitrified ware out. */
.scale {
  margin-top: 3.5rem;
  padding-top: 0.85rem;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash-dim);
  position: relative;
}

.scale::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--grad-rule);
}

.scale span {
  position: relative;
  padding-top: 0.85rem;
}

.scale span::before {
  content: "";
  position: absolute;
  top: -0.85rem;
  left: 0;
  width: 1px;
  height: 0.5rem;
  background: var(--line);
}

.scale span:last-child {
  color: var(--celadon);
}

.scale span:last-child::before {
  background: var(--celadon);
}

/* Four firing stages do not fit in four columns on a phone. */
@media (max-width: 34rem) {
  .scale {
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem 0.5rem;
  }
}

/* --- Stats (measured numbers under the hero) ------------------------------ */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 1px;
  margin: 2.4rem 0 0;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  overflow: hidden;
}

.stat {
  background: var(--grad-surface);
  padding: 1.1rem 1.15rem 1.2rem;
}

.stat dt {
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash-dim);
  margin-bottom: 0.45rem;
}

.stat dd {
  margin: 0;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  background: var(--grad-glaze);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* --- Problems ------------------------------------------------------------- */

.problems {
  display: grid;
  /* Exactly four entries, so a fixed 2x2 beats auto-fit, which leaves a ragged
     orphan on the second row at common widths. */
  grid-template-columns: 1fr;
  gap: 1px;
  margin: 0;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  overflow: hidden;
}

@media (min-width: 44rem) {
  .problems {
    grid-template-columns: repeat(2, 1fr);
  }
}

.problem {
  position: relative;
  background: var(--grad-surface);
  padding: 1.7rem 1.5rem 1.9rem;
  transition: background 0.3s ease;
}

.problem:hover {
  background: linear-gradient(160deg, var(--stone-700) 0%, var(--stone-800) 100%);
}

/* The problem is stated as the thing you already recognise; the answer sits
   under it, so the pairing reads as a claim and its evidence. */
.problem dt {
  font-family: var(--font-display);
  font-size: 1.08rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.25;
  color: var(--chalk);
  margin-bottom: 0.7rem;
  padding-left: 1.1rem;
  position: relative;
}

.problem dt::before {
  content: "×";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--ash-dim);
  font-family: var(--font-mono);
  font-size: 0.9rem;
}

.problem dd {
  margin: 0;
  padding-left: 1.1rem;
  color: var(--ash);
  font-size: 0.94rem;
  position: relative;
}

.problem dd::before {
  content: "→";
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  background: var(--grad-glaze);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  padding: 0.7rem 1.15rem;
  border-radius: 3px;
  border: 1px solid var(--line);
  color: var(--chalk);
  background: var(--grad-glaze-soft);
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease,
    transform 0.2s ease;
}

.btn:hover {
  border-color: var(--celadon);
  color: var(--mint);
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--celadon) 24%, transparent),
    0 10px 30px -16px var(--celadon);
  transform: translateY(-1px);
}

.btn--solid {
  background: var(--grad-glaze);
  border-color: transparent;
  color: var(--on-glaze);
  font-weight: 600;
}

.btn--solid:hover {
  color: var(--on-glaze);
  filter: brightness(1.08);
}

/* --- Sections ------------------------------------------------------------- */

.section {
  padding-block: clamp(3.5rem, 9vh, 6.5rem);
  position: relative;
}

.section::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--grad-rule);
}

.section__head {
  max-width: var(--measure);
  margin-bottom: 2.6rem;
}

.section__head p {
  color: var(--ash);
  margin-top: 0.9rem;
}

/* --- Principles ----------------------------------------------------------- */

.principles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  overflow: hidden;
}

.principle {
  position: relative;
  background: var(--grad-surface);
  padding: 1.9rem 1.6rem 2.1rem;
  overflow: hidden;
  transition: background 0.3s ease;
}

.principle:hover {
  background: linear-gradient(160deg, var(--stone-700) 0%, var(--stone-800) 100%);
}

/* Glaze runs along the bottom edge on hover. */
.principle::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--grad-glaze);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.42s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.principle:hover::after {
  transform: scaleX(1);
}

.principle__index {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  background: var(--grad-glaze);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  display: block;
  margin-bottom: 1rem;
}

.principle h3 {
  margin-bottom: 0.6rem;
}

.principle p {
  color: var(--ash);
  font-size: 0.95rem;
  margin: 0;
}

/* --- Code ----------------------------------------------------------------- */

.code {
  position: relative;
  background: var(--grad-surface);
  border: 1px solid var(--line);
  border-radius: 4px;
  margin: 1.6rem 0;
  overflow: hidden;
}

.code__label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ash-dim);
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--line-soft);
  background: var(--stone-700);
}

.code pre {
  margin: 0;
  padding: 1.1rem 1.15rem;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.75;
  tab-size: 2;
}

.code code {
  background: none;
  border: 0;
  padding: 0;
  font-size: inherit;
}

/* Server-side syntax highlighting: real elements, escaped normally, zero JS. */
.t-key { color: var(--celadon); }
.t-str { color: var(--mint); }
.t-com { color: var(--ash-dim); font-style: italic; }
.t-num { color: var(--slate); }
.t-fn  { color: var(--chalk); }
.t-tag { color: var(--jade); }

/* --- Figures (monospace diagrams) ----------------------------------------- */

.figure {
  margin: 1.8rem 0;
  padding: 0;
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  background:
    linear-gradient(160deg, color-mix(in oklab, var(--celadon) 5%, transparent), transparent 60%),
    var(--stone-850);
  overflow: hidden;
}

.figure pre {
  margin: 0;
  padding: 1.35rem 1.25rem;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  line-height: 1.62;
  color: var(--ash);
  tab-size: 2;
}

/* Box-drawing rules should read as structure, not as text. */
.figure figcaption {
  padding: 0.7rem 1.25rem;
  border-top: 1px solid var(--line-soft);
  background: color-mix(in oklab, var(--stone-700) 60%, transparent);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  color: var(--ash-dim);
}

@media (max-width: 34rem) {
  .figure pre {
    font-size: 0.66rem;
  }
}

/* --- Split feature -------------------------------------------------------- */

.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}

.split__text p {
  color: var(--ash);
}

.demo-frame {
  border: 1px solid var(--line);
  background: var(--grad-surface);
  border-radius: 4px;
  padding: 2rem 1.6rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
}

/* --- Docs layout ---------------------------------------------------------- */

.docs {
  display: grid;
  grid-template-columns: 14rem minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  padding-block: 3.5rem 6rem;
  align-items: start;
}

@media (max-width: 56rem) {
  .docs {
    grid-template-columns: minmax(0, 1fr);
  }
}

.docs__nav {
  position: sticky;
  top: 5rem;
  font-family: var(--font-mono);
  font-size: 0.78rem;
}

.docs__nav ol {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--line);
}

.docs__nav a {
  display: block;
  padding: 0.42rem 0 0.42rem 1rem;
  margin-left: -1px;
  border-left: 1px solid transparent;
  color: var(--ash);
  text-decoration: none;
  transition: color 0.18s ease, border-color 0.18s ease;
}

.docs__nav a:hover {
  color: var(--chalk);
  border-left-color: var(--ash-dim);
}

.docs__nav a[aria-current="page"] {
  color: var(--celadon);
  border-left-color: var(--celadon);
}

/* Sections in the sidebar.

   The label sits outside the rail and the rail restarts beneath it, so the
   grouping reads as a break in the line rather than as a new component. Same
   mono/uppercase treatment as .eyebrow, one step dimmer than the links it
   heads, because a label competing with its own contents is a label doing too
   much. */
.docs__group + .docs__group {
  margin-top: 1.6rem;
}

/* The whole row is the control, so the target is the width of the sidebar
   rather than the width of the words. */
.docs__group-label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0;
  cursor: pointer;
  list-style: none;
  color: var(--ash-dim);
  transition: color 0.18s ease;
}

/* Both are needed: WebKit uses its own pseudo-element for the triangle and
   ignores `list-style` on the summary. */
.docs__group-label::-webkit-details-marker {
  display: none;
}

.docs__group-label h2 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: inherit;
}

/* A chevron drawn from a rotated square: one element, no asset, and it takes
   currentColor so it dims and brightens with the label it belongs to. */
.docs__group-label::after {
  content: "";
  width: 0.32rem;
  height: 0.32rem;
  margin-left: auto;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-1px) rotate(-45deg);
  transition: transform 0.22s cubic-bezier(0.32, 0.72, 0, 1);
}

.docs__group[open] > .docs__group-label::after {
  transform: translateY(1px) rotate(45deg);
}

.docs__group-label:hover {
  color: var(--chalk);
}

/* Keyboard focus has to stay visible - this is the one control here that is
   not a link, so it cannot inherit the link focus treatment. */
.docs__group-label:focus-visible {
  outline: 1px solid var(--celadon);
  outline-offset: 3px;
  border-radius: 2px;
}

/* The open section's label is the heading of where you are, so it reads at
   full strength while the collapsed ones recede. */
.docs__group[open] > .docs__group-label {
  color: var(--chalk);
}

.docs__group[open] > ol {
  margin-top: 0.35rem;
}

/* Must come after the .docs__nav rules above: a media query adds no
   specificity, so an earlier override would simply lose to them.
   Stacked, the nav sits above the article rather than beside it — left sticky,
   it would pin to the top and let the article scroll underneath. */
@media (prefers-reduced-motion: reduce) {
  .docs__group-label::after {
    transition: none;
  }
}

@media (max-width: 56rem) {
  .docs__nav {
    position: static;
    padding-bottom: 1.75rem;
    margin-bottom: 2rem;
    border-bottom: 1px solid var(--line-soft);
  }

  /* Stacked, the sections run vertically with nothing beside them, so they
     need the separation the sticky column got from the article next to it. */
  .docs__group + .docs__group {
    margin-top: 1.9rem;
  }
}

.prose {
  max-width: 40rem;
}

.prose h2 {
  margin: 2.6rem 0 0.9rem;
}

.prose ul {
  color: var(--ash);
  padding-left: 1.1rem;
  margin: 0 0 1.1em;
}

.prose li {
  margin-bottom: 0.4rem;
}

.prose li::marker {
  color: var(--celadon);
}

.prose blockquote {
  margin: 1.6rem 0;
  padding: 0.6rem 0 0.6rem 1.2rem;
  border-left: 2px solid transparent;
  border-image: var(--grad-glaze) 1;
  color: var(--ash);
  font-style: italic;
}

.doc-nav {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: 0.78rem;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 4px;
  overflow: hidden;
}

.card {
  background: var(--grad-surface);
  padding: 1.6rem;
  text-decoration: none;
  color: inherit;
  display: block;
  position: relative;
  transition: background 0.25s ease;
}

.card::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--grad-glaze);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.card:hover::after {
  transform: scaleX(1);
}

.card:hover {
  background: linear-gradient(160deg, var(--stone-700) 0%, var(--stone-800) 100%);
}

.card h3 {
  color: var(--chalk);
  margin-bottom: 0.45rem;
}

.card:hover h3 {
  color: var(--celadon);
}

.card p {
  color: var(--ash);
  font-size: 0.92rem;
  margin: 0;
}

/* --- Island: install command --------------------------------------------- */

.install {
  border: 1px solid var(--line);
  background: var(--grad-surface);
  border-radius: 4px;
  overflow: hidden;
  max-width: 34rem;
}

.install__tabs {
  display: flex;
  border-bottom: 1px solid var(--line-soft);
  background: var(--stone-700);
}

.install__tab {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.65rem 1.1rem;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--ash-dim);
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.install__tab:hover {
  color: var(--chalk);
}

.install__tab[aria-selected="true"] {
  color: var(--celadon);
  border-bottom-color: var(--celadon);
}

.install__body {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.1rem;
}

.install__cmd {
  font-family: var(--font-mono);
  font-size: 0.84rem;
  color: var(--chalk);
  margin: 0;
  flex: 1;
  overflow-x: auto;
  white-space: nowrap;
}

.install__cmd::before {
  content: "$ ";
  color: var(--celadon);
}

.install__copy {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ash);
  border-radius: 3px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.install__copy:hover {
  color: var(--celadon);
  border-color: var(--celadon);
}

.install__note {
  padding: 0 1.1rem 0.9rem;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--ash-dim);
  line-height: 1.6;
}

/* --- Island: counter ------------------------------------------------------ */

.counter {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  padding: 0.75rem 1.2rem;
  border: 1px solid var(--line);
  background: var(--grad-glaze-soft);
  color: var(--chalk);
  border-radius: 3px;
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.counter:hover {
  border-color: var(--celadon);
  box-shadow: 0 0 28px -14px var(--celadon);
}

.counter b {
  color: var(--celadon);
  font-variant-numeric: tabular-nums;
  font-weight: 400;
}

.demo-note {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--ash-dim);
  margin: 0;
  line-height: 1.7;
}

/* --- Island: firing gauge ------------------------------------------------- */

/* Fixed rail. --heat (0…1) is written on :root by the island through the
   CSSOM; every visual below is derived from it here, in CSS. */
.gauge {
  position: fixed;
  right: clamp(0.75rem, 2vw, 1.5rem);
  top: 50%;
  transform: translateY(-50%);
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  pointer-events: none;
}

@media (max-width: 64rem) {
  .gauge {
    display: none;
  }
}

.gauge__track {
  position: relative;
  width: 3px;
  height: 42vh;
  max-height: 20rem;
  background: var(--line);
  border-radius: 2px;
  overflow: hidden;
}

.gauge__fill {
  position: absolute;
  inset: auto 0 0 0;
  height: calc(var(--heat) * 100%);
  background: linear-gradient(to top, var(--celadon-deep), var(--celadon) 48%, var(--mint));
  box-shadow: 0 0 14px color-mix(in oklab, var(--celadon) 58%, transparent);
  transition: height 0.12s linear;
}

.gauge__readout {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  color: var(--ash-dim);
  writing-mode: vertical-rl;
  font-variant-numeric: tabular-nums;
}

.gauge__readout b {
  color: var(--celadon);
  font-weight: 400;
}

/* --- Island: feedback ----------------------------------------------------- */

.feedback {
  border: 1px solid var(--line);
  background: var(--grad-surface);
  border-radius: 4px;
  padding: 1.5rem;
  max-width: 34rem;
}

.feedback label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ash-dim);
  margin-bottom: 0.7rem;
}

.feedback__row {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.feedback input[type="text"] {
  flex: 1;
  min-width: 12rem;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  padding: 0.6rem 0.75rem;
  background: var(--stone-900);
  border: 1px solid var(--line);
  border-radius: 3px;
  color: var(--chalk);
}

.feedback input[type="text"]:focus-visible {
  outline: none;
  border-color: var(--celadon);
}

.feedback__msg {
  margin: 0.8rem 0 0;
  min-height: 1.3rem;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  color: var(--ash-dim);
}

.feedback__msg.sent {
  color: var(--celadon);
}

.feedback__msg.error {
  color: var(--alarm);
}

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

.colophon {
  padding-block: 2.5rem 4rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--ash-dim);
  line-height: 1.9;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2.5rem;
  justify-content: space-between;
  position: relative;
}

.colophon::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--grad-rule);
}

.colophon a {
  color: var(--ash);
  text-decoration: none;
}

.colophon a:hover {
  color: var(--celadon);
}

/* --- Motion --------------------------------------------------------------- */

/* One orchestrated page load; children stagger by position. The delays live in
   CSS rather than inline style attributes, which the default CSP would block. */
.rise {
  animation: rise 0.75s cubic-bezier(0.16, 0.84, 0.28, 1) both;
}

.rise:nth-child(1) { animation-delay: 0.02s; }
.rise:nth-child(2) { animation-delay: 0.1s; }
.rise:nth-child(3) { animation-delay: 0.18s; }
.rise:nth-child(4) { animation-delay: 0.26s; }
.rise:nth-child(5) { animation-delay: 0.34s; }
.rise:nth-child(6) { animation-delay: 0.42s; }
.rise:nth-child(7) { animation-delay: 0.5s; }

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(3px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

/* Scroll-linked reveal where supported. Pure CSS — no observer, no JS. */
@supports (animation-timeline: view()) {
  .reveal {
    animation: reveal linear both;
    animation-timeline: view();
    animation-range: entry 5% cover 26%;
  }

  @keyframes reveal {
    from {
      opacity: 0;
      transform: translateY(22px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }
}

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

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* --- Focus & selection ---------------------------------------------------- */

:focus-visible {
  outline: 2px solid var(--celadon);
  outline-offset: 3px;
}

::selection {
  background: color-mix(in oklab, var(--celadon) 30%, transparent);
  color: var(--chalk);
}

.skip {
  position: absolute;
  left: -9999px;
}

.skip:focus {
  position: fixed;
  left: 1rem;
  top: 1rem;
  z-index: 100;
  padding: 0.6rem 1rem;
  background: var(--celadon);
  color: var(--on-glaze);
  border-radius: 3px;
}
