/* ============================================================
   Desk Anvil — shared stylesheet for every tool page
   Used by: site/index.html (later) + site/tools/<slug>/index.html
   Rules: no build step, no external requests (no webfonts, no CDNs),
   plain CSS so Claude and Codex can both edit it. Add a tool page by
   copying the previous one — never restart from a blank file, and never
   give one page its own visual trick. Tricks land here or get dropped.
   ============================================================ */

/* ---------- tokens ---------- */
:root {
  /* Light is the committed default, not a system-preference coin flip: these
     tools are used at a desk in daylight, and light is the look the brand is
     designed in. Dark still ships — it is one click on the header toggle, and
     it is a real theme, not an inversion. To go back to following the OS,
     restore the `@media (prefers-color-scheme: dark)` block below. */
  color-scheme: light;

  /* type — system stack on purpose: zero network requests, no webfont
     flash, and it renders as Segoe UI / SF / Roboto per platform.
     Swap for a self-hosted woff2 only if the brand ever needs it.
     --display matches the homepage's condensed headline face (2026-09-17
     merge): headings, the header/footer wordmark, buttons and nav labels
     share it everywhere now, so a page never reveals which stylesheet it's
     on. */
  --display: "Roboto Condensed", "Arial Narrow", "Helvetica Neue Condensed",
             "Liberation Sans Narrow", Arial, sans-serif;
  --font: ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;

  --measure: 68ch;          /* readable line length */
  --radius: 12px;
  --radius-sm: 8px;
  --pad: clamp(1.25rem, 4vw, 2rem);
  --gap: clamp(1rem, 2.5vw, 1.5rem);
  --section: clamp(4.5rem, 11vw, 8.5rem);   /* air is the cheapest premium signal */

  --ease: cubic-bezier(.2, .7, .3, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);   /* confident arrival, never bounce */
  --dur: 200ms;

  /* z-index scale */
  --z-header: 20;
  --z-top: 50;

  /* light theme — values match the homepage's --ground/--surface/--rule/--ink
     tokens exactly (2026-09-17), same names kept here so the 50+ component
     classes below (.card, .compare, .browser-frame, .faq…) never had to
     change. A subpage and the homepage now render the identical colour,
     they just reach it through differently-named custom properties. */
  --bg: #eef1f5;
  --bg-soft: #e5e9ef;
  --surface: #ffffff;
  --border: #d3d9e2;
  --border-strong: #b3bcc9;
  --text: #12151b;
  --muted: #4c5563;

  /* Violet-blue on ink. Chosen over the previous pure blue because it reads as
     a considered brand rather than default-framework blue — and, critically,
     violet stays clear of the status hues below, which belong to the
     extensions' own semantics and can never be borrowed for brand. */
  --accent: #4b57c7;          /* 6.0:1 on white — passes AA for body text */
  --accent-blue: #2f70d9;     /* homepage's primary-button gradient end, matched 2026-09-17 */
  --accent-hover: #3e49ad;
  --accent-on: #ffffff;
  --accent-soft: #eef0ff;
  --ring: #4b57c7;

  /* hero atmosphere — very low saturation, never a "gradient hero" */
  --wash-a: rgba(75, 87, 199, .10);
  --wash-b: rgba(140, 110, 255, .08);

  /* status — must match the extension's own semantics */
  --ok: #15803d;
  --ok-soft: #e9f7ee;
  --warn: #b45309;
  --warn-soft: #fdf3e3;
  --bad: #b91c1c;
  --bad-soft: #fdecec;

  --shadow-sm: 0 1px 2px rgba(16, 20, 28, .06), 0 1px 3px rgba(16, 20, 28, .04);
  --shadow-md: 0 4px 12px rgba(16, 20, 28, .07), 0 2px 4px rgba(16, 20, 28, .04);
  --shadow-lg: 0 18px 50px rgba(16, 20, 28, .10), 0 4px 12px rgba(16, 20, 28, .05);
}

