/* ============================================================
   veruapis - public site
   ------------------------------------------------------------
   Tokens inherited from the VeruSuite marketing system at
   verusuite/apps/verumail/static/css/site.css. Teal is the acting
   colour; ember marks the one place per view where the brand names
   itself. Depth is carried by hairlines, not shadows.

   One departure, documented in docs/design.md: --va-code is a real
   monospace face. Upstream --vm-mono resolves to Inter, which is fine
   on a page with no code and wrong on a site that is mostly code.
   ============================================================ */

/* ------------------------------------------------------------
   Fonts are self-hosted. No request leaves for a third party, which
   is the same reason the rest of the suite stopped loading them from
   Google: a hard runtime dependency on a host we do not control, on a
   product whose copy says no third-party trackers.

   Files copied from verusuite/apps/shared/fonts. Both are variable, so
   one file covers every weight from 100 to 900.

   The unicode-range on each face is what makes the split pay: an
   English page never downloads the Arabic file, and a page with no
   Lithuanian diacritics never downloads latin-ext.

   Licences: SIL Open Font License 1.1, see the fonts directory.
   ------------------------------------------------------------ */

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/static/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/static/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Surfaces: cool off-white, faintly green. Never stark. */
  --vm-paper:        #f4f5f3;
  --vm-paper-sunken: #eaece9;
  --vm-paper-raised: #ffffff;

  /* Ink: a very dark slate-teal, so black never appears. */
  --vm-ink:   #111817;
  --vm-ink-2: #3c4746;
  --vm-ink-3: #5f6e6c;
  --vm-ink-4: #7e8c8a;

  /* Lines are the structural element, so they are defined against ink. */
  --vm-line:        rgba(17, 24, 23, 0.11);
  --vm-line-strong: rgba(17, 24, 23, 0.22);
  --vm-line-faint:  rgba(17, 24, 23, 0.055);

  --vm-teal:       #0f6b6c;
  --vm-teal-hover: #0c5758;
  --vm-teal-press: #094849;
  --vm-teal-soft:  #e2eeed;
  --vm-teal-ink:   #ffffff;

  --vm-ember:      #c2571b;
  --vm-ember-deep: #a44710;
  --vm-ember-soft: #f7e9df;

  --vm-green:      #3d7a5e;
  --vm-green-soft: #e3efe9;
  --vm-amber:      #96690f;
  --vm-amber-soft: #f5e9cf;
  --vm-red:        #a8453a;
  --vm-red-soft:   #f3dcd6;

  --vm-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;

  /* No monospace face is self-hosted anywhere in the suite, and fetching one
     would reintroduce the third-party request the fonts above exist to remove.
     The platform stack costs nothing and works offline. Self-hosting a face
     here is a one-file change if consistent code rendering is wanted. */
  --va-code: ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;

  --vm-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --vm-dur-1: 120ms;
  --vm-dur-2: 200ms;

  --measure: 68ch;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --wide: 1120px;

  accent-color: var(--vm-teal);
  caret-color: var(--vm-teal);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --vm-paper:        #0e1413;
    --vm-paper-sunken: #0a0f0f;
    --vm-paper-raised: #161e1d;
    --vm-ink:   #e7ebea;
    --vm-ink-2: #a9b5b4;
    --vm-ink-3: #7b8a88;
    --vm-ink-4: #5d6b69;
    --vm-line:        rgba(231, 235, 234, 0.11);
    --vm-line-strong: rgba(231, 235, 234, 0.24);
    --vm-line-faint:  rgba(231, 235, 234, 0.055);
    --vm-teal:       #45b0ab;
    --vm-teal-hover: #5cc2bd;
    --vm-teal-press: #369490;
    --vm-teal-soft:  #12302f;
    --vm-teal-ink:   #06100f;
    --vm-ember:      #e58444;
    --vm-ember-deep: #f0a068;
    --vm-ember-soft: #33200f;
    --vm-green:      #6fae8b;
    --vm-green-soft: #16261f;
    --vm-amber:      #d3a445;
    --vm-amber-soft: #2a2313;
    --vm-red:        #c97167;
    --vm-red-soft:   #2e1f1c;
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --vm-paper:        #0e1413;
  --vm-paper-sunken: #0a0f0f;
  --vm-paper-raised: #161e1d;
  --vm-ink:   #e7ebea;
  --vm-ink-2: #a9b5b4;
  --vm-ink-3: #7b8a88;
  --vm-ink-4: #5d6b69;
  --vm-line:        rgba(231, 235, 234, 0.11);
  --vm-line-strong: rgba(231, 235, 234, 0.24);
  --vm-line-faint:  rgba(231, 235, 234, 0.055);
  --vm-teal:       #45b0ab;
  --vm-teal-hover: #5cc2bd;
  --vm-teal-press: #369490;
  --vm-teal-soft:  #12302f;
  --vm-teal-ink:   #06100f;
  --vm-ember:      #e58444;
  --vm-ember-deep: #f0a068;
  --vm-ember-soft: #33200f;
  --vm-green:      #6fae8b;
  --vm-green-soft: #16261f;
  --vm-amber:      #d3a445;
  --vm-amber-soft: #2a2313;
  --vm-red:        #c97167;
  --vm-red-soft:   #2e1f1c;
  color-scheme: dark;
}

/* ---------- reset ---------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--vm-paper);
  color: var(--vm-ink);
  font-family: var(--vm-sans);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'cv11', 'ss01';
}

img, svg { max-width: 100%; height: auto; display: block; }

/* ---------- type ---------- */

h1, h2, h3, h4 {
  line-height: 1.18;
  letter-spacing: -0.018em;
  font-weight: 600;
  text-wrap: balance;
  margin: 0 0 .6em;
}
h1 { font-size: clamp(2rem, 1.5rem + 2.2vw, 3.15rem); letter-spacing: -0.028em; }
h2 { font-size: clamp(1.45rem, 1.2rem + 1.1vw, 2rem); }
h3 { font-size: clamp(1.12rem, 1.03rem + .4vw, 1.3rem); }
h4 { font-size: 1rem; }

p { margin: 0 0 1.1rem; }
p, li { max-width: var(--measure); }

a { color: var(--vm-teal); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--vm-teal-hover); }
a:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 2px solid var(--vm-teal);
  outline-offset: 3px;
  border-radius: 3px;
}

ul, ol { padding-inline-start: 1.25rem; margin: 0 0 1.1rem; }
li { margin-bottom: .4rem; }
li::marker { color: var(--vm-ink-4); }

strong { font-weight: 600; }
hr { border: 0; border-top: 1px solid var(--vm-line); margin: 2.5rem 0; }

.lede {
  font-size: clamp(1.06rem, 1rem + .35vw, 1.25rem);
  color: var(--vm-ink-2);
  max-width: 60ch;
}

.eyebrow {
  font-family: var(--va-code);
  font-size: .74rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--vm-ember);
  margin: 0 0 1rem;
}

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

code, kbd, pre, .mono { font-family: var(--va-code); font-variant-ligatures: none; }

