/* ==========================================================================
   Veriql: shared design system (single source of truth for every page).
   Verification-violet accent on cool ink. Green/amber/red are VERDICTS only:
   the brand is never the "safe" color (a scan's job is telling you the un-safe truth).
   Contract classes are stable: pages consume these names, do not rename.
   All motion is gated behind prefers-reduced-motion (see bottom of file).
   ========================================================================== */

/* --- Design tokens -------------------------------------------------------- */
:root{
  --bg:#0B0B12; --bg-2:#12121C; --surface:rgba(255,255,255,.04); --surface-2:rgba(255,255,255,.06);
  --line:rgba(255,255,255,.09); --line-2:rgba(255,255,255,.14);
  --ink:#ECEDF2; --muted:#9A9BA8; --faint:#6A6B78;
  --brand:#6D5EFF; --brand-d:#5A49E6; --brand-2:#8B7DFF; --brand-ink:#FFFFFF; --glow:rgba(109,94,255,.32);
  --teal:#2FE6C2; --teal-2:#66F0D6; --teal-ink:#08120F; --glow-teal:rgba(47,230,194,.28);
  --safe:#2FBF71; --warn:#E9B23C; --danger:#F0503A; --critical:#E23D5B;
  --r:14px; --r-sm:10px; --r-lg:20px;
  --sans:"IBM Plex Sans",system-ui,sans-serif; --disp:"Poppins",var(--sans); --mono:"IBM Plex Mono",ui-monospace,monospace;
  --ease:cubic-bezier(.22,.61,.36,1); --dur:.5s;
  --shadow:0 1px 0 rgba(255,255,255,.05) inset, 0 24px 60px -24px rgba(0,0,0,.7);
}

/* Light theme (opt-in via html[data-theme="light"], flipped by the header
   toggle button and persisted to localStorage; see the inline no-flash +
   toggle scripts shipped on every page). Dark stays the DEFAULT look (no
   attribute = dark): this block only overrides the neutral + verdict tokens,
   every component class below reads through --bg/--ink/--line/etc, so
   nothing else needs a light-specific rule.

   REWORKED 2026-09-29 for identity AND legibility.

   Identity: the old light mode was a neutral cool grey (#F7F7FB on #15151F)
   that carried none of the brand and looked like every other SaaS landing.
   The paper is now a WARM IVORY under COOL INDIGO ink. That tension is the
   brand on purpose: every rival scanner is cold, dark and techy, and this
   file already commits to a warm display face (Poppins) for exactly that
   reason, so the light mode should read human and approachable rather than
   clinical. Warm ground also makes the cool violet/teal accents pop harder
   than a grey ground does, and pure-white cards (--bg-2) now lift off the
   paper so depth comes from the surface itself, not heavy shadows. Surfaces
   and rules are tinted with the indigo ink hue rather than neutral grey, so
   every border belongs to the palette instead of sitting on top of it.

   Legibility: the OLD light values silently failed WCAG AA on the things
   that carry the actual meaning. Measured on the old #F7F7FB paper:
   --safe 3.75:1, --warn 3.61:1, --danger 4.25:1, --teal 2.79:1, and
   --brand-as-link 4.19:1 (white on the brand button was 4.47:1). A product
   whose entire job is an unmistakable verdict cannot ship a "safe" green
   that fails contrast. Every token below is now >=4.5:1 on both the paper
   and a white card (accents >=3:1), verified numerically, which is why the
   violet is deepened here rather than inheriting its dark-theme value. */
html[data-theme="light"]{
  --bg:#FAF7F2; --bg-2:#FFFFFF; --surface:rgba(38,28,74,.04); --surface-2:rgba(38,28,74,.065);
  --line:rgba(38,28,74,.11); --line-2:rgba(38,28,74,.18);
  --ink:#1A1726; --muted:#59536B; --faint:#8A8499;
  --brand:#5B49F0; --brand-d:#4A38DC; --brand-2:#7A68FF;
  /* Kept deliberately faint. --glow also drives body's big top-right radial
     wash, and every card surface is semi-transparent, so a strong violet here
     bleeds THROUGH the cards: at .18 the trending grid visibly graded from
     warm-white on the left to lavender on the right, which reads as a bug
     rather than an aura. Low enough to stay a tint, not a stain. */
  --glow:rgba(91,73,240,.07); --glow-teal:rgba(15,127,105,.08);
  --teal:#0F7F69; --teal-2:#14A188;
  --safe:#1E7F4A; --warn:#8F6410; --danger:#CE3018; --critical:#C22348;
  --shadow:0 1px 0 rgba(255,255,255,.9) inset, 0 20px 46px -26px rgba(38,28,74,.18);
}

/* --- Base ----------------------------------------------------------------- */
*{box-sizing:border-box}
/* Anchor-jump offset: the nav is position:sticky at top:0, so jumping to a
   #section would otherwise land with the section's top hidden UNDER the nav.
   scroll-padding-top on the scroll container reserves the nav's height (+ a little
   breathing room) for every in-page anchor jump. */
html{scroll-padding-top:84px}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);font-size:17px;line-height:1.6;-webkit-font-smoothing:antialiased;
  background-image:radial-gradient(1100px 560px at 84% -8%,var(--glow),transparent 60%);
  background-attachment:fixed}
h1,h2,h3{font-family:var(--disp);letter-spacing:-.02em;line-height:1.05;color:var(--ink);margin:0 0 .5em}
h1{font-size:clamp(34px,6vw,60px)} h2{font-size:clamp(24px,3.4vw,34px)} h3{font-size:19px}
p{margin:0 0 1em}
a{color:var(--brand)}
img,svg{max-width:100%}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:6px}

