/* VocalVault shared design system — tokens, base, components, nav, footer.
   Loaded on every page; page-specific CSS stays inline. Theme via [data-theme]. */

:root {
  --brand: #5468ee;
  --brand-600: #4152e0;
  --brand-700: #354bd0;
  --brand-050: #eef1fe;
  --brand-100: #e0e6fd;
  --brand-200: #c7d2fb;
  /* --brand is the FILL (white-on-brand is 4.57:1). --brand-ink is the same
     hue tuned for TEXT: plain --brand as a link colour was 4.27:1 on --bg,
     under the 4.5:1 WCAG AA floor, so every link on the site failed. */
  --brand-ink: #4a5fe8;
  /* Signed-in sidebar. These are their own tokens because the rail is the one
     surface whose light and dark treatments are not simply inverses: it is a
     panel in light, and a console darker than the page in dark. */
  --rail: #ffffff;
  --rail-line: var(--line);
  --rail-fg: #56607a;
  --rail-fg-strong: #141a2b;
  --rail-grp: #66718b;
  --rail-hover: #f4f7ff;
  --rail-active-bg: var(--brand-050);
  --rail-active-fg: var(--brand-ink);
  --bg: #f5f7fe;
  --panel: #ffffff;
  --panel2: #f4f7ff;
  --line: #e5e9f5;
  /* Greys and semantics re-tuned for WCAG AA (>=4.5:1 on the worst surface,
     --bg). Previous values measured: dim 4.40, faint 2.30, ok 3.16, bad 3.80,
     warn 2.98, idle 2.25 — all failing. The three-level grey ramp is kept
     distinct rather than collapsed to the darkest passing value. */
  --text: #141a2b;
  --dim: #56607a;
  --faint: #66718b;
  --ok: #127a45;
  --bad: #cf2d22;
  --warn: #8f6213;
  --idle: #5c6f8c;
  --code: #101a30;
  --code-fg: #e6ecfb;
  --mono: ui-monospace, "SF Mono", Consolas, monospace;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --r-sm: 9px;
  --r: 14px;
  --r-lg: 20px;
  --r-xl: 26px;
  --shadow: 0 1px 2px rgba(16, 32, 80, .04), 0 18px 40px -28px rgba(41, 64, 148, .45);
  --shadow-lg: 0 2px 6px rgba(16, 32, 80, .05), 0 34px 60px -34px rgba(41, 64, 148, .55);
  --nav-h: 60px;
}

[data-theme="dark"] {
  --brand-050: #1b2646;
  --brand-100: #2c3c66;
  --brand-200: #3a4f86;
  --bg: #0d111c;
  --panel: #151b29;
  --panel2: #1a2130;
  --line: #273042;
  --brand-ink: #8b99f5;
  /* --brand is only 3.52:1 on --panel2 in dark */
  --rail: #0a0f1c;
  --rail-line: rgba(255, 255, 255, .08);
  --rail-fg: #9fb2d4;
  --rail-fg-strong: #e6ecfb;
  --rail-grp: #7d8cab;
  --rail-hover: rgba(255, 255, 255, .055);
  --rail-active-bg: rgba(84, 104, 238, .20);
  --rail-active-fg: #a3aef8;
  --text: #e8edf8;
  --dim: #a3b0c6;
  --faint: #8592a8;
  --ok: #3fce85;
  --bad: #ff8279;
  --warn: #e6b455;
  --idle: #9aa8bd;
  --code: #0a0f1c;
  --code-fg: #dbe6ff;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 18px 40px -28px rgba(0, 0, 0, .7);
  --shadow-lg: 0 2px 8px rgba(0, 0, 0, .35), 0 40px 70px -34px rgba(0, 0, 0, .8);
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 12px);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--brand-ink);
  text-decoration: none;
}

a:hover {
  color: var(--brand-600);
}

h1,
h2,
h3,
h4 {
  letter-spacing: -.02em;
  line-height: 1.12;
  margin: 0 0 .4em;
}

p {
  margin: 0 0 1em;
}

img {
  max-width: 100%;
}

::selection {
  background: var(--brand-200);
}

/* ---------- layout ---------- */
.container {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 22px;
}

.container-narrow {
  max-width: 860px;
  margin: 0 auto;
  padding: 0 22px;
}

.section {
  padding: 56px 0;
}

.eyebrow {
  color: var(--brand-ink);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  margin-bottom: 10px;
}

