/* ===========================================================================
   DOCS — a separate system from the marketing pages.

   It inherits the colour tokens and the three faces from site.css and nothing
   else. No particle field, no smooth scroll, no character reveal, no giant
   display type. Documentation is read while something is broken; every one of
   those would be in the way.

   The layout is the one every good docs site converges on, because it answers
   the three questions a reader has at once: sidebar (where am I in the whole
   thing), content (the answer), table of contents (where am I on this page).
   ========================================================================= */

:root{
  --side-w:290px;
  --toc-w:236px;
  --doc-measure:custom;     /* set below; kept as a name so it reads in devtools */
  --topbar-h:60px;
}

html:has(body.docs){background:var(--bg)}
body.docs{
  background:var(--bg);
  background-image:none;          /* the marketing glow is noise here */
  font-size:16px;
}

/* ---------------------------------------------------------------- topbar */
.doc-top{position:sticky;top:0;z-index:40;height:var(--topbar-h);
  display:grid;grid-template-columns:var(--side-w) minmax(0,1fr) auto;align-items:center;
  gap:20px;padding:0 22px;
  background:color-mix(in srgb,var(--bg) 92%,transparent);
  border-bottom:1px solid color-mix(in srgb,var(--border) 55%,transparent);
  backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}
.doc-top .brand{font-size:13px}

.doc-search{position:relative;max-width:420px;width:100%}
.doc-search input{width:100%;height:36px;padding:0 34px 0 34px;font:inherit;font-size:14px;
  color:var(--fg);background:var(--secondary);border-radius:9px;
  border:1px solid color-mix(in srgb,var(--border) 70%,transparent);
  transition:border-color .2s,background .2s}
.doc-search input::placeholder{color:var(--muted)}
.doc-search input:focus{outline:2px solid var(--focus);outline-offset:0;
  border-color:transparent;background:var(--card)}
.doc-search .mag{position:absolute;left:11px;top:50%;transform:translateY(-50%);
  width:15px;height:15px;color:var(--muted);pointer-events:none}
/* The shortcut is shown, not just supported. An undiscoverable shortcut is
   the same as no shortcut. */
.doc-search kbd{position:absolute;right:9px;top:50%;transform:translateY(-50%);
  font-family:"JetBrains Mono",monospace;font-size:11px;color:var(--muted);
  border:1px solid color-mix(in srgb,var(--border) 90%,transparent);
  border-radius:5px;padding:1px 6px;pointer-events:none}
.doc-search input:focus + .mag + kbd,
.doc-search input:not(:placeholder-shown) ~ kbd{opacity:0}

.doc-results{position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:50;
  max-height:60vh;overflow-y:auto;padding:6px;margin:0;list-style:none;
  background:var(--card);border-radius:12px;
  border:1px solid color-mix(in srgb,var(--border) 70%,transparent);
  box-shadow:0 20px 44px -20px rgb(0 0 0 / .6);display:none}
.doc-results.open{display:block}
.doc-results a{display:block;padding:9px 11px;border-radius:8px;color:var(--fg);font-size:14px}
.doc-results a:hover,.doc-results li.sel a{background:var(--primary-soft);color:var(--primary)}
.doc-results .g{display:block;font-family:"JetBrains Mono",monospace;font-size:11px;
  color:var(--muted);margin-top:2px}
.doc-results .none{padding:12px;color:var(--muted);font-size:14px}

/* ---------------------------------------------------------------- shell */
.doc-shell{display:grid;grid-template-columns:var(--side-w) minmax(0,1fr) var(--toc-w);
  align-items:start;gap:0;max-width:1560px;margin:0 auto}

/* ---------------------------------------------------------------- sidebar */
.doc-side{position:sticky;top:var(--topbar-h);height:calc(100svh - var(--topbar-h));
  overflow-y:auto;padding:22px 14px 60px 22px;
  border-right:1px solid color-mix(in srgb,var(--border) 45%,transparent);
  scrollbar-width:thin}
.side-home{display:block;font-family:"JetBrains Mono",monospace;font-size:12px;
  color:var(--muted);padding:6px 10px;margin-bottom:14px;transition:color .2s}
.side-home:hover{color:var(--primary)}

.side-group{margin-bottom:2px}
.side-group > summary{display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:8px 10px;border-radius:8px;cursor:pointer;list-style:none;
  font-size:14px;font-weight:500;color:var(--fg);transition:background .18s}
.side-group > summary::-webkit-details-marker{display:none}
.side-group > summary:hover{background:var(--secondary)}
.side-group .chev{width:14px;height:14px;flex:none;color:var(--muted);
  transition:transform .25s var(--ease-ui)}