/* --- Layout --------------------------------------------------------------- */
/* .wrap owns the horizontal gutter; .band owns only the vertical rhythm.
   .band MUST set padding via longhand (padding-top/-bottom): a `padding` shorthand
   here would reset left/right to 0 and, on a `class="wrap band"` element, silently
   wipe .wrap's gutter (equal specificity, later rule wins). That collision is what
   pushed every band's content to the screen edge on mobile. Keep these longhand. */
.wrap{max-width:1080px;margin:0 auto;padding:0 22px}
.band{padding-top:72px;padding-bottom:72px}
.band + .band{padding-top:0}
@media (max-width:640px){
  .wrap{padding:0 18px}
  .band{padding-top:52px;padding-bottom:52px}
}

/* --- Nav / chrome --------------------------------------------------------- */
.nav{position:sticky;top:0;z-index:50;
  background:color-mix(in srgb,var(--bg) 72%,transparent);
  backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%);
  border-bottom:1px solid var(--line)}
/* Wider than .wrap's 1080px on purpose: the flagship links (added for the
   wash-trading + honeypot-sim features) push the full 7-item bar past what
   fits inside a 1080px column for several locales (verified: RU/ES/PT/VI/FR
   all overflow a 1080px cap even with zero shrink). Giving the bar its own,
   larger cap lets it show without wrapping on genuinely wide screens; the
   burger/sheet (below, see the 1400px query) covers every narrower one. */
.nav__in{max-width:1440px;margin:0 auto;padding:14px 22px;display:flex;align-items:center;justify-content:space-between;gap:20px}
.brand{display:inline-flex;align-items:center;gap:10px;font-family:var(--disp);font-weight:700;font-size:18px;
  letter-spacing:-.02em;color:var(--ink);text-decoration:none;white-space:nowrap}
.mk{width:30px;height:30px;flex:none;display:grid;place-items:center;border-radius:9px;
  background:var(--surface-2);border:1px solid var(--line-2);box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 4px 14px -8px var(--glow)}
.mk svg{width:19px;height:19px}
.mk:not(.mk--v) svg [stroke]{stroke:var(--brand)}
.mk:not(.mk--v) svg [fill]:not([fill="none"]){fill:var(--brand)}
/* The Aperture-V brand mark (.mk--v) ships its own violet->teal gradient
   (baked into the inline SVG's <linearGradient>), so it must NOT be flattened
   to a solid --brand fill by the rule above. It also draws its own rounded-
   square backdrop + ring at low opacity, so the chip's neutral background/
   border/shadow would just double up behind it, drop those for this variant
   and let the mark be the whole chip. */
.mk--v{background:none;border:0;box-shadow:none}
.nav__links{display:flex;align-items:center;gap:20px}
.nav__links a{color:var(--muted);font-size:14.5px;font-weight:500;text-decoration:none;transition:color var(--dur) var(--ease)}
.nav__links a:hover{color:var(--ink)}
.nav__right{display:flex;align-items:center;gap:14px}
.nav__cta{display:inline-flex;align-items:center;gap:8px;background:var(--brand);color:var(--brand-ink);font-weight:650;
  border:0;border-radius:var(--r-sm);padding:9px 16px;font-size:14.5px;text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:background var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.nav__cta:hover{background:var(--brand-d);box-shadow:0 8px 24px -8px var(--glow)}
/* "NEW" flag on a nav link (flagship features). Sits inline after the label
   in both the desktop bar and the mobile sheet, same badge in both. */
.nav__new{display:inline-block;margin-left:5px;padding:1px 6px;border-radius:999px;font-size:10px;font-weight:700;
  letter-spacing:.04em;line-height:1.5;color:#fff;background:var(--brand);vertical-align:middle}

/* Mobile menu button: hidden on desktop, shown when the inline nav collapses. */
.nav__burger{display:none;width:44px;height:44px;flex:none;align-items:center;justify-content:center;
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-sm);color:var(--ink);cursor:pointer;
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease)}
.nav__burger:hover{border-color:var(--brand);background:var(--surface-2)}
.nav__burger svg{width:20px;height:20px}

/* Light/dark theme toggle: a small icon button shipped in every page's nav
   (see the shared markup + inline scripts, not gated behind the 1400px
   burger collapse below, it stays visible at every width). Sun = "switch to
   light" (shown in dark mode); moon = "switch to dark" (shown in light
   mode), swapped purely by CSS off html[data-theme] so no re-render is
   needed on click, the toggle script only flips the attribute + aria state. */
.theme-toggle{display:inline-flex;width:44px;height:44px;flex:none;align-items:center;justify-content:center;
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-sm);color:var(--ink);cursor:pointer;
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease)}
.theme-toggle:hover{border-color:var(--brand);background:var(--surface-2)}
.theme-toggle svg{width:19px;height:19px}
.theme-toggle__moon{display:none}

/* One height for the whole nav control cluster.
   These three sit side by side and were each sized by their own padding, so
   they rendered at three DIFFERENT heights (measured: language 33px, theme
   toggle 44px, CTA 41.2px). Vertically centred, so it read as a subtly ragged,
   unfinished bar, and the mismatch is more obvious in light mode where the
   borders carry more contrast (which is why it looks like a light/dark bug: it
   is not, the heights are identical in both themes).
   Only applied where the inline bar actually shows. Below that the toggle and
   burger must keep their full 44x44 touch target, so this must not leak into
   the mobile nav. */
@media (min-width:1241px){
  .nav__right>.switcher>summary,
  .nav__right>.theme-toggle,
  .nav__right>.nav__cta{height:40px;box-sizing:border-box;display:inline-flex;align-items:center}
  .nav__right>.theme-toggle{width:40px}
}
html[data-theme="light"] .theme-toggle__sun{display:none}
html[data-theme="light"] .theme-toggle__moon{display:block}
/* Slide-down sheet holding the nav links, language and CTA on mobile. */
.nav__sheet{display:none}