/* Visually hidden but available to screen readers — for text that describes a
   decorative visual the sighted reader already understands. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- skip link (WCAG 2.4.1) ----------
   Off-screen until focused, then pinned over the nav. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--brand);
  color: #fff;
  font-weight: 650;
  font-size: 15px;
  padding: 11px 18px;
  border-radius: 0 0 var(--r-sm) 0;
}

.skip-link:focus {
  left: 0;
  color: #fff;
  outline: 2px solid var(--text);
  outline-offset: -4px;
}

/* ---------- navbar (injected by vv-nav.js) ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--nav-h);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s ease, background 0.35s ease, border-color 0.35s ease;
  will-change: transform;
}

.nav.nav-hidden {
  transform: translateY(-100%);
  opacity: 0;
  pointer-events: none;
}

.nav-inner {
  max-width: 1120px;
  margin: 0 auto;
  height: 100%;
  padding: 0 20px;
  display: flex;
  align-items: center;
  gap: 16px;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -.02em;
  font-size: 17px;
}

.nav-brand img {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  box-shadow: 0 3px 10px -3px var(--brand);
}

.nav-links {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.nav-links>a {
  color: var(--dim);
  font-weight: 600;
  font-size: 14.5px;
  padding: 8px 12px;
  border-radius: 999px;
  position: relative;
}

.nav-links>a:hover {
  color: var(--text);
  background: var(--panel2);
}

.nav-links>a.active {
  color: var(--brand-ink);
}

.nav-links>a.active::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 2px;
  height: 2px;
  border-radius: 2px;
  background: var(--brand);
}

/* Written as `.nav-links > a.nav-cta` because `.nav-links > a` above is more
   specific than a bare `.nav-cta` and was winning — which is why this button
   rendered with dim text instead of white on brand. */
.nav-cta,
.nav-links>a.nav-cta {
  background: var(--brand);
  color: #fff;
  font-weight: 650;
  font-size: 14px;
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid var(--brand);
}

.nav-cta:hover,
.nav-links>a.nav-cta:hover {
  background: var(--brand-600);
  border-color: var(--brand-600);
  color: #fff;
}

.nav-links>a.nav-cta.active::after {
  display: none;
}

.nav-burger {
  display: none;
  margin-left: auto;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  background: var(--panel);
  border-radius: 11px;
  cursor: pointer;
  position: relative;
}

.nav-burger span,
.nav-burger span::before,
.nav-burger span::after {
  content: "";
  position: absolute;
  left: 11px;
  width: 16px;
  height: 2px;
  background: var(--text);
  border-radius: 2px;
  transition: .2s;
}

.nav-burger span {
  top: 19px;
}

.nav-burger span::before {
  top: -5px;
}

.nav-burger span::after {
  top: 5px;
}

.nav.open .nav-burger span {
  background: transparent;
}

.nav.open .nav-burger span::before {
  top: 0;
  transform: rotate(45deg);
}

.nav.open .nav-burger span::after {
  top: 0;
  transform: rotate(-45deg);
}

@media (max-width:760px) {
  .nav-burger {
    display: block;
  }

  .nav-links {
    position: fixed;
    inset: var(--nav-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    padding: 12px 16px 18px;
    box-shadow: var(--shadow);
    transform: translateY(-12px);
    opacity: 0;
    pointer-events: none;
    /* visibility (not just opacity) so the closed drawer leaves the tab order —
       without it a keyboard user tabs through five invisible links after the
       burger. Delayed on the way out so the .18s fade still plays. */
    visibility: hidden;
    transition: transform .18s, opacity .18s, visibility 0s .18s;
  }

  .nav.open .nav-links {
    transform: none;
    opacity: 1;
    pointer-events: auto;
    visibility: visible;
    transition: transform .18s, opacity .18s, visibility 0s;
  }

  .nav-links>a {
    padding: 12px 14px;
    font-size: 16px;
  }

  /* Same specificity trap as the .nav-cta fix above: `.nav-links > a.nav-cta`
     beats the plain `.nav-links > a` rule, so the CTA kept its compact desktop
     padding in the drawer and came out 40px tall — under the 44px touch
     minimum, on the one control the page most wants tapped. */
  .nav-links>a.nav-cta {
    padding: 12px 14px;
    font-size: 16px;
  }

  .nav-links>a.active::after {
    display: none;
  }

  .nav-links .btn {
    justify-content: center;
  }
}

/* ---------- footer (injected) ---------- */
.site-footer {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  background: #000000;
  color: #8e9bb2;
  margin-top: 40px;
}

.footer-inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: 26px 22px;
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  color: #8e9bb2;
  font-size: 13.5px;
}

.footer-inner .fb {
  display: flex;
  align-items: center;
  gap: 9px;
  color: #ffffff;
  font-weight: 700;
}

.footer-inner .fb img {
  width: 22px;
  height: 22px;
  border-radius: 50%;
}

.footer-links {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.footer-legal {
  font-size: 12.5px;
  line-height: 1.55;
  color: #738096;
  width: 100%;
  border-top: 1px solid rgba(255, 255, 255, 0.09);
  padding-top: 14px;
  margin-top: 4px;
}

.footer-legal strong {
  color: #e1e7f5;
  font-weight: 700;
}

.footer-legal a {
  color: #9bb2ff;
}

.footer-legal a:hover {
  color: #ffffff;
}

.footer-links a {
  color: #8e9bb2;
  font-weight: 600;
  transition: color 0.15s ease;
}

.footer-links a:hover {
  color: #ffffff;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: inherit;
  font-weight: 650;
  font-size: 15px;
  padding: 11px 20px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  transition: .14s;
  white-space: nowrap;
}

.btn:hover {
  border-color: var(--brand);
  color: var(--brand-ink);
  transform: translateY(-1px);
}

.btn:disabled {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
}

.btn-primary {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
  box-shadow: 0 12px 22px -12px var(--brand);
}

.btn-primary:hover {
  background: var(--brand-600);
  border-color: var(--brand-600);
  color: #fff;
}

.btn-ghost {
  background: transparent;
}

.btn-sm {
  padding: 8px 14px;
  font-size: 14px;
  border-radius: 999px;
}

/* ---------- surfaces & bits ---------- */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 24px;
  box-shadow: var(--shadow);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--brand-050);
  border: 1px solid var(--brand-100);
  color: var(--brand-ink);
}