.side-group[open] > summary .chev{transform:rotate(180deg)}
.side-pill{font-family:"JetBrains Mono",monospace;font-size:10px;letter-spacing:.02em;
  color:var(--primary);background:var(--primary-soft);border-radius:var(--r-pill);
  padding:2px 7px;margin-left:8px}

.side-group ul{list-style:none;margin:2px 0 8px;padding:0 0 0 10px;
  border-left:1px solid color-mix(in srgb,var(--border) 60%,transparent)}
.side-group li a{display:block;padding:7px 10px;border-radius:8px;font-size:14px;
  color:var(--muted);transition:color .18s,background .18s}
.side-group li a:hover{color:var(--fg);background:var(--secondary)}
/* The current page is filled, not merely coloured: on a list of twenty links
   a colour change alone is easy to miss when you arrive mid-scroll. */
.side-group li a[aria-current="page"]{color:var(--primary);background:var(--primary-soft);
  font-weight:500}

/* ---------------------------------------------------------------- content */
.doc-main{min-width:0;padding:34px clamp(24px,3.4vw,56px) 90px}
.doc-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;
  flex-wrap:wrap;margin-bottom:26px}
.crumb{font-family:"JetBrains Mono",monospace;font-size:12px;color:var(--muted);margin:0}
.crumb a:hover{color:var(--primary)}
.crumb span{opacity:.5;margin:0 6px}

/* Copy the page as markdown.
   People paste documentation into an assistant constantly, and copying
   rendered HTML gives them mangled text with the code blocks flattened.
   Handing over the actual source is one button and removes that whole class
   of "the docs said something weird". */
.md-copy{display:inline-flex;align-items:center;gap:7px;cursor:pointer;
  min-height:32px;padding:0 12px;border-radius:8px;background:var(--secondary);
  color:var(--ink-soft);border:1px solid color-mix(in srgb,var(--border) 70%,transparent);
  font-family:"JetBrains Mono",monospace;font-size:11.5px;
  transition:color .2s,border-color .2s,background .2s}
.md-copy:hover{color:var(--primary);border-color:color-mix(in srgb,var(--primary) 45%,transparent)}
.md-copy svg{width:13px;height:13px}

/* One measure, ~72 characters. Wider and the eye loses the line start on the
   way back; narrower and code samples wrap. */
.doc-body{max-width:70ch}
.doc-body h1{font-family:"Cabinet Grotesk",sans-serif;font-weight:700;
  font-size:clamp(30px,3.4vw,40px);line-height:1.12;letter-spacing:-.02em;
  margin:0 0 20px;color:var(--fg)}
.doc-body h2{font-family:"Cabinet Grotesk",sans-serif;font-weight:500;
  font-size:25px;line-height:1.2;letter-spacing:-.012em;color:var(--fg);
  /* More space above than below: a heading belongs to what follows it. */
  margin:52px 0 14px;padding-top:2px;scroll-margin-top:calc(var(--topbar-h) + 20px)}
.doc-body h3{font-size:18px;font-weight:600;color:var(--fg);margin:32px 0 10px;
  scroll-margin-top:calc(var(--topbar-h) + 20px)}
.doc-body p{margin:0 0 16px;color:var(--ink-soft);line-height:1.68}
.doc-body a{color:var(--primary);text-decoration:underline;
  text-underline-offset:3px;text-decoration-thickness:1px;
  text-decoration-color:color-mix(in srgb,var(--primary) 40%,transparent)}
.doc-body a:hover{text-decoration-color:var(--primary)}
.doc-body strong{color:var(--fg);font-weight:600}
.doc-body ul,.doc-body ol{margin:0 0 16px;padding-left:22px;color:var(--ink-soft);line-height:1.68}
.doc-body li{margin:0 0 7px}
.doc-body li::marker{color:var(--muted)}
.doc-body hr{border:0;border-top:1px solid color-mix(in srgb,var(--border) 50%,transparent);
  margin:40px 0}
.doc-body code{font-family:"JetBrains Mono",monospace;font-size:.87em;
  background:var(--secondary);border-radius:5px;padding:2px 6px;color:var(--fg)}

/* The anchor appears on hover but is always in the tab order, so it is
   reachable without a pointer. */
.h-anchor{margin-left:10px;color:var(--muted);text-decoration:none;opacity:0;
  transition:opacity .18s}
.doc-body h2:hover .h-anchor,.doc-body h3:hover .h-anchor,.h-anchor:focus-visible{opacity:1}

.code-block{position:relative;margin:0 0 20px}
.code-block pre{margin:0;overflow-x:auto;padding:16px 18px;border-radius:11px;
  background:var(--secondary);border:1px solid color-mix(in srgb,var(--border) 60%,transparent)}