/* With 7 nav items (5 original + 2 flagship "NEW" links) the inline bar needs
   real room, so the burger takes over below this point. The collapse is scoped
   with :has(.nav__burger) so it only fires on navs that actually ship a burger
   + sheet fallback (the landing). A nav without a burger (e.g. api.html:
   Endpoints/Pricing/OpenAPI, no sheet) must keep its links visible: otherwise
   they'd vanish with nothing to recover them.

   LOWERED 1400px -> 1240px (2026-09-29). 1400 was picked for the WIDEST locale
   (measured: ru needs ~1423px, es ~1380, pt ~1367 at default sizing) and then
   applied to everyone, so English (~1123px) and most other locales showed a
   MOBILE BURGER on perfectly wide desktop screens and TVs: anything from
   1123px to 1400px got a hamburger for no reason. A large display running OS
   scaling (a 1920px TV at 150% reports 1280 CSS px) landed squarely in that
   dead band, which is exactly the reported bug.
   The fix is a two-tier bar: collapse below 1240px, and between 1241-1440px
   keep the links inline but TIGHTENED (see the tier below) so that even the
   widest locale still fits instead of forcing everyone down to the burger. */
@media (max-width:1240px){
  .nav:has(.nav__burger) .nav__links{display:none}
  /* Scoped to burger navs too: content pages (learn/articles) have a
     .nav__right switcher + CTA but NO burger/sheet: unscoped, these would
     vanish with nothing to recover them, collapsing the nav to a bare logo. */
  .nav:has(.nav__burger) .nav__right>.switcher,
  .nav:has(.nav__burger) .nav__right>.nav__cta{display:none} /* these live in the sheet on mobile */
  .nav:has(.nav__burger) .nav__burger{display:inline-flex}
  .nav:has(.nav__burger) .nav__sheet{display:block;border-bottom:1px solid var(--line);
    background:color-mix(in srgb,var(--bg) 84%,transparent);
    backdrop-filter:blur(16px) saturate(140%);-webkit-backdrop-filter:blur(16px) saturate(140%)}
  /* Must out-specify the sheet-show rule above (0,3,0) or the burger can't
     close the menu: [hidden] alone (0,2,0) loses and the sheet stays open. */
  .nav:has(.nav__burger) .nav__sheet[hidden]{display:none}
  .nav__sheet-in{max-width:1080px;margin:0 auto;padding:8px 22px 18px;display:flex;flex-direction:column;gap:2px}
  .nav__sheet .nav__link{display:block;padding:14px 4px;color:var(--ink);text-decoration:none;font-weight:500;
    font-size:16px;border-bottom:1px solid var(--line);transition:color var(--dur) var(--ease)}
  .nav__sheet .nav__link:active,.nav__sheet .nav__link:hover{color:var(--brand)}
  .nav__sheet .switcher{margin:14px 0 6px}
  .nav__sheet .switcher summary{width:100%;padding:13px 16px;font-size:15px}
  .nav__sheet .switcher summary::after{margin-left:auto} /* hug the right edge like a native select */
  .nav__sheet .switcher__t{display:inline} /* keep the language label in the sheet */
  /* Flow the menu in-place (full width, below the button) instead of a narrow floating popover. */
  .nav__sheet .switcher__menu{position:static;width:100%;min-width:0;margin-top:8px;max-height:300px;
    box-shadow:none;background:color-mix(in srgb,var(--bg-2) 72%,transparent)}
  .nav__sheet .switcher__menu a{padding:12px 12px;font-size:15px}
  .nav__sheet .nav__sheet-cta{width:100%;margin-top:6px;padding:14px 20px;font-size:15px}
}

/* Mid-width tier: keep the full inline bar, but tighten it so the widest
   locales (ru/es/pt/vi) still fit rather than dragging every locale down to a
   burger. Trims the link gap, drops the link font a touch, and hides the
   language switcher's text label (the globe icon still reads as "language",
   and <=560px already hides this same label). Scoped to burger navs so slim
   navs and no-burger navs are untouched. */
@media (min-width:1241px) and (max-width:1440px){
  .nav:has(.nav__burger) .nav__links{gap:11px}
  .nav:has(.nav__burger) .nav__links a{font-size:13px}
  .nav:has(.nav__burger) .nav__right>.switcher .switcher__t{display:none}
  .nav:has(.nav__burger) .nav__right>.switcher summary{padding:8px 11px}
  .nav:has(.nav__burger) .nav__right>.nav__cta{padding-left:15px;padding-right:15px}
}

/* Slim navs (the API docs page + the learn/article content hub) carry only a
   few links (or just a switcher + CTA), so they stay inline far longer than
   the landing's 7-item bar: they collapse to the burger only at phone widths.
   .nav--slim opts a nav out of the collapse above, down to 680px. */
@media (min-width:681px) and (max-width:1240px){
  .nav.nav--slim:has(.nav__burger) .nav__links{display:flex}
  .nav.nav--slim:has(.nav__burger) .nav__burger{display:none}
  .nav.nav--slim .nav__right>.nav__cta{display:inline-flex}
  /* Content-page slim navs have a switcher; re-show it inline here (the base
     <=1400 rule hides .nav:has(.nav__burger) .nav__right>.switcher). The
     :has() form gives a clean (0,5,0) win over that (0,4,0) hide. */
  .nav.nav--slim:has(.nav__burger) .nav__right>.switcher{display:block}
  /* :has() kept here so this (0,4,0) override beats the now-scoped sheet-show
     rule above (0,3,0) on specificity, not source order. */
  .nav.nav--slim:has(.nav__burger) .nav__sheet{display:none}
}

/* Language / chain switcher: <details> glass dropdown (dark port). */
.switcher{position:relative;font-size:13.5px}
.switcher summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:8px;color:var(--muted);
  padding:8px 14px;border:1px solid var(--line-2);border-radius:var(--r-sm);user-select:none;
  transition:border-color var(--dur) var(--ease),color var(--dur) var(--ease)}
