/* =========================================================================
   daidocs.com: shared 2030 design system.
   Structure and components live here; each site supplies its own :root
   token block in theme.css. Motion is CSS-only and fully disabled under
   prefers-reduced-motion.
   ========================================================================= */

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

/* The UA rule for [hidden] is a plain `display:none`, so ANY author display
   declaration on the same element silently beats it: .btn is inline-flex,
   .metrics and .feed are grid, .btn-row is flex. That is how media.html came
   to render its own "DD Mon YYYY / Headline" feed template underneath the
   line saying nothing is published yet, and how app.html showed "Download
   all" before a single file existed. Elements that mark themselves hidden
   must stay hidden whatever their component class asks for. */
[hidden] { display: none !important; }

/* The ambient field, ticker and light beams are deliberately wider than the
   viewport. `clip` contains their bleed without creating a scroll container,
   so position:sticky (the header and the docs TOC) keeps working. `hidden`
   would silently break both. */
/* scroll-padding-top clears the sticky header for fragment navigation the
   router never sees: a pasted #anchor URL, a reload, or a same-page jump.
   Without it the target heading lands underneath the header. */
html { scroll-behavior: smooth; scroll-padding-top: 84px; -webkit-text-size-adjust: 100%; overflow-x: clip; }
body { overflow-x: clip; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  /* horizontal containment is handled by overflow-x: clip above; using
     `hidden` here would turn body into a scroll container and break sticky */
}

::selection { background: var(--accent-sel); color: var(--accent-ink); }

a { color: var(--link); text-decoration: none; transition: color .18s ease; }
a:hover { color: var(--link-hi); }

code, pre, .mono { font-family: var(--mono); }
code {
  font-size: 0.9em; background: var(--code-bg); border: 1px solid var(--hairline);
  border-radius: 4px; padding: 0.1em 0.4em; color: var(--code-ink); overflow-wrap: anywhere;
}
pre code { background: none; border: none; padding: 0; color: inherit; }

img, svg { max-width: 100%; }
.wrap { max-width: 1140px; margin: 0 auto; padding: 0 24px; position: relative; }

:focus-visible { outline: 2px solid var(--accent2); outline-offset: 3px; border-radius: 4px; }

/* Skip link: first focusable element, visible only when focused. */
.skip-link {
  position: fixed; left: 12px; top: 12px; z-index: 100;
  background: var(--accent); color: var(--accent-ink);
  font-weight: 600; font-size: 14px; padding: 10px 16px; border-radius: 8px;
  transform: translateY(-200%);
  transition: transform .18s ease;
}
.skip-link:focus { transform: translateY(0); color: var(--accent-ink); }

/* ---------------- ambient field: aurora + grid + grain ---------------- */

.field { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.field .aurora {
  position: absolute; border-radius: 50%; filter: blur(90px); opacity: .5;
  animation: drift 26s ease-in-out infinite alternate;
}
.field .a1 { width: 60vw; height: 60vw; left: -14vw; top: -22vw; background: var(--aurora-1); }
.field .a2 { width: 52vw; height: 52vw; right: -16vw; top: 4vw; background: var(--aurora-2); animation-delay: -9s; }
.field .a3 { width: 46vw; height: 46vw; left: 26vw; top: 62vh; background: var(--aurora-3); animation-delay: -17s; }
@keyframes drift {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(3vw,-4vh,0) scale(1.12); }
  100% { transform: translate3d(-3vw,4vh,0) scale(0.95); }
}
.field .mesh {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 110% 78% at 50% 0%, #000 12%, transparent 72%);
}
.field .grain {
  position: absolute; inset: -200%; opacity: .16;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

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

.site-header {
  position: sticky; top: 0; z-index: 60;
  background: var(--header-bg);
  backdrop-filter: blur(18px) saturate(1.5);
  -webkit-backdrop-filter: blur(18px) saturate(1.5);
  border-bottom: 1px solid var(--hairline);
}
.site-header .wrap { display: flex; align-items: center; gap: 26px; height: 66px; }

.brand { display: flex; align-items: center; gap: 11px; flex: none; }
.brand:hover { color: inherit; }
.brand-mark { width: 32px; height: 32px; display: block; filter: drop-shadow(var(--glow-sm)); }
.brand-txt { display: flex; flex-direction: column; line-height: 1; }
.brand-name { font-size: 19px; font-weight: 600; letter-spacing: -0.02em; color: var(--text-hi); }
.brand-name .dot { color: var(--accent); }
.brand-by {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted); margin-top: 3px;
}

.site-nav { display: flex; gap: 20px; margin-left: auto; align-items: center; }
/* padding brings the hit area to the 24px minimum (WCAG 2.5.8) without
   changing the visual rhythm of the bar */
.site-nav a { color: var(--text-2); font-size: 14.5px; position: relative; padding: 5px 0; }
.site-nav a:hover { color: var(--text-hi); }
.site-nav a.active { color: var(--text-hi); }
.site-nav a.active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -5px; height: 2px;
  background: var(--accent); border-radius: 2px; box-shadow: var(--glow-sm);
}
/* Selector must be at least as specific as `.site-nav a` above, or that rule's
   vertical-only padding wins and collapses the button onto its own text. */
/* Sign in sits in its own account group, separated from the section tabs by a
   hairline: navigating the site and getting into your account are different
   jobs, and mixing them made Sign in read as a seventh tab. It stays visible
   at every width. A returning user must always be able to find the way in. */
.nav-sep {
  width: 1px; height: 20px; background: var(--hairline-2);
  margin: 0 2px; flex: none;
}
.site-nav a.nav-signin { color: var(--text-2); font-size: 14.5px; }
.site-nav a.nav-signin:hover { color: var(--text-hi); }
@media (max-width: 940px) {
  .nav-sep { width: 100%; height: 1px; margin: 10px 0 4px; }
}
.site-nav a.nav-cta {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--accent-ink) !important;
  font-weight: 600; font-size: 14px; line-height: 1;
  padding: 11px 20px; border-radius: 8px; white-space: nowrap;
  box-shadow: var(--glow-sm); transition: transform .18s ease, box-shadow .18s ease;
}
.site-nav a.nav-cta:hover { transform: translateY(-1px); box-shadow: var(--glow-md); }

.nav-toggle {
  display: none; margin-left: auto; background: none;
  border: 1px solid var(--hairline-2); color: var(--text-hi);
  border-radius: 8px; padding: 6px 11px; font-family: var(--mono); cursor: pointer;
}
@media (max-width: 940px) {
  .nav-toggle { display: block; }
  .site-nav {
    display: none; position: absolute; top: 66px; left: 0; right: 0;
    flex-direction: column; align-items: flex-start; gap: 0;
    background: var(--surface-solid); border-bottom: 1px solid var(--hairline);
    padding: 10px 24px 18px;
  }
  .site-nav.open { display: flex; }
  .site-nav a { padding: 11px 0; font-size: 16px; }
  .site-nav a.active::after { display: none; }
  /* keep the button a button in the mobile sheet, not a full-width text row */
  .site-nav a.nav-cta { margin-top: 12px; align-self: flex-start; padding: 12px 22px; font-size: 15px; }
}

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

h1, h2, h3 { font-weight: 600; letter-spacing: -0.025em; }
h1 { font-size: clamp(38px, 6vw, 68px); line-height: 1.02; margin: 0 0 20px; }
h2 { font-size: clamp(26px, 3.6vw, 40px); line-height: 1.1; margin: 0 0 12px; }
h3 { font-size: 19px; letter-spacing: -0.015em; margin: 32px 0 8px; }

.grad-text {
  background: linear-gradient(100deg, var(--accent) 0%, var(--accent2) 55%, var(--accent) 100%);
  background-size: 220% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: sheen 9s linear infinite;
}
@keyframes sheen { to { background-position: 220% 0; } }