.mono {
  font-family: var(--mono);
}

.dim {
  color: var(--dim);
}

.ok {
  color: var(--ok)
}

.bad {
  color: var(--bad)
}

.warn {
  color: var(--warn)
}

/* ---------- forms ----------
   Typed selectors were missing `email`, `search`, `url`, `tel` and `date`, so
   those rendered with browser defaults next to styled siblings. Matching on
   `input:not(...)` covers every text-like field and keeps covering them when a
   new type is used. */
input:not([type=checkbox]):not([type=radio]):not([type=file]):not([type=range]):not([type=submit]):not([type=button]),
select,
textarea {
  font-family: inherit;
  font-size: 14px;
  line-height: 1.4;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 9px 12px;
  transition: border-color .14s, box-shadow .14s;
}

input:hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) {
  border-color: var(--brand-200);
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  border-color: var(--brand);
}

/* Focus ring for every other interactive element. The UA default is fine in
   WebKit but disappears against dark surfaces in some browsers, and
   --brand-200 was too pale to meet the 3:1 non-text contrast floor for a
   focus indicator — --brand clears it on every surface we paint. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible,
summary:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 3px;
}

input:disabled,
select:disabled,
textarea:disabled {
  opacity: .55;
  cursor: not-allowed;
  background: var(--panel2);
}

input::placeholder,
textarea::placeholder {
  color: var(--faint);
}

/* Native selects carry system chrome — a different height, font and arrow on
   every platform — so they never sit level with the inputs beside them.
   `appearance:none` removes it; the chevron is drawn back in as a background
   image, one per theme because a background image cannot inherit currentColor. */
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  cursor: pointer;
  background-repeat: no-repeat;
  background-position: right 11px center;
  background-size: 15px 15px;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23697488" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>');
}

[data-theme="dark"] select {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%2394a1b8" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>');
}

select:focus {
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%235468ee" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>');
}

/* The dropdown list itself is drawn by the OS; these are the only two
   properties browsers reliably honour, and they stop a dark theme showing
   white-on-white options. */
select option {
  background: var(--panel);
  color: var(--text);
}

/* File inputs: the button half is the only stylable part, and only via this
   pseudo-element. */
input[type=file] {
  font-family: inherit;
  font-size: 14px;
  color: var(--dim);
  max-width: 100%;
}

input[type=file]::file-selector-button {
  font-family: inherit;
  font-weight: 650;
  font-size: 14px;
  margin-right: 12px;
  padding: 9px 16px;
  border-radius: var(--r-sm);
  cursor: pointer;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--text);
  transition: .14s;
}

input[type=file]::file-selector-button:hover {
  border-color: var(--brand);
  color: var(--brand-ink);
}

/* Checkboxes keep native behaviour — accent-color is enough to brand them and
   avoids reimplementing focus and keyboard handling badly. */
input[type=checkbox],
input[type=radio] {
  accent-color: var(--brand);
  width: 16px;
  height: 16px;
  cursor: pointer;
}

/* ---------- code ---------- */
.code {
  background: var(--code);
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: var(--shadow);
}

.code-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 14px;
  background: rgba(255, 255, 255, .04);
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.code-head .lang {
  color: #8ea2c8;
  font: 12px var(--mono);
  letter-spacing: .05em;
}

.code-head .copy {
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .14);
  color: #cdd9f2;
  border-radius: 7px;
  padding: 5px 11px;
  font: 12px var(--font);
  font-weight: 600;
  cursor: pointer;
}

.code-head .copy:hover {
  border-color: var(--brand);
  color: #fff;
}

.code pre {
  margin: 0;
  padding: 16px;
  overflow: auto;
}

.code code {
  font: 13.5px/1.6 var(--mono);
  color: var(--code-fg);
  white-space: pre;
}

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

  .btn:hover {
    transform: none;
  }
}

/* ==========================================================================
   APP SHELL — signed-in pages. Public pages keep the marketing nav above;
   everything under /app and /admin uses this sidebar layout instead.
   ========================================================================== */

/* The shell reads as an instrument rather than a generic SaaS dashboard. The
   rail follows the theme through its own --rail-* tokens: a white panel in
   light, a console darker than the page in dark. Every pairing below clears
   4.5:1 in both. */
.app {
  display: grid;
  grid-template-columns: 252px 1fr;
  min-height: 100vh;
}