.switcher summary::-webkit-details-marker{display:none}
.switcher summary::after{content:"";width:7px;height:7px;margin-left:6px;flex:none;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:translateY(-2px) rotate(45deg);opacity:.7;
  transition:transform var(--dur) var(--ease)}
.switcher[open] summary::after{transform:translateY(1px) rotate(-135deg)}
.switcher summary:hover{color:var(--ink);border-color:var(--line-2)}
.switcher[open] summary{border-color:var(--brand);color:var(--ink)}
.switcher summary svg{width:15px;height:15px;flex:none;opacity:.85}
/* On narrow screens the switcher collapses to its globe icon (the sheet keeps the
   label via .nav__sheet .switcher__t). Keeps content-page navs from overflowing. */
@media (max-width:560px){.switcher__t{display:none}}
.switcher__menu{position:absolute;right:0;top:calc(100% + 8px);min-width:184px;max-height:60vh;overflow:auto;
  display:flex;flex-direction:column;padding:6px;z-index:60;
  background:color-mix(in srgb,var(--bg-2) 92%,transparent);backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);
  border:1px solid var(--line-2);border-radius:var(--r);box-shadow:var(--shadow)}
.switcher__menu a{padding:8px 11px;border-radius:var(--r-sm);color:var(--ink);text-decoration:none;font-size:14px;
  transition:background var(--dur) var(--ease)}
.switcher__menu a:hover{background:var(--surface-2)}
.switcher__menu a[aria-current="true"]{color:var(--brand);font-weight:600}

/* --- Utilities -------------------------------------------------------------- */
/* Two-tone gradient text (violet → teal). Used by the hero headline + section
   eyebrows; background-clip:text needs an explicit transparent color fallback
   for engines without background-clip support. */
.grad-vt{background:linear-gradient(100deg,var(--brand-2) 10%,var(--teal) 90%);-webkit-background-clip:text;background-clip:text;color:transparent}

/* --- Hero ----------------------------------------------------------------- */
.hero{padding-top:clamp(56px,9vw,96px);padding-bottom:36px;display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:22px}
.hero h1{max-width:16ch}
.hero .lede{margin-left:auto;margin-right:auto}
.lede{color:var(--muted);font-size:clamp(17px,2vw,20px);max-width:62ch}

/* Trust row: small reassurance line under the hero. */
.trust{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 22px;margin:4px 0 0;padding:0;list-style:none}
.trust li{display:inline-flex;align-items:center;gap:8px;color:var(--muted);font-size:13.5px}
.trust svg{width:16px;height:16px;flex:none;color:var(--brand)}

/* --- Actions -------------------------------------------------------------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;background:var(--brand);color:var(--brand-ink);
  font-family:var(--sans);font-weight:650;font-size:15px;border:0;border-radius:var(--r-sm);padding:13px 20px;
  text-decoration:none;cursor:pointer;box-shadow:0 0 0 0 var(--glow);
  transition:box-shadow var(--dur) var(--ease),background var(--dur) var(--ease)}
.btn:hover{background:var(--brand-d);box-shadow:0 8px 30px -6px var(--glow)}
.btn:disabled{opacity:.55;cursor:default;box-shadow:none}
.btn2{display:inline-flex;align-items:center;justify-content:center;gap:8px;background:var(--surface);color:var(--ink);
  font-family:var(--sans);font-weight:600;font-size:15px;border:1px solid var(--line-2);border-radius:var(--r-sm);
  padding:13px 20px;text-decoration:none;cursor:pointer;transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease)}
.btn2:hover{border-color:var(--brand);background:var(--surface-2)}

/* Small brand chip (eyebrow / status pill). */
.pill{display:inline-flex;align-items:center;gap:8px;line-height:1;font-size:13px;font-weight:600;padding:6px 13px;border-radius:999px;
  color:var(--brand);background:color-mix(in srgb,var(--brand) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--brand) 30%,transparent)}
.pill::before{content:"";width:7px;height:7px;flex:none;border-radius:50%;background:var(--brand);box-shadow:0 0 10px var(--glow)}

/* Outline chip: also the look of related-link pills (see .related a). */
.chip,.related a{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;font-weight:500;padding:7px 14px;border-radius:999px;
  color:var(--muted);background:var(--surface);border:1px solid var(--line-2);text-decoration:none;
  transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease),background var(--dur) var(--ease)}
.chip:hover,.related a:hover{color:var(--ink);border-color:var(--brand);background:var(--surface-2)}

/* --- Surfaces ------------------------------------------------------------- */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);padding:22px;
  transition:border-color var(--dur) var(--ease),transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.card:hover{border-color:var(--line-2);transform:translateY(-2px)}
a.card,.card a{color:inherit;text-decoration:none}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px}

/* Card micro-interactions: a warmer hover for the three "come explore this" surfaces (New
   and trending's .trend__card, the toolkit's .card.tool, and the flagship .card.teaser
   feature cards) instead of the bare border-color+2px lift every plain .card gets above.
   Two-class selectors (.card.tool/.card.teaser) so this wins on specificity over any
   page-local .tool:hover/.teaser:hover left in a template's inline <style>, the usual way a
   shared system rule stays authoritative over a page override rather than relying on
   source order. A soft cursor-follow highlight rides along: --mx/--my (0-100%) are set by a
   tiny shared pointermove handler where these cards are used; left at their 50%/50% default
   when that hasn't run (or is skipped for prefers-reduced-motion), the glow just centers
   instead of tracking, so it degrades to a plain static highlight rather than breaking.
   Transitions (and so the lift itself, which would otherwise still apply instantly on
   hover/unhover) are covered by this file's global prefers-reduced-motion block below. */
