/* ===========================================================================
   @arag — documentation site chrome
   ---------------------------------------------------------------------------
   This file styles the docs site ONLY. It is not part of the package and is
   never shipped to consumers.

   It sits in its own `docs` layer, appended after the package's six layers, so
   it can never be mistaken for system CSS and never fights it. Same rules as
   the package though, because the docs are also an integration test:
     - no priority-raising declarations
     - no hardcoded colours, sizes, or durations — @arag tokens only
   Literal values appear only for pure scaffolding the system has no token for
   (sidebar track width, code-block gutters), and are commented where they do.
   =========================================================================== */

@layer docs;

@layer docs {
  /* ---------------------------------------------------------------------------
     Shell
     --------------------------------------------------------------------------- */

  /* base.css turns on smooth scrolling, which is right for an app and wrong
     here: these pages run to 40,000px, so jumping from the last section to the
     first animated for seconds. A smooth scroll's duration is not settable from
     CSS, so snappy means instant. The reduced-motion case was already instant. */
  html {
    scroll-behavior: auto;
  }

  body {
    margin: var(--space-0);
    /* The masthead's own block size, shared with whatever must clear it. */
    --docs-masthead-block-size: var(--space-9);
  }

  /* .skip-link and .masthead / .masthead__brand / .masthead__spacer are now
     shipped from src/components/skip-link.css and src/components/masthead.css
     and are deliberately NOT restated here — a surviving copy in this file's
     `docs` layer, which is declared after all six package layers, would
     silently shadow the shipped components on every page that links both
     files. See src/components/masthead.css for the promoted shape;
     .masthead__version below stays docs-only and now decorates the shipped
     .masthead__brand from the outside rather than being part of it. */

  .masthead__version {
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    font-weight: var(--weight-regular);
    color: var(--color-text-muted);
    padding: var(--space-1) var(--space-2);
    border: var(--border-width-1) solid var(--color-border-subtle);
    border-radius: var(--radius-full);
  }

  /* ---------------------------------------------------------------------------
     Theme control
     --------------------------------------------------------------------------- */

  .themer {
    display: flex;
    gap: var(--space-0);
    padding: var(--space-1);
    background-color: var(--color-surface-sunken);
    border: var(--border-width-1) solid var(--color-border-subtle);
    border-radius: var(--radius-full);
  }

  .themer button {
    min-block-size: var(--space-7);
    padding-inline: var(--space-4);
    font-size: var(--text-xs);
    border: var(--border-width-0) solid transparent;
    border-radius: var(--radius-full);
    background-color: transparent;
    color: var(--color-text-muted);

    &[aria-pressed="true"] {
      background-color: var(--color-surface);
      color: var(--color-text);
      box-shadow: var(--shadow-xs);
    }
  }

  /* ---------------------------------------------------------------------------
     Command palette
     ---------------------------------------------------------------------------
     Trigger and dialog are both built and inserted by docs.js — see
     initPalette() there for why nothing here ships as static markup.
     .sidebar__search stays the no-JS-safe fallback (an inert but harmless text
     box with scripting off); this is the enhancement on top of it, reachable
     by mouse (the masthead trigger) or keyboard (Ctrl/Cmd K).

     Built on .dialog (native <dialog>: Escape, an inert background and focus
     trapping are the platform's, not hand-rolled) and .menu__item for each
     result row. Only the parts neither component already has an opinion on —
     the search field row, the eyebrow line, the roving highlight — live here.
     --------------------------------------------------------------------------- */

  .palette-trigger {
    gap: var(--space-2);
    color: var(--color-text-muted);
  }

  .palette-trigger kbd {
    font-size: var(--text-xs);
  }

  .palette__header {
    /* .dialog__header defaults to align-items: start, right for a title that
       may wrap to two lines. A single-line icon-and-input row wants its own
       baseline centred instead. */
    align-items: center;
  }

  .palette__field {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-inline-size: 0;
    flex: 1 1 auto;
  }

  .palette__field svg {
    flex: 0 0 auto;
    inline-size: var(--size-icon);
    block-size: var(--size-icon);
    color: var(--color-text-subtle);
  }

  .palette__input {
    flex: 1 1 auto;
    min-inline-size: 0;
    border: none;
    background-color: transparent;
    font-family: inherit;
    font-size: var(--text-base);
    color: var(--color-text);

    &::placeholder {
      color: var(--color-text-subtle);
    }
  }

  .palette__body {
    padding-block: var(--space-2);
  }

  .palette__results {
    /* .menu__item reads these as its local API rather than assuming a parent
       .menu — that container is a positioned popover with its own border,
       shadow and scroll, all of which .dialog already provides here. Setting
       only the item-level locals is what the API is for: reuse the row
       styling without the box it usually ships inside. */
    --menu-item-fg: var(--color-text);
    --menu-item-bg: transparent;
    /* The RAISED state pair, matching menu.css's own defaults — .dialog paints
       itself --color-surface-raised, and in dark mode that already sits a step
       lighter than --color-surface, so --color-surface-hover lands within a
       point of the dialog's own background and the highlight disappears
       (measured: 52,55,58 on 53,56,61). See the note above the raised
       derivations in tokens.css. */
    --menu-item-bg-hover: var(--color-surface-raised-hover);
    --menu-item-bg-active: var(--color-surface-raised-active);
    --menu-item-min-block-size: var(--size-touch);
    --menu-item-padding-block: var(--space-3);
    --menu-item-padding-inline: var(--space-4);
    --menu-item-radius: var(--radius-sm);

    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }

  .palette__results .menu__item {
    /* The base rule lays a menu item out as a row; a result needs a small
       muted eyebrow line above the bold match, so both axis properties it
       sets are overridden here. */
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-1);
    text-align: start;
  }

  /* Roving highlight during arrow-key navigation. Focus itself never leaves
     the input — see initPalette() — so this is a plain state, not :focus. */
  .palette__results .menu__item[data-active="true"] {
    background-color: var(--menu-item-bg-hover);
  }

  .palette__eyebrow {
    font-size: var(--text-xs);
    color: var(--color-text-subtle);
  }

  .palette__empty {
    margin-block: var(--space-0);
    padding: var(--space-6) var(--space-4);
    text-align: center;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
  }

  .palette__footer {
    justify-content: flex-start;
    gap: var(--space-4);
    font-size: var(--text-xs);
    color: var(--color-text-subtle);
  }

  .palette__footer kbd {
    font-size: var(--text-xs);
  }

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

  .layout {
    display: grid;
    /* 17rem is scaffolding: the sidebar track. Nav labels are English here, but
       it is sized with headroom on purpose — see docs/bilingual.html. */
    grid-template-columns: 17rem minmax(0, 1fr);
    gap: var(--space-8);
    max-inline-size: var(--size-container-2xl);
    margin-inline: auto;
    padding: var(--space-7) var(--space-6) var(--space-9);
  }

  @media (max-width: 60rem) {
    .layout {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-6);
    }
  }

  /* ---------------------------------------------------------------------------
     Sidebar
     --------------------------------------------------------------------------- */

  .sidebar {
    align-self: start;
    position: sticky;
    /* Clears the sticky masthead — same number the masthead itself is sized by,
       plus its bottom border. */
    inset-block-start: calc(var(--docs-masthead-block-size) + var(--border-width-1));
    max-block-size: calc(
      100dvb - var(--docs-masthead-block-size) - var(--border-width-1) - var(--space-7)
    );
    overflow-y: auto;
    /* Reaching the end of the nav must not start scrolling the page behind it. */
    overscroll-behavior: contain;
    /* base.css leaves scrollbars to the app on purpose — see its closing note.
       This is the app. The default 15px bar next to 13rem of nav was the single
       loudest thing in the sidebar. */
    scrollbar-width: thin;
    scrollbar-color: var(--color-border-subtle) transparent;
    /* An ancestor with overflow other than visible clips any descendant's
       focus outline that paints past its own box — outline is ink, not layout,
       so it does not push this padding open by itself. Without it, tabbing to
       the filter input (flush against this box's start-start corner) or the
       last nav link (flush against its end-end corner) drew a ring with the
       bleeding edge sheared off. --space-2 covers the ring's 4px bleed
       (--focus-ring-width + --focus-ring-offset) with a little headroom; the
       end side also doubles as clearance for the scrollbar thumb. */
    padding: var(--space-2);
  }

  @media (max-width: 60rem) {
    .sidebar {
      position: static;
      max-block-size: none;
      padding-block-end: var(--space-5);
      border-block-end: var(--border-width-1) solid var(--color-border-subtle);
    }
  }

  .sidebar__search {
    inline-size: 100%;
    margin-block-end: var(--space-5);
    font-size: var(--text-sm);
  }

  .sidebar h2 {
    margin-block: var(--space-5) var(--space-2);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    color: var(--color-text-subtle);

    &:first-of-type {
      margin-block-start: var(--space-0);
    }
  }

  .sidebar ul {
    margin-block: var(--space-0);
    padding-inline-start: var(--space-0);
    list-style: none;
  }

  .sidebar li {
    margin-block-end: var(--space-0);
  }

  .sidebar a {
    display: block;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    text-decoration-line: none;

    /* Guarded behind a hover-capable pointer, the same convention src/ applies
       to every :hover it ships — see the header block in src/components/button.css
       for the full statement. Unguarded, tapping a nav link on a touch screen
       latches the hover fill until something else is tapped, and the sidebar
       ends up showing two "current" rows. @media inside @layer changes neither
       specificity nor layer order, so this only gates whether the block is
       reached. */
    @media (hover: hover) {
      &:hover {
        background-color: var(--color-surface-hover);
        color: var(--color-text);
      }
    }

    &[aria-current="page"] {
      background-color: var(--color-brand-subtle);
      color: var(--color-brand-text);
      font-weight: var(--weight-medium);
    }
  }

  /* -------------------------------------------------------------------------
     Sub-sections
     Only the CURRENT page carries a sub-list — every page's nav is generated
     with its own h2 ids nested under its own link. That keeps the markup static
     (so the docs navigate with scripting disabled) without every page shipping
     every other page's table of contents.
     ------------------------------------------------------------------------- */

  .sidebar__sub {
    margin-block: var(--space-1) var(--space-3);
    margin-inline-start: var(--space-4);
  }

  /* Every page ships every page's sub-list, so the nav is identical everywhere
     and needs no build step. Shown all at once that is 126 links — 3563px of
     nav inside a 764px sticky box, which is a scrollbar, not a table of
     contents. docs.js marks the current page and sets data-nav, so the other
     thirteen sub-lists collapse and only the page you are on is expanded.
     Scripting off means no data-nav, nothing is hidden, and the full static nav
     is there — the same degradation as everything else in this file. */
  .sidebar[data-nav="scoped"]:not([data-filtering]) .sidebar__sub:not([data-current]) {
    display: none;
  }

  .sidebar__sub a {
    padding-block: var(--space-1);
    padding-inline-start: var(--space-4);
    border-radius: var(--radius-sm);
    font-size: var(--text-xs);
    color: var(--color-text-subtle);
    line-height: var(--leading-snug);

    @media (hover: hover) {
      &:hover {
        background-color: transparent;
        color: var(--color-text);
      }
    }

    &[aria-current="true"] {
      background-color: transparent;
      color: var(--color-brand-text);
      font-weight: var(--weight-medium);
    }
  }

  .sidebar a[data-stub]::after {
    content: "soon";
    float: inline-end;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--color-text-subtle);
  }

  .sidebar li[hidden] {
    display: none;
  }

  /* ---------------------------------------------------------------------------
     Content column
     --------------------------------------------------------------------------- */

  .content {
    min-inline-size: 0;
  }

  .content > h1 {
    margin-block-start: var(--space-0);
  }

  .lede {
    max-inline-size: var(--size-measure);
    font-size: var(--text-lg);
    color: var(--color-text-muted);
    line-height: var(--leading-snug);
  }

  .content h2 {
    margin-block-start: var(--space-9);
    padding-block-end: var(--space-3);
    border-block-end: var(--border-width-1) solid var(--color-border-subtle);
  }

  /* Every in-page jump — a sidebar sub-link, a heading anchor, the back button
     landing on a hash — targets a heading that sits directly under the sticky
     masthead. Without this the masthead covers the top of the heading text. */
  .content :is(h2, h3) {
    scroll-margin-block-start: calc(var(--docs-masthead-block-size) + var(--space-4));
  }

  .content :is(h2, h3) > a.anchor {
    margin-inline-start: var(--space-3);
    font-size: var(--text-sm);
    color: var(--color-text-subtle);
    text-decoration-line: none;
    opacity: 0;
    transition: opacity var(--transition-base);
  }

  /* Split rather than listed together: :focus-visible stays unconditional — it
     is how a keyboard user reaches the anchor, and it is real on touch too, so
     sweeping it behind the hover guard would hide the link from every device
     without a mouse. Only the :hover half moves behind the guard. */
  .content :is(h2, h3) > a.anchor:focus-visible {
    opacity: 1;
  }

  @media (hover: hover) {
    .content :is(h2, h3):hover > a.anchor {
      opacity: 1;
    }
  }

  /* ---------------------------------------------------------------------------
     Callouts
     --------------------------------------------------------------------------- */

  .note {
    margin-block: var(--space-6);
    padding: var(--space-5);
    border-inline-start: var(--border-width-4) solid var(--color-brand-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface-sunken);

    & > :first-child {
      margin-block-start: var(--space-0);
    }
  }

  .note--warn {
    border-inline-start-color: var(--color-warn-border);
  }

  .note--danger {
    border-inline-start-color: var(--color-danger-border);
  }

  .note__label {
    display: block;
    margin-block-end: var(--space-2);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    color: var(--color-text-muted);
  }

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

  .code {
    position: relative;
    margin-block: var(--space-5);
  }

  .code pre {
    margin-block: var(--space-0);
    /* Right gutter reserves room for the copy button so long lines never slide
       underneath it. */
    padding-inline-end: var(--space-9);
    /* Block floor reserves room the same way the inline gutter does. The copy
       button is pinned to the block-start corner, so the block needs to be at
       least the button plus its inset on both sides — otherwise a one-line
       snippet collapses to roughly the button's own height and the button
       ends up flush against the bottom border with a gap only above it.
       At exactly this minimum the corner IS the centre, so one rule gives a
       corner button on a tall block and a centred one on a short block. */
    min-block-size: calc(var(--space-7) + var(--space-3) * 2);
    border: var(--border-width-1) solid var(--color-border-subtle);
  }

  .code__copy {
    position: absolute;
    inset-block-start: var(--space-3);
    inset-inline-end: var(--space-3);
    min-block-size: var(--space-7);
    /* Without this the min-block-size above is decorative: base.css gives every
       button --space-3 of block padding, which puts the content box past 2rem
       on its own and means the declared minimum never governs anything. */
    padding-block: var(--space-1);
    padding-inline: var(--space-3);
    font-size: var(--text-xs);
    font-family: var(--font-mono);
    border-radius: var(--radius-sm);
  }

  /* ---------------------------------------------------------------------------
     Live examples
     --------------------------------------------------------------------------- */

  .example {
    margin-block: var(--space-6);
    border: var(--border-width-1) solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    overflow: hidden;
  }

  .example__preview {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-6);
    background-color: var(--color-surface);
  }

  .example__preview--stack {
    display: block;
  }

  .example__code {
    border-block-start: var(--border-width-1) solid var(--color-border-subtle);
    padding: var(--space-0);
    margin-block-end: var(--space-0);
    border-radius: var(--radius-none);
    border-inline: var(--border-width-0) solid transparent;
    border-block-end: var(--border-width-0) solid transparent;
  }

  .example__code > summary {
    padding: var(--space-3) var(--space-5);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    background-color: var(--color-surface-sunken);
  }

  .example__code .code {
    margin-block: var(--space-0);
  }

  .example__code .code pre {
    border-inline: var(--border-width-0) solid transparent;
    border-block-end: var(--border-width-0) solid transparent;
    border-radius: var(--radius-none);
  }

  /* .duo / .duo__panel / .duo__label are now shipped from
     src/components/duo.css and are deliberately NOT restated here beyond the
     one property below — see the note above .masthead__version for why a
     surviving copy in this file's `docs` layer would silently shadow the
     shipped component. Docs pages using .duo now add the .duo__panel class
     to each panel (the shipped component's markup contract), which the
     plain `.duo > *` selector here never required.

     The one exception is outer spacing. The shipped .duo carries no
     margin-block on the house rule that a component does not dictate the
     space around it, so every page placing a .duo lost the margin-block:
     var(--space-6) the old docs-only rule gave it. Restored once, here, so
     every consuming page keeps that rhythm without each one re-declaring
     it. Margin only — padding, border, background, colour and --duo-gap
     stay exclusively the shipped component's, so this layer (which sits
     after all six package layers) can never shadow it. */
  .duo {
    margin-block: var(--space-6);
  }

  /* ---------------------------------------------------------------------------
     Token reference tables
     --------------------------------------------------------------------------- */

  .table-wrap {
    overflow-x: auto;
    margin-block: var(--space-6);
  }

  .tokens {
    font-size: var(--text-sm);
  }

  .tokens :is(th, td) {
    vertical-align: top;
  }

  .tokens code {
    font-size: var(--text-xs);
    white-space: normal;
  }

  .swatch {
    display: inline-block;
    inline-size: var(--space-7);
    block-size: var(--space-7);
    border: var(--border-width-1) solid var(--color-border-subtle);
    border-radius: var(--radius-sm);
    vertical-align: middle;
  }

  .ramp {
    display: grid;
    grid-template-columns: repeat(11, minmax(0, 1fr));
    gap: var(--space-1);
    margin-block: var(--space-3) var(--space-6);
    min-inline-size: 34rem;
  }

  .ramp__step {
    display: grid;
    place-items: center;
    aspect-ratio: 1;
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
  }

  /* ---------------------------------------------------------------------------
     Prev / next
     --------------------------------------------------------------------------- */

  .pager {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    justify-content: space-between;
    margin-block-start: var(--space-9);
    padding-block-start: var(--space-6);
    border-block-start: var(--border-width-1) solid var(--color-border-subtle);
  }

  .pager a {
    flex: 1 1 14rem;
    padding: var(--space-4) var(--space-5);
    border: var(--border-width-1) solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    text-decoration-line: none;
    color: var(--color-text);

    @media (hover: hover) {
      &:hover {
        border-color: var(--color-border);
        background-color: var(--color-surface-hover);
      }
    }
  }

  .pager small {
    display: block;
    color: var(--color-text-subtle);
  }

  .pager__next {
    text-align: end;
  }

  /* ---------------------------------------------------------------------------
     Stub pages
     --------------------------------------------------------------------------- */

  .stub {
    margin-block: var(--space-7);
    padding: var(--space-8) var(--space-6);
    text-align: center;
    border: var(--border-width-2) dashed var(--color-border-subtle);
    border-radius: var(--radius-lg);
    color: var(--color-text-muted);
  }

  .stub h2 {
    margin-block-start: var(--space-0);
    border-block-end: var(--border-width-0) solid transparent;
  }
}