.app-side {
  background: var(--rail);
  border-right: 1px solid var(--rail-line);
  padding: 20px 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.app-side .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 800;
  color: var(--rail-fg-strong);
  font-size: 16.5px;
  padding: 10px 12px 10px;
  letter-spacing: -.02em;
}

.app-side .brand img {
  width: 28px;
  height: 28px;
  border-radius: 50%;
}

.app-side .grp {
  color: var(--rail-grp);
  font: 700 10.5px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  padding: 20px 12px 8px;
}

.app-side .grp::after {
  content: "";
  display: block;
  height: 1px;
  margin-top: 8px;
  background: var(--rail-line);
}

.app-side a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border-radius: 9px;
  color: var(--rail-fg);
  font-weight: 600;
  font-size: 14.5px;
  position: relative;
  transition: color .15s, background .15s;
}

.app-side a:hover {
  background: var(--rail-hover);
  color: var(--rail-fg-strong);
}

.app-side a.active {
  background: var(--rail-active-bg);
  color: var(--rail-active-fg);
}

/* A lit bar on the active item — the rail reads as a signal path. */
.app-side a.active::before {
  content: "";
  position: absolute;
  left: -12px;
  top: 9px;
  bottom: 9px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--brand);
}

.app-side a:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

.app-side .side-foot {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--rail-line);
}

.app-side .side-upgrade,
.app-side a.side-upgrade {
  justify-content: center;
  background: var(--brand);
  color: #fff;
  margin: 14px 4px 0;
  font-weight: 650;
}

.app-side a.side-upgrade:hover {
  background: var(--brand-600);
  color: #fff;
}

.app-side a.side-upgrade::before {
  display: none;
}

.app-main {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-top {
  height: var(--nav-h);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 26px;
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(12px);
}

.app-top .ctx {
  font: 600 11.5px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
}

.app-top .who {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

.app-body {
  padding: 30px 26px 72px;
  max-width: 1220px;
  width: 100%;
}

.app-burger {
  display: none;
}

/* ---------- page header ----------
   Mono kicker over a large title, closed by a rule — the same head shape the
   public pages use, so the product reads as one thing across the sign-in line. */
.page-head {
  display: flex;
  align-items: flex-end;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 26px;
  padding-bottom: 13px;
  border-bottom: 1px solid var(--line);
}

.page-head .eyebrow-m {
  font: 700 10.5px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brand-ink);
  margin-bottom: 9px;
  display: block;
}

.page-head h1 {
  font-size: 29px;
  margin: 0 0 5px;
  letter-spacing: -.028em;
}

.page-head p {
  color: var(--dim);
  margin: 0;
  font-size: 14.5px;
  max-width: 64ch;
}

.page-head .actions {
  margin-left: auto;
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
  padding-bottom: 2px;
}

/* ---------- stat row ----------
   Not tiles. A single hairline-divided row: mono label, tabular number, note.
   Four boxes in a line is the shape every dashboard defaults to; this reads as
   a readout instead. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: 26px;
}

.stat {
  padding: 18px 22px 17px;
  border-left: 1px solid var(--line);
}

.stat:first-child {
  border-left: 0;
  padding-left: 2px;
}

.stat .k {
  color: var(--faint);
  font: 700 10.5px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
}

.stat .v {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -.035em;
  margin-top: 10px;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.stat .v.ok {
  color: var(--ok);
}

.stat .v.bad {
  color: var(--bad);
}

.stat .v.warn {
  color: var(--warn);
}

.stat .s {
  font-size: 12.5px;
  color: var(--dim);
  margin-top: 6px;
}

@media (max-width:820px) {
  .stat {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-left: 2px;
  }

  .stat:first-child {
    border-top: 0;
  }
}

/* ---------- cards ---------- */
.card>h2:first-child {
  font-size: 15px;
  letter-spacing: .01em;
  margin: -4px 0 5px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
  color: var(--text);
}

/* A ruled header sitting directly on a row list left 25px between the rule and
   the first row against 19px between every row after it — a visible dent at the
   top of the card. Tuck the first row up so the rhythm is even all the way down. */
.card>h2:first-child+.kv,
.card>h2:first-child+.pending-row {
  padding-top: 3px;
}

/* ---------- sub-tabs ----------
   Views of one list (devices in use / revoked), underlined like the hairline
   tables they sit above. */
.subtabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 8px;
}

.subtabs button {
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--dim);
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 9px 12px;
  cursor: pointer;
}

.subtabs button:hover {
  color: var(--text);
}

.subtabs button[aria-selected="true"] {
  color: var(--brand-ink);
  border-bottom-color: var(--brand);
}

.subtabs .count {
  font: 600 11.5px var(--mono);
  color: var(--faint);
  margin-left: 6px;
}

/* ---------- tables ----------
   Hairline-bounded rather than a floating rounded panel, so a table reads as
   part of the page rather than as another card sitting on it. */
.tablewrap {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
}