/* The OS-preference auto-dark block was removed deliberately: light is the
   committed default (see :root above). Dark remains available through the
   header toggle, which writes data-theme and is handled below. */

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0e1116; --bg-soft: #12161d; --surface: #161a21;
  --border: #262c36; --border-strong: #39414e;
  --text: #eef1f6; --muted: #9aa4b3;
  --accent: #9b8cff; --accent-hover: #b6abff; --accent-on: #0e1116; --accent-soft: #1d1946; --ring: #9b8cff;
  --wash-a: rgba(123, 106, 255, .14); --wash-b: rgba(160, 120, 255, .10);
  --ok: #4ade80; --ok-soft: #10241a; --warn: #fbbf24; --warn-soft: #2a2110; --bad: #f87171; --bad-soft: #2b1416;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.5);
  --shadow-md: 0 6px 16px rgba(0,0,0,.45);
  --shadow-lg: 0 24px 60px rgba(0,0,0,.55);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1.0625rem;           /* 17px — never below 16 on mobile */
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;             /* the page never scrolls sideways */
}

/* Same condensed display face and weight as the homepage (2026-09-17); the
   size scale stays this file's own — a privacy page doesn't need a 6.75rem
   H1, it needs the same typographic voice at text-page scale. */
h1, h2, h3 {
  font-family: var(--display); font-weight: 700;
  line-height: .96; margin: 0 0 .5em; text-wrap: balance;
}
h1 { font-size: clamp(2.1rem, 6vw, 3.4rem); letter-spacing: -.025em; text-transform: uppercase; }
h2 { font-size: clamp(1.5rem, 3.6vw, 2.1rem); letter-spacing: -.02em; }
h3 { font-size: 1.125rem; letter-spacing: -.01em; line-height: 1.15; }
p { margin: 0 0 1rem; max-width: var(--measure); }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-hover); }
strong { font-weight: 640; }
code, kbd { font-family: var(--mono); font-size: .875em; }
img, svg { max-width: 100%; }
:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: 4px; }

/* Surfaces the browser draws that belong to no design system. Theming them is
   the cheapest signal that a page was built rather than assembled. */
::selection { background: var(--accent); color: var(--accent-on); }
:root { scrollbar-color: var(--border-strong) transparent; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong); border-radius: 999px;
  border: 3px solid var(--bg); background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: padding-box; }

.wrap { width: 100%; max-width: 1180px; margin-inline: auto; padding-inline: var(--pad); }
.narrow { max-width: 760px; }
.lede { font-size: clamp(1.0625rem, 2.2vw, 1.25rem); color: var(--muted); }
.eyebrow {
  display: inline-flex; align-items: center; gap: .65rem;
  font-family: var(--display); font-size: .75rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--muted);
  margin: 0 0 1rem;
}
.eyebrow::before {
  content: ""; width: 1.75rem; height: 2px; flex: 0 0 auto;
  background: linear-gradient(90deg, var(--accent), #2f70d9);
}
section { padding-block: var(--section); }

/* ---------- install strip (2026-09-17) ----------
   A live tool's header was carrying wordmark + 3 nav links + CTA + theme
   switch on one row — crowded, and the CTA read as just another small
   button among several. This gives the same CTA its own full-width row
   instead, directly under the header, so it can't get lost. Only used on
   pages that are genuinely live (a real store link), never on a "coming
   soon" tool.
   Sticky on purpose: without this it sat directly above the hero's own
   identical CTA, so the page showed "Add to Chrome" twice in one screen
   before any scrolling — pure repetition, not reinforcement. Pinned, it
   earns a different job: a persistent install reminder once the hero's
   own CTA has scrolled out of view. */
.install-strip {
  /* Sticks directly under the header (76px, this file's fixed height at every
     breakpoint) rather than at top:0, which would overlap it instead of
     stacking below it. */
  position: sticky; top: 76px; z-index: 19;
  background: linear-gradient(120deg, var(--accent), var(--accent-blue));
  text-align: center;
}
.install-strip .wrap {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: .35rem .9rem; padding-block: .8rem;
}
.install-strip p {
  margin: 0; color: #fff; font-size: .9375rem;
}
.install-strip a {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .35rem .9rem; border-radius: 999px;
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .3);
  color: #fff; font-family: var(--display); font-weight: 700; font-size: .875rem;
  letter-spacing: .06em; text-decoration: none;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.install-strip a:hover { background: rgba(255, 255, 255, .28); border-color: rgba(255, 255, 255, .5); color: #fff; }

/* Platform mark inside a button (ported from the homepage's desk-anvil.css,
   which this file never had — the reason the Chrome logo wasn't rendering
   here at all). */
.btn-icon {
  display: inline-block; width: 1.1em; height: 1.1em; flex: 0 0 auto;
  background: currentColor;
  -webkit-mask: url("assets/icons/chrome.svg") center / contain no-repeat;
  mask: url("assets/icons/chrome.svg") center / contain no-repeat;
}
.section-soft { background: var(--bg-soft); border-block: 1px solid var(--border); }

/* ---------- header ---------- */
.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: var(--surface);                                      /* fallback first */
  background: color-mix(in srgb, var(--surface) 88%, transparent); /* translucent where supported */
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.site-header .wrap {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 76px;
}
.wordmark {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--display); font-weight: 700; font-size: 1.1875rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--text); text-decoration: none; white-space: nowrap;
}
.wordmark:hover { color: var(--text); }
.site-header .wordmark { font-size: 1.3125rem; }
/* Keep the existing `.dot` hook so every page shares the approved Desk Anvil
   mark without duplicate markup. The footer switches to the light-D variant. */