.trend__card,.card.tool,.card.teaser{background-repeat:no-repeat;background-position:center}
.trend__card:hover,.card.tool:hover,.card.teaser:hover{
  transform:translateY(-4px);
  border-color:color-mix(in srgb,var(--brand-2) 55%,transparent);
  box-shadow:0 18px 40px -20px var(--glow),0 18px 40px -20px var(--glow-teal),var(--shadow);
  background-image:radial-gradient(240px circle at var(--mx,50%) var(--my,50%),color-mix(in srgb,var(--brand-2) 14%,transparent),transparent 70%)
}

/* --- Data-viz ------------------------------------------------------------- */
/* Score ring. Colour follows [data-band]; JS drives the arc via data-score. */
.ring{--ring:var(--brand);position:relative;width:120px;height:120px}
.ring svg{transform:rotate(-90deg)}
.ring__track{fill:none;stroke:var(--surface-2);stroke-width:10}
.ring__fill{fill:none;stroke:var(--ring);stroke-width:10;stroke-linecap:round;
  filter:drop-shadow(0 0 6px var(--glow));transition:stroke-dashoffset 1.1s var(--ease)}
.ring__num{position:absolute;inset:0;display:grid;place-items:center;font-family:var(--disp);font-size:30px;font-weight:700;color:var(--ring)}
.ring[data-band="safe"]{--ring:var(--safe)}
.ring[data-band="warn"]{--ring:var(--warn)}
.ring[data-band="danger"]{--ring:var(--danger)}
.ring[data-band="critical"]{--ring:var(--critical)}
.ring[data-band="unknown"]{--ring:var(--faint)}

/* Metric tile. */
.metric{display:flex;flex-direction:column;gap:8px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:18px 20px;box-shadow:var(--shadow)}
.metric__label{color:var(--muted);font-size:12.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase}
.metric__val{font-family:var(--mono);font-size:clamp(24px,3vw,30px);font-weight:600;line-height:1;letter-spacing:-.01em;color:var(--ink)}
.metric__val small{font-family:var(--sans);font-size:14px;font-weight:500;color:var(--muted)}

/* Cost / risk driver row. */
.driver{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:14px 0;border-top:1px solid var(--line)}
.driver:first-child{border-top:0}
.driver__cost{font-family:var(--mono);font-weight:600;font-size:14.5px;white-space:nowrap;color:var(--danger)}

/* Thin progress / meter bar (fill = direct child or .bar__fill). */
.bar{height:8px;border-radius:999px;background:var(--surface-2);overflow:hidden}
.bar>i,.bar>span,.bar__fill{display:block;height:100%;width:0;border-radius:inherit;
  background:linear-gradient(90deg,var(--brand-d),var(--brand));box-shadow:0 0 12px -2px var(--glow);
  transition:width 1s var(--ease)}