table.vt {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

table.vt th {
  text-align: left;
  font: 700 10.5px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--faint);
  padding: 14px 16px 13px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

table.vt th:first-child,
table.vt td:first-child {
  padding-left: 2px;
}

table.vt td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

table.vt tr:last-child td {
  border-bottom: 0;
}

table.vt tbody tr {
  transition: background .13s;
}

table.vt tbody tr:hover {
  background: var(--panel2);
}

table.vt td.num,
table.vt th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Anything a reader could check independently is set in mono. */
table.vt td .mono,
table.vt td.mono {
  font-family: var(--mono);
  font-size: 12.5px;
}

/* ---------- app shell: narrow ---------- */
@media (max-width:900px) {
  .app {
    grid-template-columns: 1fr;
  }

  .app-side {
    position: fixed;
    inset: 0 auto 0 0;
    width: 252px;
    z-index: 60;
    transform: translateX(-100%);
    transition: transform .2s cubic-bezier(.22, .7, .3, 1);
    visibility: hidden;
  }

  .app.side-open .app-side {
    transform: none;
    visibility: visible;
    box-shadow: 0 0 0 100vmax rgba(6, 10, 20, .5);
  }

  .app-burger {
    display: block;
    width: 38px;
    height: 38px;
    border: 1px solid var(--line);
    background: var(--panel);
    border-radius: 10px;
    cursor: pointer;
    font-size: 16px;
  }

  .app-body {
    padding: 24px 18px 60px;
  }

  .page-head h1 {
    font-size: 24px;
  }
}

/* Page entrance. Each view fades up once on mount; the stagger comes from an
   --i index so nothing has to be timed by hand. Collapses to nothing when the
   viewer has asked for reduced motion. */
@media (prefers-reduced-motion:no-preference) {
  .app-body>* {
    animation: appIn .42s cubic-bezier(.22, .7, .3, 1) backwards;
    animation-delay: calc(var(--i, 0) * 55ms);
  }

  @keyframes appIn {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
  }
}

/* ---------- badges ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid transparent;
  white-space: nowrap;
}

.badge.ok {
  background: color-mix(in srgb, var(--ok) 14%, transparent);
  color: var(--ok);
  border-color: color-mix(in srgb, var(--ok) 30%, transparent);
}

.badge.bad {
  background: color-mix(in srgb, var(--bad) 14%, transparent);
  color: var(--bad);
  border-color: color-mix(in srgb, var(--bad) 30%, transparent);
}

.badge.warn {
  background: color-mix(in srgb, var(--warn) 16%, transparent);
  color: var(--warn);
  border-color: color-mix(in srgb, var(--warn) 32%, transparent);
}

.badge.idle {
  background: var(--panel2);
  color: var(--dim);
  border-color: var(--line);
}

.badge.brand {
  background: var(--brand-050);
  color: var(--brand-ink);
  border-color: var(--brand-100);
}

/* ---------- forms (app) ---------- */
.field {
  margin-bottom: 15px;
}

.field label {
  display: block;
  font-size: 13px;
  font-weight: 650;
  margin-bottom: 6px;
}

.field .hint {
  font-size: 12.5px;
  color: var(--faint);
  margin-top: 5px;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 11px 13px;
  font-size: 15px;
}

/* Keep room for the chevron — the rule above would otherwise let long option
   text run underneath it. */
.field select {
  padding-right: 36px;
  background-position: right 12px center;
}

.field input[type=file] {
  padding: 0;
}

.row2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

@media (max-width:620px) {
  .row2 {
    grid-template-columns: 1fr;
  }
}

/* ---------- auth pages ---------- */
.auth-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 40px 20px;
  background: radial-gradient(760px 420px at 50% -60px, var(--brand-050), transparent 70%);
}

.auth-card {
  width: 100%;
  max-width: 420px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 32px;
  box-shadow: var(--shadow-lg);
}

.auth-card .lg {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-content: center;
  font-weight: 800;
  font-size: 18px;
  margin-bottom: 6px;
}

.auth-card .lg img {
  width: 34px;
  height: 34px;
  border-radius: 50%;
}

.auth-card h1 {
  font-size: 22px;
  text-align: center;
  margin: 12px 0 6px;
}

.auth-card .sub {
  text-align: center;
  color: var(--dim);
  font-size: 14px;
  margin-bottom: 22px;
}

.auth-alt {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--faint);
  font-size: 12.5px;
  margin: 18px 0;
}

.auth-alt::before,
.auth-alt::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.btn-google {
  width: 100%;
  justify-content: center;
  gap: 10px;
}

.auth-foot {
  text-align: center;
  font-size: 14px;
  color: var(--dim);
  margin-top: 20px;
}

/* ---------- misc ---------- */
/* .empty is the older class; .t-empty above supersedes it. Kept as an alias so
   any page still using it does not lose its centring. */
.empty,
.t-empty {
  text-align: center;
  color: var(--dim);
}

.empty {
  padding: 46px 20px;
}

.empty .ic {
  font-size: 34px;
  opacity: .5;
  margin-bottom: 10px;
}

.t-loading p {
  opacity: .8;
}

.grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.grid3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
}

@media (max-width:820px) {
  .grid2 {
    grid-template-columns: 1fr;
  }
}