.wordmark .dot {
  width: 42px; height: 42px; flex: 0 0 auto;
  background: url("assets/brand/deskanvil-mark.png") no-repeat center / contain;
}
:root[data-theme="dark"] .wordmark .dot { background-image: url("assets/brand/deskanvil-mark-dark.png"); }
.header-actions { display: flex; align-items: center; gap: 1.25rem; }

/* Station signage, not a button — matches the homepage nav exactly. */
.nav-link {
  font-family: var(--display); font-size: .8125rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); text-decoration: none;
  padding-bottom: 2px; border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.nav-link:hover { color: var(--text); border-bottom-color: var(--accent); }

/* A real switch, identical to the homepage's: a track, both states visible,
   and a knob that travels to the one you are in. */
.theme-switch {
  position: relative; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: space-between;
  width: 64px; height: 34px; padding: 0 9px;
  border: 1px solid var(--border-strong); border-radius: 999px;
  background: var(--surface); cursor: pointer;
  transition: border-color var(--dur) var(--ease-out);
}
.theme-switch:hover { border-color: var(--muted); }
.theme-switch .knob {
  position: absolute; top: 3px; left: 3px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 1px 3px rgba(10, 12, 18, .3);
  transition: transform var(--dur) var(--ease-out);
}
:root[data-theme="dark"] .theme-switch .knob { transform: translateX(30px); }
.theme-switch svg {
  position: relative; z-index: 1; width: 15px; height: 15px;
  color: var(--muted); transition: color var(--dur) var(--ease-out);
}
.theme-switch .i-sun { color: #fff; }
:root[data-theme="dark"] .theme-switch .i-sun { color: var(--muted); }
:root[data-theme="dark"] .theme-switch .i-moon { color: #fff; }
@media (prefers-reduced-motion: reduce) { .theme-switch .knob { transition: none; } }

/* ---------- buttons ----------
   Byte-for-byte the same as the homepage now (corrected 2026-09-17 — an
   earlier pass kept this file's own gradient/glow treatment on
   .btn-primary and called it "close enough"; it wasn't the actual goal,
   so it's gone). .btn-ghost/.btn-line: the homepage's .btn-ghost is styled
   for its dark board and would be invisible on these light pages, so both
   names render the light outline style here — there's no dark section on
   any subpage for a real .btn-ghost use to collide with. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 46px; padding: .7rem 1.35rem;
  font-family: var(--display); font-size: .9375rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid transparent; border-radius: 7px;
  cursor: pointer; text-decoration: none;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}
.btn-primary {
  background: linear-gradient(120deg, var(--accent), var(--accent-blue));
  color: #fff; box-shadow: 0 4px 0 color-mix(in srgb, var(--accent) 62%, #111 38%);
  transform: translateY(0);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.btn-primary:hover {
  background: linear-gradient(120deg, var(--accent-hover), #1766dc);
  color: #fff; transform: translateY(1px); box-shadow: 0 3px 0 color-mix(in srgb, var(--accent) 62%, #111 38%);
}
.btn-ghost, .btn-line { background: transparent; color: var(--text); border-color: var(--border-strong); }
.btn-ghost:hover, .btn-line:hover { background: var(--bg-soft); color: var(--text); border-color: var(--muted); }
.btn-pending {
  font-family: var(--display); font-size: .8125rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted); background: var(--bg-soft); border-color: var(--border-strong); cursor: default;
}
.btn-lg { min-height: 54px; padding: .9rem 1.7rem; font-size: 1rem; }
.btn svg { flex: 0 0 auto; }

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--radius-sm);
  background: transparent; border: 1px solid transparent; color: var(--muted);
  cursor: pointer; transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.icon-btn:hover { color: var(--text); background: var(--bg-soft); }

/* ---------- hero ----------
   Centred, large, and sitting on a low-saturation wash. The wash is the single
   cheapest "premium" signal there is — but keep it near-invisible: the moment it
   reads as a gradient hero it looks like a template. */
.hero {
  position: relative; isolation: isolate; text-align: center;
  padding-top: clamp(3rem, 8vw, 5.5rem); padding-bottom: clamp(2rem, 5vw, 3rem);
}
.hero::before {
  content: ""; position: absolute; z-index: -1;
  inset: -6rem 0 auto; height: 46rem;
  background:
    radial-gradient(60rem 26rem at 50% 0%, var(--wash-a), transparent 70%),
    radial-gradient(40rem 20rem at 78% 12%, var(--wash-b), transparent 70%);
  pointer-events: none;
}
.hero h1 { max-width: 20ch; margin-inline: auto; }
.hero .lede { max-width: 56ch; margin-inline: auto; }
.hero .eyebrow { margin-bottom: 1rem; }
.hero .trust-strip { justify-content: center; }
.hero-cta { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.75rem; justify-content: center; }
.hero-note {
  display: flex; align-items: center; gap: .45rem;
  margin-top: 1rem; font-size: .9375rem; color: var(--muted);
}
.hero-note svg { color: var(--ok); flex: 0 0 auto; }

/* ---------- hero trust strip (three scannable proofs under the CTA) ---------- */
.trust-strip {
  display: flex; flex-wrap: wrap; gap: .6rem 1.5rem;
  margin: 1.25rem 0 0; padding: 0; list-style: none;
}
.trust-strip li {
  display: flex; align-items: center; gap: .45rem;
  font-size: .9375rem; color: var(--muted);
}
.trust-strip svg { color: var(--ok); flex: 0 0 auto; }
.trust-strip b { color: var(--text); font-weight: 600; }

/* ---------- alternating feature split ---------- */
.split {
  display: grid; gap: clamp(1.5rem, 5vw, 3.5rem);
  grid-template-columns: 1fr; align-items: center;
}
@media (min-width: 52rem) {
  .split { grid-template-columns: 1fr 1fr; }
  .split.reverse .split-visual { order: 2; }
}
.split-text h2 { margin-bottom: .75rem; }
.split-text p { color: var(--muted); }
.split-text p strong { color: var(--text); }

/* the mismatch comparison — the wedge, shown rather than described */
.compare {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-lg); overflow: hidden;
}
.compare-row {
  display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap;
  padding: .9rem 1.1rem;
}
.compare-row + .compare-row { border-top: 1px solid var(--border); }
.compare-label {
  font-size: .75rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); flex: 0 0 6.5rem;
}
.compare-value { font-family: var(--mono); font-size: 1rem; font-weight: 600; }
.compare-value.ok { color: var(--ok); }
.compare-value.bad { color: var(--bad); }
.compare-verdict {
  padding: .85rem 1.1rem; background: var(--bad-soft);
  border-top: 1px solid var(--border);
  font-size: .9375rem; color: var(--bad); font-weight: 600;
}