/* Status badges. */
.badge{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:600;padding:4px 10px;border-radius:999px;border:1px solid}
.badge--safe{color:var(--safe);border-color:color-mix(in srgb,var(--safe) 40%,transparent);background:color-mix(in srgb,var(--safe) 12%,transparent)}
.badge--warn{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 40%,transparent);background:color-mix(in srgb,var(--warn) 12%,transparent)}
.badge--danger{color:var(--danger);border-color:color-mix(in srgb,var(--danger) 40%,transparent);background:color-mix(in srgb,var(--danger) 12%,transparent)}
.badge--critical{color:#fff;border-color:var(--critical);background:color-mix(in srgb,var(--critical) 30%,transparent)}
.badge--unknown{color:var(--muted);border-color:var(--line-2);background:var(--surface)}

/* Metric explanation sub-line: what the number means + the benchmark, sitting
   under a .metric__val so a raw number is never shown without plain-language
   meaning (see the rug-checker's grouped-sections result panel). */
.metric__note{margin-top:4px;color:var(--muted);font-size:13px;line-height:1.55}

/* Labeled sections inside a result panel (e.g. "Can you sell?" / "Rug risk" /
   "Real vs fake activity" / "Contract"), grouping a flat metrics grid into a
   scannable, handcrafted hierarchy instead of one undifferentiated wall. */
.section{margin-top:24px}
.section__title{margin:0 0 10px;font-family:var(--disp);font-size:12.5px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}

/* "Is this volume real?" wash-trading readout: a dedicated, prominent panel
   (not just another metric tile) since real-vs-fake activity is the signal
   users most need and most often miss. Colour follows the verdict tier via
   the --safe/--warn/--danger/--faint modifier classes below. */
.volume-panel{border-radius:var(--r);border:1px solid var(--line);background:var(--surface);
  padding:18px 20px;box-shadow:var(--shadow)}
.volume-panel__verdict{display:flex;align-items:center;gap:9px;font-family:var(--disp);
  font-weight:650;font-size:16px;margin:0 0 6px;color:var(--ink)}
.volume-panel__dot{width:9px;height:9px;border-radius:50%;flex:none;background:var(--vp,var(--faint));
  box-shadow:0 0 10px var(--vp,transparent)}
.volume-panel--safe{border-color:color-mix(in srgb,var(--safe) 35%,var(--line))}
.volume-panel--safe .volume-panel__dot{--vp:var(--safe)}
.volume-panel--safe .volume-panel__verdict{color:var(--safe)}
.volume-panel--warn{border-color:color-mix(in srgb,var(--warn) 35%,var(--line))}
.volume-panel--warn .volume-panel__dot{--vp:var(--warn)}
.volume-panel--warn .volume-panel__verdict{color:var(--warn)}
.volume-panel--danger{border-color:color-mix(in srgb,var(--danger) 40%,var(--line))}
.volume-panel--danger .volume-panel__dot{--vp:var(--danger)}
.volume-panel--danger .volume-panel__verdict{color:var(--danger)}
.volume-panel__why{margin:0;color:var(--muted);font-size:13.5px;line-height:1.55}
.volume-panel__stats{margin:10px 0 0;padding-top:10px;border-top:1px solid var(--line);color:var(--faint);font-size:12px}

/* Trust / data-source reassurance line, sat right under the verdict summary. */
.source-note{display:flex;align-items:center;gap:6px;margin:10px 0 0;color:var(--muted);font-size:13px}

/* "The read": the synthesized projection that leads a rug-check verdict (see
   rug-checker.html theRead()). Deliberately distinct from the metric tiles, a
   subtle brand-edged panel with larger, high-contrast prose, so it reads as the
   handcrafted analyst take and the raw metric grid below is its evidence. */
.the-read{position:relative;margin:22px 0 0;padding:22px 24px;border-radius:var(--r);
  border:1px solid var(--line-2);overflow:hidden;
  background:linear-gradient(180deg,color-mix(in srgb,var(--brand) 7%,var(--surface)),var(--surface))}
.the-read::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,var(--brand),var(--teal))}
.the-read__head{margin:0;font-family:var(--disp);font-size:19px;font-weight:700;letter-spacing:-.01em;color:var(--ink)}
.the-read__story{margin:10px 0 0;font-size:15px;line-height:1.62;color:var(--ink)}
.the-read__sub{margin:20px 0 0;font-family:var(--disp);font-size:12.5px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.the-read__risks{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:13px}
.the-read__risk{display:flex;gap:12px;align-items:flex-start;font-size:14.5px;line-height:1.55;color:var(--ink)}
.the-read__risk b{font-weight:700}
.the-read__dot{flex:none;width:10px;height:10px;border-radius:50%;margin-top:6px;background:var(--faint)}
.the-read__risk--critical .the-read__dot{background:var(--critical)}
.the-read__risk--danger .the-read__dot{background:var(--danger)}
.the-read__risk--warn .the-read__dot{background:var(--warn)}
.the-read__watch{color:var(--muted)}
.the-read__ok{margin:16px 0 0;padding-top:14px;border-top:1px solid var(--line);
  display:flex;gap:9px;align-items:flex-start;font-size:14px;line-height:1.55;color:var(--muted)}
.the-read__ok b{color:var(--safe);font-weight:700}

/* Trade-safely primary CTA (the rev-share path): only ever rendered on a
   genuine PASS, see tradeCta()'s band==="safe"&&isSol guard. Deliberately
   self-contained (not composed from .btn) so its prominence can't drift if
   .btn's base styling changes elsewhere. */
.trade-cta{display:flex;flex-direction:column;gap:2px;margin-top:18px;padding:18px 20px;border-radius:var(--r);
  background:linear-gradient(135deg,color-mix(in srgb,var(--brand-2) 14%,var(--surface)),color-mix(in srgb,var(--teal) 10%,var(--surface)));
  border:1px solid color-mix(in srgb,var(--teal) 38%,var(--line-2))}
.trade-cta__head{margin:0;font-family:var(--disp);font-weight:650;font-size:15.5px;color:var(--ink)}
.trade-cta__sub{margin:2px 0 12px;color:var(--muted);font-size:13.5px}
.trade-cta__btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;align-self:flex-start;
  padding:14px 22px;border-radius:var(--r-sm);border:0;cursor:pointer;text-decoration:none;
  font-family:var(--sans);font-weight:700;font-size:15.5px;color:#08120F;white-space:nowrap;
  background:linear-gradient(100deg,var(--brand-2),var(--teal));box-shadow:0 14px 34px -14px var(--glow-teal);
  transition:transform var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.trade-cta__btn:hover{transform:translateY(-1px);box-shadow:0 18px 40px -14px var(--glow-teal)}
.trade-cta--blocked{margin-top:18px;padding:12px 14px;border:1px solid var(--danger);border-radius:12px;
  color:var(--ink);font-size:14px;background:color-mix(in srgb,var(--danger) 8%,transparent)}

/* --- Marquee -------------------------------------------------------------- */
.marquee{overflow:hidden;-webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.marquee__track{display:flex;gap:44px;width:max-content;animation:mq 34s linear infinite}
.marquee:hover .marquee__track{animation-play-state:paused}
.marquee__item{display:inline-flex;align-items:center;gap:8px;color:var(--muted);opacity:.85}
.marquee__item svg{width:26px;height:26px;filter:drop-shadow(0 0 10px var(--glow))}
@keyframes mq{to{transform:translateX(-50%)}}

/* --- Content -------------------------------------------------------------- */
.faq{max-width:760px;margin:0 auto}
.qa{border-bottom:1px solid var(--line);padding:22px 0}
.qa:last-child{border-bottom:0}
.qa h3,.qa summary{font-family:var(--disp);font-weight:600;font-size:18px;color:var(--ink);margin:0}
.qa summary{cursor:pointer;list-style:none;display:flex;align-items:center;justify-content:space-between;gap:16px}
.qa summary::-webkit-details-marker{display:none}
.qa summary::after{content:"+";color:var(--muted);font-family:var(--sans);font-weight:400;font-size:22px;line-height:1;
  transition:transform var(--dur) var(--ease)}
.qa[open] summary::after{transform:rotate(45deg)}
.qa p{color:var(--muted);font-size:15px;line-height:1.6;margin:10px 0 0}
.qa h3 + p{margin-top:8px}

.related{display:flex;flex-wrap:wrap;gap:10px}

/* Inline footnote/caveat under content (e.g. a tool's coverage note). Sits off
   the element above with a hairline + space so it reads as a considered footnote,
   not text glued to the block before it. */
.note{margin-top:44px;padding-top:22px;border-top:1px solid var(--line);color:var(--muted);font-size:14.5px;line-height:1.65;max-width:760px}
.note b{color:var(--ink)}
.note a{color:var(--brand)}
.note + .note{margin-top:16px;padding-top:0;border-top:0} /* a second note follows without doubling the rule */

/* --- Extension bar (collapsed pill -> expandable card) -------------------- */
/* Default state is a small pill/FAB anchored to the corner so it never covers
   page content (the homepage trending cards, in particular). Tapping/clicking
   it expands the full promo card (name, description, store chips, CTA); a
   collapse control folds it back to the pill. Both states reveal after the
   reader scrolls in (or a short delay) and tuck away while the footer is on
   screen (unchanged; see the inline script). Store chips default to "coming
   soon": a script activates them once / resolve
   to real URLs. The X is a PERMANENT dismiss, remembered in localStorage
   ("veriql-guardian-dismissed") so neither the pill nor the card returns. */
.stickybar{position:fixed;right:20px;bottom:20px;left:auto;z-index:60;
  transform:translateY(calc(100% + 30px));opacity:0;transition:transform .5s var(--ease),opacity .4s var(--ease)}
.stickybar.show{transform:none;opacity:1}

.stickybar__pill{display:inline-flex;align-items:center;gap:9px;padding:10px 18px 10px 11px;border-radius:999px;
  background:color-mix(in srgb,var(--bg-2) 92%,transparent);
  backdrop-filter:blur(20px) saturate(150%);-webkit-backdrop-filter:blur(20px) saturate(150%);
  border:1px solid var(--line-2);box-shadow:0 18px 40px -18px rgba(0,0,0,.75),inset 0 1px 0 rgba(255,255,255,.05);
  color:var(--ink);font-family:var(--disp);font-weight:600;font-size:14px;cursor:pointer;
  transition:border-color var(--dur) var(--ease)}
.stickybar__pill:hover{border-color:var(--brand)}
/* An author rule sets display on this element (needed for the icon+label row),
   which otherwise beats the UA [hidden]{display:none} rule regardless of
   specificity (author origin always wins over UA origin) - same gotcha as
   .nav__sheet[hidden] above; this override restores the expected hide. */
.stickybar__pill[hidden]{display:none}
.stickybar__pill .stickybar__mk{width:24px;height:24px;border-radius:8px}
.stickybar__pill .stickybar__mk svg{width:14px;height:14px}

.stickybar__panel{width:calc(100vw - 40px);max-width:384px;padding:16px 18px;border-radius:var(--r-lg);
  background:color-mix(in srgb,var(--bg-2) 92%,transparent);
  backdrop-filter:blur(20px) saturate(150%);-webkit-backdrop-filter:blur(20px) saturate(150%);
  border:1px solid var(--line-2);box-shadow:0 26px 64px -22px rgba(0,0,0,.85),inset 0 1px 0 rgba(255,255,255,.05)}
.stickybar__panelhead{display:flex;align-items:center;justify-content:flex-end;gap:6px;margin-bottom:8px}
.stickybar__collapse,.stickybar__x{width:30px;height:30px;display:grid;place-items:center;border-radius:var(--r-sm);
  border:1px solid var(--line);background:transparent;color:var(--muted);cursor:pointer;flex:none;
  transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease)}
.stickybar__collapse:hover,.stickybar__x:hover{color:var(--ink);border-color:var(--line-2)}
.stickybar__collapse svg,.stickybar__x svg{width:15px;height:15px}
.stickybar__row{display:flex;align-items:center;gap:11px}
.stickybar__mk{width:34px;height:34px;flex:none;display:grid;place-items:center;border-radius:10px;color:var(--brand);
  background:color-mix(in srgb,var(--brand) 12%,transparent);border:1px solid color-mix(in srgb,var(--brand) 30%,transparent)}
.stickybar__mk svg{width:19px;height:19px}
.stickybar__name{font-family:var(--disp);font-weight:600;font-size:16px;color:var(--ink)}
.stickybar__desc{margin:11px 0 14px;color:var(--muted);font-size:13px;line-height:1.55}
.stickybar__desc b{color:var(--ink);font-weight:600}
.stickybar__act{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.stickybar__cta{width:100%;justify-content:center;margin-top:3px;padding:10px 16px;font-size:14px}
.stickybar__cta svg{width:15px;height:15px;flex:none}

/* Store chips: shared. */
.extbar__store{display:inline-flex;align-items:center;gap:7px;padding:8px 12px;border:1px solid var(--line-2);
  border-radius:var(--r-sm);background:var(--surface);color:var(--ink);text-decoration:none;font-weight:600;font-size:13px;
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease),color var(--dur) var(--ease)}
.extbar__store svg{width:15px;height:15px;flex:none}
.extbar__store:not(.is-soon):hover{border-color:var(--brand);background:var(--surface-2)}
.extbar__store.is-soon{color:var(--muted);cursor:default}
.extbar__soon{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);
  border:1px solid var(--line-2);border-radius:5px;padding:1px 5px}