/* The pairing code, read off the screen and typed on a phone. Wide letter
   spacing because the alphabet deliberately excludes I, L, O and U but a
   reader still has to tell 8 from B. */
.pair-code {
  font-size: 38px;
  font-weight: 700;
  letter-spacing: .22em;
  padding: 16px 0 4px;
  color: var(--fg);
  user-select: all;
}

button.linklike {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: var(--brand-ink);
  cursor: pointer;
  text-decoration: underline;
}

/* A device awaiting approval: description on the left, the decision on the
   right. Wraps rather than crushing the buttons on a narrow screen. */
.pending-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}

.pending-row:first-of-type {
  border-top: 0;
}

.pending-row .btn[disabled] {
  opacity: .45;
  cursor: not-allowed;
}

.kv {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

.kv:last-child {
  border-bottom: 0;
}

.kv .k {
  color: var(--dim);
  margin-top: 4px;
  margin-bottom: 5px;
}

.kv .v {
  font-weight: 600;
  text-align: right;
  word-break: break-all;
  margin-top: 4px;
}

.trunc {
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
  vertical-align: bottom;
}

/* dev-only role switcher — REMOVE before production */
.devbar {
  position: fixed;
  bottom: 14px;
  right: 14px;
  z-index: 90;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 9px 7px 14px;
  display: flex;
  gap: 9px;
  align-items: center;
  box-shadow: var(--shadow-lg);
  font-size: 12.5px;
}

.devbar b {
  color: var(--warn);
  letter-spacing: .05em;
  font-size: 10.5px;
  text-transform: uppercase;
}

.devbar select {
  padding: 5px 8px;
  font-size: 12.5px;
}

/* ---------- SPA-only pieces ---------- */
.drop {
  border: 2px dashed var(--line);
  border-radius: var(--r-lg);
  padding: 40px 24px;
  text-align: center;
  background: var(--panel);
  transition: .15s;
}

.drop:hover {
  border-color: var(--brand);
  background: var(--brand-050);
}

.drop .dropicon {
  color: var(--faint);
}

.drop:hover .dropicon {
  color: var(--brand-ink);
}

.verdicts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin-top: 14px;
}

/* Verdict cards carry their state on a left rule rather than a full coloured
   border, so the grey "unverified" case does not have to shout to be legible. */
.vc {
  border: 1px solid var(--line);
  border-left: 3px solid var(--idle);
  border-radius: var(--r);
  padding: 16px 18px;
  background: var(--panel);
}

.vc-ok {
  border-left-color: var(--ok);
}

.vc-bad {
  border-left-color: var(--bad);
}

.vc-idle {
  border-left-color: var(--idle);
}

.vc h4 {
  margin: 0 0 8px;
  font-size: 15px;
}

.vc p {
  margin: 0;
  font-size: 13.5px;
  color: var(--dim);
  line-height: 1.6;
}

/* Empty state for tables and panels. An empty table used to render as a bare
   header row, which reads as breakage rather than as "nothing here yet". */
.t-empty {
  text-align: center;
  padding: 38px 20px;
  color: var(--dim);
}

.t-empty strong {
  display: block;
  font-size: 15px;
  color: var(--text);
  margin-bottom: 6px;
  letter-spacing: -.01em;
}

.t-empty p {
  margin: 0 auto;
  max-width: 42ch;
  font-size: 14px;
  line-height: 1.6;
}

/* The unverified badge takes the idle token explicitly: it is a verdict, not
   a neutral chip, and must stay distinguishable from --dim body text. */
.badge.idle {
  color: var(--idle);
  border-color: color-mix(in srgb, var(--idle) 30%, transparent);
  background: color-mix(in srgb, var(--idle) 12%, transparent);
}

/* icons sit on the text baseline inside links and buttons */
.app-side a svg,
.btn svg,
.side-foot a svg {
  flex: none;
}

.vv-themebtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--dim);
  border-radius: 10px;
  cursor: pointer;
}

.vv-themebtn:hover {
  color: var(--brand-ink);
  border-color: var(--brand);
}

/* ---------- modal ---------- */
.modal-back {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(10, 14, 26, .5);
  backdrop-filter: blur(3px);
  display: grid;
  place-items: center;
  padding: 20px;
}

.modal {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 460px;
  padding: 22px 24px 24px;
}

.modal-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.modal-head h2 {
  font-size: 18px;
  margin: 0;
}

.modal-x {
  margin-left: auto;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--dim);
  border-radius: 9px;
  cursor: pointer;
}

.modal-x:hover {
  color: var(--bad);
  border-color: var(--bad);
}

/* ---------- upgrade call-to-action in the sidebar ---------- */
/* Scoped under `.app-side a` so it outranks that rule's hover state. Without
   this the hover painted `--panel2` (near-white in light mode) behind white
   text and the label vanished. */
.app-side a.side-upgrade {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  padding: 11px 12px;
  border-radius: 11px;
  font-weight: 650;
  font-size: 14px;
  color: #fff;
  /* Solid brand, not a gradient into violet: the page has one accent, and an
     upgrade CTA is the last place to introduce a second hue. */
  background: var(--brand);
  box-shadow: 0 10px 22px -12px var(--brand);
}