.code-block code{background:none;padding:0;font-size:13px;line-height:1.6;color:var(--fg)}
.code-copy{position:absolute;top:9px;right:9px;cursor:pointer;opacity:0;
  font-family:"JetBrains Mono",monospace;font-size:11px;padding:4px 9px;border-radius:6px;
  color:var(--muted);background:var(--card);
  border:1px solid color-mix(in srgb,var(--border) 80%,transparent);
  transition:opacity .18s,color .18s}
.code-block:hover .code-copy,.code-copy:focus-visible{opacity:1}
.code-copy:hover{color:var(--primary)}

.table-wrap{overflow-x:auto;margin:0 0 20px}
.doc-body table{width:100%;border-collapse:collapse;font-size:14.5px}
.doc-body th,.doc-body td{text-align:left;padding:10px 13px;
  border-bottom:1px solid color-mix(in srgb,var(--border) 45%,transparent)}
.doc-body th{font-family:"JetBrains Mono",monospace;font-size:11.5px;letter-spacing:.04em;
  text-transform:uppercase;color:var(--muted);font-weight:400}
.doc-body td{color:var(--ink-soft)}

/* A blockquote is the summary at the top of a legal page: the same shape as a
   callout without the label, because the label would be the only word on it
   and would say "note" about a paragraph that is the point of the page. */
blockquote{border-radius:11px;padding:14px 16px;margin:0 0 22px;
  border:1px solid color-mix(in srgb,var(--border) 70%,transparent);
  border-left:2px solid var(--primary);background:var(--secondary)}
blockquote p{margin:0;color:var(--ink-soft)}

.callout{border-radius:11px;padding:14px 16px;margin:0 0 20px;
  border:1px solid color-mix(in srgb,var(--border) 70%,transparent);background:var(--secondary)}
.callout-t{font-family:"JetBrains Mono",monospace;font-size:11px;letter-spacing:.05em;
  text-transform:uppercase;margin:0 0 6px;color:var(--muted)}
