/*
 * Documentation-specific styles only.
 *
 * Do not recreate Actual CSS components, layout primitives,
 * variants, utilities or spacing systems here. If this file
 * reimplements .stack/.cluster/.grid/.card/.btn/.badge/.prose,
 * that is a product signal — fix the framework instead.
 */

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

/* A grid demo that wants subdivision puts .container-query in its own markup
   inside the preview, and that wrapper adds no padding — so the preview's
   content box is still the width .grid-N thresholds resolve against. The
   documentation therefore has a hard geometric obligation: a preview must be
   able to reach the widest documented threshold, 64rem (.grid-4 -> 4,
   .grid-6 -> 6). Work backwards from it.

     64rem      preview content box (widest grid threshold)
   +  2rem      .docs-preview padding-inline (2 x --space-40)
   +  0.125rem  .docs-example border
   ------------------------------------------------------------
     ~66.2rem   minimum .docs-example outer width

   --docs-demo-track sits above that minimum on purpose, so a later padding or
   border tweak cannot silently push every grid demo below a threshold. The
   demo measure is not the prose measure: .docs-prose is a framework .prose and
   keeps its own 70ch reading measure inside this wider track.

   The shell then needs the nav track + demo track + TOC track plus two
   column gaps, and .center subtracts 2 x --center-pad from --center-size:

     12 + 1 + 68 + 1 + 11 = 93rem of track -> --center-size 95rem

   Regression-tested in tests/docs-geometry.test.js. */
:root {
  --docs-demo-track: 68rem;
  --docs-nav-track: 12rem;
  --docs-toc-track: 11rem;
  --docs-shell-size: 95rem;
}

/* --- Site chrome --- */

.docs-header {
  border-block-end: var(--border-width) solid var(--border);
  background: var(--surface-raised);
}

.docs-header-inner {
  --cluster-justify: space-between;
  --center-size: var(--docs-shell-size);
  padding-block: var(--space-30);
}

.docs-brand-mark {
  inline-size: 1rem;
  block-size: 1rem;
  border-radius: var(--radius-sm);
  background:
    radial-gradient(circle at 30% 30%, var(--secondary), transparent 60%),
    var(--primary);
}

.docs-theme-field .select {
  min-inline-size: 8rem;
}

.docs-shell {
  --center-size: var(--docs-shell-size);
  /* .center's auto margins otherwise let fixed grid tracks shrink-wrap this
     flex item. Fill the shared shell so the sidebar starts with the header
     brand. */
  inline-size: calc(100% - var(--center-pad, 1rem) * 2);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
  padding-block: var(--space-40);
}

.docs-sidebar,
.docs-toc {
  display: none;
}

.docs-main {
  min-inline-size: 0;
}