.lede { font-size: clamp(17px, 1.9vw, 20.5px); color: var(--text-2); max-width: 700px; margin: 0 0 34px; }
.sub { color: var(--text-2); max-width: 760px; margin: 0 0 34px; font-size: 16.5px; }
.footnote { color: var(--muted); font-size: 13px; }
hr.thin { border: none; border-top: 1px solid var(--hairline); margin: 42px 0; }

/* mono label with leading rule */
.eyebrow, .kicker {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: 11px; font-weight: 500;
  letter-spacing: .16em; text-transform: uppercase; color: var(--accent2);
  margin-bottom: 14px;
}
.eyebrow::before, .kicker::before {
  content: ""; width: 22px; height: 1px; background: currentColor; opacity: .8;
}
.kicker { margin-bottom: 22px; }

/* ---------------- hero ---------------- */

.hero { position: relative; padding: 104px 0 78px; overflow: hidden; }
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent2), transparent); opacity: .45;
}
.hero h1 { max-width: 15ch; }
.hero .lede { max-width: 640px; }

/* two-column hero: copy left, brand illustration right.
   minmax(0,…) lets both tracks shrink so the art never forces overflow. */
.hero-grid {
  display: grid;
  /* copy gets the wider track: it is the primary message, and it lets the
     headline break at its natural clause rather than mid-phrase */
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.94fr);
  gap: 48px; align-items: center;
}
/* inside the two-column hero the grid track already constrains the measure,
   so the 15ch cap would only force an extra line break */
.hero-copy { min-width: 0; }
.hero-grid .hero-copy h1 { max-width: none; font-size: clamp(38px, 4.4vw, 60px); }
.hero-grid .hero-copy .lede { max-width: 46ch; }
.hero-art { margin: 0; min-width: 0; position: relative; }
/* On wide screens let the art reclaim the outer gutter so its internal labels
   (Claude / GPT / Gemini / Local models) stay legible. Bounded by min() so it
   can never pull more than the gutter actually available. */
@media (min-width: 1200px) {
  /* min() keeps the pull from ever exceeding the real gutter; max() caps it at
     120px so on very wide screens the art cannot outgrow and outrank the copy */
  .hero-art { margin-right: max(-120px, min(0px, calc((1140px - 100vw) / 2 + 28px))); }
}
.hero-art img {
  display: block; width: 100%; height: auto;
  /* the art is transparent, so it sits on the page gradient as intended */
  filter: drop-shadow(0 24px 60px rgba(0, 0, 0, .55));
}
/* soft brand glow behind the deck, tying the art into the field */
.hero-art::before {
  content: ""; position: absolute; left: 50%; top: 56%;
  width: 78%; aspect-ratio: 1.6; transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, var(--accent-sel), transparent 72%);
  filter: blur(38px); opacity: .5; z-index: -1; pointer-events: none;
}

/* 1150px, not 1000px. Between 1001 and 1140 the two-column hero survives while
   .wrap has stopped centring, so the page runs to a flat 24px gutter and the
   art reaches the viewport edge exactly as the copy does. Nothing overflows,
   but it reads as though the illustration has broken out of the layout, and
   the measure on the left drops to around 40 characters at the same time.
   Stacking earlier gives both the full width instead. 1150 clears 1140 by
   enough that the change never lands on the boundary itself. */
@media (max-width: 1150px) {
  .hero-grid { grid-template-columns: 1fr; gap: 36px; }
  .hero-art { order: 2; max-width: 620px; }
  .hero h1 { max-width: 18ch; }
}

/* format chip: the .dai product icon beside the extension */
.fmt-chip {
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--glass); border: 1px solid var(--hairline-2);
  border-radius: 999px; padding: 7px 18px 7px 8px; margin-bottom: 24px;
  backdrop-filter: blur(10px);
}
.fmt-chip img { width: 26px; height: 26px; display: block; }
.fmt-chip .t {
  font-family: var(--mono); font-size: 12px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--text-2);
}
.fmt-chip .t b { color: var(--accent); font-weight: 600; }

/* install command */
.install {
  display: flex; align-items: stretch; max-width: 580px;
  background: var(--code-panel); border: 1px solid var(--hairline-2);
  border-radius: 12px; overflow: hidden;
  box-shadow: var(--shadow-lg);
  position: relative;
}
.install::before {
  content: ""; position: absolute; inset: 0; border-radius: 12px; padding: 1px;
  background: linear-gradient(120deg, var(--accent), transparent 40%, transparent 60%, var(--accent2));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: .55; pointer-events: none;
}
.install pre { margin: 0; padding: 16px 20px; flex: 1; overflow-x: auto; }
.install code { font-size: 14.5px; color: var(--code-ink); }
.install code .p { color: var(--accent); }
.copy-btn {
  flex: none; border: none; border-left: 1px solid var(--hairline);
  background: transparent; color: var(--accent2);
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
  padding: 0 20px; cursor: pointer; transition: background .18s ease, color .18s ease;
}
.copy-btn:hover { background: var(--glass-hi); color: var(--link-hi); }
.install-note { font-size: 13.5px; color: var(--muted); margin-top: 14px; }

/* ---------------- glass panels + bento ---------------- */

.card, .viz, .tier, .waitlist, .tbl-scroll, .honesty, .term {
  background: var(--glass);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--hairline);
  border-radius: 14px;
}
.card { padding: 26px; position: relative; overflow: hidden; transition: border-color .2s ease, transform .2s ease; }
.card:hover { border-color: var(--hairline-2); transform: translateY(-2px); }
.card h3 { margin-top: 0; }
.card p:last-child { margin-bottom: 0; }
.card .mono-tag { font-family: var(--mono); font-size: 12px; color: var(--muted); }

.bento { display: grid; grid-template-columns: repeat(6, 1fr); gap: 16px; }
.bento > * { grid-column: span 2; }
.bento .w3 { grid-column: span 3; }
.bento .w4 { grid-column: span 4; }
.bento .w6 { grid-column: span 6; }
@media (max-width: 960px) { .bento { grid-template-columns: repeat(2, 1fr); } .bento > *, .bento .w3, .bento .w4, .bento .w6 { grid-column: span 2; } }
@media (max-width: 620px) { .bento { grid-template-columns: 1fr; } .bento > *, .bento .w3, .bento .w4, .bento .w6 { grid-column: span 1; } }

.cols-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 44px; align-items: start; }
.cols-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 940px) { .cols-2, .cols-3 { grid-template-columns: 1fr; gap: 28px; } }
.cols-2 > *, .cols-3 > *, .docs-layout > *, .tiers > *, .bento > * { min-width: 0; }

/* ---------------- sections ---------------- */

section.band { padding: 84px 0; position: relative; border-bottom: 1px solid var(--hairline); }
section.band.alt::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--band-alt); pointer-events: none;
}

/* ---------------- stat tiles ---------------- */

.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 56px 0 0; }
@media (max-width: 860px) { .stats { grid-template-columns: 1fr; } }
.stat {
  display: block; position: relative; overflow: hidden; color: inherit;
  background: var(--glass); backdrop-filter: blur(14px);
  border: 1px solid var(--hairline); border-radius: 14px; padding: 26px 24px 20px;
  transition: transform .22s ease, border-color .22s ease;
}
.stat::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent 65%);
}
.stat:hover { transform: translateY(-3px); border-color: var(--hairline-2); color: inherit; }
.stat .num {
  font-size: clamp(32px, 4vw, 40px); font-weight: 600; letter-spacing: -0.03em;
  line-height: 1.05; color: var(--text-hi);
}
.stat .num small { font-size: 17px; font-weight: 500; color: var(--text-2); letter-spacing: -0.01em; }
.stat .what { color: var(--text-2); font-size: 14.5px; margin-top: 8px; }
.stat .src {
  color: var(--muted); font-size: 10.5px; margin-top: 12px; font-family: var(--mono);
  letter-spacing: .12em; text-transform: uppercase;
}
.stat .src::before { content: "// "; color: var(--accent2); }

/* ---------------- lists ---------------- */