:not(pre) > code {
  font-size: .875em;
  background: var(--vm-paper-sunken);
  border: 1px solid var(--vm-line-faint);
  border-radius: 4px;
  padding: .1em .35em;
  color: var(--vm-ink);
  word-break: break-word;
}

pre {
  font-size: .845rem;
  line-height: 1.62;
  background: var(--vm-paper-raised);
  border: 1px solid var(--vm-line);
  border-radius: 6px;
  padding: 1rem 1.15rem;
  overflow-x: auto;
  margin: 0 0 1.4rem;
  color: var(--vm-ink-2);
  tab-size: 2;
}
pre code { background: none; border: 0; padding: 0; font-size: inherit; color: inherit; }
pre b { color: var(--vm-ink); font-weight: 500; }
pre i { color: var(--vm-ink-4); font-style: normal; }
pre u { color: var(--vm-teal); text-decoration: none; }

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

.wrap { max-width: var(--wide); margin: 0 auto; padding-inline: var(--gutter); }
.prose { max-width: var(--measure); }

.band { padding-block: clamp(3rem, 7vw, 5.5rem); }
.band + .band { border-top: 1px solid var(--vm-line); }
.band--sunken { background: var(--vm-paper-sunken); }

.skip {
  position: absolute; inset-inline-start: -9999px;
  background: var(--vm-teal); color: var(--vm-teal-ink);
  padding: .6rem 1rem; border-radius: 0 0 6px 0; z-index: 100;
}
.skip:focus { inset-inline-start: 0; top: 0; }

/* ---------- header ---------- */

.site-header {
  border-bottom: 1px solid var(--vm-line);
  background: var(--vm-paper);
  position: sticky; top: 0; z-index: 50;
}
.site-header .wrap {
  display: flex; align-items: center; gap: 1.5rem;
  min-height: 60px;
}
.brand {
  font-weight: 600; font-size: 1.02rem; letter-spacing: -.02em;
  color: var(--vm-ink); text-decoration: none; white-space: nowrap;
}
.brand span { color: var(--vm-ember); }
.site-nav { display: flex; gap: 1.35rem; margin-inline-start: auto; align-items: center; flex-wrap: wrap; }
/* :not(.btn) is a guard rather than a fix now that the Console action sits
   outside the nav. It stays because the hazard has not gone away: a bare
   ".site-nav a" rule is specificity 0-1-1 and beats ".btn--primary" at 0-1-0,
   so the first button put back in here would have its label repainted with
   body ink on a teal fill. */
.site-nav a:not(.btn) {
  color: var(--vm-ink-2); text-decoration: none; font-size: .925rem;
  transition: color var(--vm-dur-1) var(--vm-ease);
}
.site-nav a:not(.btn):hover,
.site-nav a:not(.btn)[aria-current="page"] { color: var(--vm-ink); }
.site-nav a:not(.btn)[aria-current="page"] { font-weight: 500; }
.site-cta { padding: .45rem .95rem; font-size: .9rem; }

/* ---------- the header on a narrow screen ----------
   
   The nav used to be one flex row that wrapped, which on a phone put four
   links and a button into two or three ragged right-aligned lines under a
   sticky bar. Two deliberate rows instead: the brand and the one action on
   top, the destinations on their own line below.
   
   No disclosure, because this site ships no JavaScript, and the CSS-only
   substitutes all depend on overriding how a browser hides a closed
   <details>, which is exactly the behaviour the specification is currently
   changing. Four short links fit on a row at any width worth designing for,
   and a link nobody has to open a menu to see is better than one they do. */

@media (max-width: 40rem) {
  .site-header .wrap {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 1rem;
    row-gap: .55rem;
    min-height: 0;
    padding-block: .7rem;
  }

  .brand    { grid-area: 1 / 1; }
  .site-cta { grid-area: 1 / 2; }

  .site-nav {
    grid-area: 2 / 1 / 3 / 3;
    margin-inline-start: 0;
    flex-wrap: nowrap;
    gap: 1.15rem;

    /* The safety net, not the plan: the links fit unscrolled on a 360px
       screen. It is here for a narrower one, a longer translation, or a
       reader who has turned their text size up. */
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;

    /* Bleed to the screen edge so a strip that does scroll is not cut off
       inside the gutter, while the padding keeps the first link aligned
       with the brand above it. */
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
  }
  .site-nav::-webkit-scrollbar { display: none; }
  .site-nav a { white-space: nowrap; }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; gap: .5rem;
  font: inherit; font-size: .94rem; font-weight: 500;
  padding: .62rem 1.15rem;
  border-radius: 6px;
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--vm-dur-1) var(--vm-ease), border-color var(--vm-dur-1) var(--vm-ease);
}
.btn--primary { background: var(--vm-teal); color: var(--vm-teal-ink); }
.btn--primary:hover { background: var(--vm-teal-hover); color: var(--vm-teal-ink); }
.btn--primary:active { background: var(--vm-teal-press); }
.btn--ghost { border-color: var(--vm-line-strong); color: var(--vm-ink); background: transparent; }
.btn--ghost:hover { border-color: var(--vm-ink-3); color: var(--vm-ink); }

.actions { display: flex; gap: .75rem; flex-wrap: wrap; margin-top: 1.75rem; }

/* ---------- cards and grids ---------- */

.grid { display: grid; gap: 1px; background: var(--vm-line); border: 1px solid var(--vm-line); border-radius: 8px; overflow: hidden; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }

.cell { background: var(--vm-paper-raised); padding: 1.4rem 1.5rem; }
.cell h3 { margin-bottom: .35rem; }
.cell p { color: var(--vm-ink-2); font-size: .94rem; margin-bottom: 0; }
.cell a.cell-link { text-decoration: none; }

a.cell { text-decoration: none; color: inherit; transition: background var(--vm-dur-1) var(--vm-ease); }
a.cell:hover { background: var(--vm-teal-soft); }
a.cell h3 { color: var(--vm-teal); }

/* ---------- tables ---------- */

.table-wrap { overflow-x: auto; border: 1px solid var(--vm-line); border-radius: 6px; margin: 0 0 1.5rem; background: var(--vm-paper-raised); }
table { border-collapse: collapse; width: 100%; font-size: .9rem; }
th, td { text-align: left; padding: .65rem .85rem; border-bottom: 1px solid var(--vm-line); vertical-align: top; }
thead th {
  font-family: var(--va-code); font-size: .72rem; font-weight: 500;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--vm-ink-3); background: var(--vm-paper-sunken); white-space: nowrap;
}
tbody tr:last-child td { border-bottom: 0; }
td.num { font-variant-numeric: tabular-nums; }
table code { white-space: nowrap; }

/* ---------- method + status chips ---------- */