/* ---------- browser availability strip ---------- */
.browsers {
  /* Constrained and centred: at full text width the heading, single browser row
     and note floated in a large empty box with nothing holding them together. */
  margin: 2.5rem auto 0; max-width: 30rem; padding: 1.35rem 1.5rem;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); text-align: center;
}
.browsers-title {
  font-size: .8125rem; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 1.1rem;
}
.browsers-list {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 1rem 2.5rem; margin: 0; padding: 0; list-style: none;
}
.browsers-list li {
  display: flex; align-items: center; gap: .55rem;
  font-weight: 600; color: var(--text);
}
.browsers-list li.pending { color: var(--muted); font-weight: 500; }
/* The browser name is the install link once a listing exists. It keeps the row
   layout and inherits currentColor so the masked brand icon still themes. */
.browsers-list .browser-link {
  display: inline-flex; align-items: center; gap: .55rem;
  color: var(--accent); text-decoration: none; font-weight: 600;
  border-bottom: 1px solid transparent;
}
.browsers-list .browser-link:hover,
.browsers-list .browser-link:focus-visible { border-bottom-color: currentColor; }

/* Brand icons as CSS masks, so a flat Simple Icons SVG takes currentColor and
   follows the theme instead of staying black in dark mode. Paths are relative
   to THIS file, so they work from any page depth.
   Canonical copies: 03_reference\assets\icons\ (see its readme). */