.extbar__store:not(.is-soon) .extbar__soon{display:none}

@media (max-width:560px){
  .stickybar{right:12px;bottom:12px}
  .stickybar__panel{width:calc(100vw - 24px);max-width:none;padding:15px 16px}
}
@media (prefers-reduced-motion:reduce){ .stickybar{transition:none} }

/* --- Footer --------------------------------------------------------------- */
.footer{border-top:1px solid var(--line);margin-top:56px;padding:44px 0;color:var(--muted);font-size:14px}
.footer a{color:var(--muted);text-decoration:none;transition:color var(--dur) var(--ease)}
.footer a:hover{color:var(--ink)}
.footer h4{font-family:var(--disp);font-size:13px;font-weight:600;color:var(--muted);margin:0 0 14px}
.footer .legal{color:var(--muted);font-size:12.5px;line-height:1.7;margin-top:24px;max-width:88ch}

/* --- Forms / results ------------------------------------------------------ */
.field{display:flex;gap:8px;max-width:560px;width:100%}
.field input{flex:1;min-width:0;background:var(--bg-2);border:1px solid var(--line-2);color:var(--ink);
  border-radius:var(--r-sm);padding:13px 15px;font-family:var(--mono);font-size:14px;line-height:1.4;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.field input::placeholder{color:var(--muted)}
.field input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--glow)}
/* Chain picker <select>: custom chevron so the arrow isn't jammed against the
   wall like the native control, and real vertical padding so it keeps the input's
   height instead of collapsing to a sliver when the row stacks on mobile. */