.callout p:last-child{margin:0;color:var(--ink-soft)}
.callout-note{border-left:2px solid var(--primary)}
.callout-note .callout-t{color:var(--primary)}
.callout-warning{border-left:2px solid #E0A73C}
.callout-warning .callout-t{color:#E0A73C}

/* ---------------------------------------------------------------- meta + pager */
.doc-meta{display:flex;align-items:center;justify-content:space-between;gap:16px;
  flex-wrap:wrap;margin-top:56px;padding-top:18px;
  border-top:1px solid color-mix(in srgb,var(--border) 45%,transparent);
  font-family:"JetBrains Mono",monospace;font-size:11.5px;color:var(--muted)}
.doc-meta a:hover{color:var(--primary)}

/* Docs have a reading order. Without a pager the bottom of a page is a dead
   end and the reader has to go back to the sidebar to continue. */
.doc-pager{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:22px}
.doc-pager a{display:flex;flex-direction:column;gap:4px;padding:14px 16px;border-radius:12px;
  border:1px solid color-mix(in srgb,var(--border) 60%,transparent);
  transition:border-color .2s,background .2s}
.doc-pager a:hover{border-color:color-mix(in srgb,var(--primary) 45%,transparent);
  background:var(--primary-soft)}
.doc-pager .k{font-family:"JetBrains Mono",monospace;font-size:11px;color:var(--muted)}
.doc-pager .t{font-size:15px;color:var(--fg)}
.pager-next{text-align:right;grid-column:2}
.pager-prev{grid-column:1}

/* ---------------------------------------------------------------- toc */
.doc-toc{position:sticky;top:var(--topbar-h);height:calc(100svh - var(--topbar-h));
  overflow-y:auto;padding:34px 22px 60px 6px}
.toc-t{font-family:"JetBrains Mono",monospace;font-size:11px;letter-spacing:.05em;
  text-transform:uppercase;color:var(--muted);margin:0 0 12px}
.toc ul{list-style:none;margin:0;padding:0;
  border-left:1px solid color-mix(in srgb,var(--border) 55%,transparent)}
.toc li a{display:block;padding:6px 0 6px 14px;margin-left:-1px;font-size:13.5px;
  color:var(--muted);border-left:1px solid transparent;transition:color .18s,border-color .18s}
.toc li a:hover{color:var(--fg)}
.toc li.lvl-3 a{padding-left:26px;font-size:13px}
/* Scrollspy: on a page with eight sections, knowing which one you are in
   saves scrolling back up to find out. */
.toc li a.active{color:var(--primary);border-left-color:var(--primary)}

/* ---------------------------------------------------------------- mobile */
.doc-side-toggle{display:none}
@media (max-width:1180px){
  .doc-shell{grid-template-columns:var(--side-w) minmax(0,1fr)}
  .doc-toc{display:none}
  .doc-top{grid-template-columns:var(--side-w) minmax(0,1fr) auto}
}
@media (max-width:900px){
  .doc-shell{grid-template-columns:1fr}
  .doc-top{grid-template-columns:auto minmax(0,1fr) auto}
  .doc-side{position:fixed;inset:var(--topbar-h) auto 0 0;width:min(84vw,var(--side-w));
    z-index:45;background:var(--bg);transform:translateX(-102%);
    transition:transform .28s var(--ease-out)}
  .doc-side.open{transform:none;box-shadow:0 0 60px rgb(0 0 0 / .5)}
  .doc-side-toggle{display:grid;place-items:center;width:36px;height:36px;flex:none;
    background:transparent;border:1px solid color-mix(in srgb,var(--border) 70%,transparent);
    border-radius:8px;color:var(--fg);cursor:pointer}
  .doc-side-toggle svg{width:16px;height:16px}
  .doc-main{padding:26px 20px 70px}
  .doc-pager{grid-template-columns:1fr}
  .pager-next,.pager-prev{grid-column:1;text-align:left}
}

/* ===========================================================================
   PAGE TRANSITIONS

   Navigating between two docs pages repaints the whole window. On a dark
   theme that shows as a white flash, because the browser paints its own
   canvas for a frame between unloading one document and painting the next —
   which is genuinely unpleasant to read into, and worse at night.

   Two mechanisms, because coverage differs:

   1. View Transitions where supported. The browser holds the outgoing frame
      and cross-fades, so there is no gap to flash through at all. Only the
      article and the table of contents animate — the sidebar and the top bar
      are shared furniture, and moving them would make a page change look
      like a site change.

   2. Everywhere else, a short fade-in on arrival. It cannot remove the gap,
      but it means the new page resolves rather than snapping, and the eye
      has nothing hard to land on.

   Both are ~200ms. Long enough to read as deliberate, short enough that
   nobody clicking through six pages feels held up.
   ========================================================================= */
@view-transition{navigation:auto}

::view-transition-old(root),
::view-transition-new(root){animation-duration:.2s;
  animation-timing-function:cubic-bezier(.4,0,.2,1)}

/* Shared furniture keeps its identity across the navigation. */
.doc-top{view-transition-name:doc-top}
.doc-side{view-transition-name:doc-side}
::view-transition-old(doc-top),::view-transition-new(doc-top),
::view-transition-old(doc-side),::view-transition-new(doc-side){animation:none}

.doc-main{view-transition-name:doc-main}
::view-transition-old(doc-main){animation:doc-out .16s var(--ease-ui) both}
::view-transition-new(doc-main){animation:doc-in .24s var(--ease-out) both}
.doc-toc{view-transition-name:doc-toc}
::view-transition-old(doc-toc){animation:doc-out .12s var(--ease-ui) both}
::view-transition-new(doc-toc){animation:doc-in .22s var(--ease-out) .04s both}

@keyframes doc-out{to{opacity:0;transform:translateY(-5px)}}
@keyframes doc-in{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}

/* Fallback for browsers without view transitions. Behind .js so a page that
   never runs a script is not left invisible. */
.js.no-vt .doc-main,.js.no-vt .doc-toc{animation:doc-in .24s var(--ease-out) both}

@media (prefers-reduced-motion:reduce){
  .doc-side{transition:none}
  *{scroll-behavior:auto !important}
  /* Someone who asked for less motion should not be given a new kind of it. */
  @view-transition{navigation:none}
  ::view-transition-old(*),::view-transition-new(*){animation:none !important}
  .js.no-vt .doc-main,.js.no-vt .doc-toc{animation:none}
}

@media print{
  .doc-top,.doc-side,.doc-toc,.doc-pager,.md-copy,.code-copy{display:none}
  .doc-shell{grid-template-columns:1fr}
  .doc-body{max-width:none}
}

/* The legal line, on every docs page.
   A person reading how a product works is exactly the person who might want to
   know what it is allowed to do with their data, and until now the docs were
   the one part of the site with no route to either document. Quiet: it is a
   footnote, not a call to action, so it takes --muted and no accent until the
   pointer is on it. */
.doc-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:10px 20px;margin-top:34px;padding-top:16px;border-top:1px solid var(--border);
  font-size:12.5px;color:var(--muted)}
.doc-foot p{margin:0}
.doc-foot nav{display:flex;gap:18px}
.doc-foot a{color:var(--muted);text-decoration:none}
.doc-foot a:hover{color:var(--primary)}