.bicon {
  display: inline-block;   /* never let it collapse on a non-flex parent */
  width: 20px; height: 20px; flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.bicon-chrome { -webkit-mask-image: url("assets/icons/chrome.svg"); mask-image: url("assets/icons/chrome.svg"); }
.bicon-firefox { -webkit-mask-image: url("assets/icons/firefox.svg"); mask-image: url("assets/icons/firefox.svg"); }
.browsers-note { margin: 1.1rem 0 0; font-size: .875rem; color: var(--muted); }

/* ---------- FAQ (native details — no JS, keyboard accessible) ---------- */
.faq { margin-top: 2rem; border-top: 1px solid var(--border); }
.faq details { border-bottom: 1px solid var(--border); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.15rem .25rem; cursor: pointer; list-style: none;
  font-weight: 600; font-size: 1.0625rem; color: var(--text);
  transition: color var(--dur) var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary::after {
  content: ""; flex: 0 0 auto; width: 10px; height: 10px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--dur) var(--ease);
}
.faq details[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.faq details > p { padding: 0 .25rem 1.25rem; color: var(--muted); margin: 0 0 .75rem; }
.faq details > p:last-child { margin-bottom: 0; }
.faq-more { margin-top: 2rem; text-align: center; color: var(--muted); }

/* ---------- browser frame ----------
   Wrapping the product shot in browser chrome is the single strongest visual
   device on the benchmark page: it says "this happens in your browser" before
   a word is read, and it makes a plain panel look like a product. */
.browser-frame {
  margin-top: clamp(2.25rem, 5vw, 3.5rem);
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--bg-soft); box-shadow: var(--shadow-lg);
  overflow: hidden; text-align: left;
}
.browser-bar {
  display: flex; align-items: center; gap: .75rem;
  padding: .7rem .9rem; background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.browser-dots { display: flex; gap: .35rem; flex: 0 0 auto; }
.browser-dots i { display: block; width: 10px; height: 10px; border-radius: 50%; background: var(--border-strong); }
.browser-url {
  flex: 1 1 auto; max-width: 24rem; margin-inline: auto;
  padding: .3rem .8rem; border: 1px solid var(--border); border-radius: 999px;
  background: var(--bg-soft); color: var(--muted);
  font-family: var(--mono); font-size: .75rem; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.browser-body { padding: clamp(.75rem, 2.2vw, 1.5rem); }
.browser-body .demo { margin-top: 0; box-shadow: var(--shadow-md); }

/* ---------- product demo panel (stand-in for the real screenshot) ---------- */
.demo {
  margin-top: clamp(2rem, 5vw, 3rem);
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-lg); overflow: hidden;
}
.demo-bar {
  display: flex; align-items: center; gap: .5rem;
  padding: .6rem .85rem; border-bottom: 1px solid var(--border); background: var(--bg-soft);
}
.demo-bar .title { font-size: .875rem; font-weight: 600; color: var(--muted); }
.demo-bar .spacer { flex: 1; }
.demo-bar .pip { width: 9px; height: 9px; border-radius: 50%; background: var(--border-strong); }
.demo-body { padding: .85rem; display: grid; gap: .5rem; }
.demo-group {
  font-size: .75rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); margin-top: .35rem;
}
.demo-group:first-child { margin-top: 0; }
.row {
  display: flex; align-items: center; gap: .65rem; flex-wrap: wrap;
  padding: .6rem .7rem; border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius-sm); background: var(--bg);
}
.row .url {
  font-family: var(--mono); font-size: .8125rem; color: var(--text);
  overflow-wrap: anywhere; flex: 1 1 14rem; min-width: 0;
}
.row.ok { border-left-color: var(--ok); }
.row.warn { border-left-color: var(--warn); }
.row.bad { border-left-color: var(--bad); }
.chip {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .75rem; font-weight: 650; padding: .2rem .5rem;
  border-radius: 999px; white-space: nowrap;
}
/* status is never colour alone — every chip carries a word */
.chip.ok { background: var(--ok-soft); color: var(--ok); }
.chip.warn { background: var(--warn-soft); color: var(--warn); }
.chip.bad { background: var(--bad-soft); color: var(--bad); }
.chip.neutral { background: var(--bg-soft); color: var(--muted); }
.demo-caption {
  font-size: .875rem; color: var(--muted); margin: .85rem 0 0; text-align: center;
}