.chip {
  display: inline-block;
  font-family: var(--va-code); font-size: .7rem; font-weight: 500;
  letter-spacing: .06em; text-transform: uppercase;
  padding: .15rem .45rem; border-radius: 4px; white-space: nowrap;
  border: 1px solid transparent;
}
.chip--get    { color: var(--vm-teal);  background: var(--vm-teal-soft);  border-color: var(--vm-teal); }
.chip--post   { color: var(--vm-green); background: var(--vm-green-soft); border-color: var(--vm-green); }
.chip--patch  { color: var(--vm-amber); background: var(--vm-amber-soft); border-color: var(--vm-amber); }
.chip--put    { color: var(--vm-amber); background: var(--vm-amber-soft); border-color: var(--vm-amber); }
.chip--delete { color: var(--vm-red);   background: var(--vm-red-soft);   border-color: var(--vm-red); }
.chip--scope  { color: var(--vm-ink-2); background: var(--vm-paper-sunken); border-color: var(--vm-line); text-transform: none; letter-spacing: 0; }

/* An endpoint that is designed and routed but not yet answering. Amber rather
   than red: it is not broken, it is not here yet, and the reader's decision is
   "build against something else for now" rather than "report a fault". */
.chip--soon   { color: var(--vm-ember); background: var(--vm-ember-soft); border-color: var(--vm-ember); }


.soon { border: 1px solid var(--vm-line); border-radius: 8px; padding: 1.5rem; background: var(--vm-paper-raised); }
.soon-badge { margin: 0 0 .75rem; }
.soon h2 { margin-top: 1.5rem; font-size: 1rem; }

/* ---------- notes ---------- */

.note {
  border: 1px solid var(--vm-line);
  /* Logical, not left: the rule flips to the right edge in Arabic. */
  border-inline-start: 3px solid var(--vm-teal);
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  background: var(--vm-paper-raised);
  padding: 1rem 1.15rem;
  margin: 0 0 1.5rem;
}
.note--warn { border-inline-start-color: var(--vm-ember); }
.note > :last-child { margin-bottom: 0; }
.note-label {
  font-family: var(--va-code); font-size: .7rem; font-weight: 500;
  letter-spacing: .09em; text-transform: uppercase;
  color: var(--vm-teal); display: block; margin-bottom: .35rem;
}
.note--warn .note-label { color: var(--vm-ember); }

/* ---------- docs layout ---------- */

.docs { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 3.5rem); align-items: start; }
@media (max-width: 820px) { .docs { grid-template-columns: 1fr; } }

.docs-nav { position: sticky; top: 76px; font-size: .92rem; }
.docs-nav h4 {
  font-family: var(--va-code); font-size: .7rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--vm-ink-3); margin: 1.4rem 0 .5rem; font-weight: 500;
}
.docs-nav h4:first-child { margin-top: 0; }
.docs-nav ul { list-style: none; padding: 0; margin: 0; }
.docs-nav li { margin: 0; max-width: none; }
.docs-nav a {
  display: block; padding: .22rem 0; color: var(--vm-ink-2); text-decoration: none;
}
.docs-nav a:hover { color: var(--vm-ink); }
.docs-nav a[aria-current="page"] { color: var(--vm-teal); font-weight: 500; }

.docs-body > h2 { margin-top: 2.4rem; padding-top: 1.2rem; border-top: 1px solid var(--vm-line); }
.docs-body > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

/* ---------- endpoint header ---------- */

.endpoint {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  font-family: var(--va-code); font-size: .95rem;
  background: var(--vm-paper-raised);
  border: 1px solid var(--vm-line);
  border-radius: 6px;
  padding: .7rem .9rem;
  margin: 0 0 1.5rem;
}
.endpoint .path { color: var(--vm-ink); word-break: break-all; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--vm-line);
  background: var(--vm-paper-sunken);
  padding-block: 2.75rem;
  margin-top: 4rem;
  font-size: .9rem;
}
.site-footer .cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1.75rem; }
.site-footer h4 {
  font-family: var(--va-code); font-size: .7rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--vm-ink-3); font-weight: 500; margin-bottom: .6rem;
}
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: .35rem; max-width: none; }
.site-footer a { color: var(--vm-ink-2); text-decoration: none; }
.site-footer a:hover { color: var(--vm-ink); }
.site-footer .colophon {
  margin-top: 2.25rem; padding-top: 1.25rem; border-top: 1px solid var(--vm-line);
  color: var(--vm-ink-3); display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.site-footer .colophon p { margin: 0; max-width: none; }


/* ---------- right to left ---------- */

/* Code stays left-to-right whatever the page direction: a shell command or a
   JSON body is not prose, and mirroring it would make it wrong rather than
   merely unfamiliar. */
[dir="rtl"] pre,
[dir="rtl"] code,
[dir="rtl"] .endpoint,
[dir="rtl"] .chip { direction: ltr; text-align: left; }

[dir="rtl"] .endpoint { justify-content: flex-end; }
[dir="rtl"] th, [dir="rtl"] td { text-align: right; }
[dir="rtl"] th code, [dir="rtl"] td code { direction: ltr; display: inline-block; }

/* Arabic sits differently on the line than Latin and needs more room. */

/* ---------- language switcher ---------- */

/* Mirrors the verusuite.com control, on <details> instead of a scripted
   button. The native disclosure gives keyboard support and Escape-to-close
   for free, which is the whole reason a public page can stay script-free. */
.lang { position: relative; }
.lang > summary {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 8px;
  border-radius: 6px; cursor: pointer;
  font-size: .82rem; color: var(--vm-ink-3);
  list-style: none;
  transition: color var(--vm-dur-1) var(--vm-ease);
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary:hover, .lang[open] > summary { color: var(--vm-ink); }
.lang > summary > svg:first-child { color: var(--vm-ink-4); }
.lang-code { text-transform: uppercase; letter-spacing: .04em; }
.lang-chev { transition: transform var(--vm-dur-1) var(--vm-ease); }
.lang[open] .lang-chev { transform: rotate(180deg); }

.lang-menu {
  position: absolute; top: calc(100% + 8px); inset-inline-end: 0;
  min-width: 172px; margin: 0; padding: 6px;
  list-style: none;
  background: var(--vm-paper-raised);
  border: 1px solid var(--vm-line-strong);
  border-radius: 10px;
  z-index: 60;
}
.lang-menu li { margin: 0; max-width: none; border-radius: 6px; }
.lang-menu li:hover { background: var(--vm-paper-sunken); }
.lang-menu a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  font-size: .85rem; color: var(--vm-ink); text-decoration: none;
}
.lang-menu li.on a { color: var(--vm-teal); font-weight: 500; }
.lang-hint {
  margin-inline-start: auto;
  font-family: var(--va-code); font-size: .68rem;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--vm-ink-4);
}
.lang-menu li.on .lang-hint { color: var(--vm-teal); }

/* ---------- reference sidebar and categories ---------- */

.docs-nav .nav-count,
.docs-nav .nav-soon {
  font-family: var(--va-code); font-size: .68rem;
  color: var(--vm-ink-4); font-variant-numeric: tabular-nums;
  margin-inline-start: .35rem;
}