ul.checks { list-style: none; padding: 0; margin: 0; }
ul.checks li { padding-left: 27px; position: relative; margin: 10px 0; color: var(--text-2); }
ul.checks li::before {
  content: ""; position: absolute; left: 4px; top: 9px; width: 7px; height: 7px;
  border-radius: 50%; background: var(--accent); box-shadow: 0 0 9px var(--accent);
}
ul.checks li strong { color: var(--text-hi); }

/* ---------------- terminal / tree ---------------- */

.term { overflow: hidden; box-shadow: var(--shadow-lg); }
.term-bar {
  display: flex; align-items: center; gap: 7px; padding: 11px 15px;
  border-bottom: 1px solid var(--hairline); background: var(--glass-hi);
}
.term-bar span { width: 10px; height: 10px; border-radius: 50%; background: var(--hairline-2); }
.term-bar span:first-child { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
.term-bar em {
  font-style: normal; font-family: var(--mono); font-size: 11px;
  color: var(--muted); margin-left: 8px; letter-spacing: .07em;
}
.term pre { margin: 0; padding: 20px 22px; overflow-x: auto; font-size: 13px; line-height: 1.75; color: var(--code-ink); }
.term .c-p { color: var(--accent); }
.term .c-cmd { color: var(--text-hi); }
.term .c-dim { color: var(--muted); }
.term .c-ok { color: var(--accent); }
.term .c-key { color: var(--accent2); }
.term .c-str { color: var(--str); }

pre.tree { margin: 0; font-size: 13px; line-height: 1.8; color: var(--code-ink); overflow-x: auto; }
pre.tree .d { color: var(--text-hi); font-weight: 500; }
pre.tree .f { color: var(--accent2); }
pre.tree .cm { color: var(--muted); font-style: italic; }

/* ---------------- format anatomy ---------------- */

.fmt-hero { display: grid; grid-template-columns: 220px 1fr; gap: 44px; align-items: center; }
@media (max-width: 860px) { .fmt-hero { grid-template-columns: 1fr; gap: 26px; } }
.fmt-icon { position: relative; display: flex; justify-content: center; }
.fmt-icon img { width: 190px; height: 190px; filter: drop-shadow(0 18px 44px rgba(0,0,0,.6)); animation: hover-y 7s ease-in-out infinite; }
@keyframes hover-y { 0%,100% { transform: translateY(-6px); } 50% { transform: translateY(6px); } }
.fmt-icon::after {
  content: ""; position: absolute; inset: 18% 8% -6% 8%; z-index: -1;
  background: radial-gradient(ellipse at center, var(--accent-glow) 0%, transparent 70%);
  filter: blur(26px);
}

.zones { display: grid; gap: 12px; margin-top: 8px; }
.zone {
  display: grid; grid-template-columns: 132px 1fr; gap: 16px; align-items: baseline;
  padding: 14px 16px; border: 1px solid var(--hairline); border-radius: 10px;
  background: var(--glass); transition: border-color .2s ease;
}
.zone:hover { border-color: var(--hairline-2); }
@media (max-width: 620px) { .zone { grid-template-columns: 1fr; gap: 4px; } }
.zone .zn {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent); font-weight: 600;
}
.zone .zd { color: var(--text-2); font-size: 14.5px; }

/* ---------------- surfaces ticker ---------------- */

.ticker { overflow: hidden; position: relative; padding: 8px 0; mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.ticker-row { display: flex; gap: 12px; width: max-content; animation: slide 42s linear infinite; }
@keyframes slide { to { transform: translateX(-50%); } }
.ticker:hover .ticker-row { animation-play-state: paused; }
.chip {
  display: inline-flex; align-items: center; gap: 9px; white-space: nowrap;
  border: 1px solid var(--hairline); border-radius: 999px; padding: 9px 18px;
  background: var(--glass); font-size: 14px; color: var(--text-2);
}
.chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px var(--accent); font-style: normal; }
.chip.cloud i { background: var(--accent2); box-shadow: 0 0 8px var(--accent2); }

/* ---------------- charts ---------------- */

.viz { padding: 24px 26px 20px; overflow: hidden; }
.viz .viz-title { font-weight: 600; font-size: 15px; margin: 0 0 3px; }
.viz .viz-sub { color: var(--muted); font-size: 12.5px; margin: 0 0 20px; }
.bars { display: grid; gap: 13px; }
.bar-row { display: grid; grid-template-columns: 160px 1fr; gap: 14px; align-items: center; }
@media (max-width: 560px) { .bar-row { grid-template-columns: 104px 1fr; gap: 10px; } }
.bar-row .lbl { font-size: 13.5px; color: var(--text-2); text-align: right; line-height: 1.3; }
.bar-row .lbl strong { color: var(--text-hi); display: block; }
.bar-track { position: relative; height: 28px; background: var(--track); border-radius: 5px; overflow: hidden; }
/* The bar's resting state is the DRAWN bar. Growing it is decoration, and
   decoration must never be what makes data visible.
   Previously this rule carried `animation: grow 1.1s ... both`, so the fill
   held the from-state (scaleX(0)) whenever the animation had not run or had
   not advanced: a backgrounded tab, throttled frames, a non-compositing
   window. The chart then rendered as empty tracks with a value chip floating
   beside them. Same rule the reveal system already follows: content is never
   trapped invisible behind an effect. */
.bar-fill {
  position: absolute; left: 0; top: 3px; bottom: 3px; border-radius: 0 5px 5px 0; min-width: 3px;
  transform-origin: left center;
}
/* Deliberately no grow animation on the fill. Gating it behind the reveal
   observer was tried and still failed: once the class lands while frames are
   throttled, the animation holds its from-state and the bar stays empty. A bar
   IS the datum, so nothing about whether it is drawn may depend on an effect
   running. The card still arrives with the reveal fade, and fx-2040 keeps the
   sheen on .bar-fill::after, which can safely never run. */
.bar-val {
  position: absolute; top: 50%; transform: translateY(-50%);
  font-family: var(--mono); font-size: 12px; color: var(--text-hi); white-space: nowrap; padding-left: 9px;
}
.bar-val.in { left: auto !important; right: 9px; padding-left: 0; color: var(--bg); font-weight: 600; }
/* Bar fills use gradients so the comparison reads at a glance rather than as
   two similar rectangles. .dai carries the brand accent; the comparison arms
   are deliberately warmer/cooler so they never read as "our other result". */