/* ---------- feature cards ---------- */
.grid {
  display: grid; gap: var(--gap); margin-top: 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15.5rem), 1fr));
}
/* The catalogue is a lead card plus a row of thirds, not an even 2×2. Four
   identical boxes would rank a flagship that ships first equal with three that
   do not, and a grid of same-size cards is the lazy container. Breakpoint
   matches .standards so the two sections change shape together. */
@media (min-width: 46rem) {
  .tools-grid { grid-template-columns: repeat(3, 1fr); }
  .tools-grid .lead { grid-column: 1 / -1; }
}
.card {
  padding: 1.35rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-sm);
  /* hover = pop + ring, never a lift */
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.card:hover {
  transform: scale(1.015);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md), 0 0 0 3px var(--accent-soft);
}
.card h3 { margin-bottom: .4rem; }
.card p { color: var(--muted); margin: 0; font-size: .9375rem; }
.card-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; margin-bottom: .9rem;
  border-radius: 10px; background: var(--accent-soft); color: var(--accent);
}
.why { color: var(--text); }

/* ---------- tool cards (umbrella homepage) ---------- */
.tool-card {
  display: flex; flex-direction: column; gap: .6rem;
  padding: 1.5rem; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface); box-shadow: var(--shadow-sm);
  text-decoration: none; color: inherit;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
a.tool-card:hover {
  transform: scale(1.015); color: inherit;
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md), 0 0 0 3px var(--accent-soft);
}
/* Nothing inside a card may force the card wider than its grid track. Flex and
   grid children default to min-width:auto, which is what let a long title shove
   the status chip out through the card's right edge. */
.tool-card > *, .tool-card-main > * { min-width: 0; }
.tool-card h3 { margin: 0; }
.tool-card p { margin: 0; color: var(--muted); font-size: .9375rem; }

/* Status sits with the action, not beside the title: availability is something
   you check when you are deciding to click, and putting it on the title's line
   made two nowrap items compete for one row. */
.tool-foot {
  margin-top: auto; padding-top: 1.1rem;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: .55rem 1rem;
}
.tool-card .go {
  font-weight: 600; font-size: .9375rem; color: var(--accent);
  display: inline-flex; align-items: center; gap: .35rem;
}
.tool-card .go svg { transition: transform var(--dur) var(--ease); }
a.tool-card:hover .go svg { transform: translateX(3px); }

.tool-card.soon { border-style: dashed; box-shadow: none; }
.tool-card.soon h3 { color: var(--muted); }

/* The lead card earns a different rhythm from the three below it: on a wide
   screen its evidence moves alongside the copy instead of under it, so the
   flagship reads as a peak in the scroll rather than a taller box. */
.tool-card-main { display: flex; flex-direction: column; gap: .6rem; flex: 1 1 55%; }

/* Below the split, the wrapper stops being a box so its children join the
   card's own column — otherwise the action row would sit above the evidence
   it is asking you to act on. */
@media (max-width: 59.99rem) {
  .tool-card.lead .tool-card-main { display: contents; }
  .tool-card.lead .tool-preview { order: 1; }
  .tool-card.lead .tool-foot { order: 2; }
}

@media (min-width: 60rem) {
  .tool-card.lead { flex-direction: row; gap: 2rem; padding: 1.9rem; }
  .tool-card.lead .tool-preview {
    flex: 1 1 45%; align-self: center;
    margin-top: 0; padding-top: 0; padding-left: 1.9rem;
    border-top: 0; border-left: 1px dashed var(--border);
  }
  .tool-card.lead h3 { font-size: 1.3rem; }
}

/* A card's own miniature output. Deliberately NOT the browser-frame panel used
   on the tool pages: the homepage's job is "what do these tools tell you", the
   tool page's job is "here is this one in full". Repeating the same panel on
   both would make the click-through feel like nothing happened. */
.tool-preview {
  margin-top: 1rem; padding-top: .9rem;
  border-top: 1px dashed var(--border);
  display: grid; gap: .4rem;
}
/* No status border here on purpose. The chip at the end of the row already
   carries the colour AND the word, so a coloured left edge repeats what the
   chip says and adds the one border treatment that reads as generated UI. */