.docs-nav-group {
  margin: var(--space-40) 0 var(--space-20);
  color: var(--text-muted);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.docs-nav-group:first-child {
  margin-block-start: 0;
}

.docs-toc-list .nav-link[data-level="3"] {
  padding-inline-start: var(--space-40);
  font-size: var(--font-size-sm);
}

.docs-drawer-header {
  margin-block-end: var(--space-30);
  /* The close button is absolutely positioned against the drawer; reserve
     inline room so the title never runs under it. */
  padding-inline-end: calc(var(--control-size) + var(--space-30));
}

/* --- Content --- */

/* The article is a .stack; its own rhythm goes on `gap`, never on --gap.
   The token inherits, so tuning it here re-spaced every .stack, .cluster and
   .grid inside a demo preview — showing readers 24px where the framework
   default is 12px, on every page of the site. */
.docs-article {
  gap: var(--space-50);
  min-inline-size: 0;
}

/* The first blockquote is the page summary emitted by the Markdown sources,
   not an in-flow quotation. Keep its lead treatment without separating it
   from the article with the normal blockquote inset and rule. */
.docs-prose > h1 + blockquote {
  max-inline-size: 42rem;
  margin-inline: 0;
  padding-inline-start: 0;
  border-inline-start: 0;
  color: var(--text-muted);
  font-size: var(--font-size-lg);
}

.docs-prevnext {
  --cluster-justify: space-between;
  margin-block-start: var(--space-60);
  padding-block-start: var(--space-40);
  border-block-start: var(--border-width) solid var(--border);
}

.docs-footer {
  border-block-start: var(--border-width) solid var(--border);
  padding-block: var(--space-40);
  color: var(--text-muted);
  text-align: center;
}

/* --- Demo examples --- */

.docs-example {
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  overflow: hidden;
}

.docs-preview {
  /* A neutral environment: no query container. actual-container is a public
     contract an author declares, so a demo that inherited it here would render
     unlike the snippet printed beside it — and one shared name reaches every
     size-aware component, not just .grid-N. An example that needs the context
     establishes it in its own markup. */
  padding: var(--space-40);
  overflow-x: auto;
}

/* The opt-in `resize` demo flag turns the preview into a width test bench:
   the reader drags this box to scrub an example through its actual-container
   thresholds (.grid-N subdivisions, .steps label collapse). 12rem keeps every
   documented step reachable — 14rem is the narrowest .steps threshold — while
   still leaving enough room for the sequence; below it the row scrolls, which
   is the behaviour the widest transport is for. */
.docs-preview-resizable {
  resize: horizontal;
  min-inline-size: 12rem;
  max-inline-size: 100%;
}


/* Preview-only viewport for the fixed FAB. Production keeps .fab fixed to the
   real viewport; the docs replace only its positioning context. */
.docs-fab-preview {
  position: relative;
  isolation: isolate;
  min-block-size: 22rem;
  max-inline-size: 32rem;
  margin-inline: auto;
  padding: var(--space-40);
  overflow: hidden;
  border: var(--border-width) solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-subtle);
}

.docs-fab-preview > .fab {
  position: absolute;
}

.docs-fab-preview > .card {
  --card-max-inline-size: 18rem;
}

/* --surface-subtle is an expressive tinted surface in several presets (a wide
   yellow panel under brutalist), which is a lot to ask of a long code listing.
   Keep a quarter of it so the block still carries the theme, over the neutral
   raised surface. */
.docs-code {
  position: relative;
  border-block-start: var(--border-width) solid var(--border);
  background: var(--surface-raised);
}

@supports (color: color-mix(in oklab, red, white)) {
  .docs-code {
    background: color-mix(in oklab, var(--surface-raised), var(--surface-subtle) 25%);
  }
}

.docs-code pre {
  margin: 0;
  padding: var(--space-30);
  overflow-x: auto;
  font-size: var(--font-size-sm);
  line-height: 1.6;
}

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

.docs-copy {
  position: absolute;
  inset-block-start: var(--space-20);
  inset-inline-end: var(--space-20);
}

/* --- Search --- */

.docs-search-dialog .stack {
  min-inline-size: min(28rem, 90vw);
}

.docs-search-title {
  margin-block: 0;
  font-size: var(--font-size-lg);
}

.docs-search-input {
  inline-size: 100%;
}

.docs-search-results {
  margin: 0;
  padding: 0;
  list-style: none;
}

.docs-search-results a {
  display: block;
  padding: var(--space-20);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
}

.docs-search-results a:hover,
.docs-search-results a:focus-visible {
  background: var(--surface-subtle);
}

.docs-search-results .docs-search-match {
  color: var(--text-muted);
  font-size: var(--font-size-sm);
}

.docs-search-results .docs-search-active a {
  background: var(--surface-subtle);
}

/* --- Homepage --- */

.docs-hero {
  padding-block: calc(var(--space-60) * 1.5) var(--space-60);
}

.docs-hero-title {
  max-inline-size: 12ch;
  margin-inline: auto;
  font-size: clamp(2rem, 5vw, 3.25rem);
  line-height: 1.05;
}