.field select{-webkit-appearance:none;-moz-appearance:none;appearance:none;
  background-color:var(--bg-2);border:1px solid var(--line-2);color:var(--ink);border-radius:var(--r-sm);
  padding:13px 42px 13px 15px;font:600 14px var(--sans);line-height:1.4;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14' fill='none'%3E%3Cpath d='M3.5 5.25 7 8.75l3.5-3.5' stroke='%239BA8A1' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 15px center;
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}
.field select:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--glow)}
.field .btn,.field button{white-space:nowrap}
@media (max-width:560px){.field{flex-direction:column}}

/* "Try an example" affordance: a small, honest link under a check form that
   fills the input(s) with a real sample value and re-submits the SAME form
   (never a fabricated/canned result: it runs the actual live check). Composed
   only from existing tokens (--brand/--faint), no new color. The button's
   clickable box hits the 44px min tap target via min-height/min-width, not
   extra visual padding, so it still reads as a plain, understated text link. */
.example-try{margin:10px 0 0;display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:2px 10px}
.example-link{background:none;border:0;padding:0;margin:0;font:inherit;font-size:13.5px;font-weight:600;
  color:var(--brand);cursor:pointer;text-decoration:none;
  display:inline-flex;align-items:center;justify-content:center;min-height:44px;min-width:44px}
.example-link:hover{text-decoration:underline}
.example-hint{color:var(--faint);font-size:12px}

.results{display:flex;flex-direction:column;gap:12px;margin-top:20px}
.result{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:18px 20px;box-shadow:var(--shadow);
  animation:rise .4s var(--ease) both}
@keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

.skeleton{position:relative;overflow:hidden;min-height:16px;border-radius:var(--r-sm);background:var(--surface-2)}
/* Theme-relative sheen (not a hardcoded white): reads as a light glint on the
   dark surface and a soft dark glint on the light surface, instead of going
   invisible (white-on-white) once a light theme exists. */
.skeleton::after{content:"";position:absolute;inset:0;transform:translateX(-100%);
  background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--ink) 12%,transparent),transparent);animation:shimmer 1.4s var(--ease) infinite}
@keyframes shimmer{to{transform:translateX(100%)}}

.empty{color:var(--muted);text-align:center;padding:28px 20px;font-size:15px}
.error{color:var(--danger);font-size:14.5px;padding:12px 16px;border-radius:var(--r-sm);
  background:color-mix(in srgb,var(--danger) 10%,transparent);border:1px solid color-mix(in srgb,var(--danger) 32%,transparent)}

/* --- Scanning loader (on-brand "actively scanning" loading state) ---------
   Reuses the mark's corner-aperture motif (see .mk) and the product's
   signature UV-scan gesture (see .report--demo::before / .dw__scan): 4
   corner brackets frame the container, plus a violet->teal beam that
   sweeps top to bottom. Opt in with class="scanning" on any container, plus
   4 child .scanning__corner--{tl,tr,bl,br} spans and one .scanning__beam
   span (same explicit-child pattern as .dw__cnr/.dw__scan above, kept as
   its own general-purpose primitive rather than reusing those Drain-Watch-
   specific classes). Unlike Drain Watch's always-on viewfinder, this is a
   plain loading state, so it's gated behind prefers-reduced-motion below
   like every other animation in this file. */
.scanning{position:relative;overflow:hidden}
.scanning__corner{display:none;position:absolute;width:18px;height:18px;z-index:2;pointer-events:none;
  border:0 solid var(--brand-2);opacity:.9}
.scanning .scanning__corner{display:block}
.scanning__corner--tl{top:7px;left:7px;border-top-width:2px;border-left-width:2px;border-top-left-radius:7px}
.scanning__corner--tr{top:7px;right:7px;border-top-width:2px;border-right-width:2px;border-top-right-radius:7px}
.scanning__corner--bl{bottom:7px;left:7px;border-bottom-width:2px;border-left-width:2px;border-bottom-left-radius:7px}
.scanning__corner--br{bottom:7px;right:7px;border-bottom-width:2px;border-right-width:2px;border-bottom-right-radius:7px}
.scanning__beam{display:none;position:absolute;left:0;right:0;top:0;height:2px;z-index:1;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--brand-2),var(--teal),transparent);
  box-shadow:0 0 14px 2px var(--glow-teal);animation:scanbeam 1.2s cubic-bezier(.65,0,.35,1) infinite}
.scanning .scanning__beam{display:block}
@keyframes scanbeam{0%{top:0;opacity:0}8%{opacity:1}92%{opacity:1}100%{top:calc(100% - 2px);opacity:0}}

/* --- Motion --------------------------------------------------------------
   PRODUCT DECISION (2026-09-29): Veriql's ambient motion is always on.

   This block used to be a blanket `*{animation:none!important}` kill-switch.
   The problem: Windows' "Show animations in Windows" = Off (and macOS "Reduce
   motion") sets prefers-reduced-motion, which silently flattened the ENTIRE
   product into a dead static page: no marquee, no ticker, no scan-line, no
   count-ups, no reveals. The "live instrument" read is a big part of why the
   verdicts feel authoritative, so losing it on a whole class of machines was
   costing us the first impression. Drain Watch already opted out of this gate
   with !important; this generalises that call to the whole design system.

   What a reduced-motion user still gets: instant (non-smooth) scrolling. That
   is the accommodation that actually matters for vestibular comfort, and it
   costs the design nothing. Individual pages must NOT re-add a blanket
   animation:none. */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
}