.tool-preview .mini { display: flex; align-items: center; gap: .5rem; }
.tool-preview .u {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--mono); font-size: .6875rem; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tool-preview .chip { font-size: .6875rem; padding: .1rem .4rem; }
.tool-card.soon .tool-preview { opacity: .65; }

/* ---------- standards list (what every tool promises) ---------- */
.standards { list-style: none; padding: 0; margin: 2.5rem 0 0; display: grid; gap: 1.75rem; }
@media (min-width: 46rem) { .standards { grid-template-columns: 1fr 1fr; gap: 2rem 3rem; } }
.standards li { max-width: 34rem; }
.standards h3 { margin-bottom: .35rem; }
.standards p { margin: 0; color: var(--muted); font-size: .9375rem; }

/* ---------- trust + limits ---------- */
.trust-list, .limit-list { list-style: none; padding: 0; margin: 1.5rem 0 0; display: grid; gap: .8rem; }
.trust-list li, .limit-list li {
  display: flex; gap: .7rem; align-items: flex-start;
  max-width: var(--measure); color: var(--muted);
}
.trust-list svg { color: var(--ok); flex: 0 0 auto; margin-top: .2rem; }
.limit-list svg { color: var(--warn); flex: 0 0 auto; margin-top: .2rem; }
.trust-list b, .limit-list b { color: var(--text); font-weight: 640; }

.callout {
  margin-top: 1.5rem; padding: 1.1rem 1.25rem;
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm); background: var(--surface);
}
.callout p:last-child { margin-bottom: 0; }

/* ---------- signup form ---------- */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.signup { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.5rem; max-width: 30rem; }
.signup input {
  flex: 1 1 14rem; min-width: 0; min-height: 48px;
  padding: .7rem .95rem; font: inherit; color: var(--text);
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.signup input::placeholder { color: var(--muted); }
.signup input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.signup .btn { min-height: 48px; }
.signup-note { margin-top: .85rem; font-size: .875rem; color: var(--muted); }

/* ---------- follow band (a real channel, used until the list exists) ---------- */
.follow {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem 2rem;
  padding: clamp(1.5rem, 4vw, 2.25rem);
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-sm);
}
.follow-text { flex: 1 1 20rem; }
.follow-text h3 { margin-bottom: .35rem; font-size: 1.25rem; }
.follow-text p { margin: 0; color: var(--muted); }

/* ---------- final CTA ---------- */
.cta-band { text-align: center; }
.cta-band h2 { max-width: 26ch; margin-inline: auto; }
.cta-band p { margin-inline: auto; }
.cta-band .hero-cta { justify-content: center; }