.s-aidoc { background: linear-gradient(90deg, var(--accent) 0%, var(--accent2) 100%); box-shadow: 0 0 18px var(--accent-glow); }
.s-full  { background: linear-gradient(90deg, #f0842f 0%, #d9432c 100%); }
.s-live  { background: linear-gradient(90deg, #22c58a 0%, #0e9488 100%); }
.s-none  { background: linear-gradient(90deg, #6b7280 0%, #4b5563 100%); }
.s-rival { background: linear-gradient(90deg, #a78bfa 0%, #7c5cf0 100%); }
.viz-foot { color: var(--muted); font-size: 12.5px; margin-top: 16px; border-top: 1px solid var(--hairline); padding-top: 12px; }
.viz-foot a { color: var(--text-2); text-decoration: underline; text-underline-offset: 3px; }

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

.tbl-scroll { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 14.5px; }
th, td { text-align: left; padding: 12px 17px; border-bottom: 1px solid var(--hairline); vertical-align: top; }
th {
  font-family: var(--mono); font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .14em; color: var(--accent2); font-weight: 500; background: var(--glass-hi);
  position: sticky; top: 0;
}
tr:last-child td { border-bottom: none; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); font-size: 13px; }
td strong { color: var(--text-hi); }
tbody tr { transition: background .16s ease; }
tbody tr:hover { background: var(--glass-hi); }
.tbl-note { color: var(--muted); font-size: 13px; margin-top: 12px; }
tr.hl td { background: var(--hl-row); }
tr.hl td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* ---------------- badges ---------------- */

.badge {
  display: inline-block; font-family: var(--mono); font-size: 10px; font-weight: 500;
  letter-spacing: .13em; text-transform: uppercase; border-radius: 4px;
  padding: 3px 9px; vertical-align: 2px; white-space: nowrap;
}
.badge.now { color: var(--accent); border: 1px solid var(--accent-b); background: var(--accent-bg); }
.badge.cloud { color: var(--accent2); border: 1px solid var(--accent2-b); background: var(--accent2-bg); }
.badge.soon { color: var(--warn); border: 1px solid var(--warn-b); background: var(--warn-bg); }

/* ---------------- honesty ---------------- */

.honesty { padding: 30px 32px; position: relative; overflow: hidden; border-color: var(--accent-b); }
.honesty::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, var(--accent), transparent 72%);
}
.honesty h3 { margin-top: 0; }
.honesty p { color: var(--text-2); }

/* ---------------- pricing ---------------- */

/* billing period switch */
.price-switch {
  display: inline-flex; gap: 4px; margin: 0 0 26px;
  padding: 4px; border-radius: 999px;
  background: var(--glass); border: 1px solid var(--hairline-2);
}
.ps-btn {
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 14px; font-weight: 600;
  color: var(--text-2); background: none; border: 0; cursor: pointer;
  padding: 9px 18px; border-radius: 999px; min-height: 24px;
  transition: background .18s ease, color .18s ease;
}
.ps-btn:hover { color: var(--text-hi); }
.ps-btn.is-on {
  background: var(--accent); color: var(--accent-ink);
  box-shadow: var(--glow-sm);
}
.ps-save {
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  padding: 2px 7px; border-radius: 999px;
  background: var(--accent-sel); color: var(--accent);
}
.ps-btn.is-on .ps-save { background: rgba(0, 0, 0, .22); color: inherit; }

.tiers { display: grid; grid-template-columns: repeat(5, 1fr); gap: 14px; align-items: stretch; }
@media (max-width: 1120px) { .tiers { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 740px) { .tiers { grid-template-columns: 1fr; } }
.tier { padding: 26px 22px; display: flex; flex-direction: column; transition: transform .2s ease, border-color .2s ease; }
.tier:hover { transform: translateY(-3px); border-color: var(--hairline-2); }
.tier.featured { border-color: var(--accent-b); box-shadow: 0 0 40px var(--accent-glow); }
.tier .t-name { font-weight: 600; font-size: 16px; }
/* Reserves two lines for the period label. Keeps all five tiers on one baseline
   grid, and stops the cards resizing when the billing period is switched, since
   the monthly and yearly labels differ in length. */
.tier .t-price { font-size: 32px; font-weight: 600; letter-spacing: -0.03em; margin: 10px 0 2px; line-height: 1.12; min-height: 75px; }
.tier .t-price small { display: block; font-size: 12.5px; color: var(--muted); font-weight: 400; letter-spacing: 0; line-height: 1.4; margin-top: 4px; min-height: 1.4em; }
.tier .t-tag { color: var(--muted); font-size: 10.5px; margin-bottom: 16px; font-family: var(--mono); letter-spacing: .13em; text-transform: uppercase; }
.tier ul { list-style: none; padding: 0; margin: 0 0 20px; flex: 1; }
.tier li { font-size: 13.5px; color: var(--text-2); padding-left: 19px; position: relative; margin: 8px 0; }
.tier li::before { content: ""; position: absolute; left: 3px; top: 8px; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.tier .t-cta { display: block; text-align: center; border-radius: 9px; padding: 10px 0; font-weight: 600; font-size: 14px; border: 1px solid var(--hairline-2); color: var(--text-hi); transition: all .18s ease; }
.tier .t-cta:hover { border-color: var(--accent); color: var(--accent); }
.tier.featured .t-cta { background: var(--accent); color: var(--accent-ink); border-color: transparent; box-shadow: var(--glow-sm); }
.tier.featured .t-cta:hover { color: var(--accent-ink); transform: translateY(-1px); box-shadow: var(--glow-md); }

.waitlist { padding: 34px; max-width: 640px; }
.waitlist form { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 18px; }
.waitlist input[type="email"], .waitlist select {
  background: var(--code-panel); color: var(--text-hi); border: 1px solid var(--hairline-2);
  border-radius: 9px; padding: 11px 15px; font-size: 15px; font-family: inherit;
}
.waitlist input[type="email"] { flex: 1; min-width: 220px; }
.waitlist button {
  background: var(--accent); color: var(--accent-ink); border: none; border-radius: 9px;
  padding: 11px 22px; font-size: 15px; font-weight: 600; cursor: pointer; font-family: inherit;
  box-shadow: var(--glow-sm); transition: transform .18s ease;
}
.waitlist button:hover { transform: translateY(-1px); }
.waitlist .form-note { color: var(--muted); font-size: 12.5px; margin-top: 12px; }
.waitlist .form-ok { color: var(--accent); font-size: 14.5px; margin-top: 14px; display: none; }

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

.docs-layout { display: grid; grid-template-columns: 232px 1fr; gap: 52px; align-items: start; }
@media (max-width: 940px) { .docs-layout { grid-template-columns: 1fr; gap: 30px; } .docs-toc { position: static !important; } }
/* align-self:start is required for sticky to work here: a grid item stretches
   to the full row height by default, leaving the sticky box no travel. */
.docs-toc { position: sticky; top: 92px; align-self: start; font-size: 14px; }
.docs-toc .t-head { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .14em; color: var(--accent2); margin: 20px 0 9px; }
.docs-toc a { display: block; color: var(--text-2); padding: 5px 0; }
.docs-toc a:hover { color: var(--text-hi); }
.docs-body h2 { scroll-margin-top: 96px; margin-top: 60px; padding-top: 28px; border-top: 1px solid var(--hairline); }
.docs-body h2:first-of-type { margin-top: 0; border-top: none; padding-top: 0; }
.docs-body h3 { scroll-margin-top: 96px; }
.step-flag { font-family: var(--mono); background: var(--glass-hi); border: 1px solid var(--hairline); border-radius: 5px; padding: 2px 9px; font-size: 12.5px; color: var(--accent2); }

/* ---------------- flow ---------------- */

.flow { display: flex; flex-direction: column; }
.flow-step { display: grid; grid-template-columns: 46px 1fr; gap: 20px; }
.flow-step > * { min-width: 0; }
.flow-rail { display: flex; flex-direction: column; align-items: center; }
.flow-dot {
  width: 36px; height: 36px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--glass-hi); border: 1px solid var(--accent-b);
  font-family: var(--mono); font-size: 13px; color: var(--accent); font-weight: 500;
  box-shadow: 0 0 14px var(--accent-glow);
}
.flow-line { width: 1px; flex: 1; background: linear-gradient(180deg, var(--accent-b), transparent); margin: 5px 0; }
.flow-step:last-child .flow-line { display: none; }
.flow-body { padding-bottom: 32px; }
.flow-body h3 { margin-top: 2px; }
.flow-body p { color: var(--text-2); margin: 7px 0 0; }

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

.btn-row { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 30px; }
.btn { display: inline-block; border-radius: 10px; padding: 12px 26px; font-weight: 600; font-size: 15px; transition: transform .18s ease, box-shadow .18s ease; }
.btn.primary { background: var(--accent); color: var(--accent-ink); box-shadow: var(--glow-md); }
.btn.primary:hover { color: var(--accent-ink); transform: translateY(-2px); box-shadow: var(--glow-lg); }
.btn.ghost { border: 1px solid var(--hairline-2); color: var(--text-hi); }
.btn.ghost:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); }

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

.site-footer { padding: 60px 0 70px; color: var(--muted); font-size: 14px; border-top: 1px solid var(--hairline); }
/* Five columns since Legal joined them. A flex row with space-between was
   tuned for four and leaves a ragged last row when one wraps; a grid keeps
   the columns aligned at every width and collapses predictably. */
.site-footer .cols { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 34px 28px; }
@media (max-width: 900px) { .site-footer .cols { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px) { .site-footer .cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.site-footer .f-head { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .14em; color: var(--accent2); margin-bottom: 11px; }
/* Only the column links stack one per row. Applying display:block to every
   footer link also caught links inside prose, which broke a sentence into
   three lines with padding above and below the link. */
.site-footer a { color: var(--muted); }
.site-footer .cols a { display: block; padding: 3px 0; }
.site-footer a:hover { color: var(--text-hi); }
/* Legal row. Sits above the claim on every page, including the ones with no
   column block, so the required notices are reachable from anywhere in one
   click rather than only from the pages that happen to have a full footer. */
.footer-legal { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 34px 0 0; font-size: 13px; }
.footer-legal a { color: var(--text-2); }
.footer-claim a {
  display: inline; padding: 0; color: var(--text-2);
  text-decoration: underline; text-decoration-color: var(--hairline-2);
  text-underline-offset: 2px;
}
.footer-claim a:hover { color: var(--text-hi); text-decoration-color: var(--accent); }
.footer-claim { margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--hairline); font-size: 13px; max-width: 760px; }
.footer-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.footer-brand img { width: 26px; height: 26px; }
.footer-brand span { font-size: 16px; font-weight: 600; color: var(--text-hi); letter-spacing: -0.02em; }

/* ---------------- scroll reveal ---------------- */

/* Hidden state applies ONLY once JS is alive and has taken responsibility for
   revealing (html.js-reveal). Without JS, or if the script fails, every
   .reveal element renders normally. Content must never be trapped invisible. */
.js-reveal .reveal { opacity: 0; transform: translateY(18px); transition: opacity .7s cubic-bezier(.22,1,.36,1), transform .7s cubic-bezier(.22,1,.36,1); }
.js-reveal .reveal.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .reveal { opacity: 1; transform: none; }
  .bar-fill { animation: none; }
}

/* ---------------- head-to-head comparison (2040) ---------------- */

.h2h {
  margin-top: 30px; padding: 30px 32px 26px; border-radius: 16px;
  position: relative; overflow: hidden;
  background: linear-gradient(160deg, rgba(255,255,255,.045), rgba(255,255,255,.012));
  border: 1px solid var(--hairline-2);
  box-shadow: 0 30px 80px -50px rgba(0,0,0,.9);
}
.h2h::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), var(--accent2), transparent);
  opacity: .55;
}
.h2h-head {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start;
  justify-content: space-between; margin-bottom: 26px;
}
.h2h-title { margin: 0; font-size: 15px; color: var(--text-hi); font-weight: 600; }
.h2h-sub { margin: 4px 0 0; font-family: var(--mono); font-size: 11.5px; color: var(--text-2); letter-spacing: .04em; }
.h2h-deltas { display: flex; flex-wrap: wrap; gap: 8px; }
.h2h-chip {
  font-family: var(--mono); font-size: 11px; padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--hairline-2); color: var(--text-2); white-space: nowrap;
}
.h2h-chip.up { color: var(--accent); border-color: var(--accent-b); background: var(--accent-bg); }
.h2h-chip.down { color: var(--text-2); }