.app-side a.side-upgrade:hover {
  color: #fff;
  background: var(--brand-600);
}

/* ---------- plan cards ---------- */
.plans-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
}

.plan-card {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px;
  display: flex;
  flex-direction: column;
}

.plan-card.current {
  border-color: var(--brand);
  box-shadow: 0 16px 40px -28px var(--brand);
}

.plan-tag {
  position: absolute;
  top: -10px;
  left: 20px;
  background: var(--brand);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .05em;
  padding: 3px 10px;
  border-radius: 999px;
}

.plan-card h3 {
  font-size: 18px;
  margin: 0 0 6px;
}

.plan-price {
  font-size: 30px;
  font-weight: 750;
  letter-spacing: -.03em;
  margin-bottom: 12px;
}

.plan-price span {
  font-size: 14px;
  font-weight: 600;
  color: var(--dim);
}

.plan-list {
  list-style: none;
  padding: 0;
  margin: 0 0 14px;
  font-size: 14px;
}

.plan-list li {
  padding: 5px 0 5px 22px;
  position: relative;
  color: var(--dim);
}

.plan-list li::before {
  content: "\2713";
  position: absolute;
  left: 0;
  color: var(--ok);
  font-weight: 700;
}

.plan-note {
  font-size: 12.5px;
  color: var(--faint);
  margin: 0 0 14px;
}

.plan-card .btn,
.plan-card a.btn {
  margin-top: auto;
  width: 100%;
}

/* ==========================================================================
   PAGE LANGUAGE — the shared vocabulary introduced with the home redesign.
   Left-aligned, hairline-separated, one accent. Every page below the nav is
   built from these; page-specific pieces stay inline in the page.
   ========================================================================== */

/* Vertical rhythm. Sections are separated by a rule, not by floating gaps, so
   a page reads as one document rather than a stack of blocks. */
.band {
  padding: 80px 0;
  border-top: 1px solid var(--line);
}

.band:first-of-type {
  border-top: 0;
}

.band.tight {
  padding: 64px 0;
}

.lede {
  font-size: clamp(16.5px, 1.4vw, 18.5px);
  color: var(--dim);
  max-width: 62ch;
}

/* Section label. Names the topic in plain language — never numbers it. */
.kicker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font: 600 11.5px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brand-ink);
  margin-bottom: 20px;
}

.kicker::before {
  content: "";
  width: 26px;
  height: 1px;
  background: currentColor;
  opacity: .55;
}

h2.display {
  font-size: clamp(26px, 3.4vw, 38px);
  letter-spacing: -.025em;
  line-height: 1.1;
  max-width: 20ch;
  text-wrap: balance;
  margin: 0 0 16px;
}

h1.display {
  font-size: clamp(32px, 4.6vw, 52px);
  letter-spacing: -.032em;
  line-height: 1.05;
  max-width: 18ch;
  text-wrap: balance;
  margin: 0 0 18px;
}

/* Asymmetric two-column. The default page layout; centred is the exception. */
.split {
  display: grid;
  grid-template-columns: 1.25fr .75fr;
  gap: 60px;
  align-items: start;
}

.split.even {
  grid-template-columns: 1fr 1fr;
}

.split.wide {
  grid-template-columns: .8fr 1.2fr;
}

/* A single number, given room. */
.figure {
  border-left: 2px solid var(--brand);
  padding-left: 22px;
}

.figure .n {
  font-size: clamp(34px, 4.4vw, 50px);
  font-weight: 800;
  letter-spacing: -.04em;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.figure .u {
  font-size: 15.5px;
  font-weight: 650;
  color: var(--brand-ink);
  margin-top: 2px;
}

.figure p {
  font-size: 13.5px;
  color: var(--dim);
  margin: 14px 0 0;
  line-height: 1.55;
}

/* Term/definition list with hairlines — the default alternative to a card grid. */
.spec {
  margin: 0;
  border-top: 1px solid var(--line);
}

.spec-row {
  display: grid;
  grid-template-columns: minmax(170px, .42fr) 1fr;
  gap: 28px;
  padding: 22px 4px;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}

.spec-row:hover {
  background: var(--panel2);
}

.spec-row dt {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--text);
}

.spec-row dd {
  margin: 0;
  font-size: 14.5px;
  color: var(--dim);
  line-height: 1.6;
}

.spec-row dd code,
.spec-row dt code {
  font: 13px var(--mono);
  color: var(--brand-ink);
}

/* Numbered rows for a short sequence of parallel items. */
.zig {
  display: grid;
  gap: 0;
}

.zig-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 26px;
  align-items: start;
  padding: 28px 4px;
  border-top: 1px solid var(--line);
}

.zig-row:last-child {
  border-bottom: 1px solid var(--line);
}

.zig-row .idx {
  font: 700 13px/1 var(--mono);
  color: var(--brand-ink);
  padding-top: 6px;
  font-variant-numeric: tabular-nums;
}

.zig-row h3 {
  font-size: 19px;
  letter-spacing: -.02em;
  margin: 0 0 8px;
}