/* "Soon" is metadata about the item, exactly like the count beside it, so it
   takes the count's treatment rather than an accent of its own.
   
   It was an ember badge at label weight, which made "Contacts Soon" read as
   one phrase — the name of a section rather than a section with a note. Ember
   also marks the single place per view where the brand names itself
   (DESIGN.md §1), and five of them down one sidebar spends that on nothing.
   
   nowrap keeps it on the label's last line: "Workspace administration" wraps,
   and a tag that wrapped with it would sit alone under the text it belongs to. */
.docs-nav .nav-soon { white-space: nowrap; }
.docs-nav a { display: flex; align-items: baseline; gap: .2rem; }

.cat-list { display: grid; gap: .6rem; margin: 1.25rem 0 2rem; }
.cat {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .15rem 1rem;
  align-items: baseline;
  padding: .95rem 1.15rem;
  background: var(--vm-paper-raised);
  border: 1px solid var(--vm-line);
  border-radius: 7px;
  text-decoration: none; color: inherit;
  transition: border-color var(--vm-dur-1) var(--vm-ease);
}
.cat:hover { border-color: var(--vm-teal); }
.cat--admin { border-inline-start: 3px solid var(--vm-ember); }
.cat-title { font-weight: 600; color: var(--vm-teal); }
.cat-blurb { grid-column: 1; color: var(--vm-ink-2); font-size: .89rem; }
.cat-count {
  grid-row: 1 / span 2; grid-column: 2; align-self: center;
  font-family: var(--va-code); font-size: .95rem;
  color: var(--vm-ink-3); font-variant-numeric: tabular-nums;
}

.row-summary { display: block; color: var(--vm-ink-3); font-size: .84rem; margin-top: .2rem; }

.sibling-list { list-style: none; padding: 0; margin: 1rem 0 0; }
.sibling-list li { display: flex; align-items: center; gap: .6rem; margin-bottom: .45rem; max-width: none; }

.eyebrow a { color: inherit; text-decoration: none; }
.eyebrow a:hover { text-decoration: underline; }

.perm { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; margin-bottom: .6rem; }


/* ---------------------------------------------------------------------------
   Try it

   A modal, because running a request is a task with its own inputs and its own
   result, and it should not sit permanently between the reader and the page it
   interrupts. The page documents; this executes.

   Depth is the backdrop and a hairline, not a shadow. The marketing surface
   carries depth with hairlines (DESIGN.md §5) and a modal already detaches
   from the page by dimming everything behind it, so a drop shadow would be a
   second answer to a question already settled.
   ------------------------------------------------------------------------ */

.try-open-row { display: flex; align-items: center; gap: .85rem; flex-wrap: wrap;
                margin: 1.5rem 0; }
.try-open-note { font-size: .875rem; color: var(--vm-ink-3); }

dialog.try {
  width: min(46rem, calc(100vw - 2rem));
  max-height: min(44rem, calc(100vh - 3rem));
  padding: 0;
  border: 1px solid var(--vm-line-strong);
  border-radius: 10px;
  background: var(--vm-paper-raised);
  color: var(--vm-ink);
  overflow: hidden;
}
dialog.try::backdrop { background: rgba(17, 24, 23, .42); }
:root[data-theme="dark"] dialog.try::backdrop { background: rgba(0, 0, 0, .6); }

.try-form { display: flex; flex-direction: column; max-height: inherit; min-height: 0; }

.try-head {
  display: flex; align-items: center; gap: 1rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--vm-line);
}
.try-head h2 { margin: 0; font-size: 1rem; font-weight: 600;
               display: flex; align-items: center; gap: .6rem; min-width: 0; }
/* A path is not prose: it stays left to right inside a right-to-left page. */
.try-head code { font-family: var(--va-code); font-size: .85rem; color: var(--vm-ink-2);
                 direction: ltr; unicode-bidi: isolate;
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.try-x { margin-inline-start: auto; display: grid; place-items: center;
         width: 2rem; height: 2rem; flex: none;
         border: 0; border-radius: 6px; background: transparent;
         color: var(--vm-ink-3); cursor: pointer; }
.try-x:hover { background: var(--vm-paper-sunken); color: var(--vm-ink); }

.try-body { padding: 1.25rem; overflow-y: auto; flex: 1; min-height: 0; }

.field { display: grid; gap: .35rem; margin-bottom: 1.1rem; }
.field--tight { margin-bottom: .8rem; }
.field-label { font-size: .8rem; font-weight: 500; color: var(--vm-ink-2); }
.field-label code { font-family: var(--va-code); font-size: .78rem; color: var(--vm-ink-2);
                    direction: ltr; unicode-bidi: isolate; }
.field-hint { font-size: .78rem; color: var(--vm-ink-3); }
.field-row { display: flex; gap: .5rem; align-items: stretch; }
.field-row > input, .field-row > select { flex: 1; min-width: 0; }

/* Code, ids and JSON stay left to right whatever the page direction. */
.try-body input, .try-body select, .try-body textarea {
  font: inherit; font-family: var(--va-code); font-size: .85rem;
  padding: .5rem .65rem;
  border: 1px solid var(--vm-line-strong); border-radius: 6px;
  background: var(--vm-paper); color: var(--vm-ink);
  direction: ltr; unicode-bidi: isolate; width: 100%;
}
.try-body textarea { line-height: 1.55; resize: vertical; }
.try-body input::placeholder { color: var(--vm-ink-3); }
.try-body input:focus-visible,
.try-body select:focus-visible,
.try-body textarea:focus-visible {
  outline: 2px solid var(--vm-teal); outline-offset: 1px; border-color: var(--vm-teal);
}

.try-tabs { display: inline-flex; gap: .25rem; padding: .2rem;
            background: var(--vm-paper-sunken); border-radius: 7px; margin-bottom: .85rem; }
.try-tab { border: 0; border-radius: 5px; padding: .3rem .7rem;
           font: inherit; font-size: .82rem; color: var(--vm-ink-2);
           background: transparent; cursor: pointer; }
.try-tab:hover { color: var(--vm-ink); }
.try-tab.is-on { background: var(--vm-paper-raised); color: var(--vm-teal); font-weight: 500; }
.try-tab:focus-visible { outline: 2px solid var(--vm-teal); outline-offset: 1px; }

.try-out { margin: 1.1rem 0 0; padding: .85rem 1rem;
           background: var(--vm-paper-sunken); border: 1px solid var(--vm-line);
           border-radius: 6px; max-height: 18rem; overflow: auto;
           font-size: .82rem; direction: ltr; unicode-bidi: isolate; }
.try-out code { white-space: pre; }
/* Teal marks a result that came back; red one that did not. Both are answers. */
.try-out--ok  { border-color: var(--vm-teal); }
.try-out--err { border-color: var(--vm-red); }
.try-out--err code { color: var(--vm-red); }

.try-foot {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--vm-line);
  background: var(--vm-paper-sunken);
}
.try-note { font-size: .82rem; color: var(--vm-ink-3); max-width: 34ch; }

@media (max-width: 560px) {
  dialog.try { width: 100vw; max-width: 100vw; max-height: 100vh; border-radius: 0; border: 0; }
  .try-note { max-width: none; }
}