.h2h-group { padding: 14px 0; border-top: 1px solid var(--hairline); }
.h2h-group:first-of-type { border-top: none; padding-top: 0; }
.h2h-group.overall {
  margin: -6px -14px 8px; padding: 16px 14px 14px; border-radius: 12px;
  background: rgba(74,222,135,.05); border: 1px solid var(--accent-b);
}
.h2h-cat {
  font-family: var(--mono); font-size: 10.5px; text-transform: uppercase;
  letter-spacing: .14em; color: var(--accent2); margin-bottom: 10px;
}
.h2h-group.overall .h2h-cat { color: var(--accent); }

.h2h-bar-row {
  display: grid; grid-template-columns: 132px minmax(0, 1fr) 52px;
  gap: 12px; align-items: center; margin: 5px 0;
}
.h2h-name { font-size: 12.5px; color: var(--text-2); }
.h2h-track {
  position: relative; height: 16px; border-radius: 5px;
  background: rgba(255,255,255,.055); overflow: hidden;
}
.h2h-fill {
  display: block; height: 100%; border-radius: 5px;
  transition: width .7s cubic-bezier(.2,.7,.3,1);
}
.h2h-fill.dai { background: linear-gradient(90deg, rgba(74,222,135,.35), #4ade87); box-shadow: var(--glow-sm); }
.h2h-fill.mas { background: linear-gradient(90deg, rgba(56,189,248,.28), rgba(56,189,248,.85)); }
.h2h-fill.sup { background: rgba(255,255,255,.30); }
.h2h-fill.zep { background: rgba(255,255,255,.17); }
.h2h-fill.win::after {
  content: ""; position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 5px; height: 5px; border-radius: 50%; background: var(--text-hi); opacity: .85;
}
.h2h-val {
  font-family: var(--mono); font-size: 11.5px; color: var(--text-2);
  text-align: right; font-variant-numeric: tabular-nums;
}
.h2h-bar-row:has(.dai) .h2h-name,
.h2h-bar-row:has(.dai) .h2h-val { color: var(--text-hi); font-weight: 600; }
.h2h-foot {
  margin: 20px 0 0; padding-top: 16px; border-top: 1px solid var(--hairline);
  font-size: 12.5px; line-height: 1.65; color: var(--text-2);
}
@media (max-width: 720px) {
  .h2h { padding: 22px 18px 20px; }
  .h2h-bar-row { grid-template-columns: 104px minmax(0, 1fr) 46px; gap: 8px; }
  .h2h-name { font-size: 11.5px; }
}
@media (prefers-reduced-motion: reduce) { .h2h-fill { transition: none; } }

/* Home tab. Carries the wordmark's own colouring so the site name reads as the
   brand rather than as another section label: body in the high-contrast ink,
   the .com in the accent, exactly as the header wordmark does. */
.site-nav a.nav-home { font-weight: 600; color: var(--text-hi); letter-spacing: -0.015em; }
.site-nav a.nav-home .dot { color: var(--accent); }
.site-nav a.nav-home:hover { color: var(--text-hi); }
.site-nav a.nav-home:hover .dot { color: var(--accent); }

/* Shared footnote under the three hero stats. The conditions belong to all
   three numbers, so repeating them inside each card made every box taller and
   made the page read like a disclaimer rather than a result. */
.stats-note {
  margin: 18px 0 0; max-width: 96ch;
  color: var(--muted); font-size: 12px; line-height: 1.6;
}
.stats-note b { color: var(--text-2); font-weight: 600; }
.stats-note code { font-size: 11.5px; background: none; border: none; padding: 0; color: var(--text-2); }
.star { color: var(--accent); font-weight: 600; }

/* ---------------- four-quadrant ledger ---------------- */

.quad { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin: 30px 0 0; }
@media (max-width: 900px) { .quad { grid-template-columns: 1fr; } }
.qcard {
  position: relative; overflow: hidden;
  background: var(--glass); backdrop-filter: blur(14px);
  border: 1px solid var(--hairline); border-radius: 14px;
  padding: 24px 24px 22px;
  transition: transform .22s ease, border-color .22s ease;
}
.qcard::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, var(--q), transparent 65%);
}
.qcard:hover { transform: translateY(-3px); border-color: var(--hairline-2); }
.qcard.minus  { --q: var(--warn); }
.qcard.plus   { --q: var(--accent); }
.qcard.reduce { --q: var(--accent2); }
.qcard.trade  { --q: var(--muted); }
.qcard .sign {
  font-family: var(--mono); font-size: 15px; font-weight: 700; letter-spacing: .18em;
  color: var(--q); line-height: 1;
}
.qcard h3 {
  font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); margin: 10px 0 12px;
}
.qcard .big {
  font-size: clamp(21px, 2.4vw, 26px); font-weight: 600; letter-spacing: -0.025em;
  line-height: 1.15; color: var(--text-hi); margin: 0 0 12px;
}
.qcard p { color: var(--text-2); font-size: 14.5px; line-height: 1.65; margin: 0 0 11px; }
.qcard p:last-child { margin-bottom: 0; }
.qcard b { color: var(--text-hi); font-weight: 600; }
.qcard ul { list-style: none; padding: 0; margin: 0; }
.qcard ul li {
  color: var(--text-2); font-size: 14.5px; line-height: 1.65;
  padding: 0 0 0 16px; margin: 0 0 10px; position: relative;
}
.qcard ul li:last-child { margin-bottom: 0; }
.qcard ul li::before {
  content: ""; position: absolute; left: 0; top: 9px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--q); opacity: .8;
}
.qcard .fine { color: var(--muted); font-size: 12.5px; line-height: 1.6; margin-top: 13px; }
.qcard .fine b { color: var(--text-2); font-weight: 600; }