/* ---------- footer ---------- */
.site-footer {
  border-top: 0; background: linear-gradient(180deg, #454c57, #232830);
  color: #aeb6c2; font-size: .9375rem;
}
.site-footer .wrap { padding-block: clamp(3.5rem, 7vw, 6rem) 2.5rem; }
.site-footer a { color: #dde2e9; text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.dead-reckoning-link { display: inline-flex; align-items: center; gap: .34em; }
.footer-top {
  display: grid; grid-template-columns: minmax(15rem, .8fr) minmax(0, 1.7fr);
  gap: clamp(3rem, 8vw, 8rem); align-items: start;
}
.site-footer .wordmark {
  color: #fff; gap: .6rem;
  font-family: "Roboto Condensed", "Arial Narrow", "Helvetica Neue Condensed", "Liberation Sans Narrow", Arial, sans-serif;
  font-weight: 700; font-size: 1.1875rem; letter-spacing: .1em;
}
.site-footer .wordmark .dot { width: 42px; height: 42px; background-image: url("assets/brand/deskanvil-mark-dark.png"); }
.footer-brand .footer-meta { max-width: 29rem; margin: .6rem 0 0; line-height: 1.6; }
.footer-columns { display: grid; grid-template-columns: 1.4fr .8fr 1fr; gap: clamp(2rem, 5vw, 5rem); }
.footer-links { display: flex; flex-direction: column; align-items: flex-start; gap: .65rem; }
.footer-label { margin-bottom: .5rem; color: #fff; font-family: "Roboto Condensed", "Arial Narrow", "Helvetica Neue Condensed", "Liberation Sans Narrow", Arial, sans-serif; font-size: .75rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.footer-state { color: #aeb6c2; line-height: 1.45; }
.footer-meta { font-size: .8125rem; color: #8f98a5; }
.footer-legal { margin-top: clamp(2.5rem, 6vw, 5rem); padding-top: 1.25rem; border-top: 1px solid rgba(255,255,255,.12); }

/* ---------- long-form pages (privacy, terms, docs) ---------- */
.prose { max-width: var(--measure); }
.prose h2 { margin-top: 2.5rem; font-size: clamp(1.25rem, 2.8vw, 1.5rem); }
.prose h2:first-of-type { margin-top: 1rem; }
.prose ul { padding-left: 1.15rem; margin: 0 0 1rem; }
.prose li { margin-bottom: .45rem; }
.prose li::marker { color: var(--muted); }
.prose .updated { color: var(--muted); font-size: .9375rem; }

/* wide content scrolls inside itself — the page never scrolls sideways */
.table-scroll { overflow-x: auto; margin: 1rem 0 1.5rem; -webkit-overflow-scrolling: touch; }
.prose table { border-collapse: collapse; width: 100%; min-width: 30rem; font-size: .9375rem; }
.prose th, .prose td {
  text-align: left; vertical-align: top;
  padding: .6rem .75rem; border-bottom: 1px solid var(--border);
}
.prose th { font-weight: 640; color: var(--text); background: var(--bg-soft); white-space: nowrap; }
.prose td { color: var(--muted); }

/* ---------- motion ----------
   Thesis: these tools report findings as they check them. So the lead card's
   verdicts arrive the way real results do — the link first, its verdict a beat
   later, one row after the next. That sequence is the page's ONE authored
   moment; every other element gets a plain, faster arrival so nothing competes
   with it. A fade-and-rise on every section is not a thesis, it is wallpaper.

   Nothing is hidden in CSS by default. The `.anim` hidden state is applied by
   script, and only once the script is confirmed running and motion is allowed,
   so a failed script or a reduced-motion visitor can never get a blank page. */
.anim { opacity: 0; transform: translateY(9px); }
.anim.in {
  opacity: 1; transform: none;
  transition: opacity 480ms var(--ease-out), transform 480ms var(--ease-out);
}

/* The focal sequence. Rows report in; each verdict chip settles after the link
   it belongs to, because in the real tool the link is known first and the
   verdict comes back from the check. */
.anim.lead .tool-preview .mini { opacity: 0; transform: translateY(6px); }
.anim.lead.in .tool-preview .mini {
  opacity: 1; transform: none;
  transition: opacity 400ms var(--ease-out), transform 400ms var(--ease-out);
}
.anim.lead.in .tool-preview .mini:nth-child(1) { transition-delay: 140ms; }
.anim.lead.in .tool-preview .mini:nth-child(2) { transition-delay: 260ms; }
.anim.lead.in .tool-preview .mini:nth-child(3) { transition-delay: 380ms; }

.anim.lead .tool-preview .mini .chip { opacity: 0; transform: scale(.9); }
.anim.lead.in .tool-preview .mini .chip {
  opacity: 1; transform: none;
  transition: opacity 240ms var(--ease-out), transform 240ms var(--ease-out);
}
.anim.lead.in .tool-preview .mini:nth-child(1) .chip { transition-delay: 340ms; }
.anim.lead.in .tool-preview .mini:nth-child(2) .chip { transition-delay: 460ms; }
.anim.lead.in .tool-preview .mini:nth-child(3) .chip { transition-delay: 580ms; }

/* Supporting cards are a list, so a capped stagger is honest — but they stay
   short and quiet, well inside the lead card's sequence. */
.anim.soon.in { transition-duration: 380ms; }
.tools-grid .soon:nth-of-type(2).in { transition-delay: 60ms; }
.tools-grid .soon:nth-of-type(3).in { transition-delay: 120ms; }

@media (prefers-reduced-motion: reduce) {
  .card:hover, a.tool-card:hover { transform: none; }
}

/* ---------- small screens ---------- */
@media (max-width: 30rem) {
  .site-header .wrap { gap: .5rem; }
  .header-actions { margin-left: auto; }
  .header-actions .btn { display: none; }
  .hero-cta .btn { width: 100%; }
  .footer-columns { grid-template-columns: 1fr; }
}

@media (max-width: 58rem) {
  .footer-top { grid-template-columns: 1fr; }
}

@media (max-width: 44rem) {
  .footer-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 46rem) {
  .site-footer .wordmark { gap: .45rem; font-size: 1rem; letter-spacing: .08em; }
  .site-footer .wordmark .dot { width: 36px; height: 36px; }
}