/* The id picker.
   
   Anchored to the field it fills rather than centred, so the answer appears
   where the question was asked. It is a list of the reader's own things, which
   is the only reason a uuid field is bearable on a documentation page. */

.field-row { position: relative; }

.picker {
  position: absolute; inset-inline-start: 0; top: calc(100% + .35rem); z-index: 5;
  width: min(30rem, 100%);
  max-height: 17rem; display: flex; flex-direction: column;
  border: 1px solid var(--vm-line-strong); border-radius: 8px;
  background: var(--vm-paper-raised);
  /* The one shadow on this surface. A layer floating above a modal that is
     itself floating needs more than a hairline to sit apart from it. */
  box-shadow: 0 6px 20px rgba(17, 24, 23, .13);
}
:root[data-theme="dark"] .picker { box-shadow: 0 6px 20px rgba(0, 0, 0, .45); }

.picker-head { display: flex; align-items: center; gap: .5rem;
               padding: .55rem .7rem; border-bottom: 1px solid var(--vm-line); }
.picker-title { font-size: .78rem; font-weight: 500; color: var(--vm-ink-2); }
.picker-x { margin-inline-start: auto; display: grid; place-items: center;
            width: 1.4rem; height: 1.4rem; border: 0; border-radius: 4px;
            background: transparent; color: var(--vm-ink-3); cursor: pointer; }
.picker-x:hover { background: var(--vm-paper-sunken); color: var(--vm-ink); }

.picker-body { overflow-y: auto; padding: .25rem; }