.ledger-run {
  margin: 16px 0 0; padding: 24px 26px; border-radius: 14px;
  background: var(--accent-bg); border: 1px solid var(--accent-b);
}
.ledger-run h3 {
  font-size: 13px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
  color: var(--accent); margin: 0 0 12px;
}
.ledger-run p { color: var(--text-2); font-size: 15px; line-height: 1.7; margin: 0 0 11px; max-width: 86ch; }
.ledger-run p:last-child { margin-bottom: 0; }
.ledger-run b { color: var(--text-hi); font-weight: 600; }
.ledger-run .fine { color: var(--muted); font-size: 12.5px; line-height: 1.6; margin-top: 14px; }
.ledger-run .fine b { color: var(--text-2); }

.ledger-also { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 16px 0 0; }
@media (max-width: 900px) { .ledger-also { grid-template-columns: 1fr; } }
.ledger-also > div {
  padding: 18px 20px; border-radius: 12px;
  border: 1px solid var(--hairline); background: var(--glass);
  color: var(--text-2); font-size: 14px; line-height: 1.6;
}
.ledger-also b { color: var(--text-hi); font-weight: 600; display: block; margin-bottom: 4px; }

/* ---------------- docs / guide sidebar (shared) ----------------
   One definition used by both the Docs guide and the Why .dai page, so the
   two sidebars are the same component rather than two lookalikes.
   ---------------------------------------------------------------- */

/* Docs sidebar: shows where you are in the guide and how much is left.
   Scoped to .dtoc so the shared .docs-toc styling on other pages is
   untouched. Everything is additive: with JS off the menu still works as a
   plain list of links. */

/* No position here: .docs-toc is already position:sticky, which is a
   positioned ancestor for the spine and the node markers. Setting
   position:relative would win on source order and kill the stickiness. */
.dtoc {
  /* Cap to the viewport and scroll internally. A sticky box taller than its
     slot has nowhere to travel, so on a short screen the last entries were
     simply unreachable. */
  max-height: calc(100vh - 116px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* extra left room so the node and its pulse ring (which sit at negative
     offsets) are not clipped by the new scroll container; the negative
     margin puts the menu back where it was visually */
  padding-left: 24px; margin-left: -6px; padding-right: 8px;
  scrollbar-width: thin;
  scrollbar-color: var(--hairline-2) transparent;
}
.dtoc::-webkit-scrollbar { width: 6px; }
.dtoc::-webkit-scrollbar-track { background: transparent; }
.dtoc::-webkit-scrollbar-thumb {
  background: var(--hairline-2); border-radius: 3px;
}
.dtoc:hover::-webkit-scrollbar-thumb { background: var(--accent-b); }

/* the spine the links hang off, with a fill that reaches the section you are
   actually in, never past it */
/* left shifts with the container's new padding so the line still runs through
   the centre of the nodes. Height is set in JS: inside a scroll container an
   absolutely positioned box resolves `bottom` against the *visible* height,
   so the spine would stop at the fold instead of spanning the whole list. */
.dtoc-spine {
  position: absolute; left: 9px; top: 4px; width: 1px;
  background: var(--hairline-2); border-radius: 1px; overflow: hidden;
}
.dtoc-spine-fill {
  display: block; width: 100%; height: 0%;
  background: linear-gradient(180deg, var(--accent), var(--accent2));
  box-shadow: 0 0 6px 1px var(--accent-glow);
  transition: height .18s linear;
}

.dtoc a { position: relative; padding: 5px 0 5px 2px; line-height: 1.32; }
/* node on the spine for every entry, lit for the one you are reading */
.dtoc a::before {
  content: ""; position: absolute; left: -18px; top: 50%;
  width: 7px; height: 7px; margin-top: -3.5px; border-radius: 50%;
  background: var(--bg); border: 1px solid var(--hairline-2);
  transition: background .22s ease, border-color .22s ease, transform .22s cubic-bezier(.2,.8,.3,1), box-shadow .22s ease;
}
.dtoc a:hover::before { border-color: var(--accent-b); transform: scale(1.2); }

.dtoc a.on { color: var(--accent); font-weight: 600; }
.dtoc a.on::before {
  background: var(--accent); border-color: var(--accent); transform: scale(1.3);
  box-shadow: 0 0 0 3px var(--accent-bg), 0 0 12px 3px var(--accent-glow);
}
/* a quiet pulse so the current section reads as live, not just coloured */
.dtoc a.on::after {
  content: ""; position: absolute; left: -21px; top: 50%;
  width: 13px; height: 13px; margin-top: -6.5px; border-radius: 50%;
  border: 1px solid var(--accent-b); pointer-events: none;
  animation: dtoc-pulse 2.6s ease-out infinite;
}
@keyframes dtoc-pulse {
  0%   { transform: scale(.55); opacity: .85; }
  100% { transform: scale(1.6); opacity: 0; }
}

/* Group headings sit to the RIGHT of the spine. Pulled left they straddled
   the line and the spine drew straight through the words. */
.dtoc .t-head { margin-left: 2px; }

@media (max-width: 940px) {
  /* stacked above the article, so it must not become its own scroll box */
  .dtoc {
    padding-left: 0; margin-left: 0;
    max-height: none; overflow: visible;
  }
  .dtoc-spine { display: none; }
  .dtoc a::before, .dtoc a.on::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .dtoc a.on::after { animation: none; }
  .dtoc a::before, .dtoc-spine-fill { transition: none; }
}

/* the Why .dai menu groups its links in <ul>s; the shared node and
   scroll behaviour must reach those too */
.dtoc ul { list-style: none; margin: 0; padding: 0; }
.dtoc li { margin: 0; }


/* ---------------- nav: GitHub link ---------------- */
/* Sits in the account group beside Sign in. Icon-only, so it needs a real
   accessible name rather than relying on the glyph. The 34px box gives it a
   comfortable hit area without making it compete with the CTA. */
.nav-github {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: none;
  border-radius: 8px; color: var(--text-2);
  border: 1px solid transparent;
  transition: color .18s ease, border-color .18s ease, background .18s ease;
}
.nav-github svg { width: 18px; height: 18px; display: block; fill: currentColor; }
.nav-github:hover {
  color: var(--text-hi);
  border-color: var(--hairline-2);
  background: var(--glass);
}
.nav-github:focus-visible { color: var(--text-hi); }
@media (max-width: 940px) {
  /* in the mobile sheet it becomes a normal labelled row, because a bare icon
     in a vertical list reads as decoration */
  .nav-github { width: auto; height: auto; justify-content: flex-start; gap: 10px; padding: 11px 0; }
  .nav-github::after { content: "GitHub"; font-size: 16px; }
}

/* ---------------- comparison chart (cmp) ----------------
   A two-entity benchmark card: one measure per plot, one axis per plot, and
   two plots rather than two scales on one track (accuracy in %, context read
   in tokens: different units, so never the same axis).

   Colours are the two entities, and they are the SAME in both plots, because
   colour follows the entity and not its rank or its row. Both were validated
   against the #05070a surface for the dark-mode lightness band, the chroma
   floor, contrast, and protan/deuteran separation (worst adjacent pair
   ΔE 24.4 simulated, 31.0 normal), rather than picked by eye. The brand's
   bright #4ade87 sits outside the band on a near-black surface: it glares, so
   the fill carries the validated step and the brightness lives in the glow. */
.cmp {
  --cmp-dai-a: #17ad80; --cmp-dai-b: #2b93c4;
  --cmp-rival-a: #8368f2; --cmp-rival-b: #6f56e8;
  /* The full-context baseline is warm, so bar length reads as cost. Validated
     against the same surface: ΔE 11.0 deutan and 23.3 normal against the .dai
     green, both above their floors. */
  --cmp-base-a: #b8641f; --cmp-base-b: #a85a2e;
}
.cmp-plot + .cmp-plot { margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--hairline); }
.cmp-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent2); margin-bottom: 16px;
}
.cmp-head span { color: var(--muted); letter-spacing: .08em; }