.zig-row p {
  color: var(--dim);
  margin: 0;
  max-width: 62ch;
  font-size: 15px;
}

.zig-row .who {
  font: 600 11px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
  margin-top: 12px;
  display: block;
}

/* Label-over-value row, under one rule. Three facts at a glance. */
.assure {
  display: flex;
  column-gap: 0;
  row-gap: 20px;
  border-top: 1px solid var(--line);
  padding-top: 18px;
  flex-wrap: wrap;
  margin: 0;
}

.assure div {
  flex: 1 1 0;
  min-width: 150px;
  padding-right: 18px;
}

.assure dt {
  font: 600 11px/1 var(--mono);
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 7px;
}

.assure dd {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.35;
}

/* Closing band. Dark in both themes like the code surface — never a gradient. */
.close {
  background: var(--code);
  border-radius: var(--r-xl);
  padding: 60px 44px;
  position: relative;
  overflow: hidden;
  text-align: center;
}

.close::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 120px;
  background: radial-gradient(70% 100% at 50% 100%, rgba(84, 104, 238, .34), transparent 70%);
  pointer-events: none;
}

.close h2 {
  position: relative;
  color: #fff;
  font-size: clamp(25px, 3.4vw, 36px);
  letter-spacing: -.03em;
  margin: 0 0 14px;
  text-wrap: balance;
}

.close p {
  position: relative;
  color: #b9c6e4;
  max-width: 52ch;
  margin: 0 auto 26px;
  font-size: 16px;
}

.close .ctas {
  position: relative;
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.close .btn {
  background: #fff;
  color: #101a30;
  border-color: #fff;
  padding: 13px 26px;
}

.close .btn:hover {
  background: #e6ecfb;
  color: #101a30;
  border-color: #e6ecfb;
}

.close .btn.ghost {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, .34);
}

.close .btn.ghost:hover {
  background: rgba(255, 255, 255, .1);
  color: #fff;
  border-color: #fff;
}

.close a:focus-visible {
  outline-color: #fff;
}

/* Notice block. One rule, one colour, no icon soup. */
.note {
  border: 1px solid var(--line);
  border-left: 3px solid var(--dim);
  border-radius: var(--r-sm);
  padding: 16px 20px;
  background: var(--panel);
  margin: 22px 0;
}

.note strong {
  display: block;
  font-size: 15px;
  margin-bottom: 5px;
  letter-spacing: -.01em;
}

.note p {
  margin: 0;
  font-size: 14px;
  color: var(--dim);
  line-height: 1.6;
}

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

.note.warn strong {
  color: var(--warn);
}

.note.bad {
  border-left-color: var(--bad);
}

.note.bad strong {
  color: var(--bad);
}

.note.info {
  border-left-color: var(--brand);
}

.note.info strong {
  color: var(--brand-ink);
}

/* Legal reading column. Long prose needs a measure and generous leading. */
.doc {
  max-width: 74ch;
}

.doc h2 {
  font-size: 21px;
  letter-spacing: -.02em;
  margin: 44px 0 12px;
  scroll-margin-top: 84px;
}

.doc h2:first-of-type {
  margin-top: 32px;
}

.doc h3 {
  font-size: 16.5px;
  margin: 26px 0 8px;
}

.doc p {
  font-size: 15.5px;
  line-height: 1.72;
  color: var(--dim);
  margin: 0 0 14px;
}

.doc p strong,
.doc li strong {
  color: var(--text);
}

.doc ul,
.doc ol {
  font-size: 15.5px;
  line-height: 1.72;
  color: var(--dim);
  padding-left: 20px;
  margin: 0 0 16px;
}

.doc li {
  margin-bottom: 7px;
}

.doc .updated {
  font: 600 12.5px/1 var(--mono);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Cards and notes inside prose need their own air — .doc p carries only a
   bottom margin, so a paragraph after a card would otherwise sit flush to it. */
.doc .card,
.doc .note {
  margin: 22px 0 26px;
}

.doc .card .kv:last-child {
  border-bottom: 0;
}

/* Scroll reveal. Opt in with .rv; vv-theme.js adds .in once, then stops watching. */
.rv {
  opacity: 0;
  transform: translateY(18px);
}

.rv.in {
  opacity: 1;
  transform: none;
  transition: opacity .62s cubic-bezier(.22, .7, .3, 1) var(--d, 0ms),
    transform .62s cubic-bezier(.22, .7, .3, 1) var(--d, 0ms);
}

@media (prefers-reduced-motion:reduce) {
  .rv {
    opacity: 1;
    transform: none;
  }

  .rv.in {
    transition: none;
  }
}

@media (max-width:960px) {

  .split,
  .split.even,
  .split.wide {
    grid-template-columns: 1fr;
    gap: 36px;
  }

  .band {
    padding: 72px 0;
  }
}

@media (max-width:620px) {
  .spec-row {
    grid-template-columns: 1fr;
    gap: 7px;
  }

  .close {
    padding: 46px 22px;
  }

  .band {
    padding: 60px 0;
  }
}