.picker-row {
  display: grid; gap: .1rem; width: 100%; text-align: start;
  padding: .45rem .6rem; border: 0; border-radius: 5px;
  background: transparent; cursor: pointer; font: inherit;
}
.picker-row:hover { background: var(--vm-paper-sunken); }
.picker-row:focus-visible { outline: 2px solid var(--vm-teal); outline-offset: -2px; }
.picker-row-label { font-size: .86rem; color: var(--vm-ink);
                    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The second line is an id or a date: code, and left to right whatever the
   page direction. */
.picker-row-sub { font-family: var(--va-code); font-size: .72rem; color: var(--vm-ink-3);
                  direction: ltr; unicode-bidi: isolate;
                  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.picker-msg { margin: 0; padding: .9rem .7rem; font-size: .82rem; color: var(--vm-ink-3); }
.picker-msg--err { color: var(--vm-red); }


/* Field tables: what an endpoint takes and returns.
   
   The name column is code and stays left to right in any page direction; the
   description is prose and follows the page. Required is a word, not a colour
   or an asterisk — the one thing a reader must not miss should not depend on
   seeing a red dot. */

table.fields { font-size: .9rem; }
table.fields td { vertical-align: top; }
table.fields td:first-child { white-space: nowrap; }
table.fields code { font-family: var(--va-code); font-size: .82rem;
                    direction: ltr; unicode-bidi: isolate; }

.req { font-size: .68rem; letter-spacing: .05em; text-transform: uppercase;
       color: var(--vm-ember); margin-inline-start: .3rem; white-space: nowrap; }

.ftype { font-family: var(--va-code); font-size: .78rem; color: var(--vm-ink-3);
         direction: ltr; unicode-bidi: isolate; white-space: nowrap; }

/* Allowed values are the answer to "what may I put here", so they sit on their
   own line rather than trailing the sentence that mentions them. */
.fvalues { display: block; margin-top: .35rem; }
.fvalues code { display: inline-block; margin: .1rem .25rem .1rem 0;
                padding: .05rem .3rem; font-size: .74rem;
                background: var(--vm-paper-sunken); border: 1px solid var(--vm-line-faint);
                border-radius: 3px; color: var(--vm-ink-2); }

.fdefault { display: block; margin-top: .3rem; font-size: .82rem; color: var(--vm-ink-3); }

/* A nested object's own table, set in from the one that referenced it so the
   containment is visible without a heavy border or a second background. */
.nested { margin: 1.25rem 0 1.5rem; padding-inline-start: 1.1rem;
          border-inline-start: 1px solid var(--vm-line); }
.nested h3 { margin: 0 0 .6rem; font-size: .92rem; font-weight: 600; color: var(--vm-ink-2); }
.nested h3 + .table-wrap table.fields { font-size: .86rem; }
.nested .nested { margin-bottom: .75rem; }

.lede-note { margin-top: -.4rem; color: var(--vm-ink-2); }

/* ===========================================================================
   MCP
   ===========================================================================

   The diagram is the one piece of imagery on the site, so it earns its place by
   being a picture of the mechanism rather than a decoration: three boxes, two
   arrows, and the two facts a reader needs. Depth is hairlines, as everywhere
   else — the shadow tokens are for older surfaces.
*/

.band--mcp { position: relative; overflow: hidden; }

/* A very soft teal wash behind the section, so it reads as its own thing
   without a border or a card. Teal because it is the acting colour; ember is
   reserved for the one place per view where the brand names itself. */
.band--mcp::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(60rem 26rem at 78% 12%, color-mix(in oklab, var(--vm-teal) 9%, transparent), transparent 70%),
    radial-gradient(44rem 22rem at 8% 96%, color-mix(in oklab, var(--vm-teal) 5%, transparent), transparent 70%);
  pointer-events: none;
}
.band--mcp > .wrap { position: relative; }

.mcp-split {
  display: grid; gap: clamp(1.75rem, 4vw, 3.25rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
}
@media (min-width: 62rem) {
  .mcp-split { grid-template-columns: minmax(0, 27rem) minmax(0, 1fr); }
}
.mcp-copy .lede { margin-bottom: 1.1rem; }

/* ---------- the diagram ---------- */

.mcp-diagram { width: 100%; height: auto; display: block; }

.mcp-node rect {
  fill: var(--vm-paper-raised);
  stroke: var(--vm-line-strong);
  stroke-width: 1;
}
/* The middle box is the thing being explained, so it is the one that is
   marked. One accent, not three. */
.mcp-node--own rect { stroke: var(--vm-teal); }

.mcp-node text { text-anchor: middle; font-family: var(--vm-sans); }
.mcp-node-title { fill: var(--vm-ink); font-size: 15px; font-weight: 600; }
.mcp-node-sub   { fill: var(--vm-ink-2); font-size: 12px; }
.mcp-node-tag   { fill: var(--vm-ink-3); font-size: 10.5px; font-family: var(--va-code); }

.mcp-wire path {
  fill: none; stroke: var(--vm-line-strong); stroke-width: 1.5;
  color: var(--vm-ink-3); /* the arrowhead reads currentColor */
}
.mcp-wire-label {
  text-anchor: middle; fill: var(--vm-ink-3);
  font-size: 10.5px; font-family: var(--va-code);
}

/* The moving part. A dash travelling the wire, which is the path a call
   actually takes — motion that means something rather than motion that fills
   a gap. */
.mcp-flow path {
  fill: none;
  stroke: var(--vm-teal);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-dasharray: 10 74;
  animation: mcp-travel 2.6s var(--vm-ease) infinite;
}
.mcp-flow path:nth-child(2) { animation-delay: .5s; }

@keyframes mcp-travel {
  from { stroke-dashoffset: 84; opacity: 0; }
  15%  { opacity: 1; }
  85%  { opacity: 1; }
  to   { stroke-dashoffset: 0; opacity: 0; }
}

.mcp-note {
  text-anchor: middle; fill: var(--vm-ink-2);
  font-size: 12px; font-family: var(--vm-sans); font-weight: 500;
}
.mcp-note--dim { fill: var(--vm-ink-3); font-weight: 400; font-size: 11px; }

/* Nothing moves for a reader who asked for nothing to move. The global reset
   above shortens durations; this stops the loop outright, because a loop that
   merely runs fast is worse than one that does not run. */
@media (prefers-reduced-motion: reduce) {
  .mcp-flow { display: none; }
}

/* ---------- ticks ---------- */

.ticks { list-style: none; margin: 0 0 1.4rem; padding: 0; display: grid; gap: .55rem; }
.ticks li {
  position: relative; padding-inline-start: 1.6rem;
  color: var(--vm-ink-2); max-width: var(--measure);
}
.ticks li::before {
  content: ""; position: absolute; inset-inline-start: 0; top: .48em;
  width: .5rem; height: .28rem;
  border-inline-start: 2px solid var(--vm-teal);
  border-block-end: 2px solid var(--vm-teal);
  transform: rotate(-45deg);
}

/* ---------- numbered steps ---------- */

.steps {
  display: grid; gap: 1.25rem; margin-block: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.step {
  border: 1px solid var(--vm-line); border-radius: 10px;
  background: var(--vm-paper-raised); padding: 1.4rem 1.35rem;
}
.step-n {
  display: inline-grid; place-items: center;
  width: 1.7rem; height: 1.7rem; margin-bottom: .7rem;
  border-radius: 999px; border: 1px solid var(--vm-teal);
  color: var(--vm-teal); font-family: var(--va-code); font-size: .8rem;
}
.step h3 { margin: 0 0 .4rem; font-size: 1rem; }
.step p { margin: 0; color: var(--vm-ink-2); font-size: .93rem; }
.step pre { margin-top: .9rem; }

/* ---------- facts ---------- */

.facts {
  display: grid; gap: 1.25rem; margin-top: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.fact { border-block-start: 2px solid var(--vm-teal); padding-block-start: .9rem; }
.fact h3 { margin: 0 0 .4rem; font-size: 1rem; }
.fact p { margin: 0; color: var(--vm-ink-2); font-size: .93rem; max-width: var(--measure); }

/* ---------- disclosure ---------- */

.disclose { margin-top: 1.75rem; border-block-start: 1px solid var(--vm-line); padding-block-start: 1rem; }
.disclose > summary {
  cursor: pointer; color: var(--vm-teal); font-weight: 500;
  list-style: none; display: flex; align-items: center; gap: .5rem;
}
.disclose > summary::-webkit-details-marker { display: none; }
.disclose > summary::before {
  content: ""; width: 0; height: 0; flex: none;
  border-inline-start: 5px solid currentColor;
  border-block: 4px solid transparent;
  transition: transform var(--vm-dur-1) var(--vm-ease);
}
.disclose[open] > summary::before { transform: rotate(90deg); }

/* ---------- the tool catalogue ---------- */

.toolgroup { border-block-end: 1px solid var(--vm-line); }
.toolgroup > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: .7rem;
  padding-block: 1rem;
}
.toolgroup > summary::-webkit-details-marker { display: none; }
.toolgroup > summary::before {
  content: ""; width: 0; height: 0; flex: none;
  border-inline-start: 5px solid var(--vm-ink-3);
  border-block: 4px solid transparent;
  transition: transform var(--vm-dur-1) var(--vm-ease);
}
.toolgroup[open] > summary::before { transform: rotate(90deg); }
.toolgroup-title { font-weight: 600; font-size: 1.05rem; }
.toolgroup-count {
  font-family: var(--va-code); font-size: .78rem; color: var(--vm-ink-3);
}

.tooltable { width: 100%; border-collapse: collapse; font-size: .9rem; }
.tooltable th {
  text-align: start; padding: .5rem .8rem;
  font-family: var(--va-code); font-size: .68rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--vm-ink-3); font-weight: 500;
  border-block-end: 1px solid var(--vm-line);
}
.tooltable td { padding: .6rem .8rem; border-block-end: 1px solid var(--vm-line-faint); vertical-align: top; }
.tooltable tr:last-child td { border-block-end: 0; }
.tooltable code { font-size: .82rem; }
.tooltable .scope {
  display: inline-block; margin-inline-end: .3rem;
  color: var(--vm-ink-2); font-size: .76rem;
}

.chip--write {
  color: var(--vm-amber); background: var(--vm-amber-soft);
  border-color: var(--vm-amber); text-transform: none; letter-spacing: 0;
}

/* ---------- closing band ---------- */

.band--cta { text-align: center; }
.band--cta .lede { margin-inline: auto; }
.band--cta .actions { justify-content: center; }

/* ===========================================================================
   The hero figure
   ===========================================================================

   Calls arriving, meeting the scope gate, landing on an app — and one per cycle
   refused, because "a key can only do what you granted" is what this product
   sells and showing it beats saying it.

   Only transform and opacity animate, so this composites on the GPU and costs
   no layout. Everything stops under prefers-reduced-motion, and the figure is
   still a readable diagram when it does.
*/

.hero-split {
  display: grid; gap: clamp(1.75rem, 4vw, 3rem);
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
}
@media (min-width: 62rem) {
  .hero-split { grid-template-columns: minmax(0, 30rem) minmax(0, 1fr); }
}

.hero-fig { width: 100%; height: auto; display: block; }

.hero-rail path {
  fill: none; stroke: var(--vm-line-strong); stroke-width: 1.25;
}
.hero-rail .hero-rail--in { stroke-dasharray: 3 5; }

.hero-source rect,
.hero-apps rect {
  fill: var(--vm-paper-raised); stroke: var(--vm-line-strong); stroke-width: 1;
}
.hero-source text,
.hero-apps text {
  text-anchor: middle; fill: var(--vm-ink-2);
  font-family: var(--vm-sans); font-size: 12.5px;
}
.hero-source text { font-family: var(--va-code); font-size: 12px; fill: var(--vm-ink-3); }

/* The gate is the one marked element. Teal, because teal is the acting colour
   and this is the thing that acts. */
.hero-gate rect { fill: var(--vm-paper-raised); stroke: var(--vm-teal); stroke-width: 1.25; }
.hero-gate text {
  text-anchor: middle; fill: var(--vm-teal);
  font-family: var(--va-code); font-size: 11px;
}
.hero-gate .hero-gate-sub { fill: var(--vm-ink-3); font-size: 9.5px; }

/* The ring is gone. A 48px circle inside a 60px box sat on top of the label
   and read as noise; the gate's own border carries the same meaning with none
   of the clutter — it lights teal as a call passes and amber as one is
   refused. */
.hero-gate-ring { display: none; }

.hero-gate rect {
  animation: hero-gate-pulse 3.2s var(--vm-ease) infinite;
}
@keyframes hero-gate-pulse {
  0%, 100%  { stroke: var(--vm-teal); stroke-width: 1.25; }
  4%, 29%   { stroke: var(--vm-teal); stroke-width: 1.25; }
  8%        { stroke: var(--vm-teal); stroke-width: 2.5; }
  33%       { stroke: var(--vm-teal); stroke-width: 2.5; }
  58%       { stroke: var(--vm-teal); stroke-width: 2.5; }
  78%       { stroke: var(--vm-amber); stroke-width: 2.5; }
  90%       { stroke: var(--vm-teal); stroke-width: 1.25; }
}

/* ---------- the calls ---------- */

.hero-packets .p {
  fill: var(--vm-teal);
  offset-rotate: 0deg;
  animation: hero-run 3.2s var(--vm-ease) infinite;
  opacity: 0;
}

/* Each call takes a different rail out of the gate, so the fan is traffic
   rather than a pattern. offset-path draws the curve; browsers without it
   simply show a still figure, which is why the diagram has to read without
   motion in the first place.

   One continuous path each, running through the gate rather than two disjoint
   subpaths with a jump between them: offset-distance across a gap is not a
   thing worth relying on, and the gate's own fill hides the packet for the
   moment it is inside, which reads exactly right. */
.hero-packets .p1 { offset-path: path("M96 170 H300 C 356 170, 372 40,  432 40");  animation-delay: 0s; }
.hero-packets .p2 { offset-path: path("M96 170 H300 C 356 170, 372 144, 432 144"); animation-delay: .8s; }
.hero-packets .p3 { offset-path: path("M96 170 H300 C 356 170, 372 248, 432 248"); animation-delay: 1.6s; }

/* The refused one stops at the gate and fades. Amber, the same colour the
   reference uses for a call that was understood and refused. */
.hero-packets .p--denied {
  fill: var(--vm-amber);
  offset-path: path("M96 170 H255");
  animation: hero-stop 3.2s var(--vm-ease) infinite;
  animation-delay: 2.4s;
}

@keyframes hero-run {
  0%   { offset-distance: 0%;   opacity: 0; }
  8%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}
@keyframes hero-stop {
  0%   { offset-distance: 0%;   opacity: 0; }
  10%  { opacity: 1; }
  55%  { offset-distance: 100%; opacity: 1; }
  75%  { offset-distance: 100%; opacity: 0; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* The cross that marks the refusal, in step with the packet that earns it. */
.hero-denied path,
.hero-denied text {
  opacity: 0;
  animation: hero-deny 3.2s var(--vm-ease) infinite;
  animation-delay: 2.4s;
}
.hero-denied path {
  fill: none; stroke: var(--vm-amber); stroke-width: 2; stroke-linecap: round;
}
.hero-denied text {
  text-anchor: middle; fill: var(--vm-amber);
  font-family: var(--va-code); font-size: 10px;
}
@keyframes hero-deny {
  0%, 50% { opacity: 0; }
  58%     { opacity: .9; }
  78%     { opacity: 0; }
  100%    { opacity: 0; }
}

/* Each app lights as its call lands, so the right-hand side is a consequence
   of the left rather than decoration beside it. */
.hero-apps .app rect { transition: none; }
.hero-apps .a1 rect { animation: hero-hit 3.2s var(--vm-ease) infinite; animation-delay: .95s; }
.hero-apps .a3 rect { animation: hero-hit 3.2s var(--vm-ease) infinite; animation-delay: 1.75s; }
.hero-apps .a5 rect { animation: hero-hit 3.2s var(--vm-ease) infinite; animation-delay: 2.55s; }

@keyframes hero-hit {
  0%, 100% { stroke: var(--vm-line-strong); }
  6%       { stroke: var(--vm-teal); }
  30%      { stroke: var(--vm-line-strong); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-packets, .hero-denied { display: none; }
  .hero-gate rect, .hero-apps .app rect { animation: none; }
}

/* ---------- use cases ---------- */

.band--tight { padding-block: clamp(2.25rem, 5vw, 3.25rem); }

.case-soon {
  position: absolute; inset-block-start: 1.1rem; inset-inline-end: 1.1rem;
  font-family: var(--va-code); font-size: .68rem; letter-spacing: .07em;
  text-transform: uppercase; color: var(--vm-ink-3);
}
.case-tags--lg code { font-size: .82rem; }

.soon--inline { margin-top: 1.5rem; max-width: var(--measure); }

/* The flow. Numbered because order is the whole point of a walkthrough. */
.flow { list-style: none; counter-reset: flow; margin: 2rem 0 0; padding: 0; }
.flow li {
  counter-increment: flow;
  position: relative; padding: 0 0 1.75rem 3.25rem;
  border-inline-start: 1px solid var(--vm-line);
  margin-inline-start: .85rem;
}
.flow li:last-child { border-inline-start-color: transparent; padding-bottom: 0; }
.flow li::before {
  content: counter(flow);
  position: absolute; inset-inline-start: -.85rem; top: 0;
  width: 1.7rem; height: 1.7rem;
  display: grid; place-items: center;
  border-radius: 999px; border: 1px solid var(--vm-teal);
  background: var(--vm-paper); color: var(--vm-teal);
  font-family: var(--va-code); font-size: .78rem;
}
.flow h3 { margin: .15rem 0 .35rem; font-size: 1rem; }
.flow p { margin: 0; color: var(--vm-ink-2); max-width: var(--measure); }
.flow-call { margin-top: .6rem !important; display: flex; align-items: center; gap: .5rem; }

/* Gotchas. Ember here and nowhere else on the page: this is the one place the
   page says "pay attention", which is what the accent is reserved for. */
.watch { list-style: none; margin: 1.5rem 0 0; padding: 0; display: grid; gap: .9rem; }
.watch li {
  position: relative; padding-inline-start: 1.6rem;
  color: var(--vm-ink-2); max-width: var(--measure);
}
.watch li::before {
  content: ""; position: absolute; inset-inline-start: 0; top: .55em;
  width: .5rem; height: .5rem; border-radius: 999px;
  background: var(--vm-ember);
}


/* ===========================================================================
   Cards and grids
   ===========================================================================

   These classes have been in the templates since the site was written and were
   never given rules, so the landing page's app grid, its use-case grid and the
   reference index have all been rendering as bare lists of links. Written to
   DESIGN.md: depth from hairlines, teal as the acting colour, and no reach for
   the legacy shadow tokens.
*/

.band--hero { padding-block: clamp(3.5rem, 8vw, 6rem); }
.band--hero h1 { margin-block: .35rem .6rem; }

/* ---------- a grid of cards ---------- */

.apps, .cases {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(17.5rem, 1fr));
  margin-top: 2rem;
}

.app, .case {
  position: relative;
  display: flex; flex-direction: column; gap: .45rem;
  padding: 1.3rem 1.35rem;
  border: 1px solid var(--vm-line); border-radius: 10px;
  background: var(--vm-paper-raised);
  color: inherit; text-decoration: none;
  transition: border-color var(--vm-dur-2) var(--vm-ease),
              transform var(--vm-dur-2) var(--vm-ease);
}
/* A card lifts by a hair. Enough to say it is a target, not enough to look
   like it is floating — this system carries depth in hairlines. */
.app:hover, .case:hover { border-color: var(--vm-teal); transform: translateY(-2px); }
.app:focus-visible, .case:focus-visible { outline: 2px solid var(--vm-teal); outline-offset: 3px; }

.app h3, .case h3 { margin: 0; font-size: 1.02rem; line-height: 1.35; }
.app p, .case p {
  margin: 0; color: var(--vm-ink-2);
  font-size: .9rem; line-height: 1.55; flex: 1;
}

.app-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.app-name {
  font-family: var(--va-code); font-size: .7rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--vm-ink-3);
}
/* The count is subtext, like every other count on the site, not a badge. */
.app-count {
  margin-top: .35rem;
  font-family: var(--va-code); font-size: .74rem; color: var(--vm-ink-3);
}

/* Scopes on a card. Wrapped and small: they answer "what would this need"
   at a glance, and the page behind answers it properly. */
.case-tags { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .35rem; }
.case-tags code {
  font-size: .72rem; padding: .1rem .35rem;
  border: 1px solid var(--vm-line); border-radius: 3px;
  background: var(--vm-paper-sunken); color: var(--vm-ink-3);
}

/* ---------- the admin strip ---------- */

/* One row rather than a card, because administration is not an app somebody
   browses to — it is the thing they arrive at already knowing they need. */
.admin-strip {
  display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap;
  margin-top: 1rem; padding: 1.2rem 1.35rem;
  border: 1px solid var(--vm-line); border-radius: 10px;
  background: var(--vm-paper-raised);
}
.admin-strip-text { flex: 1; min-width: 15rem; }
.admin-strip-text h3 { margin: 0 0 .25rem; font-size: 1rem; }
.admin-strip-text p { margin: 0; color: var(--vm-ink-2); font-size: .9rem; }

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

.section-rule {
  margin-block: 2.5rem 1.25rem;
  padding-block-end: .5rem;
  border-block-end: 1px solid var(--vm-line);
  font-family: var(--va-code); font-size: .72rem; letter-spacing: .09em;
  text-transform: uppercase; color: var(--vm-ink-3); font-weight: 500;
}
.refgroup { padding-block: 1.1rem; border-block-end: 1px solid var(--vm-line-faint); }
.refgroup:last-child { border-block-end: 0; }
.refgroup-head { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; }
.refgroup-head h3 { margin: 0; font-size: 1.02rem; }
.refgroup-head a { text-decoration: none; }
.refgroup-head a:hover { text-decoration: underline; }

/* ---------- odds ---------- */

.btn--sm { padding: .35rem .7rem; font-size: .85rem; }

.mcp-art { min-width: 0; }

/* ---------- SDKs ---------- */

/* Available is a state, so it gets the same chip vocabulary as everything
   else on the site rather than a badge of its own. */
.chip--live { color: var(--vm-green); background: var(--vm-green-soft); border-color: var(--vm-green); }

/* The install line is the one thing on the card somebody copies, so it is
   given its own weight and sits above the sample rather than inside it. */
.sdk-install { margin-bottom: 1rem; padding: .8rem 1.15rem; }
.sdk-sample { margin-bottom: .9rem; }

.sdk-status { margin: 0 0 1rem; color: var(--vm-ink-2); font-size: .93rem; max-width: var(--measure); }
.sdk-needs { margin: 0; color: var(--vm-ink-4); font-size: .85rem; }

/* ---------- the language picker ----------
   
   A radio group, not buttons, because this site ships no JavaScript. It is
   also the truthful control: one language is chosen at a time, and a screen
   reader announces "1 of 4, selected" without any ARIA having to claim it.
   
   Every radio is a sibling of .sdkpanels and precedes it, which is what lets
   :checked reach the matching panel. Each radio also sits immediately before
   its own label, so :checked and :focus-visible can style the chip with a
   plain adjacent selector. Both facts are load-bearing: reordering the markup
   breaks the page silently, with every panel hidden and nothing to click. */

.sdkpicker {
  position: relative;
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
  margin-top: 1.6rem;
}

/* Off the page but still focusable and still hit by :checked. Not
   display:none, which would take it out of the tab order and out of the
   accessibility tree, leaving the labels unreachable from a keyboard. */
.sdkradio {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none; margin: 0;
}

.sdkchip {
  display: inline-flex; align-items: baseline; gap: .4rem;
  padding: .42rem .85rem; border-radius: 999px;
  border: 1px solid var(--vm-line);
  background: var(--vm-paper-raised);
  color: var(--vm-ink-2); font-size: .92rem; line-height: 1;
  cursor: pointer; user-select: none; white-space: nowrap;
  transition: color var(--vm-dur-1) var(--vm-ease),
              border-color var(--vm-dur-1) var(--vm-ease),
              background var(--vm-dur-1) var(--vm-ease);
}
.sdkchip:hover { color: var(--vm-ink); border-color: var(--vm-line-strong); }

.sdkradio:checked + .sdkchip {
  color: var(--vm-paper-raised);
  background: var(--vm-teal);
  border-color: var(--vm-teal);
  font-weight: 500;
}

/* The focus ring belongs on the chip, because the radio it belongs to is a
   pixel nobody can see. */
.sdkradio:focus-visible + .sdkchip {
  outline: 2px solid var(--vm-teal);
  outline-offset: 2px;
}

.sdkchip-soon {
  font-family: var(--va-code); font-size: .66rem; letter-spacing: .07em;
  text-transform: uppercase; color: var(--vm-ink-4);
}
.sdkradio:checked + .sdkchip .sdkchip-soon { color: var(--vm-teal-soft); }

/* The panels take a whole row of the flex container, under the chips. */
.sdkpanels { flex: 1 0 100%; margin-top: 1.4rem; }

.sdkpanel { display: none; }

/* One rule per language. Adding an entry to site.SDKs without adding a pair
   here leaves that language selectable and blank, so a test asserts every key
   in the table appears in this file. */
#sdk-go:checked     ~ .sdkpanels #panel-go,
#sdk-node:checked   ~ .sdkpanels #panel-node,
#sdk-python:checked ~ .sdkpanels #panel-python,
#sdk-dotnet:checked ~ .sdkpanels #panel-dotnet { display: block; }

.sdkpanel-head { display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
.sdkpanel-head h3 { margin: 0; font-size: 1.1rem; }

.sdkpanel-step {
  margin: 0 0 .5rem; color: var(--vm-ink-3); font-size: .87rem;
  text-transform: uppercase; letter-spacing: .06em;
}

/* Text that is announced but not shown. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}