/* The value column is a fixed width, not auto, so the axis row below can use
   the identical template and its ticks land exactly under the track. With an
   auto column the ticks column was wider than the track and every tick sat
   right of the gridline it named. */
.cmp-row, .cmp-axis { display: grid; grid-template-columns: 148px 1fr 104px; gap: 16px; align-items: center; }
.cmp-row + .cmp-row { margin-top: 12px; }
.cmp-lbl { text-align: right; font-size: 13.5px; color: var(--text-2); line-height: 1.3; }
/* Identity rides a swatch beside the name, never the text colour: a saturated
   fill is unreadable as type on this surface. */
.cmp-lbl strong { display: flex; align-items: center; justify-content: flex-end; gap: 7px; color: var(--text-hi); font-size: 14.5px; }
.cmp-key { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.cmp-row.is-dai .cmp-key { background: linear-gradient(135deg, var(--cmp-dai-a), var(--cmp-dai-b)); }
.cmp-row.is-rival .cmp-key { background: linear-gradient(135deg, var(--cmp-rival-a), var(--cmp-rival-b)); }
.cmp-row.is-base .cmp-key { background: linear-gradient(135deg, var(--cmp-base-a), var(--cmp-base-b)); }
.cmp-sub { display: block; font-size: 11.5px; color: var(--muted); margin-top: 2px; }

/* Gridlines are hairlines one step off the surface, solid, and behind the
   mark. They are what makes the plot readable without a number on every bar. */
.cmp-track {
  position: relative; height: 22px; border-radius: 4px;
  background:
    repeating-linear-gradient(to right, var(--hairline) 0 1px, transparent 1px 25%),
    var(--track);
}
/* The oracle ceiling, drawn as a reference line rather than a bar: it is not a
   competitor, it is the limit of the answering model itself. Dotted, because a
   solid rule at this weight would read as another gridline. */
.cmp-track.has-ceiling::after {
  content: ""; position: absolute; left: var(--ceiling); top: -3px; bottom: -3px; width: 0;
  border-left: 2px dotted var(--text-2); opacity: .75; z-index: 2;
}
.cmp-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: var(--v);
  /* Rounded at the data end, square at the baseline, so length stays honest. */
  border-radius: 0 4px 4px 0; min-width: 4px;
}
.cmp-row.is-dai .cmp-fill {
  background: linear-gradient(90deg, var(--cmp-dai-a), var(--cmp-dai-b));
  box-shadow: 0 0 20px rgba(23, 173, 128, .40), 0 1px 8px rgba(0, 0, 0, .5);
}
.cmp-row.is-rival .cmp-fill {
  background: linear-gradient(90deg, var(--cmp-rival-a), var(--cmp-rival-b));
  box-shadow: 0 0 20px rgba(131, 104, 242, .32), 0 1px 8px rgba(0, 0, 0, .5);
}
.cmp-row.is-base .cmp-fill {
  background: linear-gradient(90deg, var(--cmp-base-a), var(--cmp-base-b));
  box-shadow: 0 0 20px rgba(184, 100, 31, .28), 0 1px 8px rgba(0, 0, 0, .5);
}
/* A lit top edge, the cheapest cue that the mark has volume. */
.cmp-fill::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 45%;
  background: linear-gradient(180deg, rgba(255,255,255,.20), rgba(255,255,255,0));
  border-radius: 0 4px 0 0;
}
/* The winning end of each plot gets a bright cap: the one place the brand's
   full-strength accent is safe, because it is 3px wide and not a field. */
.cmp-row.is-best .cmp-fill::after {
  content: ""; position: absolute; right: 0; top: -2px; bottom: -2px; width: 3px;
  border-radius: 2px; background: var(--text-hi); opacity: .85;
}

.cmp-val { font-family: var(--mono); font-size: 15px; font-weight: 600; color: var(--text-hi); white-space: nowrap; }
.cmp-val small { font-size: 11px; font-weight: 500; color: var(--muted); margin-left: 2px; }

.cmp-axis { margin-top: 7px; }
.cmp-ticks {
  grid-column: 2; display: flex; justify-content: space-between;
  font-family: var(--mono); font-size: 10.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* Hover is supplementary here: every value is already direct-labelled, so the
   tooltip adds context (the raw counts) and never gates a number. */
.cmp-row { cursor: default; }
.cmp-row:hover .cmp-fill { filter: brightness(1.12); }
.cmp-row:hover .cmp-val { color: var(--accent); }

/* The headline the two plots exist to support. */
.cmp-take {
  margin: 24px 0 0; padding: 14px 16px; border-radius: 12px;
  background: linear-gradient(96deg, rgba(23,173,128,.10), rgba(43,147,196,.06));
  border: 1px solid var(--accent-b); font-size: 14px; color: var(--text-2); line-height: 1.55;
}
.cmp-take b { color: var(--text-hi); }

@media (max-width: 620px) {
  .cmp-row, .cmp-axis { grid-template-columns: 1fr 92px; }
  .cmp-lbl { grid-column: 1 / -1; text-align: left; }
  .cmp-lbl strong { justify-content: flex-start; }
  .cmp-ticks { grid-column: 1; }
}

/* ---------------- oracle ceiling panel ----------------
   Runs full width under the chart and the run-configuration table. It used to
   sit inside the right-hand column, which squeezed five paragraphs into half
   the page and left a tall empty gap under the chart on the left. */
.ceiling {
  display: grid; grid-template-columns: 1fr 260px; gap: 34px; align-items: start;
  margin-top: 30px; padding: 26px 28px; border-radius: 16px;
  background: linear-gradient(120deg, rgba(23,173,128,.09), rgba(43,147,196,.05) 55%, transparent);
  border: 1px solid var(--hairline); position: relative; overflow: hidden;
}
/* One lit edge rather than a full accent border: the panel is an aside, not an
   alert, so it should read as lifted rather than flagged. */
.ceiling::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: linear-gradient(90deg, var(--accent), var(--accent2) 45%, transparent);
}
.ceiling h3 { margin: .3em 0 14px; font-size: 21px; color: var(--text-hi); letter-spacing: -.02em; }
.ceiling p { font-size: 14.5px; color: var(--text-2); line-height: 1.62; margin: 0 0 12px; }
.ceiling .ceiling-take {
  margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--hairline);
  color: var(--text-hi); font-size: 15px;
}

/* The three numbers the argument turns on, read in one pass. */
.ceiling-figs { display: grid; gap: 10px; }
.cfig {
  display: flex; flex-direction: column; gap: 3px;
  padding: 13px 15px; border-radius: 12px;
  background: var(--glass); border: 1px solid var(--hairline);
}
.cfig .v {
  font-family: var(--mono); font-size: 21px; font-weight: 600; color: var(--text-2);
  letter-spacing: -.01em;
}
.cfig .v small { font-size: 12px; font-weight: 500; opacity: .7; margin-left: 1px; }
.cfig .k { font-size: 11.5px; color: var(--muted); line-height: 1.35; }
.cfig.is-ours { border-color: var(--accent-b); background: var(--accent-bg); }
.cfig.is-ours .v { color: var(--text-hi); }
/* The ceiling row is dashed, matching the dashed reference line in the chart
   above, so the two read as the same object. */