.docs-hero .lead {
  max-inline-size: 36rem;
  margin-inline: auto;
}

.docs-hero-cta {
  justify-content: center;
}

.docs-section {
  padding-block: var(--space-50);
}

.docs-icon {
  display: inline-grid;
  place-items: center;
  inline-size: 2rem;
  block-size: 2rem;
  border-radius: var(--radius);
  background: var(--primary);
  color: var(--primary-fg);
  font-size: 1.25rem;
}

.docs-feature-grid,
.docs-components-grid {
  --grid-min: 12rem;
}

/* Home stat strip. Figures come from size-report.json at build time
   (scripts/docs/templates.js), so the landing page cannot quote a size the
   build no longer produces. */
.docs-stats {
  --grid-min: 9rem;

  padding-block: var(--space-40);
  border-block: var(--border-width) solid var(--border);
}

.docs-stat {
  display: grid;
  gap: var(--space-10);
  text-align: center;
}

.docs-stat > strong {
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.docs-stat > .muted {
  font-size: var(--font-size-sm);
  text-wrap: balance;
}

.docs-layout-grid {
  --grid-min: 14rem;
  align-items: start;
}

.docs-demo-grid {
  --grid-min: 3rem;
}

.docs-layout-preview {
  --gap: var(--space-20);
  min-block-size: 8rem;
}

.docs-layout-line,
.docs-layout-cell {
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
}

.docs-layout-line {
  min-block-size: 1.5rem;
}

.docs-layout-cell {
  min-block-size: 2.5rem;
}

.docs-density-grid,
.docs-theme-grid {
  --grid-min: 12rem;
}

/* The preview consumes only theme tokens, making each card a compact visual
   contract check for surfaces, accents, radius, and elevation. Bars take
   --radius-sm so square themes read as square; the border token is carried by
   the surrounding .card (--border / --border-width). */
.docs-theme-preview {
  display: grid;
  align-content: end;
  gap: var(--space-20);
  min-block-size: 7.5rem;
  padding: var(--space-30);
  border-radius: var(--radius);
  background: var(--surface-solid);
  box-shadow: var(--shadow-popout);
}

.docs-theme-line {
  inline-size: 70%;
  block-size: 0.7rem;
  border-radius: var(--radius-sm);
  background: var(--surface);
  opacity: 0.9;
}

.docs-theme-line-primary {
  inline-size: 40%;
  background: var(--primary);
  opacity: 1;
}

.docs-theme-line-secondary {
  inline-size: 55%;
  background: var(--secondary);
  opacity: 1;
}

.docs-theme-showcase {
  background: var(--surface-subtle);
  border-radius: var(--radius-lg);
  padding-inline: var(--space-40);
}

.docs-component-card {
  color: var(--text);
  text-decoration: none;
}

.docs-component-card:hover {
  border-color: var(--border-strong);
}

.docs-install-grid {
  --grid-min: 15rem;
}

.docs-install-grid > * {
  min-inline-size: 0;
}

.docs-install-grid pre {
  margin: 0;
  min-inline-size: 0;
  max-inline-size: 100%;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* --- Responsive chrome --- */

@media (min-width: 56rem) {
  .docs-shell {
    /* The sidebar and TOC tracks are deliberately tighter than the demo
       track. At 1280px -- the most common desktop docs width -- the shell is
       space-limited rather than track-limited, so every rem spent on chrome is
       a rem the preview cannot use: with 13rem + 12rem of chrome the preview
       landed at 47.94rem and missed the 48rem .grid-3 threshold by a rounding
       error. 12rem + 11rem clears it with real margin. */
    grid-template-columns:
      var(--docs-nav-track)
      minmax(0, var(--docs-demo-track))
      var(--docs-toc-track);
    column-gap: var(--space-40);
    /* Keep the documentation navigation on the same starting edge as the
       brand; centering fixed tracks made the two shells look unrelated. */
    justify-content: start;
  }

  .docs-sidebar,
  .docs-toc {
    display: block;
    position: sticky;
    inset-block-start: var(--space-40);
    max-block-size: calc(var(--viewport-block) - 2 * var(--space-40));
    overflow-y: auto;
    /* Keep the active nav link's background off the scrollbar thumb. The thumb
       chrome and the reserved gutter come from .scroller.stable-gutter on the
       elements themselves — the docs site uses the framework's own utility
       rather than restating it here. */
    padding-inline-end: var(--space-20);
  }

  .docs-menu-toggle {
    display: none;
  }
}

@media (max-width: 40rem) {
  .docs-header-inner > .cluster {
    inline-size: 100%;
  }

  .docs-menu-toggle {
    margin-inline-start: auto;
  }
}

@media (min-width: 64rem) {
  .docs-header-inner {
    --cluster-wrap: nowrap;
  }
}

/* --- Prism syntax tokens (progressive enhancement: no CDN = plain code) ---
   A purpose-built palette, not a derivation of the theme intents.

   Deriving it was tried and does not work. Raw intents are a component
   palette — built to sit under their own --*-fg or to tint a surface, not to
   carry 14px text — and across the 17 presets they fall below AA on 14 of them
   (brutalist 1.36, gradient 1.45, sunset 1.55). Rebating them toward --text
   fixes that but crushes lightness and chroma together, collapsing the tokens
   onto each other: 0.023 oklab dE on the default theme, under the perceptual
   threshold, which reads as plain dark text. And no derivation can do better,
   because five semantic intents are not a syntax palette — on the monochromatic
   presets (petrol, ocean, edge, mono) they are deliberately close, 0.064 apart
   before any rebate.

   So the hues are fixed and chosen for separation: 0/47/144/251/303 plus a
   neutral, optimised so the tightest pair is as far apart as possible in BOTH
   variants at once. That lands at 0.141 oklab dE — six times the derived
   version, and twice the raw intents at their best.

   Lightness is bounded by the surfaces the block actually gets, with headroom:
   the targets are 5.2:1 rather than a bare 4.5, so a theme nudging its
   --surface-subtle cannot quietly drop the block below AA. The binding cases
   are cyberpunk's yellow code surface (luminance 0.833) for the light variant
   and dim for the dark one; the dark variant is also capped so nothing glows.

   The block still reads as part of the theme: its surface is theme-derived.
   Only the ink is fixed. Private to the docs either way — syntax highlighting
   belongs to Prism, not to the framework's public token contract.

   light-dark() follows each preset's own color-scheme, so this needs no theme
   list. Without support for it (below the framework's Safari floor) the light
   variant applies everywhere, which is wrong on the three dark presets — a
   demo-only degradation on a docs site. */

:root,
[data-theme] {
  --syntax-keyword: #bd0063;
  --syntax-string: #007013;
  --syntax-function: #0061ac;
  --syntax-property: #9001eb;
  --syntax-operator: #a24500;
  --syntax-comment: #606060;
}

@supports (color: light-dark(red, blue)) {
  :root,
  [data-theme] {
    --syntax-keyword: light-dark(#bd0063, #ff639e);
    --syntax-string: light-dark(#007013, #03cf2d);
    --syntax-function: light-dark(#0061ac, #3b9fff);
    --syntax-property: light-dark(#9001eb, #b980fe);
    --syntax-operator: light-dark(#a24500, #ff7102);
    --syntax-comment: light-dark(#606060, #b3b3b3);
  }
}

.token.comment,
.token.prolog,
.token.cdata {
  color: var(--syntax-comment);
}

.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol {
  color: var(--syntax-property);
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
  color: var(--syntax-string);
}

.token.operator,
.token.entity,
.token.url,
.token.attr-value {
  color: var(--syntax-operator);
}

.token.keyword,
.token.atrule,
.token.rule,
.token.important,
.token.deleted {
  color: var(--syntax-keyword);
}

.token.function,
.token.class-name {
  color: var(--syntax-function);
}