.cfig.is-cap { border-style: dashed; border-color: var(--hairline-2); }
.cfig.is-cap .v { color: var(--text-hi); }

@media (max-width: 860px) {
  .ceiling { grid-template-columns: 1fr; gap: 22px; padding: 22px; }
  .ceiling-figs { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}

/* ---------------- fx buttons ----------------
   The headline CTA pair. Opt-in with .fx, because the plain .btn is used
   dozens of times across the site and a page full of glowing buttons has no
   hierarchy left. Every effect here is hover-driven or decorative: the button
   is fully drawn and readable before any of it runs, which is the same rule
   the bar charts now follow. */
.btn.fx {
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 14px 30px; border-radius: 13px; font-size: 15.5px; letter-spacing: -.01em;
  transition: transform .2s cubic-bezier(.22,1,.36,1), box-shadow .2s ease, border-color .2s ease;
}
.btn.fx .arw { flex: none; transition: transform .22s cubic-bezier(.22,1,.36,1); }
.btn.fx:hover .arw { transform: translateX(4px); }
.btn.fx:active { transform: translateY(0) scale(.985); }

/* Filled: a three-stop brand gradient, an inner top highlight for volume, and
   a sheen that sweeps once on hover. */
.btn.fx.primary {
  background: linear-gradient(96deg, #2fe0a8 0%, var(--accent) 42%, var(--accent2) 100%);
  color: var(--accent-ink);
  box-shadow: 0 8px 26px rgba(47,224,168,.26), 0 2px 8px rgba(0,0,0,.4), inset 0 1px 0 rgba(255,255,255,.38);
}
.btn.fx.primary:hover { color: var(--accent-ink); transform: translateY(-2px); box-shadow: 0 14px 38px rgba(47,224,168,.34), 0 3px 10px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.45); }
.btn.fx.primary::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(105deg, transparent 35%, rgba(255,255,255,.45) 50%, transparent 65%);
  transform: translateX(-120%); transition: transform .62s cubic-bezier(.22,1,.36,1);
}
.btn.fx.primary:hover::after { transform: translateX(120%); }

/* Ghost: a gradient hairline drawn with a mask, so the border itself carries
   the brand rather than a flat grey rule. */
.btn.fx.ghost {
  border: none; color: var(--text-hi);
  background: linear-gradient(var(--glass-hi), var(--glass-hi)) padding-box;
  box-shadow: 0 2px 10px rgba(0,0,0,.35);
}
.btn.fx.ghost::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(120deg, var(--accent) 0%, var(--accent2) 48%, var(--hairline-2) 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude; pointer-events: none; opacity: .55; transition: opacity .2s ease;
}
.btn.fx.ghost:hover { color: var(--text-hi); transform: translateY(-2px); box-shadow: 0 10px 28px rgba(0,0,0,.45), 0 0 0 1px rgba(74,222,135,.10); }
.btn.fx.ghost:hover::before { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .btn.fx, .btn.fx .arw, .btn.fx.primary::after { transition: none; }
  .btn.fx:hover { transform: none; }
  .btn.fx.primary:hover::after { transform: translateX(-120%); }
}

/* ---------------- cookie consent ---------------- */
/* Anchored bottom-left rather than across the full width: a full-bleed bar on a
   phone covers the thing the visitor came to read, which is what makes people
   click accept to get rid of it. This asks without blocking. */
.consent {
  position: fixed; left: 16px; bottom: 16px; z-index: 9999;
  width: min(420px, calc(100vw - 32px));
  background: var(--glass-hi); border: 1px solid var(--hairline-2);
  border-radius: 14px; backdrop-filter: blur(14px);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .55);
}
.consent-body { padding: 18px 19px 16px; }
.consent-lead { margin: 0 0 13px; font-size: 13.5px; line-height: 1.55; color: var(--text-2); }
.consent-cats { display: grid; gap: 11px; margin: 0 0 15px; }
.consent-cat { display: grid; grid-template-columns: 16px 1fr; gap: 10px; align-items: start; font-size: 13.5px; color: var(--text-hi); cursor: pointer; }
.consent-cat input { margin: 3px 0 0; accent-color: var(--accent); }
.consent-cat input:disabled { opacity: .5; cursor: not-allowed; }
.consent-detail { display: block; margin-top: 3px; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.consent-actions { display: flex; flex-wrap: wrap; gap: 9px; }
/* Reject and Accept share one class deliberately. Giving accept the brand
   colour and reject a quiet outline is the standard dark pattern, and it is
   also the thing that makes consent invalid. */
.consent-btn {
  flex: 1 1 auto; min-width: 96px; padding: 9px 15px; border-radius: 9px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 550;
  background: var(--glass); border: 1px solid var(--hairline-2); color: var(--text-hi);
}
.consent-btn:hover { border-color: var(--accent-b); }
.consent-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.consent-ghost, .consent-save { flex: 0 0 auto; color: var(--text-2); }
.consent-note { margin: 12px 0 0; font-size: 12px; color: var(--muted); }
@media (max-width: 480px) { .consent { left: 10px; right: 10px; bottom: 10px; width: auto; } }
/* Reopening control in the footer legal row. A button because it opens a
   dialogue rather than navigating, styled to sit in the row of links without
   announcing itself as something different. */
.consent-reopen {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--text-2); text-align: left;
}
.consent-reopen:hover { color: var(--text-hi); }
/* In the footer it is the fifth entry of the Legal column and has to read as
   one of them. Left on its own colour and line-height it sat brighter than the
   links either side and drew the eye to the least interesting thing there. */
.site-footer .cols .consent-reopen { display: block; padding: 3px 0; color: var(--muted); font-size: inherit; }
.site-footer .cols .consent-reopen:hover { color: var(--text-hi); }
/* Statutory trading disclosure. The Companies Act and the 2015 Trading
   Disclosures Regulations require the registered name, number, place of
   registration and registered office to appear on the company's website, so
   this is fine print in the legal sense rather than only the visual one. Muted
   and last, because nobody comes here for it, but present on every page
   because that is the point. */
.footer-owner {
  margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--hairline);
  font-size: 12px; color: var(--muted); line-height: 1.6;
}
.footer-owner b { color: var(--text-2); font-weight: 600; }

/* ---------------- error pages ---------------- */
/* Shared by 404, 403, 429 and 500. These pages are served at whatever URL the
   visitor actually asked for, so every one of them references stylesheets with
   root-relative paths: a relative href would resolve against /some/deep/path/
   and the page would arrive unstyled at the exact moment it needs to reassure
   somebody. */
  .nf { min-height: 62vh; display: flex; align-items: center; }
  .nf-code {
    font-family: var(--mono); font-size: 12px; letter-spacing: .2em;
    text-transform: uppercase; color: var(--accent2); margin-bottom: 14px;
    display: flex; align-items: center; gap: 12px;
  }
  .nf-code::before { content: ""; width: 26px; height: 1px; background: currentColor; opacity: .8; }
  .nf h1 { font-size: clamp(34px, 5.4vw, 58px); margin: 0 0 18px; }
  .nf .lede { max-width: 60ch; }
  .nf-links { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; margin-top: 34px; }
  .nf-link {
    display: block; padding: 16px 18px; border-radius: 12px;
    border: 1px solid var(--hairline); background: var(--glass);
    transition: border-color .2s ease, transform .2s ease;
  }
  .nf-link:hover { border-color: var(--accent-b); transform: translateY(-2px); color: inherit; }
  .nf-link b { display: block; color: var(--text-hi); font-size: 15px; margin-bottom: 4px; }
  .nf-link span { font-size: 13px; color: var(--muted); line-height: 1.5; }
  .nf-path {
    font-family: var(--mono); font-size: 12.5px; color: var(--muted);
    background: var(--code-panel); border: 1px solid var(--hairline);
    border-radius: 8px; padding: 9px 13px; margin-top: 26px;
    display: inline-block; max-width: 100%; overflow-wrap: anywhere;
  }
